Merge branch 'embassy-rs:main' into main
This commit is contained in:
		
						commit
						1d4e1092c4
					
				| @ -12,7 +12,7 @@ target = "thumbv7em-none-eabi" | |||||||
| 
 | 
 | ||||||
| [features] | [features] | ||||||
| stm32wl = ["dep:embassy-stm32"] | stm32wl = ["dep:embassy-stm32"] | ||||||
| time = [] | time = ["embassy-time", "lorawan-device"] | ||||||
| defmt = ["dep:defmt", "lorawan-device/defmt"] | defmt = ["dep:defmt", "lorawan-device/defmt"] | ||||||
| 
 | 
 | ||||||
| [dependencies] | [dependencies] | ||||||
| @ -20,18 +20,11 @@ defmt = ["dep:defmt", "lorawan-device/defmt"] | |||||||
| defmt = { version = "0.3", optional = true } | defmt = { version = "0.3", optional = true } | ||||||
| log = { version = "0.4.14", optional = true } | log = { version = "0.4.14", optional = true } | ||||||
| 
 | 
 | ||||||
| embassy-time = { version = "0.1.2", path = "../embassy-time" } | embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } | ||||||
| embassy-sync = { version = "0.2.0", path = "../embassy-sync" } | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } | ||||||
| embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } | embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } | ||||||
| embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } |  | ||||||
| embedded-hal-async = { version = "=0.2.0-alpha.2" } | embedded-hal-async = { version = "=0.2.0-alpha.2" } | ||||||
| embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common", default-features = false } |  | ||||||
| futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] } |  | ||||||
| embedded-hal = { version = "0.2", features = ["unproven"] } | embedded-hal = { version = "0.2", features = ["unproven"] } | ||||||
| bit_field = { version = "0.10" } |  | ||||||
| 
 | 
 | ||||||
| lora-phy = { version = "1" } | lora-phy = { version = "1" } | ||||||
| lorawan-device = { version = "0.10.0", default-features = false, features = ["async"] } | lorawan-device = { version = "0.10.0", default-features = false, features = ["async"], optional = true } | ||||||
| 
 |  | ||||||
| [patch.crates-io] |  | ||||||
| lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } |  | ||||||
|  | |||||||
| @ -26,7 +26,7 @@ aligned = "0.4.1" | |||||||
| 
 | 
 | ||||||
