diff options
37 files changed, 537 insertions, 117 deletions
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index 85977a804..a47fb8350 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs | |||
| @@ -50,19 +50,19 @@ impl<'d, T: Pin> Input<'d, T> { | |||
| 50 | Self { pin } | 50 | Self { pin } |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | /// Test if current pin level is high. | 53 | /// Get whether the pin input level is high. |
| 54 | #[inline] | 54 | #[inline] |
| 55 | pub fn is_high(&mut self) -> bool { | 55 | pub fn is_high(&mut self) -> bool { |
| 56 | self.pin.is_high() | 56 | self.pin.is_high() |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | /// Test if current pin level is low. | 59 | /// Get whether the pin input level is low. |
| 60 | #[inline] | 60 | #[inline] |
| 61 | pub fn is_low(&mut self) -> bool { | 61 | pub fn is_low(&mut self) -> bool { |
| 62 | self.pin.is_low() | 62 | self.pin.is_low() |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | /// Returns current pin level | 65 | /// Get the pin input level. |
| 66 | #[inline] | 66 | #[inline] |
| 67 | pub fn get_level(&mut self) -> Level { | 67 | pub fn get_level(&mut self) -> Level { |
| 68 | self.pin.get_level() | 68 | self.pin.get_level() |
| @@ -158,19 +158,19 @@ impl<'d, T: Pin> Output<'d, T> { | |||
| 158 | self.pin.set_level(level) | 158 | self.pin.set_level(level) |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | /// Is the output pin set as high? | 161 | /// Get whether the output level is set to high. |
| 162 | #[inline] | 162 | #[inline] |
| 163 | pub fn is_set_high(&mut self) -> bool { | 163 | pub fn is_set_high(&mut self) -> bool { |
| 164 | self.pin.is_set_high() | 164 | self.pin.is_set_high() |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | /// Is the output pin set as low? | 167 | /// Get whether the output level is set to low. |
| 168 | #[inline] | 168 | #[inline] |
| 169 | pub fn is_set_low(&mut self) -> bool { | 169 | pub fn is_set_low(&mut self) -> bool { |
| 170 | self.pin.is_set_low() | 170 | self.pin.is_set_low() |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | /// What level output is set to | 173 | /// Get the current output level. |
| 174 | #[inline] | 174 | #[inline] |
| 175 | pub fn get_output_level(&mut self) -> Level { | 175 | pub fn get_output_level(&mut self) -> Level { |
| 176 | self.pin.get_output_level() | 176 | self.pin.get_output_level() |
| @@ -275,13 +275,13 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 275 | self.pin.conf().reset(); | 275 | self.pin.conf().reset(); |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | /// Test if current pin level is high. | 278 | /// Get whether the pin input level is high. |
| 279 | #[inline] | 279 | #[inline] |
| 280 | pub fn is_high(&mut self) -> bool { | 280 | pub fn is_high(&mut self) -> bool { |
| 281 | !self.is_low() | 281 | !self.is_low() |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | /// Test if current pin level is low. | 284 | /// Get whether the pin input level is low. |
| 285 | #[inline] | 285 | #[inline] |
| 286 | pub fn is_low(&mut self) -> bool { | 286 | pub fn is_low(&mut self) -> bool { |
| 287 | self.ref_is_low() | 287 | self.ref_is_low() |
| @@ -292,7 +292,7 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 292 | self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0 | 292 | self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0 |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | /// Returns current pin level | 295 | /// Get the pin input level. |
| 296 | #[inline] | 296 | #[inline] |
| 297 | pub fn get_level(&mut self) -> Level { | 297 | pub fn get_level(&mut self) -> Level { |
| 298 | self.is_high().into() | 298 | self.is_high().into() |
| @@ -319,25 +319,24 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 319 | } | 319 | } |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | /// Is the output pin set as high? | 322 | /// Get whether the output level is set to high. |
| 323 | #[inline] | 323 | #[inline] |
| 324 | pub fn is_set_high(&mut self) -> bool { | 324 | pub fn is_set_high(&mut self) -> bool { |
| 325 | !self.is_set_low() | 325 | !self.is_set_low() |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | /// Is the output pin set as low? | 328 | /// Get whether the output level is set to low. |
| 329 | #[inline] | 329 | #[inline] |
| 330 | pub fn is_set_low(&mut self) -> bool { | 330 | pub fn is_set_low(&mut self) -> bool { |
| 331 | self.ref_is_set_low() | 331 | self.ref_is_set_low() |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | /// Is the output pin set as low? | ||
| 335 | #[inline] | 334 | #[inline] |
| 336 | pub(crate) fn ref_is_set_low(&self) -> bool { | 335 | pub(crate) fn ref_is_set_low(&self) -> bool { |
| 337 | self.pin.block().out.read().bits() & (1 << self.pin.pin()) == 0 | 336 | self.pin.block().out.read().bits() & (1 << self.pin.pin()) == 0 |
| 338 | } | 337 | } |
| 339 | 338 | ||
| 340 | /// What level output is set to | 339 | /// Get the current output level. |
| 341 | #[inline] | 340 | #[inline] |
| 342 | pub fn get_output_level(&mut self) -> Level { | 341 | pub fn get_output_level(&mut self) -> Level { |
| 343 | self.is_set_high().into() | 342 | self.is_set_high().into() |
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index dbe53c807..2e470662d 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Analog to Digital (ADC) converter driver. | ||
| 1 | #![macro_use] | 2 | #![macro_use] |
| 2 | 3 | ||
| 3 | #[cfg(not(adc_f3_v2))] | 4 | #[cfg(not(adc_f3_v2))] |
| @@ -24,6 +25,7 @@ pub use sample_time::SampleTime; | |||
| 24 | 25 | ||
| 25 | use crate::peripherals; | 26 | use crate::peripherals; |
| 26 | 27 | ||
| 28 | /// Analog to Digital driver. | ||
| 27 | pub struct Adc<'d, T: Instance> { | 29 | pub struct Adc<'d, T: Instance> { |
| 28 | #[allow(unused)] | 30 | #[allow(unused)] |
| 29 | adc: crate::PeripheralRef<'d, T>, | 31 | adc: crate::PeripheralRef<'d, T>, |
| @@ -75,12 +77,16 @@ pub(crate) mod sealed { | |||
| 75 | } | 77 | } |
| 76 | } | 78 | } |
| 77 | 79 | ||
| 80 | /// ADC instance. | ||
| 78 | #[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0)))] | 81 | #[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0)))] |
| 79 | pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {} | 82 | pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {} |
| 83 | /// ADC instance. | ||
| 80 | #[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))] | 84 | #[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))] |
| 81 | pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {} | 85 | pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {} |
| 82 | 86 | ||
| 87 | /// ADC pin. | ||
| 83 | pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} | 88 | pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} |
| 89 | /// ADC internal channel. | ||
| 84 | pub trait InternalChannel<T>: sealed::InternalChannel<T> {} | 90 | pub trait InternalChannel<T>: sealed::InternalChannel<T> {} |
| 85 | 91 | ||
| 86 | foreach_adc!( | 92 | foreach_adc!( |
diff --git a/embassy-stm32/src/adc/resolution.rs b/embassy-stm32/src/adc/resolution.rs index 383980b5a..64c25a776 100644 --- a/embassy-stm32/src/adc/resolution.rs +++ b/embassy-stm32/src/adc/resolution.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | /// ADC resolution | ||
| 2 | #[allow(missing_docs)] | ||
| 1 | #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))] | 3 | #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))] |
| 2 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] | 4 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] |
| 3 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 5 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -8,6 +10,8 @@ pub enum Resolution { | |||
| 8 | SixBit, | 10 | SixBit, |
| 9 | } | 11 | } |
| 10 | 12 | ||
| 13 | /// ADC resolution | ||
| 14 | #[allow(missing_docs)] | ||
| 11 | #[cfg(adc_v4)] | 15 | #[cfg(adc_v4)] |
| 12 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] | 16 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] |
| 13 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 17 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -49,6 +53,9 @@ impl From<Resolution> for crate::pac::adc::vals::Res { | |||
| 49 | } | 53 | } |
| 50 | 54 | ||
| 51 | impl Resolution { | 55 | impl Resolution { |
| 56 | /// Get the maximum reading value for this resolution. | ||
| 57 | /// | ||
| 58 | /// This is `2**n - 1`. | ||
| 52 | pub fn to_max_count(&self) -> u32 { | 59 | pub fn to_max_count(&self) -> u32 { |
| 53 | match self { | 60 | match self { |
| 54 | #[cfg(adc_v4)] | 61 | #[cfg(adc_v4)] |
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index d74617cb3..048e73184 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs | |||
| @@ -32,6 +32,7 @@ const TEMP_CHANNEL: u8 = 18; | |||
| 32 | const VBAT_CHANNEL: u8 = 17; | 32 | const VBAT_CHANNEL: u8 = 17; |
| 33 | 33 | ||
| 34 | // NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs | 34 | // NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs |
| 35 | /// Internal voltage reference channel. | ||
| 35 | pub struct VrefInt; | 36 | pub struct VrefInt; |
| 36 | impl<T: Instance> InternalChannel<T> for VrefInt {} | 37 | impl<T: Instance> InternalChannel<T> for VrefInt {} |
| 37 | impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt { | 38 | impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt { |
| @@ -40,6 +41,7 @@ impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt { | |||
| 40 | } | 41 | } |
| 41 | } | 42 | } |
| 42 | 43 | ||
| 44 | /// Internal temperature channel. | ||
| 43 | pub struct Temperature; | 45 | pub struct Temperature; |
| 44 | impl<T: Instance> InternalChannel<T> for Temperature {} | 46 | impl<T: Instance> InternalChannel<T> for Temperature {} |
| 45 | impl<T: Instance> super::sealed::InternalChannel<T> for Temperature { | 47 | impl<T: Instance> super::sealed::InternalChannel<T> for Temperature { |
| @@ -48,6 +50,7 @@ impl<T: Instance> super::sealed::InternalChannel<T> for Temperature { | |||
| 48 | } | 50 | } |
| 49 | } | 51 | } |
| 50 | 52 | ||
| 53 | /// Internal battery voltage channel. | ||
| 51 | pub struct Vbat; | 54 | pub struct Vbat; |
| 52 | impl<T: Instance> InternalChannel<T> for Vbat {} | 55 | impl<T: Instance> InternalChannel<T> for Vbat {} |
| 53 | impl<T: Instance> super::sealed::InternalChannel<T> for Vbat { | 56 | impl<T: Instance> super::sealed::InternalChannel<T> for Vbat { |
| @@ -125,6 +128,7 @@ impl Prescaler { | |||
| 125 | } | 128 | } |
| 126 | 129 | ||
| 127 | impl<'d, T: Instance> Adc<'d, T> { | 130 | impl<'d, T: Instance> Adc<'d, T> { |
| 131 | /// Create a new ADC driver. | ||
| 128 | pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self { | 132 | pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self { |
| 129 | embassy_hal_internal::into_ref!(adc); | 133 | embassy_hal_internal::into_ref!(adc); |
| 130 | T::enable_and_reset(); | 134 | T::enable_and_reset(); |
| @@ -212,6 +216,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 212 | }); | 216 | }); |
| 213 | } | 217 | } |
| 214 | 218 | ||
| 219 | /// Enable reading the voltage reference internal channel. | ||
| 215 | pub fn enable_vrefint(&self) -> VrefInt { | 220 | pub fn enable_vrefint(&self) -> VrefInt { |
| 216 | T::common_regs().ccr().modify(|reg| { | 221 | T::common_regs().ccr().modify(|reg| { |
| 217 | reg.set_vrefen(true); | 222 | reg.set_vrefen(true); |
| @@ -220,6 +225,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 220 | VrefInt {} | 225 | VrefInt {} |
| 221 | } | 226 | } |
| 222 | 227 | ||
| 228 | /// Enable reading the temperature internal channel. | ||
| 223 | pub fn enable_temperature(&self) -> Temperature { | 229 | pub fn enable_temperature(&self) -> Temperature { |
| 224 | T::common_regs().ccr().modify(|reg| { | 230 | T::common_regs().ccr().modify(|reg| { |
| 225 | reg.set_vsenseen(true); | 231 | reg.set_vsenseen(true); |
| @@ -228,6 +234,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 228 | Temperature {} | 234 | Temperature {} |
| 229 | } | 235 | } |
| 230 | 236 | ||
| 237 | /// Enable reading the vbat internal channel. | ||
| 231 | pub fn enable_vbat(&self) -> Vbat { | 238 | pub fn enable_vbat(&self) -> Vbat { |
| 232 | T::common_regs().ccr().modify(|reg| { | 239 | T::common_regs().ccr().modify(|reg| { |
| 233 | reg.set_vbaten(true); | 240 | reg.set_vbaten(true); |
| @@ -236,10 +243,12 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 236 | Vbat {} | 243 | Vbat {} |
| 237 | } | 244 | } |
| 238 | 245 | ||
| 246 | /// Set the ADC sample time. | ||
| 239 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { | 247 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { |
| 240 | self.sample_time = sample_time; | 248 | self.sample_time = sample_time; |
| 241 | } | 249 | } |
| 242 | 250 | ||
| 251 | /// Set the ADC resolution. | ||
| 243 | pub fn set_resolution(&mut self, resolution: Resolution) { | 252 | pub fn set_resolution(&mut self, resolution: Resolution) { |
| 244 | T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); | 253 | T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); |
| 245 | } | 254 | } |
| @@ -263,6 +272,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 263 | T::regs().dr().read().0 as u16 | 272 | T::regs().dr().read().0 as u16 |
| 264 | } | 273 | } |
| 265 | 274 | ||
| 275 | /// Read an ADC pin. | ||
| 266 | pub fn read<P>(&mut self, pin: &mut P) -> u16 | 276 | pub fn read<P>(&mut self, pin: &mut P) -> u16 |
| 267 | where | 277 | where |
| 268 | P: AdcPin<T>, | 278 | P: AdcPin<T>, |
| @@ -273,6 +283,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 273 | self.read_channel(pin.channel()) | 283 | self.read_channel(pin.channel()) |
| 274 | } | 284 | } |
| 275 | 285 | ||
| 286 | /// Read an ADC internal channel. | ||
| 276 | pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { | 287 | pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { |
| 277 | self.read_channel(channel.channel()) | 288 | self.read_channel(channel.channel()) |
| 278 | } | 289 | } |
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index f77788db3..0cc2559cf 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs | |||
| @@ -1,6 +1,3 @@ | |||
| 1 | pub use bxcan; | ||
| 2 | use embassy_hal_internal::PeripheralRef; | ||
| 3 | |||
| 4 | use crate::peripherals; | 1 | use crate::peripherals; |
| 5 | 2 | ||
| 6 | pub(crate) mod sealed { | 3 | pub(crate) mod sealed { |
| @@ -25,27 +22,19 @@ pub(crate) mod sealed { | |||
| 25 | } | 22 | } |
| 26 | 23 | ||
| 27 | pub trait Instance { | 24 | pub trait Instance { |
| 28 | const REGISTERS: *mut bxcan::RegisterBlock; | ||
| 29 | |||
| 30 | fn regs() -> &'static crate::pac::can::Fdcan; | 25 | fn regs() -> &'static crate::pac::can::Fdcan; |
| 31 | fn state() -> &'static State; | 26 | fn state() -> &'static State; |
| 32 | } | 27 | } |
| 33 | } | 28 | } |
| 34 | 29 | ||
| 30 | /// Interruptable FDCAN instance. | ||
| 35 | pub trait InterruptableInstance {} | 31 | pub trait InterruptableInstance {} |
| 32 | /// FDCAN instance. | ||
| 36 | pub trait Instance: sealed::Instance + InterruptableInstance + 'static {} | 33 | pub trait Instance: sealed::Instance + InterruptableInstance + 'static {} |
| 37 | 34 | ||
| 38 | pub struct BxcanInstance<'a, T>(PeripheralRef<'a, T>); | ||
| 39 | |||
| 40 | unsafe impl<'d, T: Instance> bxcan::Instance for BxcanInstance<'d, T> { | ||
| 41 | const REGISTERS: *mut bxcan::RegisterBlock = T::REGISTERS; | ||
| 42 | } | ||
| 43 | |||
| 44 | foreach_peripheral!( | 35 | foreach_peripheral!( |
| 45 | (can, $inst:ident) => { | 36 | (can, $inst:ident) => { |
| 46 | impl sealed::Instance for peripherals::$inst { | 37 | impl sealed::Instance for peripherals::$inst { |
| 47 | const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _; | ||
| 48 | |||
| 49 | fn regs() -> &'static crate::pac::can::Fdcan { | 38 | fn regs() -> &'static crate::pac::can::Fdcan { |
| 50 | &crate::pac::$inst | 39 | &crate::pac::$inst |
| 51 | } | 40 | } |
diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs index b36f6018c..0c4ae55ce 100644 --- a/embassy-stm32/src/crc/v2v3.rs +++ b/embassy-stm32/src/crc/v2v3.rs | |||
| @@ -6,15 +6,19 @@ use crate::peripherals::CRC; | |||
| 6 | use crate::rcc::sealed::RccPeripheral; | 6 | use crate::rcc::sealed::RccPeripheral; |
| 7 | use crate::Peripheral; | 7 | use crate::Peripheral; |
| 8 | 8 | ||
| 9 | /// CRC driver. | ||
| 9 | pub struct Crc<'d> { | 10 | pub struct Crc<'d> { |
| 10 | _peripheral: PeripheralRef<'d, CRC>, | 11 | _peripheral: PeripheralRef<'d, CRC>, |
| 11 | _config: Config, | 12 | _config: Config, |
| 12 | } | 13 | } |
| 13 | 14 | ||
| 15 | /// CRC configuration errlr | ||
| 14 | pub enum ConfigError { | 16 | pub enum ConfigError { |
| 17 | /// The selected polynomial is invalid. | ||
| 15 | InvalidPolynomial, | 18 | InvalidPolynomial, |
| 16 | } | 19 | } |
| 17 | 20 | ||
| 21 | /// CRC configuration | ||
| 18 | pub struct Config { | 22 | pub struct Config { |
| 19 | reverse_in: InputReverseConfig, | 23 | reverse_in: InputReverseConfig, |
| 20 | reverse_out: bool, | 24 | reverse_out: bool, |
| @@ -25,14 +29,20 @@ pub struct Config { | |||
| 25 | crc_poly: u32, | 29 | crc_poly: u32, |
| 26 | } | 30 | } |
| 27 | 31 | ||
| 32 | /// Input reverse configuration. | ||
| 28 | pub enum InputReverseConfig { | 33 | pub enum InputReverseConfig { |
| 34 | /// Don't reverse anything | ||
| 29 | None, | 35 | None, |
| 36 | /// Reverse bytes | ||
| 30 | Byte, | 37 | Byte, |
| 38 | /// Reverse 16-bit halfwords. | ||
| 31 | Halfword, | 39 | Halfword, |
| 40 | /// Reverse 32-bit words. | ||
| 32 | Word, | 41 | Word, |
| 33 | } | 42 | } |
| 34 | 43 | ||
| 35 | impl Config { | 44 | impl Config { |
| 45 | /// Create a new CRC config. | ||
| 36 | pub fn new( | 46 | pub fn new( |
| 37 | reverse_in: InputReverseConfig, | 47 | reverse_in: InputReverseConfig, |
| 38 | reverse_out: bool, | 48 | reverse_out: bool, |
| @@ -57,7 +67,9 @@ impl Config { | |||
| 57 | } | 67 | } |
| 58 | } | 68 | } |
| 59 | 69 | ||
| 70 | /// Polynomial size | ||
| 60 | #[cfg(crc_v3)] | 71 | #[cfg(crc_v3)] |
| 72 | #[allow(missing_docs)] | ||
| 61 | pub enum PolySize { | 73 | pub enum PolySize { |
| 62 | Width7, | 74 | Width7, |
| 63 | Width8, | 75 | Width8, |
| @@ -81,6 +93,7 @@ impl<'d> Crc<'d> { | |||
| 81 | instance | 93 | instance |
| 82 | } | 94 | } |
| 83 | 95 | ||
| 96 | /// Reset the CRC engine. | ||
| 84 | pub fn reset(&mut self) { | 97 | pub fn reset(&mut self) { |
| 85 | PAC_CRC.cr().modify(|w| w.set_reset(true)); | 98 | PAC_CRC.cr().modify(|w| w.set_reset(true)); |
| 86 | } | 99 | } |
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 500eac4c1..9c670195d 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs | |||
| @@ -62,11 +62,11 @@ impl Mode { | |||
| 62 | /// | 62 | /// |
| 63 | /// 12-bit values outside the permitted range are silently truncated. | 63 | /// 12-bit values outside the permitted range are silently truncated. |
| 64 | pub enum Value { | 64 | pub enum Value { |
| 65 | // 8 bit value | 65 | /// 8 bit value |
| 66 | Bit8(u8), | 66 | Bit8(u8), |
| 67 | // 12 bit value stored in a u16, left-aligned | 67 | /// 12 bit value stored in a u16, left-aligned |
| 68 | Bit12Left(u16), | 68 | Bit12Left(u16), |
| 69 | // 12 bit value stored in a u16, right-aligned | 69 | /// 12 bit value stored in a u16, right-aligned |
| 70 | Bit12Right(u16), | 70 | Bit12Right(u16), |
| 71 | } | 71 | } |
| 72 | 72 | ||
| @@ -76,11 +76,11 @@ pub enum Value { | |||
| 76 | /// | 76 | /// |
| 77 | /// 12-bit values outside the permitted range are silently truncated. | 77 | /// 12-bit values outside the permitted range are silently truncated. |
| 78 | pub enum DualValue { | 78 | pub enum DualValue { |
| 79 | // 8 bit value | 79 | /// 8 bit value |
| 80 | Bit8(u8, u8), | 80 | Bit8(u8, u8), |
| 81 | // 12 bit value stored in a u16, left-aligned | 81 | /// 12 bit value stored in a u16, left-aligned |
| 82 | Bit12Left(u16, u16), | 82 | Bit12Left(u16, u16), |
| 83 | // 12 bit value stored in a u16, right-aligned | 83 | /// 12 bit value stored in a u16, right-aligned |
| 84 | Bit12Right(u16, u16), | 84 | Bit12Right(u16, u16), |
| 85 | } | 85 | } |
| 86 | 86 | ||
| @@ -88,11 +88,11 @@ pub enum DualValue { | |||
| 88 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 88 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 89 | /// Array variant of [`Value`]. | 89 | /// Array variant of [`Value`]. |
| 90 | pub enum ValueArray<'a> { | 90 | pub enum ValueArray<'a> { |
| 91 | // 8 bit values | 91 | /// 8 bit values |
| 92 | Bit8(&'a [u8]), | 92 | Bit8(&'a [u8]), |
| 93 | // 12 bit value stored in a u16, left-aligned | 93 | /// 12 bit value stored in a u16, left-aligned |
| 94 | Bit12Left(&'a [u16]), | 94 | Bit12Left(&'a [u16]), |
| 95 | // 12 bit values stored in a u16, right-aligned | 95 | /// 12 bit values stored in a u16, right-aligned |
| 96 | Bit12Right(&'a [u16]), | 96 | Bit12Right(&'a [u16]), |
| 97 | } | 97 | } |
| 98 | 98 | ||
| @@ -106,7 +106,9 @@ pub struct DacChannel<'d, T: Instance, const N: u8, DMA = NoDma> { | |||
| 106 | dma: PeripheralRef<'d, DMA>, | 106 | dma: PeripheralRef<'d, DMA>, |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | /// DAC channel 1 type alias. | ||
| 109 | pub type DacCh1<'d, T, DMA = NoDma> = DacChannel<'d, T, 1, DMA>; | 110 | pub type DacCh1<'d, T, DMA = NoDma> = DacChannel<'d, T, 1, DMA>; |
| 111 | /// DAC channel 2 type alias. | ||
| 110 | pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, 2, DMA>; | 112 | pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, 2, DMA>; |
| 111 | 113 | ||
| 112 | impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | 114 | impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { |
| @@ -492,6 +494,7 @@ pub(crate) mod sealed { | |||
| 492 | } | 494 | } |
| 493 | } | 495 | } |
| 494 | 496 | ||
| 497 | /// DAC instance. | ||
| 495 | pub trait Instance: sealed::Instance + RccPeripheral + 'static {} | 498 | pub trait Instance: sealed::Instance + RccPeripheral + 'static {} |
| 496 | dma_trait!(DacDma1, Instance); | 499 | dma_trait!(DacDma1, Instance); |
| 497 | dma_trait!(DacDma2, Instance); | 500 | dma_trait!(DacDma2, Instance); |
diff --git a/embassy-stm32/src/dac/tsel.rs b/embassy-stm32/src/dac/tsel.rs index f38dd8fd7..22d8d3dfa 100644 --- a/embassy-stm32/src/dac/tsel.rs +++ b/embassy-stm32/src/dac/tsel.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | #![allow(missing_docs)] | ||
| 2 | |||
| 1 | /// Trigger selection for STM32F0. | 3 | /// Trigger selection for STM32F0. |
| 2 | #[cfg(stm32f0)] | 4 | #[cfg(stm32f0)] |
| 3 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | 5 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] |
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index b12230794..139d8fd1b 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs | |||
| @@ -36,6 +36,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | /// The level on the VSync pin when the data is not valid on the parallel interface. | 38 | /// The level on the VSync pin when the data is not valid on the parallel interface. |
| 39 | #[allow(missing_docs)] | ||
| 39 | #[derive(Clone, Copy, PartialEq)] | 40 | #[derive(Clone, Copy, PartialEq)] |
| 40 | pub enum VSyncDataInvalidLevel { | 41 | pub enum VSyncDataInvalidLevel { |
| 41 | Low, | 42 | Low, |
| @@ -43,6 +44,7 @@ pub enum VSyncDataInvalidLevel { | |||
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | /// The level on the VSync pin when the data is not valid on the parallel interface. | 46 | /// The level on the VSync pin when the data is not valid on the parallel interface. |
| 47 | #[allow(missing_docs)] | ||
| 46 | #[derive(Clone, Copy, PartialEq)] | 48 | #[derive(Clone, Copy, PartialEq)] |
| 47 | pub enum HSyncDataInvalidLevel { | 49 | pub enum HSyncDataInvalidLevel { |
| 48 | Low, | 50 | Low, |
| @@ -50,14 +52,16 @@ pub enum HSyncDataInvalidLevel { | |||
| 50 | } | 52 | } |
| 51 | 53 | ||
| 52 | #[derive(Clone, Copy, PartialEq)] | 54 | #[derive(Clone, Copy, PartialEq)] |
| 55 | #[allow(missing_docs)] | ||
| 53 | pub enum PixelClockPolarity { | 56 | pub enum PixelClockPolarity { |
| 54 | RisingEdge, | 57 | RisingEdge, |
| 55 | FallingEdge, | 58 | FallingEdge, |
| 56 | } | 59 | } |
| 57 | 60 | ||
| 58 | pub struct State { | 61 | struct State { |
| 59 | waker: AtomicWaker, | 62 | waker: AtomicWaker, |
| 60 | } | 63 | } |
| 64 | |||
| 61 | impl State { | 65 | impl State { |
| 62 | const fn new() -> State { | 66 | const fn new() -> State { |
| 63 | State { | 67 | State { |
| @@ -68,18 +72,25 @@ impl State { | |||
| 68 | 72 | ||
| 69 | static STATE: State = State::new(); | 73 | static STATE: State = State::new(); |
| 70 | 74 | ||
| 75 | /// DCMI error. | ||
| 71 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] | 76 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] |
| 72 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 77 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 73 | #[non_exhaustive] | 78 | #[non_exhaustive] |
| 74 | pub enum Error { | 79 | pub enum Error { |
| 80 | /// Overrun error: the hardware generated data faster than we could read it. | ||
| 75 | Overrun, | 81 | Overrun, |
| 82 | /// Internal peripheral error. | ||
| 76 | PeripheralError, | 83 | PeripheralError, |
| 77 | } | 84 | } |
| 78 | 85 | ||
| 86 | /// DCMI configuration. | ||
| 79 | #[non_exhaustive] | 87 | #[non_exhaustive] |
| 80 | pub struct Config { | 88 | pub struct Config { |
| 89 | /// VSYNC level. | ||
| 81 | pub vsync_level: VSyncDataInvalidLevel, | 90 | pub vsync_level: VSyncDataInvalidLevel, |
| 91 | /// HSYNC level. | ||
| 82 | pub hsync_level: HSyncDataInvalidLevel, | 92 | pub hsync_level: HSyncDataInvalidLevel, |
| 93 | /// PIXCLK polarity. | ||
| 83 | pub pixclk_polarity: PixelClockPolarity, | 94 | pub pixclk_polarity: PixelClockPolarity, |
| 84 | } | 95 | } |
| 85 | 96 | ||
| @@ -105,6 +116,7 @@ macro_rules! config_pins { | |||
| 105 | }; | 116 | }; |
| 106 | } | 117 | } |
| 107 | 118 | ||
| 119 | /// DCMI driver. | ||
| 108 | pub struct Dcmi<'d, T: Instance, Dma: FrameDma<T>> { | 120 | pub struct Dcmi<'d, T: Instance, Dma: FrameDma<T>> { |
| 109 | inner: PeripheralRef<'d, T>, | 121 | inner: PeripheralRef<'d, T>, |
| 110 | dma: PeripheralRef<'d, Dma>, | 122 | dma: PeripheralRef<'d, Dma>, |
| @@ -115,6 +127,7 @@ where | |||
| 115 | T: Instance, | 127 | T: Instance, |
| 116 | Dma: FrameDma<T>, | 128 | Dma: FrameDma<T>, |
| 117 | { | 129 | { |
| 130 | /// Create a new DCMI driver with 8 data bits. | ||
| 118 | pub fn new_8bit( | 131 | pub fn new_8bit( |
| 119 | peri: impl Peripheral<P = T> + 'd, | 132 | peri: impl Peripheral<P = T> + 'd, |
| 120 | dma: impl Peripheral<P = Dma> + 'd, | 133 | dma: impl Peripheral<P = Dma> + 'd, |
| @@ -139,6 +152,7 @@ where | |||
| 139 | Self::new_inner(peri, dma, config, false, 0b00) | 152 | Self::new_inner(peri, dma, config, false, 0b00) |
| 140 | } | 153 | } |
| 141 | 154 | ||
| 155 | /// Create a new DCMI driver with 10 data bits. | ||
| 142 | pub fn new_10bit( | 156 | pub fn new_10bit( |
| 143 | peri: impl Peripheral<P = T> + 'd, | 157 | peri: impl Peripheral<P = T> + 'd, |
| 144 | dma: impl Peripheral<P = Dma> + 'd, | 158 | dma: impl Peripheral<P = Dma> + 'd, |
| @@ -165,6 +179,7 @@ where | |||
| 165 | Self::new_inner(peri, dma, config, false, 0b01) | 179 | Self::new_inner(peri, dma, config, false, 0b01) |
| 166 | } | 180 | } |
| 167 | 181 | ||
| 182 | /// Create a new DCMI driver with 12 data bits. | ||
| 168 | pub fn new_12bit( | 183 | pub fn new_12bit( |
| 169 | peri: impl Peripheral<P = T> + 'd, | 184 | peri: impl Peripheral<P = T> + 'd, |
| 170 | dma: impl Peripheral<P = Dma> + 'd, | 185 | dma: impl Peripheral<P = Dma> + 'd, |
| @@ -193,6 +208,7 @@ where | |||
| 193 | Self::new_inner(peri, dma, config, false, 0b10) | 208 | Self::new_inner(peri, dma, config, false, 0b10) |
| 194 | } | 209 | } |
| 195 | 210 | ||
| 211 | /// Create a new DCMI driver with 14 data bits. | ||
| 196 | pub fn new_14bit( | 212 | pub fn new_14bit( |
| 197 | peri: impl Peripheral<P = T> + 'd, | 213 | peri: impl Peripheral<P = T> + 'd, |
| 198 | dma: impl Peripheral<P = Dma> + 'd, | 214 | dma: impl Peripheral<P = Dma> + 'd, |
| @@ -223,6 +239,7 @@ where | |||
| 223 | Self::new_inner(peri, dma, config, false, 0b11) | 239 | Self::new_inner(peri, dma, config, false, 0b11) |
| 224 | } | 240 | } |
| 225 | 241 | ||
| 242 | /// Create a new DCMI driver with 8 data bits, with embedded synchronization. | ||
| 226 | pub fn new_es_8bit( | 243 | pub fn new_es_8bit( |
| 227 | peri: impl Peripheral<P = T> + 'd, | 244 | peri: impl Peripheral<P = T> + 'd, |
| 228 | dma: impl Peripheral<P = Dma> + 'd, | 245 | dma: impl Peripheral<P = Dma> + 'd, |
| @@ -245,6 +262,7 @@ where | |||
| 245 | Self::new_inner(peri, dma, config, true, 0b00) | 262 | Self::new_inner(peri, dma, config, true, 0b00) |
| 246 | } | 263 | } |
| 247 | 264 | ||
| 265 | /// Create a new DCMI driver with 10 data bits, with embedded synchronization. | ||
| 248 | pub fn new_es_10bit( | 266 | pub fn new_es_10bit( |
| 249 | peri: impl Peripheral<P = T> + 'd, | 267 | peri: impl Peripheral<P = T> + 'd, |
| 250 | dma: impl Peripheral<P = Dma> + 'd, | 268 | dma: impl Peripheral<P = Dma> + 'd, |
| @@ -269,6 +287,7 @@ where | |||
| 269 | Self::new_inner(peri, dma, config, true, 0b01) | 287 | Self::new_inner(peri, dma, config, true, 0b01) |
| 270 | } | 288 | } |
| 271 | 289 | ||
| 290 | /// Create a new DCMI driver with 12 data bits, with embedded synchronization. | ||
| 272 | pub fn new_es_12bit( | 291 | pub fn new_es_12bit( |
| 273 | peri: impl Peripheral<P = T> + 'd, | 292 | peri: impl Peripheral<P = T> + 'd, |
| 274 | dma: impl Peripheral<P = Dma> + 'd, | 293 | dma: impl Peripheral<P = Dma> + 'd, |
| @@ -295,6 +314,7 @@ where | |||
| 295 | Self::new_inner(peri, dma, config, true, 0b10) | 314 | Self::new_inner(peri, dma, config, true, 0b10) |
| 296 | } | 315 | } |
| 297 | 316 | ||
| 317 | /// Create a new DCMI driver with 14 data bits, with embedded synchronization. | ||
| 298 | pub fn new_es_14bit( | 318 | pub fn new_es_14bit( |
| 299 | peri: impl Peripheral<P = T> + 'd, | 319 | peri: impl Peripheral<P = T> + 'd, |
| 300 | dma: impl Peripheral<P = Dma> + 'd, | 320 | dma: impl Peripheral<P = Dma> + 'd, |
| @@ -538,7 +558,9 @@ mod sealed { | |||
| 538 | } | 558 | } |
| 539 | } | 559 | } |
| 540 | 560 | ||
| 561 | /// DCMI instance. | ||
| 541 | pub trait Instance: sealed::Instance + 'static { | 562 | pub trait Instance: sealed::Instance + 'static { |
| 563 | /// Interrupt for this instance. | ||
| 542 | type Interrupt: interrupt::typelevel::Interrupt; | 564 | type Interrupt: interrupt::typelevel::Interrupt; |
| 543 | } | 565 | } |
| 544 | 566 | ||
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index a7422f66b..5102330c0 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | #![macro_use] | 1 | //! Basic Direct Memory Acccess (BDMA) |
| 2 | 2 | ||
| 3 | use core::future::Future; | 3 | use core::future::Future; |
| 4 | use core::pin::Pin; | 4 | use core::pin::Pin; |
| @@ -17,6 +17,7 @@ use crate::interrupt::Priority; | |||
| 17 | use crate::pac; | 17 | use crate::pac; |
| 18 | use crate::pac::bdma::{regs, vals}; | 18 | use crate::pac::bdma::{regs, vals}; |
| 19 | 19 | ||
| 20 | /// BDMA transfer options. | ||
| 20 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 21 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| 21 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 22 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 22 | #[non_exhaustive] | 23 | #[non_exhaustive] |
| @@ -140,13 +141,17 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: usize, index | |||
| 140 | STATE.ch_wakers[index].wake(); | 141 | STATE.ch_wakers[index].wake(); |
| 141 | } | 142 | } |
| 142 | 143 | ||
| 144 | /// DMA request type alias. | ||
| 143 | #[cfg(any(bdma_v2, dmamux))] | 145 | #[cfg(any(bdma_v2, dmamux))] |
| 144 | pub type Request = u8; | 146 | pub type Request = u8; |
| 147 | /// DMA request type alias. | ||
| 145 | #[cfg(not(any(bdma_v2, dmamux)))] | 148 | #[cfg(not(any(bdma_v2, dmamux)))] |
| 146 | pub type Request = (); | 149 | pub type Request = (); |
| 147 | 150 | ||
| 151 | /// DMA channel. | ||
| 148 | #[cfg(dmamux)] | 152 | #[cfg(dmamux)] |
| 149 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {} | 153 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {} |
| 154 | /// DMA channel. | ||
| 150 | #[cfg(not(dmamux))] | 155 | #[cfg(not(dmamux))] |
| 151 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {} | 156 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {} |
| 152 | 157 | ||
| @@ -161,12 +166,14 @@ pub(crate) mod sealed { | |||
| 161 | } | 166 | } |
| 162 | } | 167 | } |
| 163 | 168 | ||
| 169 | /// DMA transfer. | ||
| 164 | #[must_use = "futures do nothing unless you `.await` or poll them"] | 170 | #[must_use = "futures do nothing unless you `.await` or poll them"] |
| 165 | pub struct Transfer<'a, C: Channel> { | 171 | pub struct Transfer<'a, C: Channel> { |
| 166 | channel: PeripheralRef<'a, C>, | 172 | channel: PeripheralRef<'a, C>, |
| 167 | } | 173 | } |
| 168 | 174 | ||
| 169 | impl<'a, C: Channel> Transfer<'a, C> { | 175 | impl<'a, C: Channel> Transfer<'a, C> { |
| 176 | /// Create a new read DMA transfer (peripheral to memory). | ||
| 170 | pub unsafe fn new_read<W: Word>( | 177 | pub unsafe fn new_read<W: Word>( |
| 171 | channel: impl Peripheral<P = C> + 'a, | 178 | channel: impl Peripheral<P = C> + 'a, |
| 172 | request: Request, | 179 | request: Request, |
| @@ -177,6 +184,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 177 | Self::new_read_raw(channel, request, peri_addr, buf, options) | 184 | Self::new_read_raw(channel, request, peri_addr, buf, options) |
| 178 | } | 185 | } |
| 179 | 186 | ||
| 187 | /// Create a new read DMA transfer (peripheral to memory), using raw pointers. | ||
| 180 | pub unsafe fn new_read_raw<W: Word>( | 188 | pub unsafe fn new_read_raw<W: Word>( |
| 181 | channel: impl Peripheral<P = C> + 'a, | 189 | channel: impl Peripheral<P = C> + 'a, |
| 182 | request: Request, | 190 | request: Request, |
| @@ -202,6 +210,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 202 | ) | 210 | ) |
| 203 | } | 211 | } |
| 204 | 212 | ||
| 213 | /// Create a new write DMA transfer (memory to peripheral). | ||
| 205 | pub unsafe fn new_write<W: Word>( | 214 | pub unsafe fn new_write<W: Word>( |
| 206 | channel: impl Peripheral<P = C> + 'a, | 215 | channel: impl Peripheral<P = C> + 'a, |
| 207 | request: Request, | 216 | request: Request, |
| @@ -212,6 +221,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 212 | Self::new_write_raw(channel, request, buf, peri_addr, options) | 221 | Self::new_write_raw(channel, request, buf, peri_addr, options) |
| 213 | } | 222 | } |
| 214 | 223 | ||
| 224 | /// Create a new write DMA transfer (memory to peripheral), using raw pointers. | ||
| 215 | pub unsafe fn new_write_raw<W: Word>( | 225 | pub unsafe fn new_write_raw<W: Word>( |
| 216 | channel: impl Peripheral<P = C> + 'a, | 226 | channel: impl Peripheral<P = C> + 'a, |
| 217 | request: Request, | 227 | request: Request, |
| @@ -237,6 +247,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 237 | ) | 247 | ) |
| 238 | } | 248 | } |
| 239 | 249 | ||
| 250 | /// Create a new write DMA transfer (memory to peripheral), writing the same value repeatedly. | ||
| 240 | pub unsafe fn new_write_repeated<W: Word>( | 251 | pub unsafe fn new_write_repeated<W: Word>( |
| 241 | channel: impl Peripheral<P = C> + 'a, | 252 | channel: impl Peripheral<P = C> + 'a, |
| 242 | request: Request, | 253 | request: Request, |
| @@ -321,6 +332,9 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 321 | }); | 332 | }); |
| 322 | } | 333 | } |
| 323 | 334 | ||
| 335 | /// Request the transfer to stop. | ||
| 336 | /// | ||
| 337 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | ||
| 324 | pub fn request_stop(&mut self) { | 338 | pub fn request_stop(&mut self) { |
| 325 | let ch = self.channel.regs().ch(self.channel.num()); | 339 | let ch = self.channel.regs().ch(self.channel.num()); |
| 326 | 340 | ||
| @@ -331,6 +345,10 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 331 | }); | 345 | }); |
| 332 | } | 346 | } |
| 333 | 347 | ||
| 348 | /// Return whether this transfer is still running. | ||
| 349 | /// | ||
| 350 | /// If this returns `false`, it can be because either the transfer finished, or | ||
| 351 | /// it was requested to stop early with [`request_stop`](Self::request_stop). | ||
| 334 | pub fn is_running(&mut self) -> bool { | 352 | pub fn is_running(&mut self) -> bool { |
| 335 | let ch = self.channel.regs().ch(self.channel.num()); | 353 | let ch = self.channel.regs().ch(self.channel.num()); |
| 336 | let en = ch.cr().read().en(); | 354 | let en = ch.cr().read().en(); |
| @@ -339,13 +357,15 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 339 | en && (circular || !tcif) | 357 | en && (circular || !tcif) |
| 340 | } | 358 | } |
| 341 | 359 | ||
| 342 | /// Gets the total remaining transfers for the channel | 360 | /// Get the total remaining transfers for the channel. |
| 343 | /// Note: this will be zero for transfers that completed without cancellation. | 361 | /// |
| 362 | /// This will be zero for transfers that completed instead of being canceled with [`request_stop`](Self::request_stop). | ||
| 344 | pub fn get_remaining_transfers(&self) -> u16 { | 363 | pub fn get_remaining_transfers(&self) -> u16 { |
| 345 | let ch = self.channel.regs().ch(self.channel.num()); | 364 | let ch = self.channel.regs().ch(self.channel.num()); |
| 346 | ch.ndtr().read().ndt() | 365 | ch.ndtr().read().ndt() |
| 347 | } | 366 | } |
| 348 | 367 | ||
| 368 | /// Blocking wait until the transfer finishes. | ||
| 349 | pub fn blocking_wait(mut self) { | 369 | pub fn blocking_wait(mut self) { |
| 350 | while self.is_running() {} | 370 | while self.is_running() {} |
| 351 | self.request_stop(); | 371 | self.request_stop(); |
| @@ -411,6 +431,7 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { | |||
| 411 | } | 431 | } |
| 412 | } | 432 | } |
| 413 | 433 | ||
| 434 | /// Ringbuffer for reading data using DMA circular mode. | ||
| 414 | pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { | 435 | pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { |
| 415 | cr: regs::Cr, | 436 | cr: regs::Cr, |
| 416 | channel: PeripheralRef<'a, C>, | 437 | channel: PeripheralRef<'a, C>, |
| @@ -418,7 +439,8 @@ pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { | |||
| 418 | } | 439 | } |
| 419 | 440 | ||
| 420 | impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { | 441 | impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { |
| 421 | pub unsafe fn new_read( | 442 | /// Create a new ring buffer. |
| 443 | pub unsafe fn new( | ||
| 422 | channel: impl Peripheral<P = C> + 'a, | 444 | channel: impl Peripheral<P = C> + 'a, |
| 423 | _request: Request, | 445 | _request: Request, |
| 424 | peri_addr: *mut W, | 446 | peri_addr: *mut W, |
| @@ -473,11 +495,15 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { | |||
| 473 | this | 495 | this |
| 474 | } | 496 | } |
| 475 | 497 | ||
| 498 | /// Start the ring buffer operation. | ||
| 499 | /// | ||
| 500 | /// You must call this after creating it for it to work. | ||
| 476 | pub fn start(&mut self) { | 501 | pub fn start(&mut self) { |
| 477 | let ch = self.channel.regs().ch(self.channel.num()); | 502 | let ch = self.channel.regs().ch(self.channel.num()); |
| 478 | ch.cr().write_value(self.cr) | 503 | ch.cr().write_value(self.cr) |
| 479 | } | 504 | } |
| 480 | 505 | ||
| 506 | /// Clear all data in the ring buffer. | ||
| 481 | pub fn clear(&mut self) { | 507 | pub fn clear(&mut self) { |
| 482 | self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); | 508 | self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); |
| 483 | } | 509 | } |
| @@ -509,10 +535,11 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { | |||
| 509 | } | 535 | } |
| 510 | 536 | ||
| 511 | /// The capacity of the ringbuffer. | 537 | /// The capacity of the ringbuffer. |
| 512 | pub const fn cap(&self) -> usize { | 538 | pub const fn capacity(&self) -> usize { |
| 513 | self.ringbuf.cap() | 539 | self.ringbuf.cap() |
| 514 | } | 540 | } |
| 515 | 541 | ||
| 542 | /// Set a waker to be woken when at least one byte is received. | ||
| 516 | pub fn set_waker(&mut self, waker: &Waker) { | 543 | pub fn set_waker(&mut self, waker: &Waker) { |
| 517 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); | 544 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); |
| 518 | } | 545 | } |
| @@ -526,6 +553,9 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { | |||
| 526 | }); | 553 | }); |
| 527 | } | 554 | } |
| 528 | 555 | ||
| 556 | /// Request DMA to stop. | ||
| 557 | /// | ||
| 558 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | ||
| 529 | pub fn request_stop(&mut self) { | 559 | pub fn request_stop(&mut self) { |
| 530 | let ch = self.channel.regs().ch(self.channel.num()); | 560 | let ch = self.channel.regs().ch(self.channel.num()); |
| 531 | 561 | ||
| @@ -539,6 +569,10 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { | |||
| 539 | }); | 569 | }); |
| 540 | } | 570 | } |
| 541 | 571 | ||
| 572 | /// Return whether DMA is still running. | ||
| 573 | /// | ||
| 574 | /// If this returns `false`, it can be because either the transfer finished, or | ||
| 575 | /// it was requested to stop early with [`request_stop`](Self::request_stop). | ||
| 542 | pub fn is_running(&mut self) -> bool { | 576 | pub fn is_running(&mut self) -> bool { |
| 543 | let ch = self.channel.regs().ch(self.channel.num()); | 577 | let ch = self.channel.regs().ch(self.channel.num()); |
| 544 | ch.cr().read().en() | 578 | ch.cr().read().en() |
| @@ -555,6 +589,7 @@ impl<'a, C: Channel, W: Word> Drop for ReadableRingBuffer<'a, C, W> { | |||
| 555 | } | 589 | } |
| 556 | } | 590 | } |
| 557 | 591 | ||
| 592 | /// Ringbuffer for writing data using DMA circular mode. | ||
| 558 | pub struct WritableRingBuffer<'a, C: Channel, W: Word> { | 593 | pub struct WritableRingBuffer<'a, C: Channel, W: Word> { |
| 559 | cr: regs::Cr, | 594 | cr: regs::Cr, |
| 560 | channel: PeripheralRef<'a, C>, | 595 | channel: PeripheralRef<'a, C>, |
| @@ -562,7 +597,8 @@ pub struct WritableRingBuffer<'a, C: Channel, W: Word> { | |||
| 562 | } | 597 | } |
| 563 | 598 | ||
| 564 | impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { | 599 | impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { |
| 565 | pub unsafe fn new_write( | 600 | /// Create a new ring buffer. |
| 601 | pub unsafe fn new( | ||
| 566 | channel: impl Peripheral<P = C> + 'a, | 602 | channel: impl Peripheral<P = C> + 'a, |
| 567 | _request: Request, | 603 | _request: Request, |
| 568 | peri_addr: *mut W, | 604 | peri_addr: *mut W, |
| @@ -617,11 +653,15 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { | |||
| 617 | this | 653 | this |
| 618 | } | 654 | } |
| 619 | 655 | ||
| 656 | /// Start the ring buffer operation. | ||
| 657 | /// | ||
| 658 | /// You must call this after creating it for it to work. | ||
| 620 | pub fn start(&mut self) { | 659 | pub fn start(&mut self) { |
| 621 | let ch = self.channel.regs().ch(self.channel.num()); | 660 | let ch = self.channel.regs().ch(self.channel.num()); |
| 622 | ch.cr().write_value(self.cr) | 661 | ch.cr().write_value(self.cr) |
| 623 | } | 662 | } |
| 624 | 663 | ||
| 664 | /// Clear all data in the ring buffer. | ||
| 625 | pub fn clear(&mut self) { | 665 | pub fn clear(&mut self) { |
| 626 | self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); | 666 | self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); |
| 627 | } | 667 | } |
| @@ -640,10 +680,11 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { | |||
| 640 | } | 680 | } |
| 641 | 681 | ||
| 642 | /// The capacity of the ringbuffer. | 682 | /// The capacity of the ringbuffer. |
| 643 | pub const fn cap(&self) -> usize { | 683 | pub const fn capacity(&self) -> usize { |
| 644 | self.ringbuf.cap() | 684 | self.ringbuf.cap() |
| 645 | } | 685 | } |
| 646 | 686 | ||
| 687 | /// Set a waker to be woken when at least one byte is sent. | ||
| 647 | pub fn set_waker(&mut self, waker: &Waker) { | 688 | pub fn set_waker(&mut self, waker: &Waker) { |
| 648 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); | 689 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); |
| 649 | } | 690 | } |
| @@ -657,6 +698,9 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { | |||
| 657 | }); | 698 | }); |
| 658 | } | 699 | } |
| 659 | 700 | ||
| 701 | /// Request DMA to stop. | ||
| 702 | /// | ||
| 703 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | ||
| 660 | pub fn request_stop(&mut self) { | 704 | pub fn request_stop(&mut self) { |
| 661 | let ch = self.channel.regs().ch(self.channel.num()); | 705 | let ch = self.channel.regs().ch(self.channel.num()); |
| 662 | 706 | ||
| @@ -670,6 +714,10 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { | |||
| 670 | }); | 714 | }); |
| 671 | } | 715 | } |
| 672 | 716 | ||
| 717 | /// Return whether DMA is still running. | ||
| 718 | /// | ||
| 719 | /// If this returns `false`, it can be because either the transfer finished, or | ||
| 720 | /// it was requested to stop early with [`request_stop`](Self::request_stop). | ||
| 673 | pub fn is_running(&mut self) -> bool { | 721 | pub fn is_running(&mut self) -> bool { |
| 674 | let ch = self.channel.regs().ch(self.channel.num()); | 722 | let ch = self.channel.regs().ch(self.channel.num()); |
| 675 | ch.cr().read().en() | 723 | ch.cr().read().en() |
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index cce0407c1..64e492c10 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs | |||
| @@ -16,6 +16,7 @@ use crate::interrupt::Priority; | |||
| 16 | use crate::pac::dma::{regs, vals}; | 16 | use crate::pac::dma::{regs, vals}; |
| 17 | use crate::{interrupt, pac}; | 17 | use crate::{interrupt, pac}; |
| 18 | 18 | ||
| 19 | /// DMA transfer options. | ||
| 19 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 20 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| 20 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 21 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 21 | #[non_exhaustive] | 22 | #[non_exhaustive] |
| @@ -69,6 +70,7 @@ impl From<Dir> for vals::Dir { | |||
| 69 | } | 70 | } |
| 70 | } | 71 | } |
| 71 | 72 | ||
| 73 | /// DMA transfer burst setting. | ||
| 72 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 74 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| 73 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 75 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 74 | pub enum Burst { | 76 | pub enum Burst { |
| @@ -93,6 +95,7 @@ impl From<Burst> for vals::Burst { | |||
| 93 | } | 95 | } |
| 94 | } | 96 | } |
| 95 | 97 | ||
| 98 | /// DMA flow control setting. | ||
| 96 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 99 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| 97 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 100 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 98 | pub enum FlowControl { | 101 | pub enum FlowControl { |
| @@ -111,6 +114,7 @@ impl From<FlowControl> for vals::Pfctrl { | |||
| 111 | } | 114 | } |
| 112 | } | 115 | } |
| 113 | 116 | ||
| 117 | /// DMA FIFO threshold. | ||
| 114 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 118 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| 115 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 119 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 116 | pub enum FifoThreshold { | 120 | pub enum FifoThreshold { |
| @@ -208,13 +212,17 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::dma::Dma, channel_num: usize, index: | |||
| 208 | STATE.ch_wakers[index].wake(); | 212 | STATE.ch_wakers[index].wake(); |
| 209 | } | 213 | } |
| 210 | 214 | ||
| 215 | /// DMA request type alias. (also known as DMA channel number in some chips) | ||
| 211 | #[cfg(any(dma_v2, dmamux))] | 216 | #[cfg(any(dma_v2, dmamux))] |
| 212 | pub type Request = u8; | 217 | pub type Request = u8; |
| 218 | /// DMA request type alias. (also known as DMA channel number in some chips) | ||
| 213 | #[cfg(not(any(dma_v2, dmamux)))] | 219 | #[cfg(not(any(dma_v2, dmamux)))] |
| 214 | pub type Request = (); | 220 | pub type Request = (); |
| 215 | 221 | ||
| 222 | /// DMA channel. | ||
| 216 | #[cfg(dmamux)] | 223 | #[cfg(dmamux)] |
| 217 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {} | 224 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {} |
| 225 | /// DMA channel. | ||
| 218 | #[cfg(not(dmamux))] | 226 | #[cfg(not(dmamux))] |
| 219 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {} | 227 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {} |
| 220 | 228 | ||
| @@ -229,12 +237,14 @@ pub(crate) mod sealed { | |||
| 229 | } | 237 | } |
| 230 | } | 238 | } |
| 231 | 239 | ||
| 240 | /// DMA transfer. | ||
| 232 | #[must_use = "futures do nothing unless you `.await` or poll them"] | 241 | #[must_use = "futures do nothing unless you `.await` or poll them"] |
| 233 | pub struct Transfer<'a, C: Channel> { | 242 | pub struct Transfer<'a, C: Channel> { |
| 234 | channel: PeripheralRef<'a, C>, | 243 | channel: PeripheralRef<'a, C>, |
| 235 | } | 244 | } |
| 236 | 245 | ||
| 237 | impl<'a, C: Channel> Transfer<'a, C> { | 246 | impl<'a, C: Channel> Transfer<'a, C> { |
| 247 | /// Create a new read DMA transfer (peripheral to memory). | ||
| 238 | pub unsafe fn new_read<W: Word>( | 248 | pub unsafe fn new_read<W: Word>( |
| 239 | channel: impl Peripheral<P = C> + 'a, | 249 | channel: impl Peripheral<P = C> + 'a, |
| 240 | request: Request, | 250 | request: Request, |
| @@ -245,6 +255,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 245 | Self::new_read_raw(channel, request, peri_addr, buf, options) | 255 | Self::new_read_raw(channel, request, peri_addr, buf, options) |
| 246 | } | 256 | } |
| 247 | 257 | ||
| 258 | /// Create a new read DMA transfer (peripheral to memory), using raw pointers. | ||
| 248 | pub unsafe fn new_read_raw<W: Word>( | 259 | pub unsafe fn new_read_raw<W: Word>( |
| 249 | channel: impl Peripheral<P = C> + 'a, | 260 | channel: impl Peripheral<P = C> + 'a, |
| 250 | request: Request, | 261 | request: Request, |
| @@ -270,6 +281,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 270 | ) | 281 | ) |
| 271 | } | 282 | } |
| 272 | 283 | ||
| 284 | /// Create a new write DMA transfer (memory to peripheral). | ||
| 273 | pub unsafe fn new_write<W: Word>( | 285 | pub unsafe fn new_write<W: Word>( |
| 274 | channel: impl Peripheral<P = C> + 'a, | 286 | channel: impl Peripheral<P = C> + 'a, |
| 275 | request: Request, | 287 | request: Request, |
| @@ -280,6 +292,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 280 | Self::new_write_raw(channel, request, buf, peri_addr, options) | 292 | Self::new_write_raw(channel, request, buf, peri_addr, options) |
| 281 | } | 293 | } |
| 282 | 294 | ||
| 295 | /// Create a new write DMA transfer (memory to peripheral), using raw pointers. | ||
| 283 | pub unsafe fn new_write_raw<W: Word>( | 296 | pub unsafe fn new_write_raw<W: Word>( |
| 284 | channel: impl Peripheral<P = C> + 'a, | 297 | channel: impl Peripheral<P = C> + 'a, |
| 285 | request: Request, | 298 | request: Request, |
| @@ -305,6 +318,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 305 | ) | 318 | ) |
| 306 | } | 319 | } |
| 307 | 320 | ||
| 321 | /// Create a new write DMA transfer (memory to peripheral), writing the same value repeatedly. | ||
| 308 | pub unsafe fn new_write_repeated<W: Word>( | 322 | pub unsafe fn new_write_repeated<W: Word>( |
| 309 | channel: impl Peripheral<P = C> + 'a, | 323 | channel: impl Peripheral<P = C> + 'a, |
| 310 | request: Request, | 324 | request: Request, |
| @@ -407,6 +421,9 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 407 | }); | 421 | }); |
| 408 | } | 422 | } |
| 409 | 423 | ||
| 424 | /// Request the transfer to stop. | ||
| 425 | /// | ||
| 426 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | ||
| 410 | pub fn request_stop(&mut self) { | 427 | pub fn request_stop(&mut self) { |
| 411 | let ch = self.channel.regs().st(self.channel.num()); | 428 | let ch = self.channel.regs().st(self.channel.num()); |
| 412 | 429 | ||
| @@ -417,6 +434,10 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 417 | }); | 434 | }); |
| 418 | } | 435 | } |
| 419 | 436 | ||
| 437 | /// Return whether this transfer is still running. | ||
| 438 | /// | ||
| 439 | /// If this returns `false`, it can be because either the transfer finished, or | ||
| 440 | /// it was requested to stop early with [`request_stop`](Self::request_stop). | ||
| 420 | pub fn is_running(&mut self) -> bool { | 441 | pub fn is_running(&mut self) -> bool { |
| 421 | let ch = self.channel.regs().st(self.channel.num()); | 442 | let ch = self.channel.regs().st(self.channel.num()); |
| 422 | ch.cr().read().en() | 443 | ch.cr().read().en() |
| @@ -429,6 +450,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 429 | ch.ndtr().read().ndt() | 450 | ch.ndtr().read().ndt() |
| 430 | } | 451 | } |
| 431 | 452 | ||
| 453 | /// Blocking wait until the transfer finishes. | ||
| 432 | pub fn blocking_wait(mut self) { | 454 | pub fn blocking_wait(mut self) { |
| 433 | while self.is_running() {} | 455 | while self.is_running() {} |
| 434 | 456 | ||
| @@ -465,12 +487,14 @@ impl<'a, C: Channel> Future for Transfer<'a, C> { | |||
| 465 | 487 | ||
| 466 | // ================================== | 488 | // ================================== |
| 467 | 489 | ||
| 490 | /// Double-buffered DMA transfer. | ||
| 468 | pub struct DoubleBuffered<'a, C: Channel, W: Word> { | 491 | pub struct DoubleBuffered<'a, C: Channel, W: Word> { |
| 469 | channel: PeripheralRef<'a, C>, | 492 | channel: PeripheralRef<'a, C>, |
| 470 | _phantom: PhantomData<W>, | 493 | _phantom: PhantomData<W>, |
| 471 | } | 494 | } |
| 472 | 495 | ||
| 473 | impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { | 496 | impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { |
| 497 | /// Create a new read DMA transfer (peripheral to memory). | ||
| 474 | pub unsafe fn new_read( | 498 | pub unsafe fn new_read( |
| 475 | channel: impl Peripheral<P = C> + 'a, | 499 | channel: impl Peripheral<P = C> + 'a, |
| 476 | _request: Request, | 500 | _request: Request, |
| @@ -554,25 +578,36 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { | |||
| 554 | }); | 578 | }); |
| 555 | } | 579 | } |
| 556 | 580 | ||
| 581 | /// Set the first buffer address. | ||
| 582 | /// | ||
| 583 | /// You may call this while DMA is transferring the other buffer. | ||
| 557 | pub unsafe fn set_buffer0(&mut self, buffer: *mut W) { | 584 | pub unsafe fn set_buffer0(&mut self, buffer: *mut W) { |
| 558 | let ch = self.channel.regs().st(self.channel.num()); | 585 | let ch = self.channel.regs().st(self.channel.num()); |
| 559 | ch.m0ar().write_value(buffer as _); | 586 | ch.m0ar().write_value(buffer as _); |
| 560 | } | 587 | } |
| 561 | 588 | ||
| 589 | /// Set the second buffer address. | ||
| 590 | /// | ||
| 591 | /// You may call this while DMA is transferring the other buffer. | ||
| 562 | pub unsafe fn set_buffer1(&mut self, buffer: *mut W) { | 592 | pub unsafe fn set_buffer1(&mut self, buffer: *mut W) { |
| 563 | let ch = self.channel.regs().st(self.channel.num()); | 593 | let ch = self.channel.regs().st(self.channel.num()); |
| 564 | ch.m1ar().write_value(buffer as _); | 594 | ch.m1ar().write_value(buffer as _); |
| 565 | } | 595 | } |
| 566 | 596 | ||
| 597 | /// Returh whether buffer0 is accessible (i.e. whether DMA is transferring buffer1 now) | ||
| 567 | pub fn is_buffer0_accessible(&mut self) -> bool { | 598 | pub fn is_buffer0_accessible(&mut self) -> bool { |
| 568 | let ch = self.channel.regs().st(self.channel.num()); | 599 | let ch = self.channel.regs().st(self.channel.num()); |
| 569 | ch.cr().read().ct() == vals::Ct::MEMORY1 | 600 | ch.cr().read().ct() == vals::Ct::MEMORY1 |
| 570 | } | 601 | } |
| 571 | 602 | ||
| 603 | /// Set a waker to be woken when one of the buffers is being transferred. | ||
| 572 | pub fn set_waker(&mut self, waker: &Waker) { | 604 | pub fn set_waker(&mut self, waker: &Waker) { |
| 573 | STATE.ch_wakers[self.channel.index()].register(waker); | 605 | STATE.ch_wakers[self.channel.index()].register(waker); |
| 574 | } | 606 | } |
| 575 | 607 | ||
| 608 | /// Request the transfer to stop. | ||
| 609 | /// | ||
| 610 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | ||
| 576 | pub fn request_stop(&mut self) { | 611 | pub fn request_stop(&mut self) { |
| 577 | let ch = self.channel.regs().st(self.channel.num()); | 612 | let ch = self.channel.regs().st(self.channel.num()); |
| 578 | 613 | ||
| @@ -583,6 +618,10 @@ impl<'a, C: Channel, W: Word> DoubleBuffered<'a, C, W> { | |||
| 583 | }); | 618 | }); |
| 584 | } | 619 | } |
| 585 | 620 | ||
| 621 | /// Return whether this transfer is still running. | ||
| 622 | /// | ||
| 623 | /// If this returns `false`, it can be because either the transfer finished, or | ||
| 624 | /// it was requested to stop early with [`request_stop`](Self::request_stop). | ||
| 586 | pub fn is_running(&mut self) -> bool { | 625 | pub fn is_running(&mut self) -> bool { |
| 587 | let ch = self.channel.regs().st(self.channel.num()); | 626 | let ch = self.channel.regs().st(self.channel.num()); |
| 588 | ch.cr().read().en() | 627 | ch.cr().read().en() |
| @@ -629,6 +668,7 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { | |||
| 629 | } | 668 | } |
| 630 | } | 669 | } |
| 631 | 670 | ||
| 671 | /// Ringbuffer for receiving data using DMA circular mode. | ||
| 632 | pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { | 672 | pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { |
| 633 | cr: regs::Cr, | 673 | cr: regs::Cr, |
| 634 | channel: PeripheralRef<'a, C>, | 674 | channel: PeripheralRef<'a, C>, |
| @@ -636,7 +676,8 @@ pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { | |||
| 636 | } | 676 | } |
| 637 | 677 | ||
| 638 | impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { | 678 | impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { |
| 639 | pub unsafe fn new_read( | 679 | /// Create a new ring buffer. |
| 680 | pub unsafe fn new( | ||
| 640 | channel: impl Peripheral<P = C> + 'a, | 681 | channel: impl Peripheral<P = C> + 'a, |
| 641 | _request: Request, | 682 | _request: Request, |
| 642 | peri_addr: *mut W, | 683 | peri_addr: *mut W, |
| @@ -706,11 +747,15 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { | |||
| 706 | this | 747 | this |
| 707 | } | 748 | } |
| 708 | 749 | ||
| 750 | /// Start the ring buffer operation. | ||
| 751 | /// | ||
| 752 | /// You must call this after creating it for it to work. | ||
| 709 | pub fn start(&mut self) { | 753 | pub fn start(&mut self) { |
| 710 | let ch = self.channel.regs().st(self.channel.num()); | 754 | let ch = self.channel.regs().st(self.channel.num()); |
| 711 | ch.cr().write_value(self.cr); | 755 | ch.cr().write_value(self.cr); |
| 712 | } | 756 | } |
| 713 | 757 | ||
| 758 | /// Clear all data in the ring buffer. | ||
| 714 | pub fn clear(&mut self) { | 759 | pub fn clear(&mut self) { |
| 715 | self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); | 760 | self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); |
| 716 | } | 761 | } |
| @@ -741,11 +786,12 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { | |||
| 741 | .await | 786 | .await |
| 742 | } | 787 | } |
| 743 | 788 | ||
| 744 | // The capacity of the ringbuffer | 789 | /// The capacity of the ringbuffer |
| 745 | pub const fn cap(&self) -> usize { | 790 | pub const fn capacity(&self) -> usize { |
| 746 | self.ringbuf.cap() | 791 | self.ringbuf.cap() |
| 747 | } | 792 | } |
| 748 | 793 | ||
| 794 | /// Set a waker to be woken when at least one byte is received. | ||
| 749 | pub fn set_waker(&mut self, waker: &Waker) { | 795 | pub fn set_waker(&mut self, waker: &Waker) { |
| 750 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); | 796 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); |
| 751 | } | 797 | } |
| @@ -763,6 +809,9 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { | |||
| 763 | }); | 809 | }); |
| 764 | } | 810 | } |
| 765 | 811 | ||
| 812 | /// Request DMA to stop. | ||
| 813 | /// | ||
| 814 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | ||
| 766 | pub fn request_stop(&mut self) { | 815 | pub fn request_stop(&mut self) { |
| 767 | let ch = self.channel.regs().st(self.channel.num()); | 816 | let ch = self.channel.regs().st(self.channel.num()); |
| 768 | 817 | ||
| @@ -774,6 +823,10 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> { | |||
| 774 | }); | 823 | }); |
| 775 | } | 824 | } |
| 776 | 825 | ||
| 826 | /// Return whether DMA is still running. | ||
| 827 | /// | ||
| 828 | /// If this returns `false`, it can be because either the transfer finished, or | ||
| 829 | /// it was requested to stop early with [`request_stop`](Self::request_stop). | ||
| 777 | pub fn is_running(&mut self) -> bool { | 830 | pub fn is_running(&mut self) -> bool { |
| 778 | let ch = self.channel.regs().st(self.channel.num()); | 831 | let ch = self.channel.regs().st(self.channel.num()); |
| 779 | ch.cr().read().en() | 832 | ch.cr().read().en() |
| @@ -790,6 +843,7 @@ impl<'a, C: Channel, W: Word> Drop for ReadableRingBuffer<'a, C, W> { | |||
| 790 | } | 843 | } |
| 791 | } | 844 | } |
| 792 | 845 | ||
| 846 | /// Ringbuffer for writing data using DMA circular mode. | ||
| 793 | pub struct WritableRingBuffer<'a, C: Channel, W: Word> { | 847 | pub struct WritableRingBuffer<'a, C: Channel, W: Word> { |
| 794 | cr: regs::Cr, | 848 | cr: regs::Cr, |
| 795 | channel: PeripheralRef<'a, C>, | 849 | channel: PeripheralRef<'a, C>, |
| @@ -797,7 +851,8 @@ pub struct WritableRingBuffer<'a, C: Channel, W: Word> { | |||
| 797 | } | 851 | } |
| 798 | 852 | ||
| 799 | impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { | 853 | impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { |
| 800 | pub unsafe fn new_write( | 854 | /// Create a new ring buffer. |
| 855 | pub unsafe fn new( | ||
| 801 | channel: impl Peripheral<P = C> + 'a, | 856 | channel: impl Peripheral<P = C> + 'a, |
| 802 | _request: Request, | 857 | _request: Request, |
| 803 | peri_addr: *mut W, | 858 | peri_addr: *mut W, |
| @@ -867,11 +922,15 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { | |||
| 867 | this | 922 | this |
| 868 | } | 923 | } |
| 869 | 924 | ||
| 925 | /// Start the ring buffer operation. | ||
| 926 | /// | ||
| 927 | /// You must call this after creating it for it to work. | ||
| 870 | pub fn start(&mut self) { | 928 | pub fn start(&mut self) { |
| 871 | let ch = self.channel.regs().st(self.channel.num()); | 929 | let ch = self.channel.regs().st(self.channel.num()); |
| 872 | ch.cr().write_value(self.cr); | 930 | ch.cr().write_value(self.cr); |
| 873 | } | 931 | } |
| 874 | 932 | ||
| 933 | /// Clear all data in the ring buffer. | ||
| 875 | pub fn clear(&mut self) { | 934 | pub fn clear(&mut self) { |
| 876 | self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); | 935 | self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); |
| 877 | } | 936 | } |
| @@ -889,11 +948,12 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { | |||
| 889 | .await | 948 | .await |
| 890 | } | 949 | } |
| 891 | 950 | ||
| 892 | // The capacity of the ringbuffer | 951 | /// The capacity of the ringbuffer |
| 893 | pub const fn cap(&self) -> usize { | 952 | pub const fn capacity(&self) -> usize { |
| 894 | self.ringbuf.cap() | 953 | self.ringbuf.cap() |
| 895 | } | 954 | } |
| 896 | 955 | ||
| 956 | /// Set a waker to be woken when at least one byte is received. | ||
| 897 | pub fn set_waker(&mut self, waker: &Waker) { | 957 | pub fn set_waker(&mut self, waker: &Waker) { |
| 898 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); | 958 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); |
| 899 | } | 959 | } |
| @@ -911,6 +971,9 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { | |||
| 911 | }); | 971 | }); |
| 912 | } | 972 | } |
| 913 | 973 | ||
| 974 | /// Request DMA to stop. | ||
| 975 | /// | ||
| 976 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | ||
| 914 | pub fn request_stop(&mut self) { | 977 | pub fn request_stop(&mut self) { |
| 915 | let ch = self.channel.regs().st(self.channel.num()); | 978 | let ch = self.channel.regs().st(self.channel.num()); |
| 916 | 979 | ||
| @@ -922,6 +985,10 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> { | |||
| 922 | }); | 985 | }); |
| 923 | } | 986 | } |
| 924 | 987 | ||
| 988 | /// Return whether DMA is still running. | ||
| 989 | /// | ||
| 990 | /// If this returns `false`, it can be because either the transfer finished, or | ||
| 991 | /// it was requested to stop early with [`request_stop`](Self::request_stop). | ||
| 925 | pub fn is_running(&mut self) -> bool { | 992 | pub fn is_running(&mut self) -> bool { |
| 926 | let ch = self.channel.regs().st(self.channel.num()); | 993 | let ch = self.channel.regs().st(self.channel.num()); |
| 927 | ch.cr().read().en() | 994 | ch.cr().read().en() |
diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs index 20601dc86..9cd494724 100644 --- a/embassy-stm32/src/dma/dmamux.rs +++ b/embassy-stm32/src/dma/dmamux.rs | |||
| @@ -22,11 +22,15 @@ pub(crate) mod dmamux_sealed { | |||
| 22 | } | 22 | } |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | /// DMAMUX1 instance. | ||
| 25 | pub struct DMAMUX1; | 26 | pub struct DMAMUX1; |
| 27 | /// DMAMUX2 instance. | ||
| 26 | #[cfg(stm32h7)] | 28 | #[cfg(stm32h7)] |
| 27 | pub struct DMAMUX2; | 29 | pub struct DMAMUX2; |
| 28 | 30 | ||
| 31 | /// DMAMUX channel trait. | ||
| 29 | pub trait MuxChannel: dmamux_sealed::MuxChannel { | 32 | pub trait MuxChannel: dmamux_sealed::MuxChannel { |
| 33 | /// DMAMUX instance this channel is on. | ||
| 30 | type Mux; | 34 | type Mux; |
| 31 | } | 35 | } |
| 32 | 36 | ||
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 29fced8fc..fb40a4b5e 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs | |||
| @@ -39,6 +39,13 @@ enum Dir { | |||
| 39 | PeripheralToMemory, | 39 | PeripheralToMemory, |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | /// "No DMA" placeholder. | ||
| 43 | /// | ||
| 44 | /// You may pass this in place of a real DMA channel when creating a driver | ||
| 45 | /// to indicate it should not use DMA. | ||
| 46 | /// | ||
| 47 | /// This often causes async functionality to not be available on the instance, | ||
| 48 | /// leaving only blocking functionality. | ||
| 42 | pub struct NoDma; | 49 | pub struct NoDma; |
| 43 | 50 | ||
| 44 | impl_peripheral!(NoDma); | 51 | impl_peripheral!(NoDma); |
diff --git a/embassy-stm32/src/dma/word.rs b/embassy-stm32/src/dma/word.rs index aef6e9700..a72c4b7d9 100644 --- a/embassy-stm32/src/dma/word.rs +++ b/embassy-stm32/src/dma/word.rs | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | //! DMA word sizes. | ||
| 2 | |||
| 3 | #[allow(missing_docs)] | ||
| 1 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 4 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| 2 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 5 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 3 | pub enum WordSize { | 6 | pub enum WordSize { |
| @@ -7,6 +10,7 @@ pub enum WordSize { | |||
| 7 | } | 10 | } |
| 8 | 11 | ||
| 9 | impl WordSize { | 12 | impl WordSize { |
| 13 | /// Amount of bytes of this word size. | ||
| 10 | pub fn bytes(&self) -> usize { | 14 | pub fn bytes(&self) -> usize { |
| 11 | match self { | 15 | match self { |
| 12 | Self::OneByte => 1, | 16 | Self::OneByte => 1, |
| @@ -20,8 +24,13 @@ mod sealed { | |||
| 20 | pub trait Word {} | 24 | pub trait Word {} |
| 21 | } | 25 | } |
| 22 | 26 | ||
| 27 | /// DMA word trait. | ||
| 28 | /// | ||
| 29 | /// This is implemented for u8, u16, u32, etc. | ||
| 23 | pub trait Word: sealed::Word + Default + Copy + 'static { | 30 | pub trait Word: sealed::Word + Default + Copy + 'static { |
| 31 | /// Word size | ||
| 24 | fn size() -> WordSize; | 32 | fn size() -> WordSize; |
| 33 | /// Amount of bits of this word size. | ||
| 25 | fn bits() -> usize; | 34 | fn bits() -> usize; |
| 26 | } | 35 | } |
| 27 | 36 | ||
| @@ -40,6 +49,7 @@ macro_rules! impl_word { | |||
| 40 | ($T:ident, $uX:ident, $bits:literal, $size:ident) => { | 49 | ($T:ident, $uX:ident, $bits:literal, $size:ident) => { |
| 41 | #[repr(transparent)] | 50 | #[repr(transparent)] |
| 42 | #[derive(Copy, Clone, Default)] | 51 | #[derive(Copy, Clone, Default)] |
| 52 | #[doc = concat!(stringify!($T), " word size")] | ||
| 43 | pub struct $T(pub $uX); | 53 | pub struct $T(pub $uX); |
| 44 | impl_word!(_, $T, $bits, $size); | 54 | impl_word!(_, $T, $bits, $size); |
| 45 | }; | 55 | }; |
diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 1e1094a1c..9c26e90f1 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs | |||
| @@ -102,6 +102,7 @@ unsafe impl PHY for GenericSMI { | |||
| 102 | 102 | ||
| 103 | /// Public functions for the PHY | 103 | /// Public functions for the PHY |
| 104 | impl GenericSMI { | 104 | impl GenericSMI { |
| 105 | /// Set the SMI polling interval. | ||
| 105 | #[cfg(feature = "time")] | 106 | #[cfg(feature = "time")] |
| 106 | pub fn set_poll_interval(&mut self, poll_interval: Duration) { | 107 | pub fn set_poll_interval(&mut self, poll_interval: Duration) { |
| 107 | self.poll_interval = poll_interval | 108 | self.poll_interval = poll_interval |
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 556aadd73..dbf91eedc 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs | |||
| @@ -22,6 +22,14 @@ const RX_BUFFER_SIZE: usize = 1536; | |||
| 22 | #[derive(Copy, Clone)] | 22 | #[derive(Copy, Clone)] |
| 23 | pub(crate) struct Packet<const N: usize>([u8; N]); | 23 | pub(crate) struct Packet<const N: usize>([u8; N]); |
| 24 | 24 | ||
| 25 | /// Ethernet packet queue. | ||
| 26 | /// | ||
| 27 | /// This struct owns the memory used for reading and writing packets. | ||
| 28 | /// | ||
| 29 | /// `TX` is the number of packets in the transmit queue, `RX` in the receive | ||
| 30 | /// queue. A bigger queue allows the hardware to receive more packets while the | ||
| 31 | /// CPU is busy doing other things, which may increase performance (especially for RX) | ||
| 32 | /// at the cost of more RAM usage. | ||
| 25 | pub struct PacketQueue<const TX: usize, const RX: usize> { | 33 | pub struct PacketQueue<const TX: usize, const RX: usize> { |
| 26 | tx_desc: [TDes; TX], | 34 | tx_desc: [TDes; TX], |
| 27 | rx_desc: [RDes; RX], | 35 | rx_desc: [RDes; RX], |
| @@ -30,6 +38,7 @@ pub struct PacketQueue<const TX: usize, const RX: usize> { | |||
| 30 | } | 38 | } |
| 31 | 39 | ||
| 32 | impl<const TX: usize, const RX: usize> PacketQueue<TX, RX> { | 40 | impl<const TX: usize, const RX: usize> PacketQueue<TX, RX> { |
| 41 | /// Create a new packet queue. | ||
| 33 | pub const fn new() -> Self { | 42 | pub const fn new() -> Self { |
| 34 | const NEW_TDES: TDes = TDes::new(); | 43 | const NEW_TDES: TDes = TDes::new(); |
| 35 | const NEW_RDES: RDes = RDes::new(); | 44 | const NEW_RDES: RDes = RDes::new(); |
| @@ -41,7 +50,18 @@ impl<const TX: usize, const RX: usize> PacketQueue<TX, RX> { | |||
| 41 | } | 50 | } |
| 42 | } | 51 | } |
| 43 | 52 | ||
| 44 | // Allow to initialize a Self without requiring it to go on the stack | 53 | /// Initialize a packet queue in-place. |
| 54 | /// | ||
| 55 | /// This can be helpful to avoid accidentally stack-allocating the packet queue in the stack. The | ||
| 56 | /// Rust compiler can sometimes be a bit dumb when working with large owned values: if you call `new()` | ||
| 57 | /// and then store the returned PacketQueue in its final place (like a `static`), the compiler might | ||
| 58 | /// place it temporarily on the stack then move it. Since this struct is quite big, it may result | ||
| 59 | /// in a stack overflow. | ||
| 60 | /// | ||
| 61 | /// With this function, you can create an uninitialized `static` with type `MaybeUninit<PacketQueue<...>>` | ||
| 62 | /// and initialize it in-place, guaranteeing no stack usage. | ||
| 63 | /// | ||
| 64 | /// After calling this function, calling `assume_init` on the MaybeUninit is guaranteed safe. | ||
| 45 | pub fn init(this: &mut MaybeUninit<Self>) { | 65 | pub fn init(this: &mut MaybeUninit<Self>) { |
| 46 | unsafe { | 66 | unsafe { |
| 47 | this.as_mut_ptr().write_bytes(0u8, 1); | 67 | this.as_mut_ptr().write_bytes(0u8, 1); |
| @@ -93,6 +113,7 @@ impl<'d, T: Instance, P: PHY> embassy_net_driver::Driver for Ethernet<'d, T, P> | |||
| 93 | } | 113 | } |
| 94 | } | 114 | } |
| 95 | 115 | ||
| 116 | /// `embassy-net` RX token. | ||
| 96 | pub struct RxToken<'a, 'd> { | 117 | pub struct RxToken<'a, 'd> { |
| 97 | rx: &'a mut RDesRing<'d>, | 118 | rx: &'a mut RDesRing<'d>, |
| 98 | } | 119 | } |
| @@ -110,6 +131,7 @@ impl<'a, 'd> embassy_net_driver::RxToken for RxToken<'a, 'd> { | |||
| 110 | } | 131 | } |
| 111 | } | 132 | } |
| 112 | 133 | ||
| 134 | /// `embassy-net` TX token. | ||
| 113 | pub struct TxToken<'a, 'd> { | 135 | pub struct TxToken<'a, 'd> { |
| 114 | tx: &'a mut TDesRing<'d>, | 136 | tx: &'a mut TDesRing<'d>, |
| 115 | } | 137 | } |
| @@ -159,6 +181,7 @@ pub(crate) mod sealed { | |||
| 159 | } | 181 | } |
| 160 | } | 182 | } |
| 161 | 183 | ||
| 184 | /// Ethernet instance. | ||
| 162 | pub trait Instance: sealed::Instance + Send + 'static {} | 185 | pub trait Instance: sealed::Instance + Send + 'static {} |
| 163 | 186 | ||
| 164 | impl sealed::Instance for crate::peripherals::ETH { | 187 | impl sealed::Instance for crate::peripherals::ETH { |
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index c77155fea..59745cba0 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs | |||
| @@ -34,6 +34,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> for InterruptHandl | |||
| 34 | } | 34 | } |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | /// Ethernet driver. | ||
| 37 | pub struct Ethernet<'d, T: Instance, P: PHY> { | 38 | pub struct Ethernet<'d, T: Instance, P: PHY> { |
| 38 | _peri: PeripheralRef<'d, T>, | 39 | _peri: PeripheralRef<'d, T>, |
| 39 | pub(crate) tx: TDesRing<'d>, | 40 | pub(crate) tx: TDesRing<'d>, |
| @@ -56,6 +57,7 @@ macro_rules! config_pins { | |||
| 56 | } | 57 | } |
| 57 | 58 | ||
| 58 | impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | 59 | impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { |
| 60 | /// Create a new Ethernet driver. | ||
| 59 | pub fn new<const TX: usize, const RX: usize>( | 61 | pub fn new<const TX: usize, const RX: usize>( |
| 60 | queue: &'d mut PacketQueue<TX, RX>, | 62 | queue: &'d mut PacketQueue<TX, RX>, |
| 61 | peri: impl Peripheral<P = T> + 'd, | 63 | peri: impl Peripheral<P = T> + 'd, |
| @@ -237,6 +239,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 237 | } | 239 | } |
| 238 | } | 240 | } |
| 239 | 241 | ||
| 242 | /// Ethernet SMI driver. | ||
| 240 | pub struct EthernetStationManagement<T: Instance> { | 243 | pub struct EthernetStationManagement<T: Instance> { |
| 241 | peri: PhantomData<T>, | 244 | peri: PhantomData<T>, |
| 242 | clock_range: u8, | 245 | clock_range: u8, |
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index e77ac30fb..371be913e 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs | |||
| @@ -39,7 +39,7 @@ fn exticr_regs() -> pac::afio::Afio { | |||
| 39 | pac::AFIO | 39 | pac::AFIO |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | pub unsafe fn on_irq() { | 42 | unsafe fn on_irq() { |
| 43 | #[cfg(feature = "low-power")] | 43 | #[cfg(feature = "low-power")] |
| 44 | crate::low_power::on_wakeup_irq(); | 44 | crate::low_power::on_wakeup_irq(); |
| 45 | 45 | ||
| @@ -85,7 +85,13 @@ impl Iterator for BitIter { | |||
| 85 | } | 85 | } |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | /// EXTI input driver | 88 | /// EXTI input driver. |
| 89 | /// | ||
| 90 | /// This driver augments a GPIO `Input` with EXTI functionality. EXTI is not | ||
| 91 | /// built into `Input` itself because it needs to take ownership of the corresponding | ||
| 92 | /// EXTI channel, which is a limited resource. | ||
| 93 | /// | ||
| 94 | /// Pins PA5, PB5, PC5... all use EXTI channel 5, so you can't use EXTI on, say, PA5 and PC5 at the same time. | ||
| 89 | pub struct ExtiInput<'d, T: GpioPin> { | 95 | pub struct ExtiInput<'d, T: GpioPin> { |
| 90 | pin: Input<'d, T>, | 96 | pin: Input<'d, T>, |
| 91 | } | 97 | } |
| @@ -93,23 +99,30 @@ pub struct ExtiInput<'d, T: GpioPin> { | |||
| 93 | impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {} | 99 | impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {} |
| 94 | 100 | ||
| 95 | impl<'d, T: GpioPin> ExtiInput<'d, T> { | 101 | impl<'d, T: GpioPin> ExtiInput<'d, T> { |
| 102 | /// Create an EXTI input. | ||
| 96 | pub fn new(pin: Input<'d, T>, _ch: impl Peripheral<P = T::ExtiChannel> + 'd) -> Self { | 103 | pub fn new(pin: Input<'d, T>, _ch: impl Peripheral<P = T::ExtiChannel> + 'd) -> Self { |
| 97 | Self { pin } | 104 | Self { pin } |
| 98 | } | 105 | } |
| 99 | 106 | ||
| 107 | /// Get whether the pin is high. | ||
| 100 | pub fn is_high(&mut self) -> bool { | 108 | pub fn is_high(&mut self) -> bool { |
| 101 | self.pin.is_high() | 109 | self.pin.is_high() |
| 102 | } | 110 | } |
| 103 | 111 | ||
| 112 | /// Get whether the pin is low. | ||
| 104 | pub fn is_low(&mut self) -> bool { | 113 | pub fn is_low(&mut self) -> bool { |
| 105 | self.pin.is_low() | 114 | self.pin.is_low() |
| 106 | } | 115 | } |
| 107 | 116 | ||
| 117 | /// Get the pin level. | ||
| 108 | pub fn get_level(&mut self) -> Level { | 118 | pub fn get_level(&mut self) -> Level { |
| 109 | self.pin.get_level() | 119 | self.pin.get_level() |
| 110 | } | 120 | } |
| 111 | 121 | ||
| 112 | pub async fn wait_for_high<'a>(&'a mut self) { | 122 | /// Asynchronously wait until the pin is high. |
| 123 | /// | ||
| 124 | /// This returns immediately if the pin is already high. | ||
| 125 | pub async fn wait_for_high(&mut self) { | ||
| 113 | let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false); | 126 | let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false); |
| 114 | if self.is_high() { | 127 | if self.is_high() { |
| 115 | return; | 128 | return; |
| @@ -117,7 +130,10 @@ impl<'d, T: GpioPin> ExtiInput<'d, T> { | |||
| 117 | fut.await | 130 | fut.await |
| 118 | } | 131 | } |
| 119 | 132 | ||
| 120 | pub async fn wait_for_low<'a>(&'a mut self) { | 133 | /// Asynchronously wait until the pin is low. |
| 134 | /// | ||
| 135 | /// This returns immediately if the pin is already low. | ||
| 136 | pub async fn wait_for_low(&mut self) { | ||
| 121 | let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true); | 137 | let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true); |
| 122 | if self.is_low() { | 138 | if self.is_low() { |
| 123 | return; | 139 | return; |
| @@ -125,15 +141,22 @@ impl<'d, T: GpioPin> ExtiInput<'d, T> { | |||
| 125 | fut.await | 141 | fut.await |
| 126 | } | 142 | } |
| 127 | 143 | ||
| 128 | pub async fn wait_for_rising_edge<'a>(&'a mut self) { | 144 | /// Asynchronously wait until the pin sees a rising edge. |
| 145 | /// | ||
| 146 | /// If the pin is already high, it will wait for it to go low then back high. | ||
| 147 | pub async fn wait_for_rising_edge(&mut self) { | ||
| 129 | ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false).await | 148 | ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false).await |
| 130 | } | 149 | } |
| 131 | 150 | ||
| 132 | pub async fn wait_for_falling_edge<'a>(&'a mut self) { | 151 | /// Asynchronously wait until the pin sees a falling edge. |
| 152 | /// | ||
| 153 | /// If the pin is already low, it will wait for it to go high then back low. | ||
| 154 | pub async fn wait_for_falling_edge(&mut self) { | ||
| 133 | ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true).await | 155 | ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true).await |
| 134 | } | 156 | } |
| 135 | 157 | ||
| 136 | pub async fn wait_for_any_edge<'a>(&'a mut self) { | 158 | /// Asynchronously wait until the pin sees any edge (either rising or falling). |
| 159 | pub async fn wait_for_any_edge(&mut self) { | ||
| 137 | ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, true).await | 160 | ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, true).await |
| 138 | } | 161 | } |
| 139 | } | 162 | } |
| @@ -284,6 +307,7 @@ macro_rules! foreach_exti_irq { | |||
| 284 | 307 | ||
| 285 | macro_rules! impl_irq { | 308 | macro_rules! impl_irq { |
| 286 | ($e:ident) => { | 309 | ($e:ident) => { |
| 310 | #[allow(non_snake_case)] | ||
| 287 | #[cfg(feature = "rt")] | 311 | #[cfg(feature = "rt")] |
| 288 | #[interrupt] | 312 | #[interrupt] |
| 289 | unsafe fn $e() { | 313 | unsafe fn $e() { |
| @@ -298,8 +322,16 @@ pub(crate) mod sealed { | |||
| 298 | pub trait Channel {} | 322 | pub trait Channel {} |
| 299 | } | 323 | } |
| 300 | 324 | ||
| 325 | /// EXTI channel trait. | ||
| 301 | pub trait Channel: sealed::Channel + Sized { | 326 | pub trait Channel: sealed::Channel + Sized { |
| 327 | /// Get the EXTI channel number. | ||
| 302 | fn number(&self) -> usize; | 328 | fn number(&self) -> usize; |
| 329 | |||
| 330 | /// Type-erase (degrade) this channel into an `AnyChannel`. | ||
| 331 | /// | ||
| 332 | /// This converts EXTI channel singletons (`EXTI0`, `EXTI1`, ...), which | ||
| 333 | /// are all different types, into the same type. It is useful for | ||
| 334 | /// creating arrays of channels, or avoiding generics. | ||
| 303 | fn degrade(self) -> AnyChannel { | 335 | fn degrade(self) -> AnyChannel { |
| 304 | AnyChannel { | 336 | AnyChannel { |
| 305 | number: self.number() as u8, | 337 | number: self.number() as u8, |
| @@ -307,9 +339,13 @@ pub trait Channel: sealed::Channel + Sized { | |||
| 307 | } | 339 | } |
| 308 | } | 340 | } |
| 309 | 341 | ||
| 342 | /// Type-erased (degraded) EXTI channel. | ||
| 343 | /// | ||
| 344 | /// This represents ownership over any EXTI channel, known at runtime. | ||
| 310 | pub struct AnyChannel { | 345 | pub struct AnyChannel { |
| 311 | number: u8, | 346 | number: u8, |
| 312 | } | 347 | } |
| 348 | |||
| 313 | impl_peripheral!(AnyChannel); | 349 | impl_peripheral!(AnyChannel); |
| 314 | impl sealed::Channel for AnyChannel {} | 350 | impl sealed::Channel for AnyChannel {} |
| 315 | impl Channel for AnyChannel { | 351 | impl Channel for AnyChannel { |
diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index eae40c7ec..e3c6d4d67 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs | |||
| @@ -59,7 +59,7 @@ impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_, Async> { | |||
| 59 | const READ_SIZE: usize = super::READ_SIZE; | 59 | const READ_SIZE: usize = super::READ_SIZE; |
| 60 | 60 | ||
| 61 | async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { | 61 | async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { |
| 62 | self.read(offset, bytes) | 62 | self.blocking_read(offset, bytes) |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | fn capacity(&self) -> usize { | 65 | fn capacity(&self) -> usize { |
diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 8acad1c7c..f8561edb3 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs | |||
| @@ -12,12 +12,14 @@ use super::{ | |||
| 12 | use crate::peripherals::FLASH; | 12 | use crate::peripherals::FLASH; |
| 13 | use crate::Peripheral; | 13 | use crate::Peripheral; |
| 14 | 14 | ||
| 15 | /// Internal flash memory driver. | ||
| 15 | pub struct Flash<'d, MODE = Async> { | 16 | pub struct Flash<'d, MODE = Async> { |
| 16 | pub(crate) inner: PeripheralRef<'d, FLASH>, | 17 | pub(crate) inner: PeripheralRef<'d, FLASH>, |
| 17 | pub(crate) _mode: PhantomData<MODE>, | 18 | pub(crate) _mode: PhantomData<MODE>, |
| 18 | } | 19 | } |
| 19 | 20 | ||
| 20 | impl<'d> Flash<'d, Blocking> { | 21 | impl<'d> Flash<'d, Blocking> { |
| 22 | /// Create a new flash driver, usable in blocking mode. | ||
| 21 | pub fn new_blocking(p: impl Peripheral<P = FLASH> + 'd) -> Self { | 23 | pub fn new_blocking(p: impl Peripheral<P = FLASH> + 'd) -> Self { |
| 22 | into_ref!(p); | 24 | into_ref!(p); |
| 23 | 25 | ||
| @@ -29,15 +31,26 @@ impl<'d> Flash<'d, Blocking> { | |||
| 29 | } | 31 | } |
| 30 | 32 | ||
| 31 | impl<'d, MODE> Flash<'d, MODE> { | 33 | impl<'d, MODE> Flash<'d, MODE> { |
| 34 | /// Split this flash driver into one instance per flash memory region. | ||
| 35 | /// | ||
| 36 | /// See module-level documentation for details on how memory regions work. | ||
| 32 | pub fn into_blocking_regions(self) -> FlashLayout<'d, Blocking> { | 37 | pub fn into_blocking_regions(self) -> FlashLayout<'d, Blocking> { |
| 33 | assert!(family::is_default_layout()); | 38 | assert!(family::is_default_layout()); |
| 34 | FlashLayout::new(self.inner) | 39 | FlashLayout::new(self.inner) |
| 35 | } | 40 | } |
| 36 | 41 | ||
| 37 | pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | 42 | /// Blocking read. |
| 43 | /// | ||
| 44 | /// NOTE: `offset` is an offset from the flash start, NOT an absolute address. | ||
| 45 | /// For example, to read address `0x0800_1234` you have to use offset `0x1234`. | ||
| 46 | pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | ||
| 38 | blocking_read(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) | 47 | blocking_read(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) |
| 39 | } | 48 | } |
| 40 | 49 | ||
| 50 | /// Blocking write. | ||
| 51 | /// | ||
| 52 | /// NOTE: `offset` is an offset from the flash start, NOT an absolute address. | ||
| 53 | /// For example, to write address `0x0800_1234` you have to use offset `0x1234`. | ||
| 41 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { | 54 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { |
| 42 | unsafe { | 55 | unsafe { |
| 43 | blocking_write( | 56 | blocking_write( |
| @@ -50,6 +63,10 @@ impl<'d, MODE> Flash<'d, MODE> { | |||
| 50 | } | 63 | } |
| 51 | } | 64 | } |
| 52 | 65 | ||
| 66 | /// Blocking erase. | ||
| 67 | /// | ||
| 68 | /// NOTE: `from` and `to` are offsets from the flash start, NOT an absolute address. | ||
| 69 | /// For example, to erase address `0x0801_0000` you have to use offset `0x1_0000`. | ||
| 53 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | 70 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { |
| 54 | unsafe { blocking_erase(FLASH_BASE as u32, from, to, erase_sector_unlocked) } | 71 | unsafe { blocking_erase(FLASH_BASE as u32, from, to, erase_sector_unlocked) } |
| 55 | } | 72 | } |
| @@ -206,7 +223,7 @@ impl<MODE> embedded_storage::nor_flash::ReadNorFlash for Flash<'_, MODE> { | |||
| 206 | const READ_SIZE: usize = READ_SIZE; | 223 | const READ_SIZE: usize = READ_SIZE; |
| 207 | 224 | ||
| 208 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { | 225 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { |
| 209 | self.read(offset, bytes) | 226 | self.blocking_read(offset, bytes) |
| 210 | } | 227 | } |
| 211 | 228 | ||
| 212 | fn capacity(&self) -> usize { | 229 | fn capacity(&self) -> usize { |
| @@ -230,16 +247,28 @@ impl<MODE> embedded_storage::nor_flash::NorFlash for Flash<'_, MODE> { | |||
| 230 | foreach_flash_region! { | 247 | foreach_flash_region! { |
| 231 | ($type_name:ident, $write_size:literal, $erase_size:literal) => { | 248 | ($type_name:ident, $write_size:literal, $erase_size:literal) => { |
| 232 | impl<MODE> crate::_generated::flash_regions::$type_name<'_, MODE> { | 249 | impl<MODE> crate::_generated::flash_regions::$type_name<'_, MODE> { |
| 250 | /// Blocking read. | ||
| 251 | /// | ||
| 252 | /// NOTE: `offset` is an offset from the flash start, NOT an absolute address. | ||
| 253 | /// For example, to read address `0x0800_1234` you have to use offset `0x1234`. | ||
| 233 | pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | 254 | pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { |
| 234 | blocking_read(self.0.base, self.0.size, offset, bytes) | 255 | blocking_read(self.0.base, self.0.size, offset, bytes) |
| 235 | } | 256 | } |
| 236 | } | 257 | } |
| 237 | 258 | ||
| 238 | impl crate::_generated::flash_regions::$type_name<'_, Blocking> { | 259 | impl crate::_generated::flash_regions::$type_name<'_, Blocking> { |
| 260 | /// Blocking write. | ||
| 261 | /// | ||
| 262 | /// NOTE: `offset` is an offset from the flash start, NOT an absolute address. | ||
| 263 | /// For example, to write address `0x0800_1234` you have to use offset `0x1234`. | ||
| 239 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { | 264 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { |
| 240 | unsafe { blocking_write(self.0.base, self.0.size, offset, bytes, write_chunk_with_critical_section) } | 265 | unsafe { blocking_write(self.0.base, self.0.size, offset, bytes, write_chunk_with_critical_section) } |
| 241 | } | 266 | } |
| 242 | 267 | ||
| 268 | /// Blocking erase. | ||
| 269 | /// | ||
| 270 | /// NOTE: `from` and `to` are offsets from the flash start, NOT an absolute address. | ||
| 271 | /// For example, to erase address `0x0801_0000` you have to use offset `0x1_0000`. | ||
| 243 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | 272 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { |
| 244 | unsafe { blocking_erase(self.0.base, from, to, erase_sector_with_critical_section) } | 273 | unsafe { blocking_erase(self.0.base, from, to, erase_sector_with_critical_section) } |
| 245 | } | 274 | } |
diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index 80d2a8166..c0a8d7022 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs | |||
| @@ -6,11 +6,11 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | |||
| 6 | use crate::flash::Error; | 6 | use crate::flash::Error; |
| 7 | use crate::pac; | 7 | use crate::pac; |
| 8 | 8 | ||
| 9 | pub const fn is_default_layout() -> bool { | 9 | pub(crate) const fn is_default_layout() -> bool { |
| 10 | true | 10 | true |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { | 13 | pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 14 | &FLASH_REGIONS | 14 | &FLASH_REGIONS |
| 15 | } | 15 | } |
| 16 | 16 | ||
diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index 27d5281a7..817ccef4d 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs | |||
| @@ -6,11 +6,11 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | |||
| 6 | use crate::flash::Error; | 6 | use crate::flash::Error; |
| 7 | use crate::pac; | 7 | use crate::pac; |
| 8 | 8 | ||
| 9 | pub const fn is_default_layout() -> bool { | 9 | pub(crate) const fn is_default_layout() -> bool { |
| 10 | true | 10 | true |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { | 13 | pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 14 | &FLASH_REGIONS | 14 | &FLASH_REGIONS |
| 15 | } | 15 | } |
| 16 | 16 | ||
diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index 017393e80..6b3e66ac6 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs | |||
| @@ -6,11 +6,11 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | |||
| 6 | use crate::flash::Error; | 6 | use crate::flash::Error; |
| 7 | use crate::pac; | 7 | use crate::pac; |
| 8 | 8 | ||
| 9 | pub const fn is_default_layout() -> bool { | 9 | pub(crate) const fn is_default_layout() -> bool { |
| 10 | true | 10 | true |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { | 13 | pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 14 | &FLASH_REGIONS | 14 | &FLASH_REGIONS |
| 15 | } | 15 | } |
| 16 | 16 | ||
diff --git a/embassy-stm32/src/flash/g.rs b/embassy-stm32/src/flash/g.rs index 08145e9c4..d97b4a932 100644 --- a/embassy-stm32/src/flash/g.rs +++ b/embassy-stm32/src/flash/g.rs | |||
| @@ -8,11 +8,11 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | |||
| 8 | use crate::flash::Error; | 8 | use crate::flash::Error; |
| 9 | use crate::pac; | 9 | use crate::pac; |
| 10 | 10 | ||
| 11 | pub const fn is_default_layout() -> bool { | 11 | pub(crate) const fn is_default_layout() -> bool { |
| 12 | true | 12 | true |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { | 15 | pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 16 | &FLASH_REGIONS | 16 | &FLASH_REGIONS |
| 17 | } | 17 | } |
| 18 | 18 | ||
diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index 555f8d155..65d163d29 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs | |||
| @@ -6,7 +6,7 @@ use super::{FlashRegion, FlashSector, BANK1_REGION, FLASH_REGIONS, WRITE_SIZE}; | |||
| 6 | use crate::flash::Error; | 6 | use crate::flash::Error; |
| 7 | use crate::pac; | 7 | use crate::pac; |
| 8 | 8 | ||
| 9 | pub const fn is_default_layout() -> bool { | 9 | pub(crate) const fn is_default_layout() -> bool { |
| 10 | true | 10 | true |
| 11 | } | 11 | } |
| 12 | 12 | ||
| @@ -14,7 +14,7 @@ const fn is_dual_bank() -> bool { | |||
| 14 | FLASH_REGIONS.len() >= 2 | 14 | FLASH_REGIONS.len() >= 2 |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | pub fn get_flash_regions() -> &'static [&'static FlashRegion] { | 17 | pub(crate) fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 18 | &FLASH_REGIONS | 18 | &FLASH_REGIONS |
| 19 | } | 19 | } |
| 20 | 20 | ||
diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index e0159a3f6..0b332dc61 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs | |||
| @@ -5,11 +5,11 @@ use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | |||
| 5 | use crate::flash::Error; | 5 | use crate::flash::Error; |
| 6 | use crate::pac; | 6 | use crate::pac; |
| 7 | 7 | ||
| 8 | pub const fn is_default_layout() -> bool { | 8 | pub(crate) const fn is_default_layout() -> bool { |
| 9 | true | 9 | true |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { | 12 | pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 13 | &FLASH_REGIONS | 13 | &FLASH_REGIONS |
| 14 | } | 14 | } |
| 15 | 15 | ||
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 3e8f2830b..6b6b4d41c 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs | |||
| @@ -14,50 +14,84 @@ pub use crate::_generated::flash_regions::*; | |||
| 14 | pub use crate::_generated::MAX_ERASE_SIZE; | 14 | pub use crate::_generated::MAX_ERASE_SIZE; |
| 15 | pub use crate::pac::{FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; | 15 | pub use crate::pac::{FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; |
| 16 | 16 | ||
| 17 | /// Get whether the default flash layout is being used. | ||
| 18 | /// | ||
| 19 | /// In some chips, dual-bank is not default. This will then return `false` | ||
| 20 | /// when dual-bank is enabled. | ||
| 21 | pub fn is_default_layout() -> bool { | ||
| 22 | family::is_default_layout() | ||
| 23 | } | ||
| 24 | |||
| 25 | /// Get all flash regions. | ||
| 26 | pub fn get_flash_regions() -> &'static [&'static FlashRegion] { | ||
| 27 | family::get_flash_regions() | ||
| 28 | } | ||
| 29 | |||
| 30 | /// Read size (always 1) | ||
| 17 | pub const READ_SIZE: usize = 1; | 31 | pub const READ_SIZE: usize = 1; |
| 18 | 32 | ||
| 19 | pub struct Blocking; | 33 | /// Blocking flash mode typestate. |
| 20 | pub struct Async; | 34 | pub enum Blocking {} |
| 35 | /// Async flash mode typestate. | ||
| 36 | pub enum Async {} | ||
| 21 | 37 | ||
| 38 | /// Flash memory region | ||
| 22 | #[derive(Debug)] | 39 | #[derive(Debug)] |
| 23 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 40 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 24 | pub struct FlashRegion { | 41 | pub struct FlashRegion { |
| 42 | /// Bank number. | ||
| 25 | pub bank: FlashBank, | 43 | pub bank: FlashBank, |
| 44 | /// Absolute base address. | ||
| 26 | pub base: u32, | 45 | pub base: u32, |
| 46 | /// Size in bytes. | ||
| 27 | pub size: u32, | 47 | pub size: u32, |
| 48 | /// Erase size (sector size). | ||
| 28 | pub erase_size: u32, | 49 | pub erase_size: u32, |
| 50 | /// Minimum write size. | ||
| 29 | pub write_size: u32, | 51 | pub write_size: u32, |
| 52 | /// Erase value (usually `0xFF`, but is `0x00` in some chips) | ||
| 30 | pub erase_value: u8, | 53 | pub erase_value: u8, |
| 31 | pub(crate) _ensure_internal: (), | 54 | pub(crate) _ensure_internal: (), |
| 32 | } | 55 | } |
| 33 | 56 | ||
| 57 | impl FlashRegion { | ||
| 58 | /// Absolute end address. | ||
| 59 | pub const fn end(&self) -> u32 { | ||
| 60 | self.base + self.size | ||
| 61 | } | ||
| 62 | |||
| 63 | /// Number of sectors in the region. | ||
| 64 | pub const fn sectors(&self) -> u8 { | ||
| 65 | (self.size / self.erase_size) as u8 | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | /// Flash sector. | ||
| 34 | #[derive(Debug, PartialEq)] | 70 | #[derive(Debug, PartialEq)] |
| 35 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 71 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 36 | pub struct FlashSector { | 72 | pub struct FlashSector { |
| 73 | /// Bank number. | ||
| 37 | pub bank: FlashBank, | 74 | pub bank: FlashBank, |
| 75 | /// Sector number within the bank. | ||
| 38 | pub index_in_bank: u8, | 76 | pub index_in_bank: u8, |
| 77 | /// Absolute start address. | ||
| 39 | pub start: u32, | 78 | pub start: u32, |
| 79 | /// Size in bytes. | ||
| 40 | pub size: u32, | 80 | pub size: u32, |
| 41 | } | 81 | } |
| 42 | 82 | ||
| 83 | /// Flash bank. | ||
| 43 | #[derive(Clone, Copy, Debug, PartialEq)] | 84 | #[derive(Clone, Copy, Debug, PartialEq)] |
| 44 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 85 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 45 | pub enum FlashBank { | 86 | pub enum FlashBank { |
| 87 | /// Bank 1 | ||
| 46 | Bank1 = 0, | 88 | Bank1 = 0, |
| 89 | /// Bank 2 | ||
| 47 | Bank2 = 1, | 90 | Bank2 = 1, |
| 91 | /// OTP region | ||
| 48 | Otp, | 92 | Otp, |
| 49 | } | 93 | } |
| 50 | 94 | ||
| 51 | impl FlashRegion { | ||
| 52 | pub const fn end(&self) -> u32 { | ||
| 53 | self.base + self.size | ||
| 54 | } | ||
| 55 | |||
| 56 | pub const fn sectors(&self) -> u8 { | ||
| 57 | (self.size / self.erase_size) as u8 | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | #[cfg_attr(any(flash_l0, flash_l1, flash_l4, flash_wl, flash_wb), path = "l.rs")] | 95 | #[cfg_attr(any(flash_l0, flash_l1, flash_l4, flash_wl, flash_wb), path = "l.rs")] |
| 62 | #[cfg_attr(flash_f0, path = "f0.rs")] | 96 | #[cfg_attr(flash_f0, path = "f0.rs")] |
| 63 | #[cfg_attr(flash_f3, path = "f3.rs")] | 97 | #[cfg_attr(flash_f3, path = "f3.rs")] |
| @@ -78,6 +112,10 @@ mod family; | |||
| 78 | #[allow(unused_imports)] | 112 | #[allow(unused_imports)] |
| 79 | pub use family::*; | 113 | pub use family::*; |
| 80 | 114 | ||
| 115 | /// Flash error | ||
| 116 | /// | ||
| 117 | /// See STM32 Reference Manual for your chip for details. | ||
| 118 | #[allow(missing_docs)] | ||
| 81 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 119 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| 82 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 120 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 83 | pub enum Error { | 121 | pub enum Error { |
diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs index a7e8d1d57..20f84a72f 100644 --- a/embassy-stm32/src/flash/other.rs +++ b/embassy-stm32/src/flash/other.rs | |||
| @@ -2,11 +2,11 @@ | |||
| 2 | 2 | ||
| 3 | use super::{Error, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | 3 | use super::{Error, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; |
| 4 | 4 | ||
| 5 | pub const fn is_default_layout() -> bool { | 5 | pub(crate) const fn is_default_layout() -> bool { |
| 6 | true | 6 | true |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { | 9 | pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { |
| 10 | &FLASH_REGIONS | 10 | &FLASH_REGIONS |
| 11 | } | 11 | } |
| 12 | 12 | ||
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index bb3cf2bc4..083b3237c 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs | |||
| @@ -29,6 +29,11 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 29 | Self { pin } | 29 | Self { pin } |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | /// Type-erase (degrade) this pin into an `AnyPin`. | ||
| 33 | /// | ||
| 34 | /// This converts pin singletons (`PA5`, `PB6`, ...), which | ||
| 35 | /// are all different types, into the same type. It is useful for | ||
| 36 | /// creating arrays of pins, or avoiding generics. | ||
| 32 | #[inline] | 37 | #[inline] |
| 33 | pub fn degrade(self) -> Flex<'d, AnyPin> { | 38 | pub fn degrade(self) -> Flex<'d, AnyPin> { |
| 34 | // Safety: We are about to drop the other copy of this pin, so | 39 | // Safety: We are about to drop the other copy of this pin, so |
| @@ -141,11 +146,13 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 141 | }); | 146 | }); |
| 142 | } | 147 | } |
| 143 | 148 | ||
| 149 | /// Get whether the pin input level is high. | ||
| 144 | #[inline] | 150 | #[inline] |
| 145 | pub fn is_high(&mut self) -> bool { | 151 | pub fn is_high(&mut self) -> bool { |
| 146 | !self.ref_is_low() | 152 | !self.ref_is_low() |
| 147 | } | 153 | } |
| 148 | 154 | ||
| 155 | /// Get whether the pin input level is low. | ||
| 149 | #[inline] | 156 | #[inline] |
| 150 | pub fn is_low(&mut self) -> bool { | 157 | pub fn is_low(&mut self) -> bool { |
| 151 | self.ref_is_low() | 158 | self.ref_is_low() |
| @@ -157,17 +164,19 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 157 | state == vals::Idr::LOW | 164 | state == vals::Idr::LOW |
| 158 | } | 165 | } |
| 159 | 166 | ||
| 167 | /// Get the current pin input level. | ||
| 160 | #[inline] | 168 | #[inline] |
| 161 | pub fn get_level(&mut self) -> Level { | 169 | pub fn get_level(&mut self) -> Level { |
| 162 | self.is_high().into() | 170 | self.is_high().into() |
| 163 | } | 171 | } |
| 164 | 172 | ||
| 173 | /// Get whether the output level is set to high. | ||
| 165 | #[inline] | 174 | #[inline] |
| 166 | pub fn is_set_high(&mut self) -> bool { | 175 | pub fn is_set_high(&mut self) -> bool { |
| 167 | !self.ref_is_set_low() | 176 | !self.ref_is_set_low() |
| 168 | } | 177 | } |
| 169 | 178 | ||
| 170 | /// Is the output pin set as low? | 179 | /// Get whether the output level is set to low. |
| 171 | #[inline] | 180 | #[inline] |
| 172 | pub fn is_set_low(&mut self) -> bool { | 181 | pub fn is_set_low(&mut self) -> bool { |
| 173 | self.ref_is_set_low() | 182 | self.ref_is_set_low() |
| @@ -179,12 +188,13 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 179 | state == vals::Odr::LOW | 188 | state == vals::Odr::LOW |
| 180 | } | 189 | } |
| 181 | 190 | ||
| 182 | /// What level output is set to | 191 | /// Get the current output level. |
| 183 | #[inline] | 192 | #[inline] |
| 184 | pub fn get_output_level(&mut self) -> Level { | 193 | pub fn get_output_level(&mut self) -> Level { |
| 185 | self.is_set_high().into() | 194 | self.is_set_high().into() |
| 186 | } | 195 | } |
| 187 | 196 | ||
| 197 | /// Set the output as high. | ||
| 188 | #[inline] | 198 | #[inline] |
| 189 | pub fn set_high(&mut self) { | 199 | pub fn set_high(&mut self) { |
| 190 | self.pin.set_high(); | 200 | self.pin.set_high(); |
| @@ -196,6 +206,7 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 196 | self.pin.set_low(); | 206 | self.pin.set_low(); |
| 197 | } | 207 | } |
| 198 | 208 | ||
| 209 | /// Set the output level. | ||
| 199 | #[inline] | 210 | #[inline] |
| 200 | pub fn set_level(&mut self, level: Level) { | 211 | pub fn set_level(&mut self, level: Level) { |
| 201 | match level { | 212 | match level { |
| @@ -204,7 +215,7 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 204 | } | 215 | } |
| 205 | } | 216 | } |
| 206 | 217 | ||
| 207 | /// Toggle pin output | 218 | /// Toggle the output level. |
| 208 | #[inline] | 219 | #[inline] |
| 209 | pub fn toggle(&mut self) { | 220 | pub fn toggle(&mut self) { |
| 210 | if self.is_set_low() { | 221 | if self.is_set_low() { |
| @@ -242,8 +253,11 @@ impl<'d, T: Pin> Drop for Flex<'d, T> { | |||
| 242 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] | 253 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] |
| 243 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 254 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 244 | pub enum Pull { | 255 | pub enum Pull { |
| 256 | /// No pull | ||
| 245 | None, | 257 | None, |
| 258 | /// Pull up | ||
| 246 | Up, | 259 | Up, |
| 260 | /// Pull down | ||
| 247 | Down, | 261 | Down, |
| 248 | } | 262 | } |
| 249 | 263 | ||
| @@ -261,6 +275,9 @@ impl From<Pull> for vals::Pupdr { | |||
| 261 | } | 275 | } |
| 262 | 276 | ||
| 263 | /// Speed settings | 277 | /// Speed settings |
| 278 | /// | ||
| 279 | /// These vary dpeending on the chip, ceck the reference manual or datasheet for details. | ||
| 280 | #[allow(missing_docs)] | ||
| 264 | #[derive(Debug, Copy, Clone)] | 281 | #[derive(Debug, Copy, Clone)] |
| 265 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 282 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 266 | pub enum Speed { | 283 | pub enum Speed { |
| @@ -305,6 +322,7 @@ pub struct Input<'d, T: Pin> { | |||
| 305 | } | 322 | } |
| 306 | 323 | ||
| 307 | impl<'d, T: Pin> Input<'d, T> { | 324 | impl<'d, T: Pin> Input<'d, T> { |
| 325 | /// Create GPIO input driver for a [Pin] with the provided [Pull] configuration. | ||
| 308 | #[inline] | 326 | #[inline] |
| 309 | pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self { | 327 | pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self { |
| 310 | let mut pin = Flex::new(pin); | 328 | let mut pin = Flex::new(pin); |
| @@ -312,6 +330,11 @@ impl<'d, T: Pin> Input<'d, T> { | |||
| 312 | Self { pin } | 330 | Self { pin } |
| 313 | } | 331 | } |
| 314 | 332 | ||
| 333 | /// Type-erase (degrade) this pin into an `AnyPin`. | ||
| 334 | /// | ||
| 335 | /// This converts pin singletons (`PA5`, `PB6`, ...), which | ||
| 336 | /// are all different types, into the same type. It is useful for | ||
| 337 | /// creating arrays of pins, or avoiding generics. | ||
| 315 | #[inline] | 338 | #[inline] |
| 316 | pub fn degrade(self) -> Input<'d, AnyPin> { | 339 | pub fn degrade(self) -> Input<'d, AnyPin> { |
| 317 | Input { | 340 | Input { |
| @@ -319,16 +342,19 @@ impl<'d, T: Pin> Input<'d, T> { | |||
| 319 | } | 342 | } |
| 320 | } | 343 | } |
| 321 | 344 | ||
| 345 | /// Get whether the pin input level is high. | ||
| 322 | #[inline] | 346 | #[inline] |
| 323 | pub fn is_high(&mut self) -> bool { | 347 | pub fn is_high(&mut self) -> bool { |
| 324 | self.pin.is_high() | 348 | self.pin.is_high() |
| 325 | } | 349 | } |
| 326 | 350 | ||
| 351 | /// Get whether the pin input level is low. | ||
| 327 | #[inline] | 352 | #[inline] |
| 328 | pub fn is_low(&mut self) -> bool { | 353 | pub fn is_low(&mut self) -> bool { |
| 329 | self.pin.is_low() | 354 | self.pin.is_low() |
| 330 | } | 355 | } |
| 331 | 356 | ||
| 357 | /// Get the current pin input level. | ||
| 332 | #[inline] | 358 | #[inline] |
| 333 | pub fn get_level(&mut self) -> Level { | 359 | pub fn get_level(&mut self) -> Level { |
| 334 | self.pin.get_level() | 360 | self.pin.get_level() |
| @@ -339,7 +365,9 @@ impl<'d, T: Pin> Input<'d, T> { | |||
| 339 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] | 365 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] |
| 340 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 366 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 341 | pub enum Level { | 367 | pub enum Level { |
| 368 | /// Low | ||
| 342 | Low, | 369 | Low, |
| 370 | /// High | ||
| 343 | High, | 371 | High, |
| 344 | } | 372 | } |
| 345 | 373 | ||
| @@ -371,6 +399,7 @@ pub struct Output<'d, T: Pin> { | |||
| 371 | } | 399 | } |
| 372 | 400 | ||
| 373 | impl<'d, T: Pin> Output<'d, T> { | 401 | impl<'d, T: Pin> Output<'d, T> { |
| 402 | /// Create GPIO output driver for a [Pin] with the provided [Level] and [Speed] configuration. | ||
| 374 | #[inline] | 403 | #[inline] |
| 375 | pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, speed: Speed) -> Self { | 404 | pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, speed: Speed) -> Self { |
| 376 | let mut pin = Flex::new(pin); | 405 | let mut pin = Flex::new(pin); |
| @@ -382,6 +411,11 @@ impl<'d, T: Pin> Output<'d, T> { | |||
| 382 | Self { pin } | 411 | Self { pin } |
| 383 | } | 412 | } |
| 384 | 413 | ||
| 414 | /// Type-erase (degrade) this pin into an `AnyPin`. | ||
| 415 | /// | ||
| 416 | /// This converts pin singletons (`PA5`, `PB6`, ...), which | ||
| 417 | /// are all different types, into the same type. It is useful for | ||
| 418 | /// creating arrays of pins, or avoiding generics. | ||
| 385 | #[inline] | 419 | #[inline] |
| 386 | pub fn degrade(self) -> Output<'d, AnyPin> { | 420 | pub fn degrade(self) -> Output<'d, AnyPin> { |
| 387 | Output { | 421 | Output { |
| @@ -442,6 +476,7 @@ pub struct OutputOpenDrain<'d, T: Pin> { | |||
| 442 | } | 476 | } |
| 443 | 477 | ||
| 444 | impl<'d, T: Pin> OutputOpenDrain<'d, T> { | 478 | impl<'d, T: Pin> OutputOpenDrain<'d, T> { |
| 479 | /// Create a new GPIO open drain output driver for a [Pin] with the provided [Level] and [Speed], [Pull] configuration. | ||
| 445 | #[inline] | 480 | #[inline] |
| 446 | pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self { | 481 | pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self { |
| 447 | let mut pin = Flex::new(pin); | 482 | let mut pin = Flex::new(pin); |
| @@ -455,6 +490,11 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> { | |||
| 455 | Self { pin } | 490 | Self { pin } |
| 456 | } | 491 | } |
| 457 | 492 | ||
| 493 | /// Type-erase (degrade) this pin into an `AnyPin`. | ||
| 494 | /// | ||
| 495 | /// This converts pin singletons (`PA5`, `PB6`, ...), which | ||
| 496 | /// are all different types, into the same type. It is useful for | ||
| 497 | /// creating arrays of pins, or avoiding generics. | ||
| 458 | #[inline] | 498 | #[inline] |
| 459 | pub fn degrade(self) -> Output<'d, AnyPin> { | 499 | pub fn degrade(self) -> Output<'d, AnyPin> { |
| 460 | Output { | 500 | Output { |
| @@ -462,17 +502,19 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> { | |||
| 462 | } | 502 | } |
| 463 | } | 503 | } |
| 464 | 504 | ||
| 505 | /// Get whether the pin input level is high. | ||
| 465 | #[inline] | 506 | #[inline] |
| 466 | pub fn is_high(&mut self) -> bool { | 507 | pub fn is_high(&mut self) -> bool { |
| 467 | !self.pin.is_low() | 508 | !self.pin.is_low() |
| 468 | } | 509 | } |
| 469 | 510 | ||
| 511 | /// Get whether the pin input level is low. | ||
| 470 | #[inline] | 512 | #[inline] |
| 471 | pub fn is_low(&mut self) -> bool { | 513 | pub fn is_low(&mut self) -> bool { |
| 472 | self.pin.is_low() | 514 | self.pin.is_low() |
| 473 | } | 515 | } |
| 474 | 516 | ||
| 475 | /// Returns current pin level | 517 | /// Get the current pin input level. |
| 476 | #[inline] | 518 | #[inline] |
| 477 | pub fn get_level(&mut self) -> Level { | 519 | pub fn get_level(&mut self) -> Level { |
| 478 | self.pin.get_level() | 520 | self.pin.get_level() |
| @@ -496,19 +538,19 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> { | |||
| 496 | self.pin.set_level(level); | 538 | self.pin.set_level(level); |
| 497 | } | 539 | } |
| 498 | 540 | ||
| 499 | /// Is the output pin set as high? | 541 | /// Get whether the output level is set to high. |
| 500 | #[inline] | 542 | #[inline] |
| 501 | pub fn is_set_high(&mut self) -> bool { | 543 | pub fn is_set_high(&mut self) -> bool { |
| 502 | self.pin.is_set_high() | 544 | self.pin.is_set_high() |
| 503 | } | 545 | } |
| 504 | 546 | ||
| 505 | /// Is the output pin set as low? | 547 | /// Get whether the output level is set to low. |
| 506 | #[inline] | 548 | #[inline] |
| 507 | pub fn is_set_low(&mut self) -> bool { | 549 | pub fn is_set_low(&mut self) -> bool { |
| 508 | self.pin.is_set_low() | 550 | self.pin.is_set_low() |
| 509 | } | 551 | } |
| 510 | 552 | ||
| 511 | /// What level output is set to | 553 | /// Get the current output level. |
| 512 | #[inline] | 554 | #[inline] |
| 513 | pub fn get_output_level(&mut self) -> Level { | 555 | pub fn get_output_level(&mut self) -> Level { |
| 514 | self.pin.get_output_level() | 556 | self.pin.get_output_level() |
| @@ -521,8 +563,11 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> { | |||
| 521 | } | 563 | } |
| 522 | } | 564 | } |
| 523 | 565 | ||
| 566 | /// GPIO output type | ||
| 524 | pub enum OutputType { | 567 | pub enum OutputType { |
| 568 | /// Drive the pin both high or low. | ||
| 525 | PushPull, | 569 | PushPull, |
| 570 | /// Drive the pin low, or don't drive it at all if the output level is high. | ||
| 526 | OpenDrain, | 571 | OpenDrain, |
| 527 | } | 572 | } |
| 528 | 573 | ||
| @@ -535,6 +580,7 @@ impl From<OutputType> for sealed::AFType { | |||
| 535 | } | 580 | } |
| 536 | } | 581 | } |
| 537 | 582 | ||
| 583 | #[allow(missing_docs)] | ||
| 538 | pub(crate) mod sealed { | 584 | pub(crate) mod sealed { |
| 539 | use super::*; | 585 | use super::*; |
| 540 | 586 | ||
| @@ -542,8 +588,11 @@ pub(crate) mod sealed { | |||
| 542 | #[derive(Debug, Copy, Clone)] | 588 | #[derive(Debug, Copy, Clone)] |
| 543 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 589 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 544 | pub enum AFType { | 590 | pub enum AFType { |
| 591 | /// Input | ||
| 545 | Input, | 592 | Input, |
| 593 | /// Output, drive the pin both high or low. | ||
| 546 | OutputPushPull, | 594 | OutputPushPull, |
| 595 | /// Output, drive the pin low, or don't drive it at all if the output level is high. | ||
| 547 | OutputOpenDrain, | 596 | OutputOpenDrain, |
| 548 | } | 597 | } |
| 549 | 598 | ||
| @@ -686,7 +735,11 @@ pub(crate) mod sealed { | |||
| 686 | } | 735 | } |
| 687 | } | 736 | } |
| 688 | 737 | ||
| 738 | /// GPIO pin trait. | ||
| 689 | pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { | 739 | pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { |
| 740 | /// EXTI channel assigned to this pin. | ||
| 741 | /// | ||
| 742 | /// For example, PC4 uses EXTI4. | ||
| 690 | #[cfg(feature = "exti")] | 743 | #[cfg(feature = "exti")] |
| 691 | type ExtiChannel: crate::exti::Channel; | 744 | type ExtiChannel: crate::exti::Channel; |
| 692 | 745 | ||
| @@ -702,7 +755,11 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat | |||
| 702 | self._port() | 755 | self._port() |
| 703 | } | 756 | } |
| 704 | 757 | ||
| 705 | /// Convert from concrete pin type PX_XX to type erased `AnyPin`. | 758 | /// Type-erase (degrade) this pin into an `AnyPin`. |
| 759 | /// | ||
| 760 | /// This converts pin singletons (`PA5`, `PB6`, ...), which | ||
| 761 | /// are all different types, into the same type. It is useful for | ||
| 762 | /// creating arrays of pins, or avoiding generics. | ||
| 706 | #[inline] | 763 | #[inline] |
| 707 | fn degrade(self) -> AnyPin { | 764 | fn degrade(self) -> AnyPin { |
| 708 | AnyPin { | 765 | AnyPin { |
| @@ -711,12 +768,15 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat | |||
| 711 | } | 768 | } |
| 712 | } | 769 | } |
| 713 | 770 | ||
| 714 | // Type-erased GPIO pin | 771 | /// Type-erased GPIO pin |
| 715 | pub struct AnyPin { | 772 | pub struct AnyPin { |
| 716 | pin_port: u8, | 773 | pin_port: u8, |
| 717 | } | 774 | } |
| 718 | 775 | ||
| 719 | impl AnyPin { | 776 | impl AnyPin { |
| 777 | /// Unsafely create an `AnyPin` from a pin+port number. | ||
| 778 | /// | ||
| 779 | /// `pin_port` is `port_num * 16 + pin_num`, where `port_num` is 0 for port `A`, 1 for port `B`, etc... | ||
| 720 | #[inline] | 780 | #[inline] |
| 721 | pub unsafe fn steal(pin_port: u8) -> Self { | 781 | pub unsafe fn steal(pin_port: u8) -> Self { |
| 722 | Self { pin_port } | 782 | Self { pin_port } |
| @@ -727,6 +787,8 @@ impl AnyPin { | |||
| 727 | self.pin_port / 16 | 787 | self.pin_port / 16 |
| 728 | } | 788 | } |
| 729 | 789 | ||
| 790 | /// Get the GPIO register block for this pin. | ||
| 791 | #[cfg(feature = "unstable-pac")] | ||
| 730 | #[inline] | 792 | #[inline] |
| 731 | pub fn block(&self) -> gpio::Gpio { | 793 | pub fn block(&self) -> gpio::Gpio { |
| 732 | pac::GPIO(self._port() as _) | 794 | pac::GPIO(self._port() as _) |
| @@ -1072,6 +1134,7 @@ impl<'d, T: Pin> embedded_hal_1::digital::StatefulOutputPin for Flex<'d, T> { | |||
| 1072 | } | 1134 | } |
| 1073 | } | 1135 | } |
| 1074 | 1136 | ||
| 1137 | /// Low-level GPIO manipulation. | ||
| 1075 | #[cfg(feature = "unstable-pac")] | 1138 | #[cfg(feature = "unstable-pac")] |
| 1076 | pub mod low_level { | 1139 | pub mod low_level { |
| 1077 | pub use super::sealed::*; | 1140 | pub use super::sealed::*; |
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index d2a50cf7e..a8dc8e0e5 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs | |||
| @@ -13,15 +13,23 @@ use embassy_sync::waitqueue::AtomicWaker; | |||
| 13 | 13 | ||
| 14 | use crate::peripherals; | 14 | use crate::peripherals; |
| 15 | 15 | ||
| 16 | /// I2C error. | ||
| 16 | #[derive(Debug, PartialEq, Eq)] | 17 | #[derive(Debug, PartialEq, Eq)] |
| 17 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 18 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 18 | pub enum Error { | 19 | pub enum Error { |
| 20 | /// Bus error | ||
| 19 | Bus, | 21 | Bus, |
| 22 | /// Arbitration lost | ||
| 20 | Arbitration, | 23 | Arbitration, |
| 24 | /// ACK not received (either to the address or to a data byte) | ||
| 21 | Nack, | 25 | Nack, |
| 26 | /// Timeout | ||
| 22 | Timeout, | 27 | Timeout, |
| 28 | /// CRC error | ||
| 23 | Crc, | 29 | Crc, |
| 30 | /// Overrun error | ||
| 24 | Overrun, | 31 | Overrun, |
| 32 | /// Zero-length transfers are not allowed. | ||
| 25 | ZeroLengthTransfer, | 33 | ZeroLengthTransfer, |
| 26 | } | 34 | } |
| 27 | 35 | ||
| @@ -47,8 +55,11 @@ pub(crate) mod sealed { | |||
| 47 | } | 55 | } |
| 48 | } | 56 | } |
| 49 | 57 | ||
| 58 | /// I2C peripheral instance | ||
| 50 | pub trait Instance: sealed::Instance + 'static { | 59 | pub trait Instance: sealed::Instance + 'static { |
| 60 | /// Event interrupt for this instance | ||
| 51 | type EventInterrupt: interrupt::typelevel::Interrupt; | 61 | type EventInterrupt: interrupt::typelevel::Interrupt; |
| 62 | /// Error interrupt for this instance | ||
| 52 | type ErrorInterrupt: interrupt::typelevel::Interrupt; | 63 | type ErrorInterrupt: interrupt::typelevel::Interrupt; |
| 53 | } | 64 | } |
| 54 | 65 | ||
| @@ -57,7 +68,7 @@ pin_trait!(SdaPin, Instance); | |||
| 57 | dma_trait!(RxDma, Instance); | 68 | dma_trait!(RxDma, Instance); |
| 58 | dma_trait!(TxDma, Instance); | 69 | dma_trait!(TxDma, Instance); |
| 59 | 70 | ||
| 60 | /// Interrupt handler. | 71 | /// Event interrupt handler. |
| 61 | pub struct EventInterruptHandler<T: Instance> { | 72 | pub struct EventInterruptHandler<T: Instance> { |
| 62 | _phantom: PhantomData<T>, | 73 | _phantom: PhantomData<T>, |
| 63 | } | 74 | } |
| @@ -68,6 +79,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::EventInterrupt> for EventInte | |||
| 68 | } | 79 | } |
| 69 | } | 80 | } |
| 70 | 81 | ||
| 82 | /// Error interrupt handler. | ||
| 71 | pub struct ErrorInterruptHandler<T: Instance> { | 83 | pub struct ErrorInterruptHandler<T: Instance> { |
| 72 | _phantom: PhantomData<T>, | 84 | _phantom: PhantomData<T>, |
| 73 | } | 85 | } |
diff --git a/embassy-stm32/src/qspi/enums.rs b/embassy-stm32/src/qspi/enums.rs index 0412d991a..e9e7fd482 100644 --- a/embassy-stm32/src/qspi/enums.rs +++ b/embassy-stm32/src/qspi/enums.rs | |||
| @@ -18,12 +18,17 @@ impl Into<u8> for QspiMode { | |||
| 18 | } | 18 | } |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | /// QSPI lane width | ||
| 21 | #[allow(dead_code)] | 22 | #[allow(dead_code)] |
| 22 | #[derive(Copy, Clone)] | 23 | #[derive(Copy, Clone)] |
| 23 | pub enum QspiWidth { | 24 | pub enum QspiWidth { |
| 25 | /// None | ||
| 24 | NONE, | 26 | NONE, |
| 27 | /// Single lane | ||
| 25 | SING, | 28 | SING, |
| 29 | /// Dual lanes | ||
| 26 | DUAL, | 30 | DUAL, |
| 31 | /// Quad lanes | ||
| 27 | QUAD, | 32 | QUAD, |
| 28 | } | 33 | } |
| 29 | 34 | ||
| @@ -38,10 +43,13 @@ impl Into<u8> for QspiWidth { | |||
| 38 | } | 43 | } |
| 39 | } | 44 | } |
| 40 | 45 | ||
| 46 | /// Flash bank selection | ||
| 41 | #[allow(dead_code)] | 47 | #[allow(dead_code)] |
| 42 | #[derive(Copy, Clone)] | 48 | #[derive(Copy, Clone)] |
| 43 | pub enum FlashSelection { | 49 | pub enum FlashSelection { |
| 50 | /// Bank 1 | ||
| 44 | Flash1, | 51 | Flash1, |
| 52 | /// Bank 2 | ||
| 45 | Flash2, | 53 | Flash2, |
| 46 | } | 54 | } |
| 47 | 55 | ||
| @@ -54,6 +62,8 @@ impl Into<bool> for FlashSelection { | |||
| 54 | } | 62 | } |
| 55 | } | 63 | } |
| 56 | 64 | ||
| 65 | /// QSPI memory size. | ||
| 66 | #[allow(missing_docs)] | ||
| 57 | #[derive(Copy, Clone)] | 67 | #[derive(Copy, Clone)] |
| 58 | pub enum MemorySize { | 68 | pub enum MemorySize { |
| 59 | _1KiB, | 69 | _1KiB, |
| @@ -113,11 +123,16 @@ impl Into<u8> for MemorySize { | |||
| 113 | } | 123 | } |
| 114 | } | 124 | } |
| 115 | 125 | ||
| 126 | /// QSPI Address size | ||
| 116 | #[derive(Copy, Clone)] | 127 | #[derive(Copy, Clone)] |
| 117 | pub enum AddressSize { | 128 | pub enum AddressSize { |
| 129 | /// 8-bit address | ||
| 118 | _8Bit, | 130 | _8Bit, |
| 131 | /// 16-bit address | ||
| 119 | _16Bit, | 132 | _16Bit, |
| 133 | /// 24-bit address | ||
| 120 | _24bit, | 134 | _24bit, |
| 135 | /// 32-bit address | ||
| 121 | _32bit, | 136 | _32bit, |
| 122 | } | 137 | } |
| 123 | 138 | ||
| @@ -132,8 +147,10 @@ impl Into<u8> for AddressSize { | |||
| 132 | } | 147 | } |
| 133 | } | 148 | } |
| 134 | 149 | ||
| 150 | /// Time the Chip Select line stays high. | ||
| 151 | #[allow(missing_docs)] | ||
| 135 | #[derive(Copy, Clone)] | 152 | #[derive(Copy, Clone)] |
| 136 | pub enum ChipSelectHightTime { | 153 | pub enum ChipSelectHighTime { |
| 137 | _1Cycle, | 154 | _1Cycle, |
| 138 | _2Cycle, | 155 | _2Cycle, |
| 139 | _3Cycle, | 156 | _3Cycle, |
| @@ -144,21 +161,23 @@ pub enum ChipSelectHightTime { | |||
| 144 | _8Cycle, | 161 | _8Cycle, |
| 145 | } | 162 | } |
| 146 | 163 | ||
| 147 | impl Into<u8> for ChipSelectHightTime { | 164 | impl Into<u8> for ChipSelectHighTime { |
| 148 | fn into(self) -> u8 { | 165 | fn into(self) -> u8 { |
| 149 | match self { | 166 | match self { |
| 150 | ChipSelectHightTime::_1Cycle => 0, | 167 | ChipSelectHighTime::_1Cycle => 0, |
| 151 | ChipSelectHightTime::_2Cycle => 1, | 168 | ChipSelectHighTime::_2Cycle => 1, |
| 152 | ChipSelectHightTime::_3Cycle => 2, | 169 | ChipSelectHighTime::_3Cycle => 2, |
| 153 | ChipSelectHightTime::_4Cycle => 3, | 170 | ChipSelectHighTime::_4Cycle => 3, |
| 154 | ChipSelectHightTime::_5Cycle => 4, | 171 | ChipSelectHighTime::_5Cycle => 4, |
| 155 | ChipSelectHightTime::_6Cycle => 5, | 172 | ChipSelectHighTime::_6Cycle => 5, |
| 156 | ChipSelectHightTime::_7Cycle => 6, | 173 | ChipSelectHighTime::_7Cycle => 6, |
| 157 | ChipSelectHightTime::_8Cycle => 7, | 174 | ChipSelectHighTime::_8Cycle => 7, |
| 158 | } | 175 | } |
| 159 | } | 176 | } |
| 160 | } | 177 | } |
| 161 | 178 | ||
| 179 | /// FIFO threshold. | ||
| 180 | #[allow(missing_docs)] | ||
| 162 | #[derive(Copy, Clone)] | 181 | #[derive(Copy, Clone)] |
| 163 | pub enum FIFOThresholdLevel { | 182 | pub enum FIFOThresholdLevel { |
| 164 | _1Bytes, | 183 | _1Bytes, |
| @@ -234,6 +253,8 @@ impl Into<u8> for FIFOThresholdLevel { | |||
| 234 | } | 253 | } |
| 235 | } | 254 | } |
| 236 | 255 | ||
| 256 | /// Dummy cycle count | ||
| 257 | #[allow(missing_docs)] | ||
| 237 | #[derive(Copy, Clone)] | 258 | #[derive(Copy, Clone)] |
| 238 | pub enum DummyCycles { | 259 | pub enum DummyCycles { |
| 239 | _0, | 260 | _0, |
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 1153455c7..bac91f300 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs | |||
| @@ -54,7 +54,7 @@ pub struct Config { | |||
| 54 | /// Number of bytes to trigger FIFO threshold flag. | 54 | /// Number of bytes to trigger FIFO threshold flag. |
| 55 | pub fifo_threshold: FIFOThresholdLevel, | 55 | pub fifo_threshold: FIFOThresholdLevel, |
| 56 | /// Minimum number of cycles that chip select must be high between issued commands | 56 | /// Minimum number of cycles that chip select must be high between issued commands |
| 57 | pub cs_high_time: ChipSelectHightTime, | 57 | pub cs_high_time: ChipSelectHighTime, |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | impl Default for Config { | 60 | impl Default for Config { |
| @@ -64,7 +64,7 @@ impl Default for Config { | |||
| 64 | address_size: AddressSize::_24bit, | 64 | address_size: AddressSize::_24bit, |
| 65 | prescaler: 128, | 65 | prescaler: 128, |
| 66 | fifo_threshold: FIFOThresholdLevel::_17Bytes, | 66 | fifo_threshold: FIFOThresholdLevel::_17Bytes, |
| 67 | cs_high_time: ChipSelectHightTime::_5Cycle, | 67 | cs_high_time: ChipSelectHighTime::_5Cycle, |
| 68 | } | 68 | } |
| 69 | } | 69 | } |
| 70 | } | 70 | } |
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index a16d38af1..3d7f65996 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs | |||
| @@ -583,10 +583,10 @@ fn get_ring_buffer<'d, T: Instance, C: Channel, W: word::Word>( | |||
| 583 | }; | 583 | }; |
| 584 | match tx_rx { | 584 | match tx_rx { |
| 585 | TxRx::Transmitter => RingBuffer::Writable(unsafe { | 585 | TxRx::Transmitter => RingBuffer::Writable(unsafe { |
| 586 | WritableRingBuffer::new_write(dma, request, dr(T::REGS, sub_block), dma_buf, opts) | 586 | WritableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts) |
| 587 | }), | 587 | }), |
| 588 | TxRx::Receiver => RingBuffer::Readable(unsafe { | 588 | TxRx::Receiver => RingBuffer::Readable(unsafe { |
| 589 | ReadableRingBuffer::new_read(dma, request, dr(T::REGS, sub_block), dma_buf, opts) | 589 | ReadableRingBuffer::new(dma, request, dr(T::REGS, sub_block), dma_buf, opts) |
| 590 | }), | 590 | }), |
| 591 | } | 591 | } |
| 592 | } | 592 | } |
diff --git a/embassy-stm32/src/traits.rs b/embassy-stm32/src/traits.rs index ffce7bd42..b4166e71a 100644 --- a/embassy-stm32/src/traits.rs +++ b/embassy-stm32/src/traits.rs | |||
| @@ -2,7 +2,9 @@ | |||
| 2 | 2 | ||
| 3 | macro_rules! pin_trait { | 3 | macro_rules! pin_trait { |
| 4 | ($signal:ident, $instance:path) => { | 4 | ($signal:ident, $instance:path) => { |
| 5 | #[doc = concat!(stringify!($signal), " pin trait")] | ||
| 5 | pub trait $signal<T: $instance>: crate::gpio::Pin { | 6 | pub trait $signal<T: $instance>: crate::gpio::Pin { |
| 7 | #[doc = concat!("Get the AF number needed to use this pin as", stringify!($signal))] | ||
| 6 | fn af_num(&self) -> u8; | 8 | fn af_num(&self) -> u8; |
| 7 | } | 9 | } |
| 8 | }; | 10 | }; |
| @@ -22,7 +24,11 @@ macro_rules! pin_trait_impl { | |||
| 22 | 24 | ||
| 23 | macro_rules! dma_trait { | 25 | macro_rules! dma_trait { |
| 24 | ($signal:ident, $instance:path) => { | 26 | ($signal:ident, $instance:path) => { |
| 27 | #[doc = concat!(stringify!($signal), " DMA request trait")] | ||
| 25 | pub trait $signal<T: $instance>: crate::dma::Channel { | 28 | pub trait $signal<T: $instance>: crate::dma::Channel { |
| 29 | #[doc = concat!("Get the DMA request number needed to use this channel as", stringify!($signal))] | ||
| 30 | /// Note: in some chips, ST calls this the "channel", and calls channels "streams". | ||
| 31 | /// `embassy-stm32` always uses the "channel" and "request number" names. | ||
| 26 | fn request(&self) -> crate::dma::Request; | 32 | fn request(&self) -> crate::dma::Request; |
| 27 | } | 33 | } |
| 28 | }; | 34 | }; |
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index b8d17e4e4..f8ada3926 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs | |||
| @@ -39,7 +39,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> { | |||
| 39 | let rx_dma = unsafe { self.rx_dma.clone_unchecked() }; | 39 | let rx_dma = unsafe { self.rx_dma.clone_unchecked() }; |
| 40 | let _peri = unsafe { self._peri.clone_unchecked() }; | 40 | let _peri = unsafe { self._peri.clone_unchecked() }; |
| 41 | 41 | ||
| 42 | let ring_buf = unsafe { ReadableRingBuffer::new_read(rx_dma, request, rdr(T::regs()), dma_buf, opts) }; | 42 | let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(T::regs()), dma_buf, opts) }; |
| 43 | 43 | ||
| 44 | // Don't disable the clock | 44 | // Don't disable the clock |
| 45 | mem::forget(self); | 45 | mem::forget(self); |
diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs index 93c54e943..56a35ddee 100644 --- a/examples/stm32f4/src/bin/flash.rs +++ b/examples/stm32f4/src/bin/flash.rs | |||
| @@ -31,7 +31,7 @@ fn test_flash(f: &mut Flash<'_, Blocking>, offset: u32, size: u32) { | |||
| 31 | 31 | ||
| 32 | info!("Reading..."); | 32 | info!("Reading..."); |
| 33 | let mut buf = [0u8; 32]; | 33 | let mut buf = [0u8; 32]; |
| 34 | unwrap!(f.read(offset, &mut buf)); | 34 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 35 | info!("Read: {=[u8]:x}", buf); | 35 | info!("Read: {=[u8]:x}", buf); |
| 36 | 36 | ||
| 37 | info!("Erasing..."); | 37 | info!("Erasing..."); |
| @@ -39,7 +39,7 @@ fn test_flash(f: &mut Flash<'_, Blocking>, offset: u32, size: u32) { | |||
| 39 | 39 | ||
| 40 | info!("Reading..."); | 40 | info!("Reading..."); |
| 41 | let mut buf = [0u8; 32]; | 41 | let mut buf = [0u8; 32]; |
| 42 | unwrap!(f.read(offset, &mut buf)); | 42 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 43 | info!("Read after erase: {=[u8]:x}", buf); | 43 | info!("Read after erase: {=[u8]:x}", buf); |
| 44 | 44 | ||
| 45 | info!("Writing..."); | 45 | info!("Writing..."); |
| @@ -53,7 +53,7 @@ fn test_flash(f: &mut Flash<'_, Blocking>, offset: u32, size: u32) { | |||
| 53 | 53 | ||
| 54 | info!("Reading..."); | 54 | info!("Reading..."); |
| 55 | let mut buf = [0u8; 32]; | 55 | let mut buf = [0u8; 32]; |
| 56 | unwrap!(f.read(offset, &mut buf)); | 56 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 57 | info!("Read: {=[u8]:x}", buf); | 57 | info!("Read: {=[u8]:x}", buf); |
| 58 | assert_eq!( | 58 | assert_eq!( |
| 59 | &buf[..], | 59 | &buf[..], |
diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs index f0a65a725..1624d842e 100644 --- a/examples/stm32f4/src/bin/flash_async.rs +++ b/examples/stm32f4/src/bin/flash_async.rs | |||
| @@ -48,7 +48,7 @@ async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) { | |||
| 48 | 48 | ||
| 49 | info!("Reading..."); | 49 | info!("Reading..."); |
| 50 | let mut buf = [0u8; 32]; | 50 | let mut buf = [0u8; 32]; |
| 51 | unwrap!(f.read(offset, &mut buf)); | 51 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 52 | info!("Read: {=[u8]:x}", buf); | 52 | info!("Read: {=[u8]:x}", buf); |
| 53 | 53 | ||
| 54 | info!("Erasing..."); | 54 | info!("Erasing..."); |
| @@ -56,7 +56,7 @@ async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) { | |||
| 56 | 56 | ||
| 57 | info!("Reading..."); | 57 | info!("Reading..."); |
| 58 | let mut buf = [0u8; 32]; | 58 | let mut buf = [0u8; 32]; |
| 59 | unwrap!(f.read(offset, &mut buf)); | 59 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 60 | info!("Read after erase: {=[u8]:x}", buf); | 60 | info!("Read after erase: {=[u8]:x}", buf); |
| 61 | 61 | ||
| 62 | info!("Writing..."); | 62 | info!("Writing..."); |
| @@ -73,7 +73,7 @@ async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) { | |||
| 73 | 73 | ||
| 74 | info!("Reading..."); | 74 | info!("Reading..."); |
| 75 | let mut buf = [0u8; 32]; | 75 | let mut buf = [0u8; 32]; |
| 76 | unwrap!(f.read(offset, &mut buf)); | 76 | unwrap!(f.blocking_read(offset, &mut buf)); |
| 77 | info!("Read: {=[u8]:x}", buf); | 77 | info!("Read: {=[u8]:x}", buf); |
| 78 | assert_eq!( | 78 | assert_eq!( |
| 79 | &buf[..], | 79 | &buf[..], |
