mirror of
https://github.com/esp-rs/esp-idf-hal.git
synced 2025-09-29 05:12:09 +00:00
Move all peripheral generics into the constructors
This commit is contained in:
parent
59629c8b49
commit
d6370068ef
@ -7,9 +7,7 @@
|
||||
//! Depending on your target and the board you are using you should change the pins.
|
||||
//! If your board doesn't have on-board LEDs don't forget to add an appropriate resistor.
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use esp_idf_hal::delay::FreeRtos;
|
||||
use esp_idf_hal::gpio::*;
|
||||
use esp_idf_hal::peripherals::Peripherals;
|
||||
|
||||
@ -24,7 +22,7 @@ fn main() -> anyhow::Result<()> {
|
||||
|
||||
loop {
|
||||
// we are using thread::sleep here to make sure the watchdog isn't triggered
|
||||
thread::sleep(Duration::from_millis(10));
|
||||
FreeRtos::delay_ms(10);
|
||||
|
||||
if button.is_high() {
|
||||
led.set_low()?;
|
||||
|
@ -65,11 +65,11 @@ fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
fn send_morse_code<'d>(
|
||||
channel: impl Peripheral<P = CHANNEL0> + 'd,
|
||||
channel: impl Peripheral<P = impl RmtChannel> + 'd,
|
||||
led: impl Peripheral<P = impl OutputPin> + 'd,
|
||||
config: &TransmitConfig,
|
||||
message: &str,
|
||||
) -> anyhow::Result<RmtDriver<'d, CHANNEL0>> {
|
||||
) -> anyhow::Result<RmtDriver<'d>> {
|
||||
println!("Sending morse message '{}'.", message);
|
||||
|
||||
let mut signal = VariableLengthSignal::new();
|
||||
|
@ -20,7 +20,7 @@ fn main() -> anyhow::Result<()> {
|
||||
let led = peripherals.pins.gpio17;
|
||||
let channel = peripherals.rmt.channel0;
|
||||
let config = TransmitConfig::new().looping(Loop::Endless);
|
||||
let mut tx: RmtDriver<'static, _> = RmtDriver::new(channel, led, &config)?;
|
||||
let mut tx: RmtDriver<'static> = RmtDriver::new(channel, led, &config)?;
|
||||
|
||||
loop {
|
||||
play_song(&mut tx, ODE_TO_JOY)?;
|
||||
@ -28,10 +28,7 @@ fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn play_song(
|
||||
tx: &mut RmtDriver<'static, impl RmtChannel>,
|
||||
song: &[NoteValue],
|
||||
) -> anyhow::Result<()> {
|
||||
pub fn play_song(tx: &mut RmtDriver<'static>, song: &[NoteValue]) -> anyhow::Result<()> {
|
||||
for note_value in song {
|
||||
play_note(tx, note_value.note.0, note_value.duration)?;
|
||||
}
|
||||
@ -39,7 +36,7 @@ pub fn play_song(
|
||||
}
|
||||
|
||||
pub fn play_note(
|
||||
tx: &mut RmtDriver<'static, impl RmtChannel>,
|
||||
tx: &mut RmtDriver<'static>,
|
||||
pitch: u16,
|
||||
duration: Duration,
|
||||
) -> anyhow::Result<()> {
|
||||
|
@ -11,11 +11,9 @@
|
||||
//! This example transfers data via SPI.
|
||||
//! Connect SDI and SDO pins to see the outgoing data is read as incoming data.
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use embedded_hal::spi::SpiDevice;
|
||||
|
||||
use esp_idf_hal::delay::FreeRtos;
|
||||
use esp_idf_hal::peripherals::Peripherals;
|
||||
use esp_idf_hal::prelude::*;
|
||||
use esp_idf_hal::spi::*;
|
||||
@ -34,14 +32,14 @@ fn main() -> anyhow::Result<()> {
|
||||
println!("Starting SPI loopback test");
|
||||
let config = config::Config::new().baudrate(26.MHz().into());
|
||||
let mut spi =
|
||||
SpiMasterDriver::<SPI2>::new(spi, sclk, serial_out, Some(serial_in), Some(cs), &config)?;
|
||||
SpiMasterDriver::new::<SPI2>(spi, sclk, serial_out, Some(serial_in), Some(cs), &config)?;
|
||||
|
||||
let mut read = [0u8; 4];
|
||||
let write = [0xde, 0xad, 0xbe, 0xef];
|
||||
|
||||
loop {
|
||||
// we are using thread::sleep here to make sure the watchdog isn't triggered
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
FreeRtos::delay_ms(500);
|
||||
spi.transfer(&mut read, &write)?;
|
||||
println!("Wrote {:x?}, read {:x?}", write, read);
|
||||
}
|
||||
|
106
src/i2c.rs
106
src/i2c.rs
@ -6,7 +6,7 @@ use esp_idf_sys::*;
|
||||
|
||||
use crate::delay::*;
|
||||
use crate::gpio::*;
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
use crate::peripheral::Peripheral;
|
||||
use crate::units::*;
|
||||
|
||||
pub use embedded_hal::i2c::Operation;
|
||||
@ -121,29 +121,24 @@ pub trait I2c: Send {
|
||||
fn port() -> i2c_port_t;
|
||||
}
|
||||
|
||||
pub struct I2cMasterDriver<'d, I2C>
|
||||
where
|
||||
I2C: I2c,
|
||||
{
|
||||
_i2c: PeripheralRef<'d, I2C>,
|
||||
pub struct I2cMasterDriver<'d> {
|
||||
i2c: u8,
|
||||
_p: PhantomData<&'d ()>,
|
||||
}
|
||||
|
||||
impl<'d, I2C> I2cMasterDriver<'d, I2C>
|
||||
where
|
||||
I2C: I2c,
|
||||
{
|
||||
pub fn new(
|
||||
i2c: impl Peripheral<P = I2C> + 'd,
|
||||
impl<'d> I2cMasterDriver<'d> {
|
||||
pub fn new<I2C: I2c>(
|
||||
_i2c: impl Peripheral<P = I2C> + 'd,
|
||||
sda: impl Peripheral<P = impl InputPin + OutputPin> + 'd,
|
||||
scl: impl Peripheral<P = impl InputPin + OutputPin> + 'd,
|
||||
config: &config::MasterConfig,
|
||||
) -> Result<I2cMasterDriver<'d, I2C>, EspError> {
|
||||
) -> Result<Self, EspError> {
|
||||
// i2c_config_t documentation says that clock speed must be no higher than 1 MHz
|
||||
if config.baudrate > 1.MHz().into() {
|
||||
return Err(EspError::from(ESP_ERR_INVALID_ARG).unwrap());
|
||||
}
|
||||
|
||||
crate::into_ref!(i2c, sda, scl);
|
||||
crate::into_ref!(sda, scl);
|
||||
|
||||
let sys_config = i2c_config_t {
|
||||
mode: i2c_mode_t_I2C_MODE_MASTER,
|
||||
@ -171,7 +166,10 @@ where
|
||||
) // TODO: set flags
|
||||
})?;
|
||||
|
||||
Ok(I2cMasterDriver { _i2c: i2c })
|
||||
Ok(I2cMasterDriver {
|
||||
i2c: I2C::port() as _,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn read(
|
||||
@ -297,22 +295,23 @@ where
|
||||
command_link: &CommandLink,
|
||||
timeout: TickType_t,
|
||||
) -> Result<(), EspError> {
|
||||
esp!(unsafe { i2c_master_cmd_begin(I2C::port(), command_link.0, timeout) })
|
||||
esp!(unsafe { i2c_master_cmd_begin(self.port(), command_link.0, timeout) })
|
||||
}
|
||||
|
||||
pub fn port(&self) -> i2c_port_t {
|
||||
self.i2c as _
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, I2C: I2c> Drop for I2cMasterDriver<'d, I2C> {
|
||||
impl<'d> Drop for I2cMasterDriver<'d> {
|
||||
fn drop(&mut self) {
|
||||
esp!(unsafe { i2c_driver_delete(I2C::port()) }).unwrap();
|
||||
esp!(unsafe { i2c_driver_delete(self.port()) }).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'d, I2C: I2c> Send for I2cMasterDriver<'d, I2C> {}
|
||||
unsafe impl<'d> Send for I2cMasterDriver<'d> {}
|
||||
|
||||
impl<'d, I2C> embedded_hal_0_2::blocking::i2c::Read for I2cMasterDriver<'d, I2C>
|
||||
where
|
||||
I2C: I2c,
|
||||
{
|
||||
impl<'d> embedded_hal_0_2::blocking::i2c::Read for I2cMasterDriver<'d> {
|
||||
type Error = I2cError;
|
||||
|
||||
fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
|
||||
@ -320,10 +319,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, I2C> embedded_hal_0_2::blocking::i2c::Write for I2cMasterDriver<'d, I2C>
|
||||
where
|
||||
I2C: I2c,
|
||||
{
|
||||
impl<'d> embedded_hal_0_2::blocking::i2c::Write for I2cMasterDriver<'d> {
|
||||
type Error = I2cError;
|
||||
|
||||
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
|
||||
@ -331,10 +327,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, I2C> embedded_hal_0_2::blocking::i2c::WriteRead for I2cMasterDriver<'d, I2C>
|
||||
where
|
||||
I2C: I2c,
|
||||
{
|
||||
impl<'d> embedded_hal_0_2::blocking::i2c::WriteRead for I2cMasterDriver<'d> {
|
||||
type Error = I2cError;
|
||||
|
||||
fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
|
||||
@ -342,18 +335,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, I2C> embedded_hal::i2c::ErrorType for I2cMasterDriver<'d, I2C>
|
||||
where
|
||||
I2C: I2c,
|
||||
{
|
||||
impl<'d> embedded_hal::i2c::ErrorType for I2cMasterDriver<'d> {
|
||||
type Error = I2cError;
|
||||
}
|
||||
|
||||
impl<'d, I2C> embedded_hal::i2c::I2c<embedded_hal::i2c::SevenBitAddress>
|
||||
for I2cMasterDriver<'d, I2C>
|
||||
where
|
||||
I2C: I2c,
|
||||
{
|
||||
impl<'d> embedded_hal::i2c::I2c<embedded_hal::i2c::SevenBitAddress> for I2cMasterDriver<'d> {
|
||||
fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
|
||||
I2cMasterDriver::read(self, addr, buffer, BLOCK).map_err(to_i2c_err)
|
||||
}
|
||||
@ -409,27 +395,22 @@ fn to_i2c_err(err: EspError) -> I2cError {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct I2cSlaveDriver<'d, I2C>
|
||||
where
|
||||
I2C: I2c,
|
||||
{
|
||||
_i2c: PeripheralRef<'d, I2C>,
|
||||
pub struct I2cSlaveDriver<'d> {
|
||||
i2c: u8,
|
||||
_p: PhantomData<&'d ()>,
|
||||
}
|
||||
|
||||
unsafe impl<'d, I2C: I2c> Send for I2cSlaveDriver<'d, I2C> {}
|
||||
unsafe impl<'d> Send for I2cSlaveDriver<'d> {}
|
||||
|
||||
impl<'d, I2C> I2cSlaveDriver<'d, I2C>
|
||||
where
|
||||
I2C: I2c,
|
||||
{
|
||||
pub fn new(
|
||||
i2c: impl Peripheral<P = I2C> + 'd,
|
||||
impl<'d> I2cSlaveDriver<'d> {
|
||||
pub fn new<I2C: I2c>(
|
||||
_i2c: impl Peripheral<P = I2C> + 'd,
|
||||
sda: impl Peripheral<P = impl InputPin + OutputPin> + 'd,
|
||||
scl: impl Peripheral<P = impl InputPin + OutputPin> + 'd,
|
||||
slave_addr: u8,
|
||||
config: &config::SlaveConfig,
|
||||
) -> Result<Self, EspError> {
|
||||
crate::into_ref!(i2c, sda, scl);
|
||||
crate::into_ref!(sda, scl);
|
||||
|
||||
#[cfg(not(esp_idf_version = "4.3"))]
|
||||
let sys_config = i2c_config_t {
|
||||
@ -476,13 +457,16 @@ where
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Self { _i2c: i2c })
|
||||
Ok(Self {
|
||||
i2c: I2C::port() as _,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn read(&mut self, buffer: &mut [u8], timeout: TickType_t) -> Result<usize, EspError> {
|
||||
let n = unsafe {
|
||||
i2c_slave_read_buffer(
|
||||
I2C::port(),
|
||||
self.port(),
|
||||
buffer.as_mut_ptr(),
|
||||
buffer.len() as u32,
|
||||
timeout,
|
||||
@ -499,7 +483,7 @@ where
|
||||
pub fn write(&mut self, bytes: &[u8], timeout: TickType_t) -> Result<usize, EspError> {
|
||||
let n = unsafe {
|
||||
i2c_slave_write_buffer(
|
||||
I2C::port(),
|
||||
self.port(),
|
||||
bytes.as_ptr() as *const u8 as *mut u8,
|
||||
bytes.len() as i32,
|
||||
timeout,
|
||||
@ -512,6 +496,16 @@ where
|
||||
Err(EspError::from(ESP_ERR_TIMEOUT).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn port(&self) -> i2c_port_t {
|
||||
self.i2c as _
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> Drop for I2cSlaveDriver<'d> {
|
||||
fn drop(&mut self) {
|
||||
esp!(unsafe { i2c_driver_delete(self.port()) }).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
|
84
src/ledc.rs
84
src/ledc.rs
@ -24,12 +24,13 @@
|
||||
//! See the `examples/` folder of this repository for more.
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::marker::PhantomData;
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use esp_idf_sys::*;
|
||||
|
||||
use crate::gpio::OutputPin;
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
use crate::peripheral::Peripheral;
|
||||
use crate::task::CriticalSection;
|
||||
|
||||
pub use chip::*;
|
||||
@ -92,19 +93,18 @@ pub mod config {
|
||||
}
|
||||
|
||||
/// LED Control timer driver
|
||||
pub struct LedcTimerDriver<'d, T: LedcTimer> {
|
||||
_timer: PeripheralRef<'d, T>,
|
||||
pub struct LedcTimerDriver<'d> {
|
||||
timer: u8,
|
||||
speed_mode: ledc_mode_t,
|
||||
max_duty: Duty,
|
||||
_p: PhantomData<&'d ()>,
|
||||
}
|
||||
|
||||
impl<'d, T: LedcTimer> LedcTimerDriver<'d, T> {
|
||||
pub fn new(
|
||||
timer: impl Peripheral<P = T> + 'd,
|
||||
impl<'d> LedcTimerDriver<'d> {
|
||||
pub fn new<T: LedcTimer>(
|
||||
_timer: impl Peripheral<P = T> + 'd,
|
||||
config: &config::TimerConfig,
|
||||
) -> Result<Self, EspError> {
|
||||
crate::into_ref!(timer);
|
||||
|
||||
let timer_config = ledc_timer_config_t {
|
||||
speed_mode: config.speed_mode,
|
||||
timer_num: T::timer(),
|
||||
@ -122,67 +122,66 @@ impl<'d, T: LedcTimer> LedcTimerDriver<'d, T> {
|
||||
esp!(unsafe { ledc_timer_config(&timer_config) })?;
|
||||
|
||||
Ok(Self {
|
||||
_timer: timer,
|
||||
timer: T::timer() as _,
|
||||
speed_mode: config.speed_mode,
|
||||
max_duty: config.resolution.max_duty(),
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
/// Pauses the timer. Operation can be resumed with [`resume_timer()`].
|
||||
pub fn pause(&mut self) -> Result<(), EspError> {
|
||||
esp!(unsafe { ledc_timer_pause(self.speed_mode, T::timer()) })?;
|
||||
esp!(unsafe { ledc_timer_pause(self.speed_mode, self.timer()) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resumes the operation of the previously paused timer
|
||||
pub fn resume(&mut self) -> Result<(), EspError> {
|
||||
esp!(unsafe { ledc_timer_resume(self.speed_mode, T::timer()) })?;
|
||||
esp!(unsafe { ledc_timer_resume(self.speed_mode, self.timer()) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> Result<(), EspError> {
|
||||
esp!(unsafe { ledc_timer_rst(self.speed_mode, T::timer()) })?;
|
||||
esp!(unsafe { ledc_timer_rst(self.speed_mode, self.timer()) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn timer(&self) -> ledc_timer_t {
|
||||
self.timer as _
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: LedcTimer> Drop for LedcTimerDriver<'d, T> {
|
||||
impl<'d> Drop for LedcTimerDriver<'d> {
|
||||
fn drop(&mut self) {
|
||||
self.reset().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'d, T: LedcTimer> Send for LedcTimerDriver<'d, T> {}
|
||||
unsafe impl<'d> Send for LedcTimerDriver<'d> {}
|
||||
|
||||
/// LED Control driver
|
||||
pub struct LedcDriver<'d, C, B>
|
||||
where
|
||||
C: LedcChannel,
|
||||
{
|
||||
_channel: PeripheralRef<'d, C>,
|
||||
_timer_driver: B,
|
||||
pub struct LedcDriver<'d> {
|
||||
channel: u8,
|
||||
timer: u8,
|
||||
duty: Duty,
|
||||
hpoint: HPoint,
|
||||
speed_mode: ledc_mode_t,
|
||||
max_duty: Duty,
|
||||
_p: PhantomData<&'d ()>,
|
||||
}
|
||||
|
||||
// TODO: Stop channel when the instance gets dropped. It seems that we can't
|
||||
// have both at the same time: a method for releasing its hardware resources
|
||||
// and implementing Drop.
|
||||
impl<'d, C: LedcChannel, B> LedcDriver<'d, C, B> {
|
||||
impl<'d> LedcDriver<'d> {
|
||||
/// Creates a new LED Control driver
|
||||
pub fn new<T>(
|
||||
channel: impl Peripheral<P = C> + 'd,
|
||||
pub fn new<C: LedcChannel, B: Borrow<LedcTimerDriver<'d>>>(
|
||||
_channel: impl Peripheral<P = C> + 'd,
|
||||
timer_driver: B,
|
||||
pin: impl Peripheral<P = impl OutputPin> + 'd,
|
||||
config: &config::TimerConfig,
|
||||
) -> Result<Self, EspError>
|
||||
where
|
||||
B: Borrow<LedcTimerDriver<'d, T>>,
|
||||
T: LedcTimer + 'd,
|
||||
{
|
||||
crate::into_ref!(channel, pin);
|
||||
) -> Result<Self, EspError> {
|
||||
crate::into_ref!(pin);
|
||||
|
||||
let duty = 0;
|
||||
let hpoint = 0;
|
||||
@ -190,7 +189,7 @@ impl<'d, C: LedcChannel, B> LedcDriver<'d, C, B> {
|
||||
let channel_config = ledc_channel_config_t {
|
||||
speed_mode: config.speed_mode,
|
||||
channel: C::channel(),
|
||||
timer_sel: T::timer(),
|
||||
timer_sel: timer_driver.borrow().timer(),
|
||||
intr_type: ledc_intr_type_t_LEDC_INTR_DISABLE,
|
||||
gpio_num: pin.pin(),
|
||||
duty,
|
||||
@ -223,8 +222,9 @@ impl<'d, C: LedcChannel, B> LedcDriver<'d, C, B> {
|
||||
hpoint,
|
||||
speed_mode: timer_driver.borrow().speed_mode,
|
||||
max_duty: timer_driver.borrow().max_duty,
|
||||
_channel: channel,
|
||||
_timer_driver: timer_driver,
|
||||
timer: timer_driver.borrow().timer() as _,
|
||||
channel: C::channel() as _,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
@ -270,26 +270,34 @@ impl<'d, C: LedcChannel, B> LedcDriver<'d, C, B> {
|
||||
}
|
||||
|
||||
fn stop(&mut self) -> Result<(), EspError> {
|
||||
esp!(unsafe { ledc_stop(self.speed_mode, C::channel(), IDLE_LEVEL,) })?;
|
||||
esp!(unsafe { ledc_stop(self.speed_mode, self.channel(), IDLE_LEVEL,) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_duty(&mut self, duty: Duty, hpoint: HPoint) -> Result<(), EspError> {
|
||||
esp!(unsafe { ledc_set_duty_and_update(self.speed_mode, C::channel(), duty, hpoint) })?;
|
||||
esp!(unsafe { ledc_set_duty_and_update(self.speed_mode, self.channel(), duty, hpoint) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn channel(&self) -> ledc_channel_t {
|
||||
self.channel as _
|
||||
}
|
||||
|
||||
pub fn timer(&self) -> ledc_timer_t {
|
||||
self.timer as _
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, C: LedcChannel, B> Drop for LedcDriver<'d, C, B> {
|
||||
impl<'d> Drop for LedcDriver<'d> {
|
||||
fn drop(&mut self) {
|
||||
self.stop().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'d, C: LedcChannel, B> Send for LedcDriver<'d, C, B> {}
|
||||
unsafe impl<'d> Send for LedcDriver<'d> {}
|
||||
|
||||
// PwmPin temporarily removed from embedded-hal-1.0.alpha7 in anticipation of e-hal 1.0 release
|
||||
// impl<'d, C: LedcChannel, B: Borrow<LedcTimerDriver<'d, T>>, T: LedcTimer> embedded_hal::pwm::blocking::PwmPin for LedcDriver<'d, C, B, T> {
|
||||
// impl<'d> embedded_hal::pwm::blocking::PwmPin for LedcDriver<'d> {
|
||||
// type Duty = Duty;
|
||||
// type Error = EspError;
|
||||
|
||||
@ -314,7 +322,7 @@ unsafe impl<'d, C: LedcChannel, B> Send for LedcDriver<'d, C, B> {}
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<'d, C: LedcChannel, B> embedded_hal_0_2::PwmPin for LedcDriver<'d, C, B> {
|
||||
impl<'d> embedded_hal_0_2::PwmPin for LedcDriver<'d> {
|
||||
type Duty = Duty;
|
||||
|
||||
fn disable(&mut self) {
|
||||
|
57
src/rmt.rs
57
src/rmt.rs
@ -52,6 +52,7 @@
|
||||
//! ahead of time.
|
||||
|
||||
use core::convert::TryFrom;
|
||||
use core::marker::PhantomData;
|
||||
use core::time::Duration;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
@ -64,7 +65,7 @@ use core::cell::UnsafeCell;
|
||||
use esp_idf_sys::*;
|
||||
|
||||
use crate::gpio::OutputPin;
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
use crate::peripheral::Peripheral;
|
||||
use crate::units::Hertz;
|
||||
|
||||
use config::TransmitConfig;
|
||||
@ -341,22 +342,23 @@ pub mod config {
|
||||
/// Use [`RmtDriver::start()`] or [`RmtDriver::start_blocking()`] to transmit pulses.
|
||||
///
|
||||
/// See the [rmt module][crate::rmt] for more information.
|
||||
pub struct RmtDriver<'d, C: RmtChannel> {
|
||||
_channel: PeripheralRef<'d, C>,
|
||||
pub struct RmtDriver<'d> {
|
||||
channel: u8,
|
||||
_p: PhantomData<&'d ()>,
|
||||
}
|
||||
|
||||
impl<'d, C: RmtChannel> RmtDriver<'d, C> {
|
||||
impl<'d> RmtDriver<'d> {
|
||||
/// Initialise the rmt module with the specified pin, channel and configuration.
|
||||
///
|
||||
/// To uninstall the driver just drop it.
|
||||
///
|
||||
/// Internally this calls `rmt_config()` and `rmt_driver_install()`.
|
||||
pub fn new(
|
||||
channel: impl Peripheral<P = C> + 'd,
|
||||
pub fn new<C: RmtChannel>(
|
||||
_channel: impl Peripheral<P = C> + 'd,
|
||||
pin: impl Peripheral<P = impl OutputPin> + 'd,
|
||||
config: &TransmitConfig,
|
||||
) -> Result<Self, EspError> {
|
||||
crate::into_ref!(channel, pin);
|
||||
crate::into_ref!(pin);
|
||||
|
||||
let mut flags = 0;
|
||||
if config.aware_dfs {
|
||||
@ -396,7 +398,10 @@ impl<'d, C: RmtChannel> RmtDriver<'d, C> {
|
||||
esp!(rmt_driver_install(C::channel(), 0, 0))?;
|
||||
}
|
||||
|
||||
Ok(Self { _channel: channel })
|
||||
Ok(Self {
|
||||
channel: C::channel() as _,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get speed of the channel’s internal counter clock.
|
||||
@ -409,7 +414,7 @@ impl<'d, C: RmtChannel> RmtDriver<'d, C> {
|
||||
/// [rmt_get_counter_clock]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/rmt.html#_CPPv421rmt_get_counter_clock13rmt_channel_tP8uint32_t
|
||||
pub fn counter_clock(&self) -> Result<Hertz, EspError> {
|
||||
let mut ticks_hz: u32 = 0;
|
||||
esp!(unsafe { rmt_get_counter_clock(C::channel(), &mut ticks_hz) })?;
|
||||
esp!(unsafe { rmt_get_counter_clock(self.channel(), &mut ticks_hz) })?;
|
||||
Ok(ticks_hz.into())
|
||||
}
|
||||
|
||||
@ -436,7 +441,7 @@ impl<'d, C: RmtChannel> RmtDriver<'d, C> {
|
||||
S: Signal,
|
||||
{
|
||||
let items = signal.as_slice();
|
||||
esp!(unsafe { rmt_write_items(C::channel(), items.as_ptr(), items.len() as i32, block) })
|
||||
esp!(unsafe { rmt_write_items(self.channel(), items.as_ptr(), items.len() as i32, block) })
|
||||
}
|
||||
|
||||
/// Transmit all items in `iter` without blocking.
|
||||
@ -458,12 +463,12 @@ impl<'d, C: RmtChannel> RmtDriver<'d, C> {
|
||||
let iter = Box::new(UnsafeCell::new(iter));
|
||||
unsafe {
|
||||
esp!(rmt_translator_init(
|
||||
C::channel(),
|
||||
self.channel(),
|
||||
Some(Self::translate_iterator::<T, true>),
|
||||
))?;
|
||||
|
||||
esp!(rmt_write_sample(
|
||||
C::channel(),
|
||||
self.channel(),
|
||||
Box::leak(iter) as *const _ as _,
|
||||
1,
|
||||
false
|
||||
@ -493,11 +498,11 @@ impl<'d, C: RmtChannel> RmtDriver<'d, C> {
|
||||
// TODO: maybe use a separate struct so that we don't have to do this when
|
||||
// transmitting the same iterator type.
|
||||
esp!(rmt_translator_init(
|
||||
C::channel(),
|
||||
self.channel(),
|
||||
Some(Self::translate_iterator::<T, false>),
|
||||
))?;
|
||||
esp!(rmt_write_sample(
|
||||
C::channel(),
|
||||
self.channel(),
|
||||
&iter as *const _ as _,
|
||||
24,
|
||||
true
|
||||
@ -563,16 +568,16 @@ impl<'d, C: RmtChannel> RmtDriver<'d, C> {
|
||||
|
||||
/// Stop transmitting.
|
||||
pub fn stop(&mut self) -> Result<(), EspError> {
|
||||
esp!(unsafe { rmt_tx_stop(C::channel()) })
|
||||
esp!(unsafe { rmt_tx_stop(self.channel()) })
|
||||
}
|
||||
|
||||
pub fn set_looping(&mut self, looping: config::Loop) -> Result<(), EspError> {
|
||||
esp!(unsafe { rmt_set_tx_loop_mode(C::channel(), looping != config::Loop::None) })?;
|
||||
esp!(unsafe { rmt_set_tx_loop_mode(self.channel(), looping != config::Loop::None) })?;
|
||||
|
||||
#[cfg(not(any(esp32, esp32c2)))]
|
||||
esp!(unsafe {
|
||||
rmt_set_tx_loop_count(
|
||||
C::channel(),
|
||||
self.channel(),
|
||||
match looping {
|
||||
config::Loop::Count(count) if count > 0 && count < 1024 => count,
|
||||
_ => 0,
|
||||
@ -582,17 +587,21 @@ impl<'d, C: RmtChannel> RmtDriver<'d, C> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, C: RmtChannel> Drop for RmtDriver<'d, C> {
|
||||
/// Stop transmitting and release the driver.
|
||||
fn drop(&mut self) {
|
||||
self.stop().unwrap();
|
||||
esp!(unsafe { rmt_driver_uninstall(C::channel()) }).unwrap();
|
||||
pub fn channel(&self) -> rmt_channel_t {
|
||||
self.channel as _
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'d, C: RmtChannel> Send for RmtDriver<'d, C> {}
|
||||
impl<'d> Drop for RmtDriver<'d> {
|
||||
/// Stop transmitting and release the driver.
|
||||
fn drop(&mut self) {
|
||||
self.stop().unwrap();
|
||||
esp!(unsafe { rmt_driver_uninstall(self.channel()) }).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'d> Send for RmtDriver<'d> {}
|
||||
|
||||
/// Signal storage for [`Transmit`] in a format ready for the RMT driver.
|
||||
pub trait Signal {
|
||||
|
48
src/spi.rs
48
src/spi.rs
@ -30,7 +30,7 @@ use esp_idf_sys::*;
|
||||
|
||||
use crate::delay::BLOCK;
|
||||
use crate::gpio::{self, InputPin, OutputPin};
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
use crate::peripheral::Peripheral;
|
||||
|
||||
crate::embedded_hal_error!(
|
||||
SpiError,
|
||||
@ -299,13 +299,14 @@ impl<'d> SpiBus for SpiBusMasterDriver<'d> {
|
||||
}
|
||||
|
||||
/// Master SPI abstraction
|
||||
pub struct SpiMasterDriver<'d, SPI: Spi> {
|
||||
_spi: PeripheralRef<'d, SPI>,
|
||||
pub struct SpiMasterDriver<'d> {
|
||||
host: u8,
|
||||
device: spi_device_handle_t,
|
||||
max_transfer_size: usize,
|
||||
_p: PhantomData<&'d ()>,
|
||||
}
|
||||
|
||||
impl<'d> SpiMasterDriver<'d, SPI1> {
|
||||
impl<'d> SpiMasterDriver<'d> {
|
||||
/// Create new instance of SPI controller for SPI1
|
||||
///
|
||||
/// SPI1 can only use fixed pin for SCLK, SDO and SDI as they are shared with SPI0.
|
||||
@ -319,11 +320,9 @@ impl<'d> SpiMasterDriver<'d, SPI1> {
|
||||
) -> Result<Self, EspError> {
|
||||
SpiMasterDriver::new_internal(spi, sclk, sdo, sdi, cs, config)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, SPI: SpiAnyPins> SpiMasterDriver<'d, SPI> {
|
||||
/// Create new instance of SPI controller for all others
|
||||
pub fn new(
|
||||
pub fn new<SPI: SpiAnyPins>(
|
||||
spi: impl Peripheral<P = SPI> + 'd,
|
||||
sclk: impl Peripheral<P = impl OutputPin> + 'd,
|
||||
sdo: impl Peripheral<P = impl OutputPin> + 'd,
|
||||
@ -333,19 +332,17 @@ impl<'d, SPI: SpiAnyPins> SpiMasterDriver<'d, SPI> {
|
||||
) -> Result<Self, EspError> {
|
||||
SpiMasterDriver::new_internal(spi, sclk, sdo, sdi, cs, config)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, SPI: Spi> SpiMasterDriver<'d, SPI> {
|
||||
/// Internal implementation of new shared by all SPI controllers
|
||||
fn new_internal(
|
||||
spi: impl Peripheral<P = SPI> + 'd,
|
||||
fn new_internal<SPI: Spi>(
|
||||
_spi: impl Peripheral<P = SPI> + 'd,
|
||||
sclk: impl Peripheral<P = impl OutputPin> + 'd,
|
||||
sdo: impl Peripheral<P = impl OutputPin> + 'd,
|
||||
sdi: Option<impl Peripheral<P = impl InputPin + OutputPin> + 'd>,
|
||||
cs: Option<impl Peripheral<P = impl OutputPin> + 'd>,
|
||||
config: &config::Config,
|
||||
) -> Result<Self, EspError> {
|
||||
crate::into_ref!(spi, sclk, sdo);
|
||||
crate::into_ref!(sclk, sdo);
|
||||
|
||||
let sdi = sdi.map(|sdi| sdi.into_ref());
|
||||
let cs = cs.map(|cs| cs.into_ref());
|
||||
@ -418,16 +415,21 @@ impl<'d, SPI: Spi> SpiMasterDriver<'d, SPI> {
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
_spi: spi,
|
||||
host: SPI::device() as _,
|
||||
device: device_handle,
|
||||
max_transfer_size: config.dma.max_transfer_size(),
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn device_handle(&mut self) -> spi_device_handle_t {
|
||||
pub fn device(&self) -> spi_device_handle_t {
|
||||
self.device
|
||||
}
|
||||
|
||||
pub fn host(&self) -> spi_host_device_t {
|
||||
self.host as _
|
||||
}
|
||||
|
||||
pub fn transaction<R, E>(
|
||||
&mut self,
|
||||
f: impl FnOnce(&mut SpiBusMasterDriver<'d>) -> Result<R, E>,
|
||||
@ -465,20 +467,20 @@ impl<'d, SPI: Spi> SpiMasterDriver<'d, SPI> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, SPI: Spi> Drop for SpiMasterDriver<'d, SPI> {
|
||||
impl<'d> Drop for SpiMasterDriver<'d> {
|
||||
fn drop(&mut self) {
|
||||
esp!(unsafe { spi_bus_remove_device(self.device) }).unwrap();
|
||||
esp!(unsafe { spi_bus_free(SPI::device()) }).unwrap();
|
||||
esp!(unsafe { spi_bus_free(self.host()) }).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'d, SPI: Spi> Send for SpiMasterDriver<'d, SPI> {}
|
||||
unsafe impl<'d> Send for SpiMasterDriver<'d> {}
|
||||
|
||||
impl<'d, SPI: Spi> embedded_hal::spi::ErrorType for SpiMasterDriver<'d, SPI> {
|
||||
impl<'d> embedded_hal::spi::ErrorType for SpiMasterDriver<'d> {
|
||||
type Error = SpiError;
|
||||
}
|
||||
|
||||
impl<'d, SPI: Spi> SpiDevice for SpiMasterDriver<'d, SPI> {
|
||||
impl<'d> SpiDevice for SpiMasterDriver<'d> {
|
||||
type Bus = SpiBusMasterDriver<'d>;
|
||||
|
||||
fn transaction<R>(
|
||||
@ -489,7 +491,7 @@ impl<'d, SPI: Spi> SpiDevice for SpiMasterDriver<'d, SPI> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, SPI: Spi> embedded_hal_0_2::blocking::spi::Transfer<u8> for SpiMasterDriver<'d, SPI> {
|
||||
impl<'d> embedded_hal_0_2::blocking::spi::Transfer<u8> for SpiMasterDriver<'d> {
|
||||
type Error = SpiError;
|
||||
|
||||
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
|
||||
@ -506,7 +508,7 @@ impl<'d, SPI: Spi> embedded_hal_0_2::blocking::spi::Transfer<u8> for SpiMasterDr
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, SPI: Spi> embedded_hal_0_2::blocking::spi::Write<u8> for SpiMasterDriver<'d, SPI> {
|
||||
impl<'d> embedded_hal_0_2::blocking::spi::Write<u8> for SpiMasterDriver<'d> {
|
||||
type Error = SpiError;
|
||||
|
||||
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
@ -528,7 +530,7 @@ impl<'d, SPI: Spi> embedded_hal_0_2::blocking::spi::Write<u8> for SpiMasterDrive
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, SPI: Spi> embedded_hal_0_2::blocking::spi::WriteIter<u8> for SpiMasterDriver<'d, SPI> {
|
||||
impl<'d> embedded_hal_0_2::blocking::spi::WriteIter<u8> for SpiMasterDriver<'d> {
|
||||
type Error = SpiError;
|
||||
|
||||
fn write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error>
|
||||
@ -563,7 +565,7 @@ impl<'d, SPI: Spi> embedded_hal_0_2::blocking::spi::WriteIter<u8> for SpiMasterD
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, SPI: Spi> embedded_hal_0_2::blocking::spi::Transactional<u8> for SpiMasterDriver<'d, SPI> {
|
||||
impl<'d> embedded_hal_0_2::blocking::spi::Transactional<u8> for SpiMasterDriver<'d> {
|
||||
type Error = SpiError;
|
||||
|
||||
fn exec<'a>(
|
||||
|
87
src/timer.rs
87
src/timer.rs
@ -1,6 +1,8 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use esp_idf_sys::*;
|
||||
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
use crate::peripheral::Peripheral;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
@ -54,23 +56,16 @@ pub trait Timer: Send {
|
||||
fn index() -> timer_idx_t;
|
||||
}
|
||||
|
||||
pub struct TimerDriver<'d, TIMER>
|
||||
where
|
||||
TIMER: Timer,
|
||||
{
|
||||
_timer: PeripheralRef<'d, TIMER>,
|
||||
pub struct TimerDriver<'d> {
|
||||
timer: u8,
|
||||
_p: PhantomData<&'d ()>,
|
||||
}
|
||||
|
||||
impl<'d, TIMER> TimerDriver<'d, TIMER>
|
||||
where
|
||||
TIMER: Timer,
|
||||
{
|
||||
pub fn new(
|
||||
timer: impl Peripheral<P = TIMER> + 'd,
|
||||
impl<'d> TimerDriver<'d> {
|
||||
pub fn new<TIMER: Timer>(
|
||||
_timer: impl Peripheral<P = TIMER> + 'd,
|
||||
config: &config::Config,
|
||||
) -> Result<TimerDriver<'d, TIMER>, EspError> {
|
||||
crate::into_ref!(timer);
|
||||
|
||||
) -> Result<Self, EspError> {
|
||||
esp!(unsafe {
|
||||
timer_init(
|
||||
TIMER::group(),
|
||||
@ -94,16 +89,19 @@ where
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(TimerDriver { _timer: timer })
|
||||
Ok(TimerDriver {
|
||||
timer: ((TIMER::group() as u8) << 4) | (TIMER::index() as u8),
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn enable(&mut self, enable: bool) -> Result<(), EspError> {
|
||||
self.check();
|
||||
|
||||
if enable {
|
||||
esp!(unsafe { timer_start(TIMER::group(), TIMER::index()) })?;
|
||||
esp!(unsafe { timer_start(self.group(), self.index()) })?;
|
||||
} else {
|
||||
esp!(unsafe { timer_pause(TIMER::group(), TIMER::index()) })?;
|
||||
esp!(unsafe { timer_pause(self.group(), self.index()) })?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -111,12 +109,12 @@ where
|
||||
|
||||
pub fn counter(&self) -> Result<u64, EspError> {
|
||||
let value = if crate::interrupt::active() {
|
||||
unsafe { timer_group_get_counter_value_in_isr(TIMER::group(), TIMER::index()) }
|
||||
unsafe { timer_group_get_counter_value_in_isr(self.group(), self.index()) }
|
||||
} else {
|
||||
let mut value = 0_u64;
|
||||
|
||||
esp!(unsafe {
|
||||
timer_get_counter_value(TIMER::group(), TIMER::index(), &mut value as *mut _)
|
||||
timer_get_counter_value(self.group(), self.index(), &mut value as *mut _)
|
||||
})?;
|
||||
|
||||
value
|
||||
@ -128,7 +126,7 @@ where
|
||||
pub fn set_counter(&mut self, value: u64) -> Result<(), EspError> {
|
||||
self.check();
|
||||
|
||||
esp!(unsafe { timer_set_counter_value(TIMER::group(), TIMER::index(), value) })?;
|
||||
esp!(unsafe { timer_set_counter_value(self.group(), self.index(), value) })?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -137,7 +135,7 @@ where
|
||||
if crate::interrupt::active() {
|
||||
if enable {
|
||||
unsafe {
|
||||
timer_group_enable_alarm_in_isr(TIMER::group(), TIMER::index());
|
||||
timer_group_enable_alarm_in_isr(self.group(), self.index());
|
||||
}
|
||||
} else {
|
||||
panic!("Disabling alarm from an ISR is not supported");
|
||||
@ -145,8 +143,8 @@ where
|
||||
} else {
|
||||
esp!(unsafe {
|
||||
timer_set_alarm(
|
||||
TIMER::group(),
|
||||
TIMER::index(),
|
||||
self.group(),
|
||||
self.index(),
|
||||
if enable {
|
||||
timer_alarm_t_TIMER_ALARM_EN
|
||||
} else {
|
||||
@ -164,7 +162,7 @@ where
|
||||
|
||||
let mut value = 0_u64;
|
||||
|
||||
esp!(unsafe { timer_get_alarm_value(TIMER::group(), TIMER::index(), &mut value) })?;
|
||||
esp!(unsafe { timer_get_alarm_value(self.group(), self.index(), &mut value) })?;
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
@ -172,10 +170,10 @@ where
|
||||
pub fn set_alarm(&mut self, value: u64) -> Result<(), EspError> {
|
||||
if crate::interrupt::active() {
|
||||
unsafe {
|
||||
timer_group_set_alarm_value_in_isr(TIMER::group(), TIMER::index(), value);
|
||||
timer_group_set_alarm_value_in_isr(self.group(), self.index(), value);
|
||||
}
|
||||
} else {
|
||||
esp!(unsafe { timer_set_alarm_value(TIMER::group(), TIMER::index(), value) })?;
|
||||
esp!(unsafe { timer_set_alarm_value(self.group(), self.index(), value) })?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -184,7 +182,7 @@ where
|
||||
pub fn enable_interrupt(&mut self) -> Result<(), EspError> {
|
||||
self.check();
|
||||
|
||||
esp!(unsafe { timer_enable_intr(TIMER::group(), TIMER::index()) })?;
|
||||
esp!(unsafe { timer_enable_intr(self.group(), self.index()) })?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -192,7 +190,7 @@ where
|
||||
pub fn disable_interrupt(&mut self) -> Result<(), EspError> {
|
||||
self.check();
|
||||
|
||||
esp!(unsafe { timer_disable_intr(TIMER::group(), TIMER::index()) })?;
|
||||
esp!(unsafe { timer_disable_intr(self.group(), self.index()) })?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -209,16 +207,16 @@ where
|
||||
|
||||
let callback: Box<dyn FnMut() + 'static> = Box::new(callback);
|
||||
|
||||
ISR_HANDLERS[(TIMER::group() * timer_group_t_TIMER_GROUP_MAX + TIMER::index()) as usize] =
|
||||
ISR_HANDLERS[(self.group() * timer_group_t_TIMER_GROUP_MAX + self.index()) as usize] =
|
||||
Some(Box::new(callback));
|
||||
|
||||
esp!(timer_isr_callback_add(
|
||||
TIMER::group(),
|
||||
TIMER::index(),
|
||||
self.group(),
|
||||
self.index(),
|
||||
Some(Self::handle_isr),
|
||||
UnsafeCallback::from(
|
||||
ISR_HANDLERS
|
||||
[(TIMER::group() * timer_group_t_TIMER_GROUP_MAX + TIMER::index()) as usize]
|
||||
[(self.group() * timer_group_t_TIMER_GROUP_MAX + self.index()) as usize]
|
||||
.as_mut()
|
||||
.unwrap(),
|
||||
)
|
||||
@ -237,16 +235,15 @@ where
|
||||
|
||||
unsafe {
|
||||
let subscribed = ISR_HANDLERS
|
||||
[(TIMER::group() * timer_group_t_TIMER_GROUP_MAX + TIMER::index()) as usize]
|
||||
[(self.group() * timer_group_t_TIMER_GROUP_MAX + self.index()) as usize]
|
||||
.is_some();
|
||||
|
||||
if subscribed {
|
||||
esp!(timer_disable_intr(TIMER::group(), TIMER::index()))?;
|
||||
esp!(timer_isr_callback_remove(TIMER::group(), TIMER::index()))?;
|
||||
esp!(timer_disable_intr(self.group(), self.index()))?;
|
||||
esp!(timer_isr_callback_remove(self.group(), self.index()))?;
|
||||
|
||||
ISR_HANDLERS
|
||||
[(TIMER::group() * timer_group_t_TIMER_GROUP_MAX + TIMER::index()) as usize] =
|
||||
None;
|
||||
[(self.group() * timer_group_t_TIMER_GROUP_MAX + self.index()) as usize] = None;
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,20 +262,28 @@ where
|
||||
UnsafeCallback::from_ptr(unsafe_callback).call();
|
||||
})
|
||||
}
|
||||
|
||||
pub fn group(&self) -> timer_group_t {
|
||||
(self.timer >> 4) as _
|
||||
}
|
||||
|
||||
pub fn index(&self) -> timer_idx_t {
|
||||
(self.timer & 0xf) as _
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, TIMER: Timer> Drop for TimerDriver<'d, TIMER> {
|
||||
impl<'d> Drop for TimerDriver<'d> {
|
||||
fn drop(&mut self) {
|
||||
#[cfg(feature = "alloc")]
|
||||
{
|
||||
self.unsubscribe().unwrap();
|
||||
}
|
||||
|
||||
esp!(unsafe { timer_deinit(TIMER::group(), TIMER::index()) }).unwrap();
|
||||
esp!(unsafe { timer_deinit(self.group(), self.index()) }).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'d, TIMER: Timer> Send for TimerDriver<'d, TIMER> {}
|
||||
unsafe impl<'d> Send for TimerDriver<'d> {}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
struct UnsafeCallback(*mut Box<dyn FnMut() + 'static>);
|
||||
|
149
src/uart.rs
149
src/uart.rs
@ -46,7 +46,7 @@ use crate::units::*;
|
||||
|
||||
use esp_idf_sys::*;
|
||||
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
use crate::peripheral::Peripheral;
|
||||
|
||||
const UART_FIFO_SIZE: i32 = 128;
|
||||
|
||||
@ -283,33 +283,34 @@ crate::embedded_hal_error!(
|
||||
|
||||
/// Serial abstraction
|
||||
///
|
||||
pub struct UartDriver<'d, UART: Uart> {
|
||||
_uart: PeripheralRef<'d, UART>,
|
||||
rx: UartRxDriver<'d, UART>,
|
||||
tx: UartTxDriver<'d, UART>,
|
||||
pub struct UartDriver<'d> {
|
||||
port: u8,
|
||||
_p: PhantomData<&'d ()>,
|
||||
}
|
||||
|
||||
/// Serial receiver
|
||||
pub struct UartRxDriver<'d, UART: Uart> {
|
||||
_uart: PhantomData<&'d UART>,
|
||||
pub struct UartRxDriver<'d> {
|
||||
port: u8,
|
||||
_p: PhantomData<&'d ()>,
|
||||
}
|
||||
|
||||
/// Serial transmitter
|
||||
pub struct UartTxDriver<'d, UART: Uart> {
|
||||
_uart: PhantomData<&'d UART>,
|
||||
pub struct UartTxDriver<'d> {
|
||||
port: u8,
|
||||
_p: PhantomData<&'d ()>,
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> UartDriver<'d, UART> {
|
||||
impl<'d> UartDriver<'d> {
|
||||
/// Create a new serial driver
|
||||
pub fn new(
|
||||
uart: impl Peripheral<P = UART> + 'd,
|
||||
pub fn new<UART: Uart>(
|
||||
_uart: impl Peripheral<P = UART> + 'd,
|
||||
tx: impl Peripheral<P = impl OutputPin> + 'd,
|
||||
rx: impl Peripheral<P = impl InputPin> + 'd,
|
||||
cts: Option<impl Peripheral<P = impl InputPin> + 'd>,
|
||||
rts: Option<impl Peripheral<P = impl OutputPin> + 'd>,
|
||||
config: &config::Config,
|
||||
) -> Result<Self, EspError> {
|
||||
crate::into_ref!(uart, tx, rx);
|
||||
crate::into_ref!(tx, rx);
|
||||
|
||||
let cts = cts.map(|cts| cts.into_ref());
|
||||
let rts = rts.map(|rts| rts.into_ref());
|
||||
@ -348,16 +349,15 @@ impl<'d, UART: Uart> UartDriver<'d, UART> {
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
_uart: uart,
|
||||
rx: UartRxDriver { _uart: PhantomData },
|
||||
tx: UartTxDriver { _uart: PhantomData },
|
||||
port: UART::port() as _,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
/// Change the number of stop bits
|
||||
pub fn change_stop_bits(&mut self, stop_bits: config::StopBits) -> Result<&mut Self, EspError> {
|
||||
esp_result!(
|
||||
unsafe { uart_set_stop_bits(UART::port(), stop_bits.into()) },
|
||||
unsafe { uart_set_stop_bits(self.port(), stop_bits.into()) },
|
||||
self
|
||||
)
|
||||
}
|
||||
@ -366,7 +366,7 @@ impl<'d, UART: Uart> UartDriver<'d, UART> {
|
||||
pub fn stop_bits(&self) -> Result<config::StopBits, EspError> {
|
||||
let mut stop_bits: uart_stop_bits_t = 0;
|
||||
esp_result!(
|
||||
unsafe { uart_get_stop_bits(UART::port(), &mut stop_bits) },
|
||||
unsafe { uart_get_stop_bits(self.port(), &mut stop_bits) },
|
||||
stop_bits.into()
|
||||
)
|
||||
}
|
||||
@ -374,7 +374,7 @@ impl<'d, UART: Uart> UartDriver<'d, UART> {
|
||||
/// Change the number of data bits
|
||||
pub fn change_data_bits(&mut self, data_bits: config::DataBits) -> Result<&mut Self, EspError> {
|
||||
esp_result!(
|
||||
unsafe { uart_set_word_length(UART::port(), data_bits.into()) },
|
||||
unsafe { uart_set_word_length(self.port(), data_bits.into()) },
|
||||
self
|
||||
)
|
||||
}
|
||||
@ -383,24 +383,21 @@ impl<'d, UART: Uart> UartDriver<'d, UART> {
|
||||
pub fn data_bits(&self) -> Result<config::DataBits, EspError> {
|
||||
let mut data_bits: uart_word_length_t = 0;
|
||||
esp_result!(
|
||||
unsafe { uart_get_word_length(UART::port(), &mut data_bits) },
|
||||
unsafe { uart_get_word_length(self.port(), &mut data_bits) },
|
||||
data_bits.into()
|
||||
)
|
||||
}
|
||||
|
||||
/// Change the type of parity checking
|
||||
pub fn change_parity(&mut self, parity: config::Parity) -> Result<&mut Self, EspError> {
|
||||
esp_result!(
|
||||
unsafe { uart_set_parity(UART::port(), parity.into()) },
|
||||
self
|
||||
)
|
||||
esp_result!(unsafe { uart_set_parity(self.port(), parity.into()) }, self)
|
||||
}
|
||||
|
||||
/// Returns the current type of parity checking
|
||||
pub fn parity(&self) -> Result<config::Parity, EspError> {
|
||||
let mut parity: uart_parity_t = 0;
|
||||
esp_result!(
|
||||
unsafe { uart_get_parity(UART::port(), &mut parity) },
|
||||
unsafe { uart_get_parity(self.port(), &mut parity) },
|
||||
parity.into()
|
||||
)
|
||||
}
|
||||
@ -417,7 +414,7 @@ impl<'d, UART: Uart> UartDriver<'d, UART> {
|
||||
baudrate: T,
|
||||
) -> Result<&mut Self, EspError> {
|
||||
esp_result!(
|
||||
unsafe { uart_set_baudrate(UART::port(), baudrate.into().into()) },
|
||||
unsafe { uart_set_baudrate(self.port(), baudrate.into().into()) },
|
||||
self
|
||||
)
|
||||
}
|
||||
@ -426,99 +423,117 @@ impl<'d, UART: Uart> UartDriver<'d, UART> {
|
||||
pub fn baudrate(&self) -> Result<Hertz, EspError> {
|
||||
let mut baudrate: u32 = 0;
|
||||
esp_result!(
|
||||
unsafe { uart_get_baudrate(UART::port(), &mut baudrate) },
|
||||
unsafe { uart_get_baudrate(self.port(), &mut baudrate) },
|
||||
baudrate.into()
|
||||
)
|
||||
}
|
||||
|
||||
/// Split the serial driver in separate TX and RX drivers
|
||||
pub fn split(&mut self) -> (&mut UartTxDriver<'d, UART>, &mut UartRxDriver<'d, UART>) {
|
||||
(&mut self.tx, &mut self.rx)
|
||||
pub fn split(mut self) -> (UartTxDriver<'d>, UartRxDriver<'d>) {
|
||||
(self.tx(), self.rx())
|
||||
}
|
||||
|
||||
/// Read multiple bytes into a slice
|
||||
pub fn read(&mut self, buf: &mut [u8], delay: TickType_t) -> Result<usize, EspError> {
|
||||
self.rx.read(buf, delay)
|
||||
self.rx().read(buf, delay)
|
||||
}
|
||||
|
||||
/// Write multiple bytes from a slice
|
||||
pub fn write(&mut self, buf: &[u8]) -> Result<usize, EspError> {
|
||||
self.tx.write(buf)
|
||||
self.tx().write(buf)
|
||||
}
|
||||
|
||||
pub fn flush_read(&mut self) -> Result<(), EspError> {
|
||||
self.rx.flush()
|
||||
self.rx().flush()
|
||||
}
|
||||
|
||||
pub fn flush_write(&mut self) -> Result<(), EspError> {
|
||||
self.tx.flush()
|
||||
self.tx().flush()
|
||||
}
|
||||
|
||||
pub fn port(&self) -> uart_port_t {
|
||||
self.port as _
|
||||
}
|
||||
|
||||
fn rx(&mut self) -> UartRxDriver<'d> {
|
||||
UartRxDriver {
|
||||
port: self.port() as _,
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn tx(&mut self) -> UartTxDriver<'d> {
|
||||
UartTxDriver {
|
||||
port: self.port() as _,
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> Drop for UartDriver<'d, UART> {
|
||||
impl<'d> Drop for UartDriver<'d> {
|
||||
fn drop(&mut self) {
|
||||
esp!(unsafe { uart_driver_delete(UART::port()) }).unwrap();
|
||||
esp!(unsafe { uart_driver_delete(self.port()) }).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'d, UART: Uart> Send for UartDriver<'d, UART> {}
|
||||
unsafe impl<'d> Send for UartDriver<'d> {}
|
||||
|
||||
impl<'d, UART: Uart> embedded_hal::serial::ErrorType for UartDriver<'d, UART> {
|
||||
impl<'d> embedded_hal::serial::ErrorType for UartDriver<'d> {
|
||||
type Error = SerialError;
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> embedded_hal_0_2::serial::Read<u8> for UartDriver<'d, UART> {
|
||||
impl<'d> embedded_hal_0_2::serial::Read<u8> for UartDriver<'d> {
|
||||
type Error = SerialError;
|
||||
|
||||
fn read(&mut self) -> nb::Result<u8, Self::Error> {
|
||||
embedded_hal_0_2::serial::Read::read(&mut self.rx)
|
||||
embedded_hal_0_2::serial::Read::read(&mut self.rx())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> embedded_hal_nb::serial::Read<u8> for UartDriver<'d, UART> {
|
||||
impl<'d> embedded_hal_nb::serial::Read<u8> for UartDriver<'d> {
|
||||
fn read(&mut self) -> nb::Result<u8, Self::Error> {
|
||||
embedded_hal_nb::serial::Read::read(&mut self.rx)
|
||||
embedded_hal_nb::serial::Read::read(&mut self.rx())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> embedded_hal_0_2::serial::Write<u8> for UartDriver<'d, UART> {
|
||||
impl<'d> embedded_hal_0_2::serial::Write<u8> for UartDriver<'d> {
|
||||
type Error = SerialError;
|
||||
|
||||
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
||||
embedded_hal_0_2::serial::Write::flush(&mut self.tx)
|
||||
embedded_hal_0_2::serial::Write::flush(&mut self.tx())
|
||||
}
|
||||
|
||||
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
|
||||
embedded_hal_0_2::serial::Write::write(&mut self.tx, byte)
|
||||
embedded_hal_0_2::serial::Write::write(&mut self.tx(), byte)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> embedded_hal_nb::serial::Write<u8> for UartDriver<'d, UART> {
|
||||
impl<'d> embedded_hal_nb::serial::Write<u8> for UartDriver<'d> {
|
||||
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
||||
embedded_hal_nb::serial::Write::flush(&mut self.tx)
|
||||
embedded_hal_nb::serial::Write::flush(&mut self.tx())
|
||||
}
|
||||
|
||||
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
|
||||
embedded_hal_nb::serial::Write::write(&mut self.tx, byte)
|
||||
embedded_hal_nb::serial::Write::write(&mut self.tx(), byte)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> core::fmt::Write for UartDriver<'d, UART> {
|
||||
impl<'d> core::fmt::Write for UartDriver<'d> {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
self.tx.write_str(s)
|
||||
self.tx().write_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> embedded_hal::serial::ErrorType for UartRxDriver<'d, UART> {
|
||||
impl<'d> embedded_hal::serial::ErrorType for UartRxDriver<'d> {
|
||||
type Error = SerialError;
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> UartRxDriver<'d, UART> {
|
||||
impl<'d> UartRxDriver<'d> {
|
||||
/// Get count of bytes in the receive FIFO
|
||||
pub fn count(&self) -> Result<u8, EspError> {
|
||||
let mut size = 0_u32;
|
||||
esp_result!(
|
||||
unsafe { uart_get_buffered_data_len(UART::port(), &mut size) },
|
||||
unsafe { uart_get_buffered_data_len(self.port(), &mut size) },
|
||||
size as u8
|
||||
)
|
||||
}
|
||||
@ -529,7 +544,7 @@ impl<'d, UART: Uart> UartRxDriver<'d, UART> {
|
||||
// 0 means timeout and nothing is yet read out
|
||||
let len = unsafe {
|
||||
uart_read_bytes(
|
||||
UART::port(),
|
||||
self.port(),
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
buf.len() as u32,
|
||||
delay,
|
||||
@ -544,13 +559,17 @@ impl<'d, UART: Uart> UartRxDriver<'d, UART> {
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> Result<(), EspError> {
|
||||
esp!(unsafe { uart_flush_input(UART::port()) })?;
|
||||
esp!(unsafe { uart_flush_input(self.port()) })?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn port(&self) -> uart_port_t {
|
||||
self.port as _
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> embedded_hal_0_2::serial::Read<u8> for UartRxDriver<'d, UART> {
|
||||
impl<'d> embedded_hal_0_2::serial::Read<u8> for UartRxDriver<'d> {
|
||||
type Error = SerialError;
|
||||
|
||||
fn read(&mut self) -> nb::Result<u8, Self::Error> {
|
||||
@ -562,7 +581,7 @@ impl<'d, UART: Uart> embedded_hal_0_2::serial::Read<u8> for UartRxDriver<'d, UAR
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> embedded_hal_nb::serial::Read<u8> for UartRxDriver<'d, UART> {
|
||||
impl<'d> embedded_hal_nb::serial::Read<u8> for UartRxDriver<'d> {
|
||||
fn read(&mut self) -> nb::Result<u8, Self::Error> {
|
||||
let mut buf = [0_u8];
|
||||
|
||||
@ -572,12 +591,12 @@ impl<'d, UART: Uart> embedded_hal_nb::serial::Read<u8> for UartRxDriver<'d, UART
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> UartTxDriver<'d, UART> {
|
||||
impl<'d> UartTxDriver<'d> {
|
||||
/// Write multiple bytes from a slice
|
||||
pub fn write(&mut self, bytes: &[u8]) -> Result<usize, EspError> {
|
||||
// `uart_write_bytes()` returns error (-1) or how many bytes were written
|
||||
let len = unsafe {
|
||||
uart_write_bytes(UART::port(), bytes.as_ptr() as *const _, bytes.len() as u32)
|
||||
uart_write_bytes(self.port(), bytes.as_ptr() as *const _, bytes.len() as u32)
|
||||
};
|
||||
|
||||
if len >= 0 {
|
||||
@ -588,17 +607,21 @@ impl<'d, UART: Uart> UartTxDriver<'d, UART> {
|
||||
}
|
||||
|
||||
pub fn flush(&mut self) -> Result<(), EspError> {
|
||||
esp!(unsafe { uart_wait_tx_done(UART::port(), 0) })?;
|
||||
esp!(unsafe { uart_wait_tx_done(self.port(), 0) })?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn port(&self) -> uart_port_t {
|
||||
self.port as _
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> embedded_hal::serial::ErrorType for UartTxDriver<'d, UART> {
|
||||
impl<'d> embedded_hal::serial::ErrorType for UartTxDriver<'d> {
|
||||
type Error = SerialError;
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> embedded_hal_0_2::serial::Write<u8> for UartTxDriver<'d, UART> {
|
||||
impl<'d> embedded_hal_0_2::serial::Write<u8> for UartTxDriver<'d> {
|
||||
type Error = SerialError;
|
||||
|
||||
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
||||
@ -610,7 +633,7 @@ impl<'d, UART: Uart> embedded_hal_0_2::serial::Write<u8> for UartTxDriver<'d, UA
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> embedded_hal_nb::serial::Write<u8> for UartTxDriver<'d, UART> {
|
||||
impl<'d> embedded_hal_nb::serial::Write<u8> for UartTxDriver<'d> {
|
||||
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
||||
UartTxDriver::flush(self).map_err(to_nb_err)
|
||||
}
|
||||
@ -620,7 +643,7 @@ impl<'d, UART: Uart> embedded_hal_nb::serial::Write<u8> for UartTxDriver<'d, UAR
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, UART: Uart> core::fmt::Write for UartTxDriver<'d, UART> {
|
||||
impl<'d> core::fmt::Write for UartTxDriver<'d> {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
let buf = s.as_bytes();
|
||||
let mut offset = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user