| bit_field = "0.10.2" | bit_field = "0.10.2" | ||||||
| stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } | stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } | ||||||
| stm32wb-hci = { version = "0.1.3", optional = true } | stm32wb-hci = { version = "0.1.4", optional = true } | ||||||
| futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||||||
| bitflags = { version = "2.3.3", optional = true } | bitflags = { version = "2.3.3", optional = true } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -161,6 +161,18 @@ impl<'d, T: Instance> Can<'d, T> { | |||||||
|             .leave_disabled(); |             .leave_disabled(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Enables the peripheral and synchronizes with the bus.
 | ||||||
|  |     ///
 | ||||||
|  |     /// This will wait for 11 consecutive recessive bits (bus idle state).
 | ||||||
|  |     /// Contrary to enable method from bxcan library, this will not freeze the executor while waiting.
 | ||||||
|  |     pub async fn enable(&mut self) { | ||||||
|  |         while self.borrow_mut().enable_non_blocking().is_err() { | ||||||
|  |             // SCE interrupt is only generated for entering sleep mode, but not leaving.
 | ||||||
|  |             // Yield to allow other tasks to execute while can bus is initializing.
 | ||||||
|  |             embassy_futures::yield_now().await; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Queues the message to be sent but exerts backpressure
 |     /// Queues the message to be sent but exerts backpressure
 | ||||||
|     pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { |     pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { | ||||||
|         poll_fn(|cx| { |         poll_fn(|cx| { | ||||||
|  | |||||||
| @ -38,11 +38,30 @@ impl Channel { | |||||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||||
| /// Trigger sources for CH1
 | /// Trigger sources for CH1
 | ||||||
| pub enum Ch1Trigger { | pub enum Ch1Trigger { | ||||||
|     Tim6, |     #[cfg(dac_v3)] | ||||||
|     Tim3, |     Tim1, | ||||||
|     Tim7, |  | ||||||
|     Tim15, |  | ||||||
|     Tim2, |     Tim2, | ||||||
|  |     #[cfg(not(dac_v3))] | ||||||
|  |     Tim3, | ||||||
|  |     #[cfg(dac_v3)] | ||||||
|  |     Tim4, | ||||||
|  |     #[cfg(dac_v3)] | ||||||
|  |     Tim5, | ||||||
|  |     Tim6, | ||||||
|  |     Tim7, | ||||||
|  |     #[cfg(dac_v3)] | ||||||
|  |     Tim8, | ||||||
|  |     Tim15, | ||||||
|  |     #[cfg(dac_v3)] | ||||||
|  |     Hrtim1Dactrg1, | ||||||
|  |     #[cfg(dac_v3)] | ||||||
|  |     Hrtim1Dactrg2, | ||||||
|  |     #[cfg(dac_v3)] | ||||||
|  |     Lptim1, | ||||||
|  |     #[cfg(dac_v3)] | ||||||
|  |     Lptim2, | ||||||
|  |     #[cfg(dac_v3)] | ||||||
|  |     Lptim3, | ||||||
|     Exti9, |     Exti9, | ||||||
|     Software, |     Software, | ||||||
| } | } | ||||||
| @ -50,14 +69,30 @@ pub enum Ch1Trigger { | |||||||
| impl Ch1Trigger { | impl Ch1Trigger { | ||||||
|     fn tsel(&self) -> dac::vals::Tsel1 { |     fn tsel(&self) -> dac::vals::Tsel1 { | ||||||
|         match self { |         match self { | ||||||
|             Ch1Trigger::Tim6 => dac::vals::Tsel1::TIM6_TRGO, |             #[cfg(dac_v3)] | ||||||
|  |             Ch1Trigger::Tim1 => dac::vals::Tsel1::TIM1_TRGO, | ||||||
|  |             Ch1Trigger::Tim2 => dac::vals::Tsel1::TIM2_TRGO, | ||||||
|             #[cfg(not(dac_v3))] |             #[cfg(not(dac_v3))] | ||||||
|             Ch1Trigger::Tim3 => dac::vals::Tsel1::TIM3_TRGO, |             Ch1Trigger::Tim3 => dac::vals::Tsel1::TIM3_TRGO, | ||||||
|             #[cfg(dac_v3)] |             #[cfg(dac_v3)] | ||||||
|             Ch1Trigger::Tim3 => dac::vals::Tsel1::TIM1_TRGO, |             Ch1Trigger::Tim4 => dac::vals::Tsel1::TIM4_TRGO, | ||||||
|  |             #[cfg(dac_v3)] | ||||||
|  |             Ch1Trigger::Tim5 => dac::vals::Tsel1::TIM5_TRGO, | ||||||
|  |             Ch1Trigger::Tim6 => dac::vals::Tsel1::TIM6_TRGO, | ||||||
|             Ch1Trigger::Tim7 => dac::vals::Tsel1::TIM7_TRGO, |             Ch1Trigger::Tim7 => dac::vals::Tsel1::TIM7_TRGO, | ||||||
|  |             #[cfg(dac_v3)] | ||||||
|  |             Ch1Trigger::Tim8 => dac::vals::Tsel1::TIM8_TRGO, | ||||||
|             Ch1Trigger::Tim15 => dac::vals::Tsel1::TIM15_TRGO, |             Ch1Trigger::Tim15 => dac::vals::Tsel1::TIM15_TRGO, | ||||||
|             Ch1Trigger::Tim2 => dac::vals::Tsel1::TIM2_TRGO, |             #[cfg(dac_v3)] | ||||||
|  |             Ch1Trigger::Hrtim1Dactrg1 => dac::vals::Tsel1::HRTIM1_DACTRG1, | ||||||
|  |             #[cfg(dac_v3)] | ||||||
|  |             Ch1Trigger::Hrtim1Dactrg2 => dac::vals::Tsel1::HRTIM1_DACTRG2, | ||||||
|  |             #[cfg(dac_v3)] | ||||||
|  |             Ch1Trigger::Lptim1 => dac::vals::Tsel1::LPTIM1_OUT, | ||||||
|  |             #[cfg(dac_v3)] | ||||||
|  |             Ch1Trigger::Lptim2 => dac::vals::Tsel1::LPTIM2_OUT, | ||||||
|  |             #[cfg(dac_v3)] | ||||||
|  |             Ch1Trigger::Lptim3 => dac::vals::Tsel1::LPTIM3_OUT, | ||||||
|             Ch1Trigger::Exti9 => dac::vals::Tsel1::EXTI9, |             Ch1Trigger::Exti9 => dac::vals::Tsel1::EXTI9, | ||||||
|             Ch1Trigger::Software => dac::vals::Tsel1::SOFTWARE, |             Ch1Trigger::Software => dac::vals::Tsel1::SOFTWARE, | ||||||
|         } |         } | ||||||
| @ -129,7 +164,7 @@ pub trait DacChannel<T: Instance, Tx> { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Set mode register of the given channel
 |     /// Set mode register of the given channel
 | ||||||
|     #[cfg(dac_v2)] |     #[cfg(any(dac_v2, dac_v3))] | ||||||
|     fn set_channel_mode(&mut self, val: u8) -> Result<(), Error> { |     fn set_channel_mode(&mut self, val: u8) -> Result<(), Error> { | ||||||
|         T::regs().mcr().modify(|reg| { |         T::regs().mcr().modify(|reg| { | ||||||
|             reg.set_mode(Self::CHANNEL.index(), val); |             reg.set_mode(Self::CHANNEL.index(), val); | ||||||
| @ -216,8 +251,9 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> { | |||||||
|     pub fn new( |     pub fn new( | ||||||
|         peri: impl Peripheral<P = T> + 'd, |         peri: impl Peripheral<P = T> + 'd, | ||||||
|         dma: impl Peripheral<P = Tx> + 'd, |         dma: impl Peripheral<P = Tx> + 'd, | ||||||
|         _pin: impl Peripheral<P = impl DacPin<T, 1>> + 'd, |         pin: impl Peripheral<P = impl DacPin<T, 1>> + crate::gpio::sealed::Pin + 'd, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|  |         pin.set_as_analog(); | ||||||
|         into_ref!(peri, dma); |         into_ref!(peri, dma); | ||||||
|         T::enable(); |         T::enable(); | ||||||
|         T::reset(); |         T::reset(); | ||||||
| @ -226,7 +262,7 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> { | |||||||
| 
 | 
 | ||||||
|         // Configure each activated channel. All results can be `unwrap`ed since they
 |         // Configure each activated channel. All results can be `unwrap`ed since they
 | ||||||
|         // will only error if the channel is not configured (i.e. ch1, ch2 are false)
 |         // will only error if the channel is not configured (i.e. ch1, ch2 are false)
 | ||||||
|         #[cfg(dac_v2)] |         #[cfg(any(dac_v2, dac_v3))] | ||||||
|         dac.set_channel_mode(0).unwrap(); |         dac.set_channel_mode(0).unwrap(); | ||||||
|         dac.enable_channel().unwrap(); |         dac.enable_channel().unwrap(); | ||||||
|         dac.set_trigger_enable(true).unwrap(); |         dac.set_trigger_enable(true).unwrap(); | ||||||
| @ -252,7 +288,6 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> { | |||||||
|     /// Note that for performance reasons in circular mode the transfer complete interrupt is disabled.
 |     /// Note that for performance reasons in circular mode the transfer complete interrupt is disabled.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// **Important:** Channel 1 has to be configured for the DAC instance!
 |     /// **Important:** Channel 1 has to be configured for the DAC instance!
 | ||||||
|     #[cfg(all(bdma, not(dma)))] // It currently only works with BDMA-only chips (DMA should theoretically work though)
 |  | ||||||
|     pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error> |     pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error> | ||||||
|     where |     where | ||||||
|         Tx: DmaCh1<T>, |         Tx: DmaCh1<T>, | ||||||
| @ -327,8 +362,9 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> { | |||||||
|     pub fn new( |     pub fn new( | ||||||
|         _peri: impl Peripheral<P = T> + 'd, |         _peri: impl Peripheral<P = T> + 'd, | ||||||
|         dma: impl Peripheral<P = Tx> + 'd, |         dma: impl Peripheral<P = Tx> + 'd, | ||||||
|         _pin: impl Peripheral<P = impl DacPin<T, 2>> + 'd, |         pin: impl Peripheral<P = impl DacPin<T, 2>> + crate::gpio::sealed::Pin + 'd, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|  |         pin.set_as_analog(); | ||||||
|         into_ref!(_peri, dma); |         into_ref!(_peri, dma); | ||||||
|         T::enable(); |         T::enable(); | ||||||
|         T::reset(); |         T::reset(); | ||||||
| @ -340,7 +376,7 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> { | |||||||
| 
 | 
 | ||||||
|         // Configure each activated channel. All results can be `unwrap`ed since they
 |         // Configure each activated channel. All results can be `unwrap`ed since they
 | ||||||
|         // will only error if the channel is not configured (i.e. ch1, ch2 are false)
 |         // will only error if the channel is not configured (i.e. ch1, ch2 are false)
 | ||||||
|         #[cfg(dac_v2)] |         #[cfg(any(dac_v2, dac_v3))] | ||||||
|         dac.set_channel_mode(0).unwrap(); |         dac.set_channel_mode(0).unwrap(); | ||||||
|         dac.enable_channel().unwrap(); |         dac.enable_channel().unwrap(); | ||||||
|         dac.set_trigger_enable(true).unwrap(); |         dac.set_trigger_enable(true).unwrap(); | ||||||
| @ -364,7 +400,6 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> { | |||||||
|     /// Note that for performance reasons in circular mode the transfer complete interrupt is disabled.
 |     /// Note that for performance reasons in circular mode the transfer complete interrupt is disabled.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// **Important:** Channel 2 has to be configured for the DAC instance!
 |     /// **Important:** Channel 2 has to be configured for the DAC instance!
 | ||||||
|     #[cfg(all(bdma, not(dma)))] // It currently only works with BDMA-only chips (DMA should theoretically work though)
 |  | ||||||
|     pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error> |     pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error> | ||||||
|     where |     where | ||||||
|         Tx: DmaCh2<T>, |         Tx: DmaCh2<T>, | ||||||
| @ -442,9 +477,11 @@ impl<'d, T: Instance, TxCh1, TxCh2> Dac<'d, T, TxCh1, TxCh2> { | |||||||
|         peri: impl Peripheral<P = T> + 'd, |         peri: impl Peripheral<P = T> + 'd, | ||||||
|         dma_ch1: impl Peripheral<P = TxCh1> + 'd, |         dma_ch1: impl Peripheral<P = TxCh1> + 'd, | ||||||
|         dma_ch2: impl Peripheral<P = TxCh2> + 'd, |         dma_ch2: impl Peripheral<P = TxCh2> + 'd, | ||||||
|         _pin_ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd, |         pin_ch1: impl Peripheral<P = impl DacPin<T, 1>> + crate::gpio::sealed::Pin + 'd, | ||||||
|         _pin_ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd, |         pin_ch2: impl Peripheral<P = impl DacPin<T, 2>> + crate::gpio::sealed::Pin + 'd, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|  |         pin_ch1.set_as_analog(); | ||||||
|  |         pin_ch2.set_as_analog(); | ||||||
|         into_ref!(peri, dma_ch1, dma_ch2); |         into_ref!(peri, dma_ch1, dma_ch2); | ||||||
|         T::enable(); |         T::enable(); | ||||||
|         T::reset(); |         T::reset(); | ||||||
| @ -461,12 +498,12 @@ impl<'d, T: Instance, TxCh1, TxCh2> Dac<'d, T, TxCh1, TxCh2> { | |||||||
| 
 | 
 | ||||||
|         // Configure each activated channel. All results can be `unwrap`ed since they
 |         // Configure each activated channel. All results can be `unwrap`ed since they
 | ||||||
|         // will only error if the channel is not configured (i.e. ch1, ch2 are false)
 |         // will only error if the channel is not configured (i.e. ch1, ch2 are false)
 | ||||||
|         #[cfg(dac_v2)] |         #[cfg(any(dac_v2, dac_v3))] | ||||||
|         dac_ch1.set_channel_mode(0).unwrap(); |         dac_ch1.set_channel_mode(0).unwrap(); | ||||||
|         dac_ch1.enable_channel().unwrap(); |         dac_ch1.enable_channel().unwrap(); | ||||||
|         dac_ch1.set_trigger_enable(true).unwrap(); |         dac_ch1.set_trigger_enable(true).unwrap(); | ||||||
| 
 | 
 | ||||||
|         #[cfg(dac_v2)] |         #[cfg(any(dac_v2, dac_v3))] | ||||||
|         dac_ch2.set_channel_mode(0).unwrap(); |         dac_ch2.set_channel_mode(0).unwrap(); | ||||||
|         dac_ch2.enable_channel().unwrap(); |         dac_ch2.enable_channel().unwrap(); | ||||||
|         dac_ch2.set_trigger_enable(true).unwrap(); |         dac_ch2.set_trigger_enable(true).unwrap(); | ||||||
|  | |||||||
| @ -466,15 +466,53 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { | |||||||
|         self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); |         self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Read bytes from the ring buffer
 |     /// Read elements from the ring buffer
 | ||||||
|     /// Return a tuple of the length read and the length remaining in the buffer
 |     /// Return a tuple of the length read and the length remaining in the buffer
 | ||||||
|     /// If not all of the bytes were read, then there will be some bytes in the buffer remaining
 |     /// If not all of the elements were read, then there will be some elements in the buffer remaining
 | ||||||
|     /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read
 |     /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
 | ||||||
|     /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
 |     /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
 | ||||||
|     pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { |     pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { | ||||||
|         self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) |         self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Read an exact number of elements from the ringbuffer.
 | ||||||
|  |     ///
 | ||||||
|  |     /// Returns the remaining number of elements available for immediate reading.
 | ||||||
|  |     /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
 | ||||||
|  |     ///
 | ||||||
|  |     /// Async/Wake Behavior:
 | ||||||
|  |     /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
 | ||||||
|  |     /// and when it wraps around. This means that when called with a buffer of length 'M', when this
 | ||||||
|  |     /// ring buffer was created with a buffer of size 'N':
 | ||||||
|  |     /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
 | ||||||
|  |     /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
 | ||||||
|  |     pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> { | ||||||
|  |         use core::future::poll_fn; | ||||||
|  |         use core::sync::atomic::compiler_fence; | ||||||
|  | 
 | ||||||
|  |         let mut read_data = 0; | ||||||
|  |         let buffer_len = buffer.len(); | ||||||
|  | 
 | ||||||
|  |         poll_fn(|cx| { | ||||||
|  |             self.set_waker(cx.waker()); | ||||||
|  | 
 | ||||||
|  |             compiler_fence(Ordering::SeqCst); | ||||||
|  | 
 | ||||||
|  |             match self.read(&mut buffer[read_data..buffer_len]) { | ||||||
|  |                 Ok((len, remaining)) => { | ||||||
|  |                     read_data += len; | ||||||
|  |                     if read_data == buffer_len { | ||||||
|  |                         Poll::Ready(Ok(remaining)) | ||||||
|  |                     } else { | ||||||
|  |                         Poll::Pending | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 Err(e) => Poll::Ready(Err(e)), | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |         .await | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// The capacity of the ringbuffer
 |     /// The capacity of the ringbuffer
 | ||||||
|     pub fn cap(&self) -> usize { |     pub fn cap(&self) -> usize { | ||||||
|         self.ringbuf.cap() |         self.ringbuf.cap() | ||||||
|  | |||||||
| @ -28,6 +28,12 @@ pub struct TransferOptions { | |||||||
|     pub flow_ctrl: FlowControl, |     pub flow_ctrl: FlowControl, | ||||||
|     /// FIFO threshold for DMA FIFO mode. If none, direct mode is used.
 |     /// FIFO threshold for DMA FIFO mode. If none, direct mode is used.
 | ||||||
|     pub fifo_threshold: Option<FifoThreshold>, |     pub fifo_threshold: Option<FifoThreshold>, | ||||||
|  |     /// Enable circular DMA
 | ||||||
|  |     pub circular: bool, | ||||||
|  |     /// Enable half transfer interrupt
 | ||||||
|  |     pub half_transfer_ir: bool, | ||||||
|  |     /// Enable transfer complete interrupt
 | ||||||
|  |     pub complete_transfer_ir: bool, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Default for TransferOptions { | impl Default for TransferOptions { | ||||||
| @ -37,6 +43,9 @@ impl Default for TransferOptions { | |||||||
|             mburst: Burst::Single, |             mburst: Burst::Single, | ||||||
|             flow_ctrl: FlowControl::Dma, |             flow_ctrl: FlowControl::Dma, | ||||||
|             fifo_threshold: None, |             fifo_threshold: None, | ||||||
|  |             circular: false, | ||||||
|  |             half_transfer_ir: false, | ||||||
|  |             complete_transfer_ir: true, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -365,7 +374,13 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||||||
|             }); |             }); | ||||||
|             w.set_pinc(vals::Inc::FIXED); |             w.set_pinc(vals::Inc::FIXED); | ||||||
|             w.set_teie(true); |             w.set_teie(true); | ||||||
|             w.set_tcie(true); |             w.set_tcie(options.complete_transfer_ir); | ||||||
|  |             if options.circular { | ||||||
|  |                 w.set_circ(vals::Circ::ENABLED); | ||||||
|  |                 debug!("Setting circular mode"); | ||||||
|  |             } else { | ||||||
|  |                 w.set_circ(vals::Circ::DISABLED); | ||||||
|  |             } | ||||||
|             #[cfg(dma_v1)] |             #[cfg(dma_v1)] | ||||||
|             w.set_trbuff(true); |             w.set_trbuff(true); | ||||||
| 
 | 
 | ||||||
| @ -646,7 +661,7 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { | |||||||
|         w.set_minc(vals::Inc::INCREMENTED); |         w.set_minc(vals::Inc::INCREMENTED); | ||||||
|         w.set_pinc(vals::Inc::FIXED); |         w.set_pinc(vals::Inc::FIXED); | ||||||
|         w.set_teie(true); |         w.set_teie(true); | ||||||
|         w.set_htie(true); |         w.set_htie(options.half_transfer_ir); | ||||||
|         w.set_tcie(true); |         w.set_tcie(true); | ||||||
|         w.set_circ(vals::Circ::ENABLED); |         w.set_circ(vals::Circ::ENABLED); | ||||||
|         #[cfg(dma_v1)] |         #[cfg(dma_v1)] | ||||||
| @ -696,15 +711,53 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { | |||||||
|         self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); |         self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Read bytes from the ring buffer
 |     /// Read elements from the ring buffer
 | ||||||
|     /// Return a tuple of the length read and the length remaining in the buffer
 |     /// Return a tuple of the length read and the length remaining in the buffer
 | ||||||
|     /// If not all of the bytes were read, then there will be some bytes in the buffer remaining
 |     /// If not all of the elements were read, then there will be some elements in the buffer remaining
 | ||||||
|     /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read
 |     /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
 | ||||||
|     /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
 |     /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
 | ||||||
|     pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { |     pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { | ||||||
|         self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) |         self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Read an exact number of elements from the ringbuffer.
 | ||||||
|  |     ///
 | ||||||
|  |     /// Returns the remaining number of elements available for immediate reading.
 | ||||||
|  |     /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
 | ||||||
|  |     ///
 | ||||||
|  |     /// Async/Wake Behavior:
 | ||||||
|  |     /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
 | ||||||
|  |     /// and when it wraps around. This means that when called with a buffer of length 'M', when this
 | ||||||
|  |     /// ring buffer was created with a buffer of size 'N':
 | ||||||
|  |     /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
 | ||||||
|  |     /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
 | ||||||
|  |     pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> { | ||||||
|  |         use core::future::poll_fn; | ||||||
|  |         use core::sync::atomic::compiler_fence; | ||||||
|  | 
 | ||||||
|  |         let mut read_data = 0; | ||||||
|  |         let buffer_len = buffer.len(); | ||||||
|  | 
 | ||||||
|  |         poll_fn(|cx| { | ||||||
|  |             self.set_waker(cx.waker()); | ||||||
|  | 
 | ||||||
|  |             compiler_fence(Ordering::SeqCst); | ||||||
|  | 
 | ||||||
|  |             match self.read(&mut buffer[read_data..buffer_len]) { | ||||||
|  |                 Ok((len, remaining)) => { | ||||||
|  |                     read_data += len; | ||||||
|  |                     if read_data == buffer_len { | ||||||
|  |                         Poll::Ready(Ok(remaining)) | ||||||
|  |                     } else { | ||||||
|  |                         Poll::Pending | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 Err(e) => Poll::Ready(Err(e)), | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |         .await | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // The capacity of the ringbuffer
 |     // The capacity of the ringbuffer
 | ||||||
|     pub fn cap(&self) -> usize { |     pub fn cap(&self) -> usize { | ||||||
|         self.ringbuf.cap() |         self.ringbuf.cap() | ||||||
|  | |||||||
| @ -72,10 +72,10 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> { | |||||||
|         self.cap() - remaining_transfers |         self.cap() - remaining_transfers | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Read bytes from the ring buffer
 |     /// Read elements from the ring buffer
 | ||||||
|     /// Return a tuple of the length read and the length remaining in the buffer
 |     /// Return a tuple of the length read and the length remaining in the buffer
 | ||||||
|     /// If not all of the bytes were read, then there will be some bytes in the buffer remaining
 |     /// If not all of the elements were read, then there will be some elements in the buffer remaining
 | ||||||
|     /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read
 |     /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
 | ||||||
|     /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
 |     /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
 | ||||||
|     pub fn read(&mut self, mut dma: impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { |     pub fn read(&mut self, mut dma: impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { | ||||||
|         /* |         /* | ||||||
| @ -95,11 +95,11 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> { | |||||||
|         */ |         */ | ||||||
|         let end = self.pos(dma.get_remaining_transfers()); |         let end = self.pos(dma.get_remaining_transfers()); | ||||||
|         if self.start == end && dma.get_complete_count() == 0 { |         if self.start == end && dma.get_complete_count() == 0 { | ||||||
|             // No bytes are available in the buffer
 |             // No elements are available in the buffer
 | ||||||
|             Ok((0, self.cap())) |             Ok((0, self.cap())) | ||||||
|         } else if self.start < end { |         } else if self.start < end { | ||||||
|             // The available, unread portion in the ring buffer DOES NOT wrap
 |             // The available, unread portion in the ring buffer DOES NOT wrap
 | ||||||
|             // Copy out the bytes from the dma buffer
 |             // Copy out the elements from the dma buffer
 | ||||||
|             let len = self.copy_to(buf, self.start..end); |             let len = self.copy_to(buf, self.start..end); | ||||||
| 
 | 
 | ||||||
|             compiler_fence(Ordering::SeqCst); |             compiler_fence(Ordering::SeqCst); | ||||||
| @ -128,7 +128,7 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> { | |||||||
|             // The DMA writer has wrapped since we last read and is currently
 |             // The DMA writer has wrapped since we last read and is currently
 | ||||||
|             // writing (or the next byte added will be) in the beginning of the ring buffer.
 |             // writing (or the next byte added will be) in the beginning of the ring buffer.
 | ||||||
| 
 | 
 | ||||||
|             // The provided read buffer is not large enough to include all bytes from the tail of the dma buffer.
 |             // The provided read buffer is not large enough to include all elements from the tail of the dma buffer.
 | ||||||
| 
 | 
 | ||||||
|             // Copy out from the dma buffer
 |             // Copy out from the dma buffer
 | ||||||
|             let len = self.copy_to(buf, self.start..self.cap()); |             let len = self.copy_to(buf, self.start..self.cap()); | ||||||
| @ -154,8 +154,8 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> { | |||||||
|             // The DMA writer has wrapped since we last read and is currently
 |             // The DMA writer has wrapped since we last read and is currently
 | ||||||
|             // writing (or the next byte added will be) in the beginning of the ring buffer.
 |             // writing (or the next byte added will be) in the beginning of the ring buffer.
 | ||||||
| 
 | 
 | ||||||
|             // The provided read buffer is large enough to include all bytes from the tail of the dma buffer,
 |             // The provided read buffer is large enough to include all elements from the tail of the dma buffer,
 | ||||||
|             // so the next read will not have any unread tail bytes in the ring buffer.
 |             // so the next read will not have any unread tail elements in the ring buffer.
 | ||||||
| 
 | 
 | ||||||
|             // Copy out from the dma buffer
 |             // Copy out from the dma buffer
 | ||||||
|             let tail = self.copy_to(buf, self.start..self.cap()); |             let tail = self.copy_to(buf, self.start..self.cap()); | ||||||
| @ -180,7 +180,7 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> { | |||||||
|     } |     } | ||||||
|     /// Copy from the dma buffer at `data_range` into `buf`
 |     /// Copy from the dma buffer at `data_range` into `buf`
 | ||||||
|     fn copy_to(&mut self, buf: &mut [W], data_range: Range<usize>) -> usize { |     fn copy_to(&mut self, buf: &mut [W], data_range: Range<usize>) -> usize { | ||||||
|         // Limit the number of bytes that can be copied
 |         // Limit the number of elements that can be copied
 | ||||||
|         let length = usize::min(data_range.len(), buf.len()); |         let length = usize::min(data_range.len(), buf.len()); | ||||||
| 
 | 
 | ||||||
|         // Copy from dma buffer into read buffer
 |         // Copy from dma buffer into read buffer
 | ||||||
|  | |||||||
| @ -265,63 +265,9 @@ pub(crate) mod sealed { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn _configure_pwr() { | fn _configure_pwr() { | ||||||
|     // TODO: move this to RCC
 |     // TODO: move the rest of this to rcc
 | ||||||
| 
 |  | ||||||
|     let pwr = crate::pac::PWR; |  | ||||||
|     let rcc = crate::pac::RCC; |     let rcc = crate::pac::RCC; | ||||||
| 
 | 
 | ||||||
|     rcc.cfgr().modify(|w| w.set_stopwuck(true)); |  | ||||||
| 
 |  | ||||||
|     pwr.cr1().modify(|w| w.set_dbp(true)); |  | ||||||
|     pwr.cr1().modify(|w| w.set_dbp(true)); |  | ||||||
| 
 |  | ||||||
|     // configure LSE
 |  | ||||||
|     rcc.bdcr().modify(|w| w.set_lseon(true)); |  | ||||||
| 
 |  | ||||||
|     // select system clock source = PLL
 |  | ||||||
|     // set PLL coefficients
 |  | ||||||
|     // m: 2,
 |  | ||||||
|     // n: 12,
 |  | ||||||
|     // r: 3,
 |  | ||||||
|     // q: 4,
 |  | ||||||
|     // p: 3,
 |  | ||||||
|     let src_bits = 0b11; |  | ||||||
|     let pllp = (3 - 1) & 0b11111; |  | ||||||
|     let pllq = (4 - 1) & 0b111; |  | ||||||
|     let pllr = (3 - 1) & 0b111; |  | ||||||
|     let plln = 12 & 0b1111111; |  | ||||||
|     let pllm = (2 - 1) & 0b111; |  | ||||||
|     rcc.pllcfgr().modify(|w| { |  | ||||||
|         w.set_pllsrc(src_bits); |  | ||||||
|         w.set_pllm(pllm); |  | ||||||
|         w.set_plln(plln); |  | ||||||
|         w.set_pllr(pllr); |  | ||||||
|         w.set_pllp(pllp); |  | ||||||
|         w.set_pllpen(true); |  | ||||||
|         w.set_pllq(pllq); |  | ||||||
|         w.set_pllqen(true); |  | ||||||
|     }); |  | ||||||
|     // enable PLL
 |  | ||||||
|     rcc.cr().modify(|w| w.set_pllon(true)); |  | ||||||
|     rcc.cr().write(|w| w.set_hsion(false)); |  | ||||||
|     // while !rcc.cr().read().pllrdy() {}
 |  | ||||||
| 
 |  | ||||||
|     // configure SYSCLK mux to use PLL clocl
 |  | ||||||
|     rcc.cfgr().modify(|w| w.set_sw(0b11)); |  | ||||||
| 
 |  | ||||||
|     // configure CPU1 & CPU2 dividers
 |  | ||||||
|     rcc.cfgr().modify(|w| w.set_hpre(0)); // not divided
 |  | ||||||
|     rcc.extcfgr().modify(|w| { |  | ||||||
|         w.set_c2hpre(0b1000); // div2
 |  | ||||||
|         w.set_shdhpre(0); // not divided
 |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     // apply APB1 / APB2 values
 |  | ||||||
|     rcc.cfgr().modify(|w| { |  | ||||||
|         w.set_ppre1(0b000); // not divided
 |  | ||||||
|         w.set_ppre2(0b000); // not divided
 |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     // TODO: required
 |     // TODO: required
 | ||||||
|     // set RF wake-up clock = LSE
 |     // set RF wake-up clock = LSE
 | ||||||
|     rcc.csr().modify(|w| w.set_rfwkpsel(0b01)); |     rcc.csr().modify(|w| w.set_rfwkpsel(0b01)); | ||||||
|  | |||||||
| @ -78,6 +78,14 @@ pub struct Clocks { | |||||||
| /// The existence of this value indicates that the clock configuration can no longer be changed
 | /// The existence of this value indicates that the clock configuration can no longer be changed
 | ||||||
| static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit(); | static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit(); | ||||||
| 
 | 
 | ||||||
|  | #[cfg(stm32wb)] | ||||||
|  | /// RCC initialization function
 | ||||||
|  | pub(crate) unsafe fn init(config: Config) { | ||||||
|  |     set_freqs(compute_clocks(&config)); | ||||||
|  | 
 | ||||||
|  |     configure_clocks(&config); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// Sets the clock frequencies
 | /// Sets the clock frequencies
 | ||||||
| ///
 | ///
 | ||||||
| /// Safety: Sets a mutable global.
 | /// Safety: Sets a mutable global.
 | ||||||
|  | |||||||
| @ -1,6 +1,5 @@ | |||||||
| use crate::pac::RCC; | use crate::rcc::Clocks; | ||||||
| use crate::rcc::{set_freqs, Clocks}; | use crate::time::{khz, mhz, Hertz}; | ||||||
| use crate::time::Hertz; |  | ||||||
| 
 | 
 | ||||||
| /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
 | /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
 | ||||||
| /// and with the addition of the init function to configure a system clock.
 | /// and with the addition of the init function to configure a system clock.
 | ||||||
| @ -13,11 +12,94 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000); | |||||||
| /// LSI speed
 | /// LSI speed
 | ||||||
| pub const LSI_FREQ: Hertz = Hertz(32_000); | pub const LSI_FREQ: Hertz = Hertz(32_000); | ||||||
| 
 | 
 | ||||||
| /// System clock mux source
 |  | ||||||
| #[derive(Clone, Copy)] | #[derive(Clone, Copy)] | ||||||
| pub enum ClockSrc { | pub enum HsePrescaler { | ||||||
|     HSE(Hertz), |     NotDivided, | ||||||
|     HSI16, |     Div2, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<HsePrescaler> for bool { | ||||||
|  |     fn from(value: HsePrescaler) -> Self { | ||||||
|  |         match value { | ||||||
|  |             HsePrescaler::NotDivided => false, | ||||||
|  |             HsePrescaler::Div2 => true, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub struct Hse { | ||||||
|  |     pub prediv: HsePrescaler, | ||||||
|  | 
 | ||||||
|  |     pub frequency: Hertz, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// System clock mux source
 | ||||||
|  | #[derive(Clone, Copy, PartialEq)] | ||||||
|  | pub enum Sysclk { | ||||||
|  |     /// MSI selected as sysclk
 | ||||||
|  |     MSI, | ||||||
|  |     /// HSI selected as sysclk
 | ||||||
|  |     HSI, | ||||||
|  |     /// HSE selected as sysclk
 | ||||||
|  |     HSE, | ||||||
|  |     /// PLL selected as sysclk
 | ||||||
|  |     Pll, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<Sysclk> for u8 { | ||||||
|  |     fn from(value: Sysclk) -> Self { | ||||||
|  |         match value { | ||||||
|  |             Sysclk::MSI => 0b00, | ||||||
|  |             Sysclk::HSI => 0b01, | ||||||
|  |             Sysclk::HSE => 0b10, | ||||||
|  |             Sysclk::Pll => 0b11, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Copy, PartialEq)] | ||||||
|  | pub enum PllSource { | ||||||
|  |     Hsi, | ||||||
|  |     Msi, | ||||||
|  |     Hse, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<PllSource> for u8 { | ||||||
|  |     fn from(value: PllSource) -> Self { | ||||||
|  |         match value { | ||||||
|  |             PllSource::Msi => 0b01, | ||||||
|  |             PllSource::Hsi => 0b10, | ||||||
|  |             PllSource::Hse => 0b11, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub enum Pll48Source { | ||||||
|  |     PllSai, | ||||||
|  |     Pll, | ||||||
|  |     Msi, | ||||||
|  |     Hsi48, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub struct PllMux { | ||||||
|  |     /// Source clock selection.
 | ||||||
|  |     pub source: PllSource, | ||||||
|  | 
 | ||||||
|  |     /// PLL pre-divider (DIVM). Must be between 1 and 63.
 | ||||||
|  |     pub prediv: u8, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub struct Pll { | ||||||
|  |     /// PLL multiplication factor. Must be between 4 and 512.
 | ||||||
|  |     pub mul: u16, | ||||||
|  | 
 | ||||||
|  |     /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128.
 | ||||||
|  |     /// On PLL1, it must be even (in particular, it cannot be 1.)
 | ||||||
|  |     pub divp: Option<u16>, | ||||||
|  |     /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128.
 | ||||||
|  |     pub divq: Option<u16>, | ||||||
|  |     /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128.
 | ||||||
|  |     pub divr: Option<u16>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// AHB prescaler
 | /// AHB prescaler
 | ||||||
| @ -84,86 +166,250 @@ impl Into<u8> for AHBPrescaler { | |||||||
| 
 | 
 | ||||||
| /// Clocks configutation
 | /// Clocks configutation
 | ||||||
| pub struct Config { | pub struct Config { | ||||||
|     pub mux: ClockSrc, |     pub hse: Option<Hse>, | ||||||
|     pub ahb_pre: AHBPrescaler, |     pub lse: Option<Hertz>, | ||||||
|  |     pub sys: Sysclk, | ||||||
|  |     pub mux: Option<PllMux>, | ||||||
|  |     pub pll48: Option<Pll48Source>, | ||||||
|  | 
 | ||||||
|  |     pub pll: Option<Pll>, | ||||||
|  |     pub pllsai: Option<Pll>, | ||||||
|  | 
 | ||||||
|  |     pub ahb1_pre: AHBPrescaler, | ||||||
|  |     pub ahb2_pre: AHBPrescaler, | ||||||
|  |     pub ahb3_pre: AHBPrescaler, | ||||||
|     pub apb1_pre: APBPrescaler, |     pub apb1_pre: APBPrescaler, | ||||||
|     pub apb2_pre: APBPrescaler, |     pub apb2_pre: APBPrescaler, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub const WPAN_DEFAULT: Config = Config { | ||||||
|  |     hse: Some(Hse { | ||||||
|  |         frequency: mhz(32), | ||||||
|  |         prediv: HsePrescaler::NotDivided, | ||||||
|  |     }), | ||||||
|  |     lse: Some(khz(32)), | ||||||
|  |     sys: Sysclk::Pll, | ||||||
|  |     mux: Some(PllMux { | ||||||
|  |         source: PllSource::Hse, | ||||||
|  |         prediv: 2, | ||||||
|  |     }), | ||||||
|  |     pll48: None, | ||||||
|  | 
 | ||||||
|  |     pll: Some(Pll { | ||||||
|  |         mul: 12, | ||||||
|  |         divp: Some(3), | ||||||
|  |         divq: Some(4), | ||||||
|  |         divr: Some(3), | ||||||
|  |     }), | ||||||
|  |     pllsai: None, | ||||||
|  | 
 | ||||||
|  |     ahb1_pre: AHBPrescaler::NotDivided, | ||||||
|  |     ahb2_pre: AHBPrescaler::Div2, | ||||||
|  |     ahb3_pre: AHBPrescaler::NotDivided, | ||||||
|  |     apb1_pre: APBPrescaler::NotDivided, | ||||||
|  |     apb2_pre: APBPrescaler::NotDivided, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| impl Default for Config { | impl Default for Config { | ||||||
|     #[inline] |     #[inline] | ||||||
|     fn default() -> Config { |     fn default() -> Config { | ||||||
|         Config { |         Config { | ||||||
|             mux: ClockSrc::HSI16, |             hse: None, | ||||||
|             ahb_pre: AHBPrescaler::NotDivided, |             lse: None, | ||||||
|  |             sys: Sysclk::HSI, | ||||||
|  |             mux: None, | ||||||
|  |             pll48: None, | ||||||
|  |             pll: None, | ||||||
|  |             pllsai: None, | ||||||
|  | 
 | ||||||
|  |             ahb1_pre: AHBPrescaler::NotDivided, | ||||||
|  |             ahb2_pre: AHBPrescaler::NotDivided, | ||||||
|  |             ahb3_pre: AHBPrescaler::NotDivided, | ||||||
|             apb1_pre: APBPrescaler::NotDivided, |             apb1_pre: APBPrescaler::NotDivided, | ||||||
|             apb2_pre: APBPrescaler::NotDivided, |             apb2_pre: APBPrescaler::NotDivided, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub(crate) unsafe fn init(config: Config) { | pub(crate) fn compute_clocks(config: &Config) -> Clocks { | ||||||
|     let (sys_clk, sw) = match config.mux { |     let hse_clk = config.hse.as_ref().map(|hse| match hse.prediv { | ||||||
|         ClockSrc::HSI16 => { |         HsePrescaler::NotDivided => hse.frequency, | ||||||
|             // Enable HSI16
 |         HsePrescaler::Div2 => hse.frequency / 2u32, | ||||||
|             RCC.cr().write(|w| w.set_hsion(true)); |  | ||||||
|             while !RCC.cr().read().hsirdy() {} |  | ||||||
| 
 |  | ||||||
|             (HSI_FREQ.0, 0x01) |  | ||||||
|         } |  | ||||||
|         ClockSrc::HSE(freq) => { |  | ||||||
|             // Enable HSE
 |  | ||||||
|             RCC.cr().write(|w| w.set_hseon(true)); |  | ||||||
|             while !RCC.cr().read().hserdy() {} |  | ||||||
| 
 |  | ||||||
|             (freq.0, 0x02) |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     RCC.cfgr().modify(|w| { |  | ||||||
|         w.set_sw(sw.into()); |  | ||||||
|         w.set_hpre(config.ahb_pre.into()); |  | ||||||
|         w.set_ppre1(config.apb1_pre.into()); |  | ||||||
|         w.set_ppre2(config.apb2_pre.into()); |  | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     let ahb_freq: u32 = match config.ahb_pre { |     let mux_clk = config.mux.as_ref().map(|pll_mux| { | ||||||
|  |         (match pll_mux.source { | ||||||
|  |             PllSource::Hse => hse_clk.unwrap(), | ||||||
|  |             PllSource::Hsi => HSI_FREQ, | ||||||
|  |             _ => unreachable!(), | ||||||
|  |         } / pll_mux.prediv) | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     let (pll_r, _pll_q, _pll_p) = match &config.pll { | ||||||
|  |         Some(pll) => { | ||||||
|  |             let pll_vco = mux_clk.unwrap() * pll.mul as u32; | ||||||
|  | 
 | ||||||
|  |             ( | ||||||
|  |                 pll.divr.map(|divr| pll_vco / divr), | ||||||
|  |                 pll.divq.map(|divq| pll_vco / divq), | ||||||
|  |                 pll.divp.map(|divp| pll_vco / divp), | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  |         None => (None, None, None), | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     let sys_clk = match config.sys { | ||||||
|  |         Sysclk::HSE => hse_clk.unwrap(), | ||||||
|  |         Sysclk::HSI => HSI_FREQ, | ||||||
|  |         Sysclk::Pll => pll_r.unwrap(), | ||||||
|  |         _ => unreachable!(), | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     let ahb1_clk = match config.ahb1_pre { | ||||||
|         AHBPrescaler::NotDivided => sys_clk, |         AHBPrescaler::NotDivided => sys_clk, | ||||||
|         pre => { |         pre => { | ||||||
|             let pre: u8 = pre.into(); |             let pre: u8 = pre.into(); | ||||||
|             let pre = 1 << (pre as u32 - 7); |             let pre = 1u32 << (pre as u32 - 7); | ||||||
|             sys_clk / pre |             sys_clk / pre | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { |     let ahb2_clk = match config.ahb2_pre { | ||||||
|         APBPrescaler::NotDivided => (ahb_freq, ahb_freq), |         AHBPrescaler::NotDivided => sys_clk, | ||||||
|         pre => { |         pre => { | ||||||
|             let pre: u8 = pre.into(); |             let pre: u8 = pre.into(); | ||||||
|             let pre: u8 = 1 << (pre - 3); |             let pre = 1u32 << (pre as u32 - 7); | ||||||
|             let freq = ahb_freq / pre as u32; |             sys_clk / pre | ||||||
|             (freq, freq * 2) |  | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { |     let ahb3_clk = match config.ahb3_pre { | ||||||
|         APBPrescaler::NotDivided => (ahb_freq, ahb_freq), |         AHBPrescaler::NotDivided => sys_clk, | ||||||
|         pre => { |         pre => { | ||||||
|             let pre: u8 = pre.into(); |             let pre: u8 = pre.into(); | ||||||
|             let pre: u8 = 1 << (pre - 3); |             let pre = 1u32 << (pre as u32 - 7); | ||||||
|             let freq = ahb_freq / pre as u32; |             sys_clk / pre | ||||||
|             (freq, freq * 2) |  | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     set_freqs(Clocks { |     let (apb1_clk, apb1_tim_clk) = match config.apb1_pre { | ||||||
|         sys: Hertz(sys_clk), |         APBPrescaler::NotDivided => (ahb1_clk, ahb1_clk), | ||||||
|         ahb1: Hertz(ahb_freq), |         pre => { | ||||||
|         ahb2: Hertz(ahb_freq), |             let pre: u8 = pre.into(); | ||||||
|         ahb3: Hertz(ahb_freq), |             let pre: u8 = 1 << (pre - 3); | ||||||
|         apb1: Hertz(apb1_freq), |             let freq = ahb1_clk / pre as u32; | ||||||
|         apb2: Hertz(apb2_freq), |             (freq, freq * 2u32) | ||||||
|         apb1_tim: Hertz(apb1_tim_freq), |         } | ||||||
|         apb2_tim: Hertz(apb2_tim_freq), |     }; | ||||||
|  | 
 | ||||||
|  |     let (apb2_clk, apb2_tim_clk) = match config.apb2_pre { | ||||||
|  |         APBPrescaler::NotDivided => (ahb1_clk, ahb1_clk), | ||||||
|  |         pre => { | ||||||
|  |             let pre: u8 = pre.into(); | ||||||
|  |             let pre: u8 = 1 << (pre - 3); | ||||||
|  |             let freq = ahb1_clk / pre as u32; | ||||||
|  |             (freq, freq * 2u32) | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     Clocks { | ||||||
|  |         sys: sys_clk, | ||||||
|  |         ahb1: ahb1_clk, | ||||||
|  |         ahb2: ahb2_clk, | ||||||
|  |         ahb3: ahb3_clk, | ||||||
|  |         apb1: apb1_clk, | ||||||
|  |         apb2: apb2_clk, | ||||||
|  |         apb1_tim: apb1_tim_clk, | ||||||
|  |         apb2_tim: apb2_tim_clk, | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub(crate) fn configure_clocks(config: &Config) { | ||||||
|  |     let pwr = crate::pac::PWR; | ||||||
|  |     let rcc = crate::pac::RCC; | ||||||
|  | 
 | ||||||
|  |     let needs_hsi = if let Some(pll_mux) = &config.mux { | ||||||
|  |         pll_mux.source == PllSource::Hsi | ||||||
|  |     } else { | ||||||
|  |         false | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     if needs_hsi || config.sys == Sysclk::HSI { | ||||||
|  |         rcc.cr().modify(|w| { | ||||||
|  |             w.set_hsion(true); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         while !rcc.cr().read().hsirdy() {} | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     match &config.lse { | ||||||
|  |         Some(_) => { | ||||||
|  |             rcc.cfgr().modify(|w| w.set_stopwuck(true)); | ||||||
|  | 
 | ||||||
|  |             pwr.cr1().modify(|w| w.set_dbp(true)); | ||||||
|  |             pwr.cr1().modify(|w| w.set_dbp(true)); | ||||||
|  | 
 | ||||||
|  |             rcc.bdcr().modify(|w| w.set_lseon(true)); | ||||||
|  |         } | ||||||
|  |         _ => {} | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     match &config.hse { | ||||||
|  |         Some(hse) => { | ||||||
|  |             rcc.cr().modify(|w| { | ||||||
|  |                 w.set_hsepre(hse.prediv.into()); | ||||||
|  |                 w.set_hseon(true); | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             while !rcc.cr().read().hserdy() {} | ||||||
|  |         } | ||||||
|  |         _ => {} | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     match &config.mux { | ||||||
|  |         Some(pll_mux) => { | ||||||
|  |             rcc.pllcfgr().modify(|w| { | ||||||
|  |                 w.set_pllm(pll_mux.prediv); | ||||||
|  |                 w.set_pllsrc(pll_mux.source.into()); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |         _ => {} | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     match &config.pll { | ||||||
|  |         Some(pll) => { | ||||||
|  |             rcc.pllcfgr().modify(|w| { | ||||||
|  |                 w.set_plln(pll.mul as u8); | ||||||
|  |                 pll.divp.map(|divp| { | ||||||
|  |                     w.set_pllpen(true); | ||||||
|  |                     w.set_pllp((divp - 1) as u8) | ||||||
|  |                 }); | ||||||
|  |                 pll.divq.map(|divq| { | ||||||
|  |                     w.set_pllqen(true); | ||||||
|  |                     w.set_pllq((divq - 1) as u8) | ||||||
|  |                 }); | ||||||
|  |                 pll.divr.map(|divr| { | ||||||
|  |                     // w.set_pllren(true);
 | ||||||
|  |                     w.set_pllr((divr - 1) as u8); | ||||||
|  |                 }); | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             rcc.cr().modify(|w| w.set_pllon(true)); | ||||||
|  | 
 | ||||||
|  |             while !rcc.cr().read().pllrdy() {} | ||||||
|  |         } | ||||||
|  |         _ => {} | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     rcc.cfgr().modify(|w| { | ||||||
|  |         w.set_sw(config.sys.into()); | ||||||
|  |         w.set_hpre(config.ahb1_pre.into()); | ||||||
|  |         w.set_ppre1(config.apb1_pre.into()); | ||||||
|  |         w.set_ppre2(config.apb2_pre.into()); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     rcc.extcfgr().modify(|w| { | ||||||
|  |         w.set_c2hpre(config.ahb2_pre.into()); | ||||||
|  |         w.set_shdhpre(config.ahb3_pre.into()); | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  | |||||||
| @ -225,6 +225,9 @@ const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOp | |||||||
|     mburst: crate::dma::Burst::Incr4, |     mburst: crate::dma::Burst::Incr4, | ||||||
|     flow_ctrl: crate::dma::FlowControl::Peripheral, |     flow_ctrl: crate::dma::FlowControl::Peripheral, | ||||||
|     fifo_threshold: Some(crate::dma::FifoThreshold::Full), |     fifo_threshold: Some(crate::dma::FifoThreshold::Full), | ||||||
|  |     circular: false, | ||||||
|  |     half_transfer_ir: false, | ||||||
|  |     complete_transfer_ir: true, | ||||||
| }; | }; | ||||||
| #[cfg(all(sdmmc_v1, not(dma)))] | #[cfg(all(sdmmc_v1, not(dma)))] | ||||||
| const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions { | const DMA_TRANSFER_OPTIONS: crate::dma::TransferOptions = crate::dma::TransferOptions { | ||||||
|  | |||||||
| @ -34,3 +34,6 @@ log = { version = "0.4.17", optional = true } | |||||||
| [[bin]] | [[bin]] | ||||||
| name = "rtos_trace" | name = "rtos_trace" | ||||||
| required-features = ["nightly"] | required-features = ["nightly"] | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -19,3 +19,6 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing | |||||||
| cortex-m-rt = "0.7.0" | cortex-m-rt = "0.7.0" | ||||||
| panic-probe = { version = "0.3", features = ["print-defmt"] } | panic-probe = { version = "0.3", features = ["print-defmt"] } | ||||||
| futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -57,5 +57,5 @@ embedded-hal-async = { version = "0.2.0-alpha.2", optional = true } | |||||||
| num-integer = { version = "0.1.45", default-features = false } | num-integer = { version = "0.1.45", default-features = false } | ||||||
| microfft = "0.5.0" | microfft = "0.5.0" | ||||||
| 
 | 
 | ||||||
| [patch.crates-io] | [profile.release] | ||||||
| lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } | debug = 2 | ||||||
|  | |||||||
| @ -53,3 +53,6 @@ rand = { version = "0.8.4", default-features = false } | |||||||
| embedded-storage = "0.3.0" | embedded-storage = "0.3.0" | ||||||
| usbd-hid = "0.6.0" | usbd-hid = "0.6.0" | ||||||
| serde = { version = "1.0.136", default-features = false } | serde = { version = "1.0.136", default-features = false } | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -54,7 +54,4 @@ pio = "0.2.1" | |||||||
| rand = { version = "0.8.5", default-features = false } | rand = { version = "0.8.5", default-features = false } | ||||||
| 
 | 
 | ||||||
| [profile.release] | [profile.release] | ||||||
| debug = true | debug = 2 | ||||||
| 
 |  | ||||||
| [patch.crates-io] |  | ||||||
| lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } |  | ||||||
|  | |||||||
| @ -23,3 +23,6 @@ clap = { version = "3.0.0-beta.5", features = ["derive"] } | |||||||
| rand_core = { version = "0.6.3", features = ["std"] } | rand_core = { version = "0.6.3", features = ["std"] } | ||||||
| heapless = { version = "0.7.5", default-features = false } | heapless = { version = "0.7.5", default-features = false } | ||||||
| static_cell = { version = "1.1", features = ["nightly"]} | static_cell = { version = "1.1", features = ["nightly"]} | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -20,3 +20,6 @@ embedded-hal = "0.2.6" | |||||||
| panic-probe = { version = "0.3", features = ["print-defmt"] } | panic-probe = { version = "0.3", features = ["print-defmt"] } | ||||||
| futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||||||
| heapless = { version = "0.7.5", default-features = false } | heapless = { version = "0.7.5", default-features = false } | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -18,3 +18,6 @@ embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["de | |||||||
| embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | ||||||
| embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | ||||||
| static_cell = { version = "1.1", features = ["nightly"]} | static_cell = { version = "1.1", features = ["nightly"]} | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -26,3 +26,6 @@ nb = "1.0.0" | |||||||
| 
 | 
 | ||||||
| [profile.dev] | [profile.dev] | ||||||
| opt-level = "s" | opt-level = "s" | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -21,3 +21,6 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } | |||||||
| futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||||||
| heapless = { version = "0.7.5", default-features = false } | heapless = { version = "0.7.5", default-features = false } | ||||||
| nb = "1.0.0" | nb = "1.0.0" | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -25,3 +25,6 @@ heapless = { version = "0.7.5", default-features = false } | |||||||
| nb = "1.0.0" | nb = "1.0.0" | ||||||
| embedded-storage = "0.3.0" | embedded-storage = "0.3.0" | ||||||
| static_cell = { version = "1.1", features = ["nightly"]} | static_cell = { version = "1.1", features = ["nightly"]} | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" | |||||||
| # Change stm32f429zi to your chip name, if necessary. | # Change stm32f429zi to your chip name, if necessary. | ||||||
| embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "embedded-sdmmc", "chrono"]  } | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "embedded-sdmmc", "chrono"]  } | ||||||
| embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | ||||||
| embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers", "arch-cortex-m", "executor-thread", "executor-interrupt"] } | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | ||||||
| embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } | ||||||
| embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | ||||||
| embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } | ||||||
|  | |||||||
| @ -40,10 +40,13 @@ async fn main(_spawner: Spawner) { | |||||||
| 
 | 
 | ||||||
|     can.as_mut() |     can.as_mut() | ||||||
|         .modify_config() |         .modify_config() | ||||||
|         .set_bit_timing(0x001c0003) // http://www.bittiming.can-wiki.info/
 |  | ||||||
|         .set_loopback(true) // Receive own frames
 |         .set_loopback(true) // Receive own frames
 | ||||||
|         .set_silent(true) |         .set_silent(true) | ||||||
|         .enable(); |         .leave_disabled(); | ||||||
|  | 
 | ||||||
|  |     can.set_bitrate(1_000_000); | ||||||
|  | 
 | ||||||
|  |     can.enable().await; | ||||||
| 
 | 
 | ||||||
|     let mut i: u8 = 0; |     let mut i: u8 = 0; | ||||||
|     loop { |     loop { | ||||||
|  | |||||||
| @ -14,11 +14,11 @@ async fn main(_spawner: Spawner) -> ! { | |||||||
|     info!("Hello World, dude!"); |     info!("Hello World, dude!"); | ||||||
| 
 | 
 | ||||||
|     let mut dac = DacCh1::new(p.DAC, NoDma, p.PA4); |     let mut dac = DacCh1::new(p.DAC, NoDma, p.PA4); | ||||||
|  |     unwrap!(dac.set_trigger_enable(false)); | ||||||
| 
 | 
 | ||||||
|     loop { |     loop { | ||||||
|         for v in 0..=255 { |         for v in 0..=255 { | ||||||
|             unwrap!(dac.set(Value::Bit8(to_sine_wave(v)))); |             unwrap!(dac.set(Value::Bit8(to_sine_wave(v)))); | ||||||
|             dac.trigger(); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -28,3 +28,6 @@ rand_core = "0.6.3" | |||||||
| critical-section = "1.1" | critical-section = "1.1" | ||||||
| embedded-storage = "0.3.0" | embedded-storage = "0.3.0" | ||||||
| static_cell = { version = "1.1", features = ["nightly"]} | static_cell = { version = "1.1", features = ["nightly"]} | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -20,3 +20,6 @@ embedded-hal = "0.2.6" | |||||||
| panic-probe = { version = "0.3", features = ["print-defmt"] } | panic-probe = { version = "0.3", features = ["print-defmt"] } | ||||||
| futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||||||
| heapless = { version = "0.7.5", default-features = false } | heapless = { version = "0.7.5", default-features = false } | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -22,3 +22,6 @@ embedded-hal = "0.2.6" | |||||||
| panic-probe = { version = "0.3", features = ["print-defmt"] } | panic-probe = { version = "0.3", features = ["print-defmt"] } | ||||||
| futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||||||
| heapless = { version = "0.7.5", default-features = false } | heapless = { version = "0.7.5", default-features = false } | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -21,11 +21,11 @@ fn main() -> ! { | |||||||
|     let p = embassy_stm32::init(config); |     let p = embassy_stm32::init(config); | ||||||
| 
 | 
 | ||||||
|     let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); |     let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); | ||||||
|  |     unwrap!(dac.set_trigger_enable(false)); | ||||||
| 
 | 
 | ||||||
|     loop { |     loop { | ||||||
|         for v in 0..=255 { |         for v in 0..=255 { | ||||||
|             unwrap!(dac.set(Value::Bit8(to_sine_wave(v)))); |             unwrap!(dac.set(Value::Bit8(to_sine_wave(v)))); | ||||||
|             dac.trigger(); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -34,5 +34,5 @@ heapless = { version = "0.7.5", default-features = false } | |||||||
| embedded-hal = "0.2.6" | embedded-hal = "0.2.6" | ||||||
| static_cell = "1.1" | static_cell = "1.1" | ||||||
| 
 | 
 | ||||||
| [patch.crates-io] | [profile.release] | ||||||
| lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } | debug = 2 | ||||||
|  | |||||||
| @ -20,3 +20,6 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } | |||||||
| futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||||||
| heapless = { version = "0.7.5", default-features = false } | heapless = { version = "0.7.5", default-features = false } | ||||||
| embedded-storage = "0.3.0" | embedded-storage = "0.3.0" | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -27,3 +27,6 @@ heapless = { version = "0.7.5", default-features = false } | |||||||
| chrono = { version = "^0.4", default-features = false } | chrono = { version = "^0.4", default-features = false } | ||||||
| 
 | 
 | ||||||
| micromath = "2.0.0" | micromath = "2.0.0" | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -13,11 +13,11 @@ fn main() -> ! { | |||||||
|     info!("Hello World!"); |     info!("Hello World!"); | ||||||
| 
 | 
 | ||||||
|     let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); |     let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); | ||||||
|  |     unwrap!(dac.set_trigger_enable(false)); | ||||||
| 
 | 
 | ||||||
|     loop { |     loop { | ||||||
|         for v in 0..=255 { |         for v in 0..=255 { | ||||||
|             unwrap!(dac.set(Value::Bit8(to_sine_wave(v)))); |             unwrap!(dac.set(Value::Bit8(to_sine_wave(v)))); | ||||||
|             dac.trigger(); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -27,3 +27,6 @@ heapless = { version = "0.7.5", default-features = false } | |||||||
| rand_core = { version = "0.6.3", default-features = false } | rand_core = { version = "0.6.3", default-features = false } | ||||||
| embedded-io = { version = "0.4.0", features = ["async"] } | embedded-io = { version = "0.4.0", features = ["async"] } | ||||||
| static_cell = { version = "1.1", features = ["nightly"]} | static_cell = { version = "1.1", features = ["nightly"]} | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -23,3 +23,6 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa | |||||||
| heapless = { version = "0.7.5", default-features = false } | heapless = { version = "0.7.5", default-features = false } | ||||||
| 
 | 
 | ||||||
| micromath = "2.0.0" | micromath = "2.0.0" | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -52,3 +52,6 @@ required-features = ["ble"] | |||||||
| [[bin]]  | [[bin]]  | ||||||
| name = "gatt_server" | name = "gatt_server" | ||||||
| required-features = ["ble"] | required-features = ["ble"] | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -28,5 +28,5 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa | |||||||
| heapless = { version = "0.7.5", default-features = false } | heapless = { version = "0.7.5", default-features = false } | ||||||
| chrono = { version = "^0.4", default-features = false } | chrono = { version = "^0.4", default-features = false } | ||||||
| 
 | 
 | ||||||
| [patch.crates-io] | [profile.release] | ||||||
| lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } | debug = 2 | ||||||
|  | |||||||
| @ -17,3 +17,6 @@ wasm-bindgen = "0.2" | |||||||
| web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Node", "Window" ] } | web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Node", "Window" ] } | ||||||
| log = "0.4.11" | log = "0.4.11" | ||||||
| critical-section = { version = "1.1", features = ["std"] } | critical-section = { version = "1.1", features = ["std"] } | ||||||
|  | 
 | ||||||
|  | [profile.release] | ||||||
|  | debug = 2 | ||||||
|  | |||||||
| @ -12,6 +12,7 @@ use common::*; | |||||||
| use embassy_executor::Spawner; | use embassy_executor::Spawner; | ||||||
| use embassy_stm32::bind_interrupts; | use embassy_stm32::bind_interrupts; | ||||||
| use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | ||||||
|  | use embassy_stm32::rcc::WPAN_DEFAULT; | ||||||
| use embassy_stm32_wpan::hci::host::uart::UartHci; | use embassy_stm32_wpan::hci::host::uart::UartHci; | ||||||
| use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; | use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; | ||||||
| use embassy_stm32_wpan::hci::types::AdvertisingType; | use embassy_stm32_wpan::hci::types::AdvertisingType; | ||||||
| @ -40,7 +41,10 @@ async fn run_mm_queue(memory_manager: mm::MemoryManager) { | |||||||
| 
 | 
 | ||||||
| #[embassy_executor::main] | #[embassy_executor::main] | ||||||
| async fn main(spawner: Spawner) { | async fn main(spawner: Spawner) { | ||||||
|     let p = embassy_stm32::init(config()); |     let mut config = config(); | ||||||
|  |     config.rcc = WPAN_DEFAULT; | ||||||
|  | 
 | ||||||
|  |     let p = embassy_stm32::init(config); | ||||||
|     info!("Hello World!"); |     info!("Hello World!"); | ||||||
| 
 | 
 | ||||||
|     let config = Config::default(); |     let config = Config::default(); | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ use common::*; | |||||||
| use embassy_executor::Spawner; | use embassy_executor::Spawner; | ||||||
| use embassy_stm32::bind_interrupts; | use embassy_stm32::bind_interrupts; | ||||||
| use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | ||||||
|  | use embassy_stm32::rcc::WPAN_DEFAULT; | ||||||
| use embassy_stm32_wpan::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest}; | use embassy_stm32_wpan::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest}; | ||||||
| use embassy_stm32_wpan::mac::event::MacEvent; | use embassy_stm32_wpan::mac::event::MacEvent; | ||||||
| use embassy_stm32_wpan::mac::typedefs::{ | use embassy_stm32_wpan::mac::typedefs::{ | ||||||
| @ -31,7 +32,10 @@ async fn run_mm_queue(memory_manager: mm::MemoryManager) { | |||||||
| 
 | 
 | ||||||
| #[embassy_executor::main] | #[embassy_executor::main] | ||||||
| async fn main(spawner: Spawner) { | async fn main(spawner: Spawner) { | ||||||
|     let p = embassy_stm32::init(config()); |     let mut config = config(); | ||||||
|  |     config.rcc = WPAN_DEFAULT; | ||||||
|  | 
 | ||||||
|  |     let p = embassy_stm32::init(config); | ||||||
|     info!("Hello World!"); |     info!("Hello World!"); | ||||||
| 
 | 
 | ||||||
|     let config = Config::default(); |     let config = Config::default(); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user