diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-05-06 04:01:54 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-05-06 04:01:54 +0200 |
| commit | 386e4bf0de6369a3338f56877a779e1e05b4dcc2 (patch) | |
| tree | 4be33adc9cc29686fb867e33a40eda8521167d47 | |
| parent | f5f98cdeab8e457911fe369e244c60855c951f43 (diff) | |
Remove unused files
| -rw-r--r-- | embassy-stm32/src/can.rs | 120 | ||||
| -rw-r--r-- | embassy-stm32/src/f4/mod.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/f4/serial.rs | 357 | ||||
| -rw-r--r-- | embassy-stm32/src/f4/spi.rs | 475 | ||||
| -rw-r--r-- | embassy-stm32/src/interrupt.rs | 59 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc.rs | 504 |
6 files changed, 0 insertions, 1517 deletions
diff --git a/embassy-stm32/src/can.rs b/embassy-stm32/src/can.rs deleted file mode 100644 index f97e900ea..000000000 --- a/embassy-stm32/src/can.rs +++ /dev/null | |||
| @@ -1,120 +0,0 @@ | |||
| 1 | //! Async low power Serial. | ||
| 2 | //! | ||
| 3 | //! The peripheral is autmatically enabled and disabled as required to save power. | ||
| 4 | //! Lowest power consumption can only be guaranteed if the send receive futures | ||
| 5 | //! are dropped correctly (e.g. not using `mem::forget()`). | ||
| 6 | |||
| 7 | use bxcan; | ||
| 8 | use bxcan::Interrupts; | ||
| 9 | use core::future::Future; | ||
| 10 | use embassy::interrupt::Interrupt; | ||
| 11 | use embassy::util::InterruptFuture; | ||
| 12 | use nb; | ||
| 13 | use nb::block; | ||
| 14 | |||
| 15 | use crate::interrupt; | ||
| 16 | |||
| 17 | /// Interface to the Serial peripheral | ||
| 18 | pub struct Can<T: Instance> { | ||
| 19 | can: bxcan::Can<T>, | ||
| 20 | tx_int: T::TInterrupt, | ||
| 21 | rx_int: T::RInterrupt, | ||
| 22 | } | ||
| 23 | |||
| 24 | impl<T: Instance> Can<T> { | ||
| 25 | pub fn new(mut can: bxcan::Can<T>, tx_int: T::TInterrupt, rx_int: T::RInterrupt) -> Self { | ||
| 26 | // Sync to the bus and start normal operation. | ||
| 27 | can.enable_interrupts( | ||
| 28 | Interrupts::TRANSMIT_MAILBOX_EMPTY | Interrupts::FIFO0_MESSAGE_PENDING, | ||
| 29 | ); | ||
| 30 | block!(can.enable()).unwrap(); | ||
| 31 | |||
| 32 | Can { | ||
| 33 | can: can, | ||
| 34 | tx_int: tx_int, | ||
| 35 | rx_int: rx_int, | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | /// Sends can frame. | ||
| 40 | /// | ||
| 41 | /// This method async-blocks until the frame is transmitted. | ||
| 42 | pub fn transmit<'a>(&'a mut self, frame: &'a bxcan::Frame) -> impl Future<Output = ()> + 'a { | ||
| 43 | async move { | ||
| 44 | let fut = InterruptFuture::new(&mut self.tx_int); | ||
| 45 | // Infallible | ||
| 46 | self.can.transmit(frame).unwrap(); | ||
| 47 | |||
| 48 | fut.await; | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | /// Receive can frame. | ||
| 53 | /// | ||
| 54 | /// This method async-blocks until the frame is received. | ||
| 55 | pub fn receive<'a>(&'a mut self) -> impl Future<Output = bxcan::Frame> + 'a { | ||
| 56 | async move { | ||
| 57 | let mut frame: Option<bxcan::Frame>; | ||
| 58 | |||
| 59 | loop { | ||
| 60 | let fut = InterruptFuture::new(&mut self.rx_int); | ||
| 61 | frame = match self.can.receive() { | ||
| 62 | Ok(frame) => Some(frame), | ||
| 63 | Err(nb::Error::WouldBlock) => None, | ||
| 64 | Err(nb::Error::Other(_)) => None, // Ignore overrun errors. | ||
| 65 | }; | ||
| 66 | if frame.is_some() { | ||
| 67 | break; | ||
| 68 | } | ||
| 69 | fut.await; | ||
| 70 | } | ||
| 71 | |||
| 72 | frame.unwrap() | ||
| 73 | } | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | mod private { | ||
| 78 | pub trait Sealed {} | ||
| 79 | } | ||
| 80 | |||
| 81 | pub trait Instance: bxcan::Instance + private::Sealed { | ||
| 82 | type TInterrupt: Interrupt; | ||
| 83 | type RInterrupt: Interrupt; | ||
| 84 | } | ||
| 85 | |||
| 86 | macro_rules! can { | ||
| 87 | ($($can:ident => ($tint:ident, $rint:ident),)+) => { | ||
| 88 | $( | ||
| 89 | impl private::Sealed for crate::hal::can::Can<crate::pac::$can> {} | ||
| 90 | impl Instance for crate::hal::can::Can<crate::pac::$can> { | ||
| 91 | type TInterrupt = interrupt::$tint; | ||
| 92 | type RInterrupt = interrupt::$rint; | ||
| 93 | } | ||
| 94 | )+ | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | #[cfg(any( | ||
| 99 | feature = "stm32f401", | ||
| 100 | feature = "stm32f405", | ||
| 101 | feature = "stm32f407", | ||
| 102 | feature = "stm32f410", | ||
| 103 | feature = "stm32f411", | ||
| 104 | feature = "stm32f412", | ||
| 105 | feature = "stm32f413", | ||
| 106 | feature = "stm32f415", | ||
| 107 | feature = "stm32f417", | ||
| 108 | feature = "stm32f423", | ||
| 109 | feature = "stm32f427", | ||
| 110 | feature = "stm32f429", | ||
| 111 | feature = "stm32f437", | ||
| 112 | feature = "stm32f439", | ||
| 113 | feature = "stm32f446", | ||
| 114 | feature = "stm32f469", | ||
| 115 | feature = "stm32f479", | ||
| 116 | ))] | ||
| 117 | can! { | ||
| 118 | CAN1 => (CAN1_TX, CAN1_RX0), | ||
| 119 | CAN2 => (CAN2_TX, CAN2_RX0), | ||
| 120 | } | ||
diff --git a/embassy-stm32/src/f4/mod.rs b/embassy-stm32/src/f4/mod.rs deleted file mode 100644 index 9edde82ca..000000000 --- a/embassy-stm32/src/f4/mod.rs +++ /dev/null | |||
| @@ -1,2 +0,0 @@ | |||
| 1 | pub mod serial; | ||
| 2 | pub mod spi; | ||
diff --git a/embassy-stm32/src/f4/serial.rs b/embassy-stm32/src/f4/serial.rs deleted file mode 100644 index 78aaa8944..000000000 --- a/embassy-stm32/src/f4/serial.rs +++ /dev/null | |||
| @@ -1,357 +0,0 @@ | |||
| 1 | //! Async Serial. | ||
| 2 | |||
| 3 | use core::future::Future; | ||
| 4 | use core::marker::PhantomData; | ||
| 5 | use embassy::interrupt::Interrupt; | ||
| 6 | use embassy::traits::uart::{Error, Read, ReadUntilIdle, Write}; | ||
| 7 | use embassy::util::InterruptFuture; | ||
| 8 | use futures::{select_biased, FutureExt}; | ||
| 9 | |||
| 10 | use crate::hal::{ | ||
| 11 | dma, | ||
| 12 | dma::config::DmaConfig, | ||
| 13 | dma::traits::{Channel, DMASet, PeriAddress, Stream}, | ||
| 14 | dma::{MemoryToPeripheral, PeripheralToMemory, Transfer}, | ||
| 15 | rcc::Clocks, | ||
| 16 | serial, | ||
| 17 | serial::config::{Config as SerialConfig, DmaConfig as SerialDmaConfig}, | ||
| 18 | serial::{Event as SerialEvent, Pins}, | ||
| 19 | }; | ||
| 20 | use crate::interrupt; | ||
| 21 | use crate::pac; | ||
| 22 | |||
| 23 | /// Interface to the Serial peripheral | ||
| 24 | pub struct Serial< | ||
| 25 | USART: PeriAddress<MemSize = u8> + WithInterrupt, | ||
| 26 | TSTREAM: Stream + WithInterrupt, | ||
| 27 | RSTREAM: Stream + WithInterrupt, | ||
| 28 | CHANNEL: Channel, | ||
| 29 | > { | ||
| 30 | tx_stream: Option<TSTREAM>, | ||
| 31 | rx_stream: Option<RSTREAM>, | ||
| 32 | usart: Option<USART>, | ||
| 33 | tx_int: TSTREAM::Interrupt, | ||
| 34 | rx_int: RSTREAM::Interrupt, | ||
| 35 | usart_int: USART::Interrupt, | ||
| 36 | channel: PhantomData<CHANNEL>, | ||
| 37 | } | ||
| 38 | |||
| 39 | // static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut(); | ||
| 40 | |||
| 41 | impl<USART, TSTREAM, RSTREAM, CHANNEL> Serial<USART, TSTREAM, RSTREAM, CHANNEL> | ||
| 42 | where | ||
| 43 | USART: serial::Instance | ||
| 44 | + PeriAddress<MemSize = u8> | ||
| 45 | + DMASet<TSTREAM, CHANNEL, MemoryToPeripheral> | ||
| 46 | + DMASet<RSTREAM, CHANNEL, PeripheralToMemory> | ||
| 47 | + WithInterrupt, | ||
| 48 | TSTREAM: Stream + WithInterrupt, | ||
| 49 | RSTREAM: Stream + WithInterrupt, | ||
| 50 | CHANNEL: Channel, | ||
| 51 | { | ||
| 52 | // Leaking futures is forbidden! | ||
| 53 | pub unsafe fn new<PINS>( | ||
| 54 | usart: USART, | ||
| 55 | streams: (TSTREAM, RSTREAM), | ||
| 56 | pins: PINS, | ||
| 57 | tx_int: TSTREAM::Interrupt, | ||
| 58 | rx_int: RSTREAM::Interrupt, | ||
| 59 | usart_int: USART::Interrupt, | ||
| 60 | mut config: SerialConfig, | ||
| 61 | clocks: Clocks, | ||
| 62 | ) -> Self | ||
| 63 | where | ||
| 64 | PINS: Pins<USART>, | ||
| 65 | { | ||
| 66 | config.dma = SerialDmaConfig::TxRx; | ||
| 67 | |||
| 68 | let (usart, _) = serial::Serial::new(usart, pins, config, clocks) | ||
| 69 | .unwrap() | ||
| 70 | .release(); | ||
| 71 | |||
| 72 | let (tx_stream, rx_stream) = streams; | ||
| 73 | |||
| 74 | Serial { | ||
| 75 | tx_stream: Some(tx_stream), | ||
| 76 | rx_stream: Some(rx_stream), | ||
| 77 | usart: Some(usart), | ||
| 78 | tx_int: tx_int, | ||
| 79 | rx_int: rx_int, | ||
| 80 | usart_int: usart_int, | ||
| 81 | channel: PhantomData, | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | impl<USART, TSTREAM, RSTREAM, CHANNEL> Read for Serial<USART, TSTREAM, RSTREAM, CHANNEL> | ||
| 87 | where | ||
| 88 | USART: serial::Instance | ||
| 89 | + PeriAddress<MemSize = u8> | ||
| 90 | + DMASet<TSTREAM, CHANNEL, MemoryToPeripheral> | ||
| 91 | + DMASet<RSTREAM, CHANNEL, PeripheralToMemory> | ||
| 92 | + WithInterrupt | ||
| 93 | + 'static, | ||
| 94 | TSTREAM: Stream + WithInterrupt + 'static, | ||
| 95 | RSTREAM: Stream + WithInterrupt + 'static, | ||
| 96 | CHANNEL: Channel + 'static, | ||
| 97 | { | ||
| 98 | type ReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | ||
| 99 | |||
| 100 | /// Receives serial data. | ||
| 101 | /// | ||
| 102 | /// The future is pending until the buffer is completely filled. | ||
| 103 | fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 104 | let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) }; | ||
| 105 | |||
| 106 | async move { | ||
| 107 | let rx_stream = self.rx_stream.take().unwrap(); | ||
| 108 | let usart = self.usart.take().unwrap(); | ||
| 109 | |||
| 110 | let mut rx_transfer = Transfer::init( | ||
| 111 | rx_stream, | ||
| 112 | usart, | ||
| 113 | static_buf, | ||
| 114 | None, | ||
| 115 | DmaConfig::default() | ||
| 116 | .transfer_complete_interrupt(true) | ||
| 117 | .memory_increment(true) | ||
| 118 | .double_buffer(false), | ||
| 119 | ); | ||
| 120 | |||
| 121 | let fut = InterruptFuture::new(&mut self.rx_int); | ||
| 122 | rx_transfer.start(|_usart| {}); | ||
| 123 | fut.await; | ||
| 124 | |||
| 125 | let (rx_stream, usart, _, _) = rx_transfer.free(); | ||
| 126 | self.rx_stream.replace(rx_stream); | ||
| 127 | self.usart.replace(usart); | ||
| 128 | |||
| 129 | Ok(()) | ||
| 130 | } | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | impl<USART, TSTREAM, RSTREAM, CHANNEL> Write for Serial<USART, TSTREAM, RSTREAM, CHANNEL> | ||
| 135 | where | ||
| 136 | USART: serial::Instance | ||
| 137 | + PeriAddress<MemSize = u8> | ||
| 138 | + DMASet<TSTREAM, CHANNEL, MemoryToPeripheral> | ||
| 139 | + DMASet<RSTREAM, CHANNEL, PeripheralToMemory> | ||
| 140 | + WithInterrupt | ||
| 141 | + 'static, | ||
| 142 | TSTREAM: Stream + WithInterrupt + 'static, | ||
| 143 | RSTREAM: Stream + WithInterrupt + 'static, | ||
| 144 | CHANNEL: Channel + 'static, | ||
| 145 | { | ||
| 146 | type WriteFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | ||
| 147 | |||
| 148 | /// Sends serial data. | ||
| 149 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 150 | #[allow(mutable_transmutes)] | ||
| 151 | let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) }; | ||
| 152 | |||
| 153 | async move { | ||
| 154 | let tx_stream = self.tx_stream.take().unwrap(); | ||
| 155 | let usart = self.usart.take().unwrap(); | ||
| 156 | |||
| 157 | let mut tx_transfer = Transfer::init( | ||
| 158 | tx_stream, | ||
| 159 | usart, | ||
| 160 | static_buf, | ||
| 161 | None, | ||
| 162 | DmaConfig::default() | ||
| 163 | .transfer_complete_interrupt(true) | ||
| 164 | .memory_increment(true) | ||
| 165 | .double_buffer(false), | ||
| 166 | ); | ||
| 167 | |||
| 168 | let fut = InterruptFuture::new(&mut self.tx_int); | ||
| 169 | |||
| 170 | tx_transfer.start(|_usart| {}); | ||
| 171 | fut.await; | ||
| 172 | |||
| 173 | let (tx_stream, usart, _buf, _) = tx_transfer.free(); | ||
| 174 | |||
| 175 | self.tx_stream.replace(tx_stream); | ||
| 176 | self.usart.replace(usart); | ||
| 177 | |||
| 178 | Ok(()) | ||
| 179 | } | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | impl<USART, TSTREAM, RSTREAM, CHANNEL> ReadUntilIdle for Serial<USART, TSTREAM, RSTREAM, CHANNEL> | ||
| 184 | where | ||
| 185 | USART: serial::Instance | ||
| 186 | + PeriAddress<MemSize = u8> | ||
| 187 | + DMASet<TSTREAM, CHANNEL, MemoryToPeripheral> | ||
| 188 | + DMASet<RSTREAM, CHANNEL, PeripheralToMemory> | ||
| 189 | + WithInterrupt | ||
| 190 | + 'static, | ||
| 191 | TSTREAM: Stream + WithInterrupt + 'static, | ||
| 192 | RSTREAM: Stream + WithInterrupt + 'static, | ||
| 193 | CHANNEL: Channel + 'static, | ||
| 194 | { | ||
| 195 | type ReadUntilIdleFuture<'a> = impl Future<Output = Result<usize, Error>> + 'a; | ||
| 196 | |||
| 197 | /// Receives serial data. | ||
| 198 | /// | ||
| 199 | /// The future is pending until either the buffer is completely full, or the RX line falls idle after receiving some data. | ||
| 200 | /// | ||
| 201 | /// Returns the number of bytes read. | ||
| 202 | fn read_until_idle<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadUntilIdleFuture<'a> { | ||
| 203 | let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) }; | ||
| 204 | |||
| 205 | async move { | ||
| 206 | let rx_stream = self.rx_stream.take().unwrap(); | ||
| 207 | let usart = self.usart.take().unwrap(); | ||
| 208 | |||
| 209 | unsafe { | ||
| 210 | /* __HAL_UART_ENABLE_IT(&uart->UartHandle, UART_IT_IDLE); */ | ||
| 211 | (*USART::ptr()).cr1.modify(|_, w| w.idleie().set_bit()); | ||
| 212 | |||
| 213 | /* __HAL_UART_CLEAR_IDLEFLAG(&uart->UartHandle); */ | ||
| 214 | (*USART::ptr()).sr.read(); | ||
| 215 | (*USART::ptr()).dr.read(); | ||
| 216 | }; | ||
| 217 | |||
| 218 | let mut rx_transfer = Transfer::init( | ||
| 219 | rx_stream, | ||
| 220 | usart, | ||
| 221 | static_buf, | ||
| 222 | None, | ||
| 223 | DmaConfig::default() | ||
| 224 | .transfer_complete_interrupt(true) | ||
| 225 | .memory_increment(true) | ||
| 226 | .double_buffer(false), | ||
| 227 | ); | ||
| 228 | |||
| 229 | let total_bytes = RSTREAM::get_number_of_transfers() as usize; | ||
| 230 | |||
| 231 | let fut = InterruptFuture::new(&mut self.rx_int); | ||
| 232 | let fut_idle = InterruptFuture::new(&mut self.usart_int); | ||
| 233 | |||
| 234 | rx_transfer.start(|_usart| {}); | ||
| 235 | |||
| 236 | futures::future::select(fut, fut_idle).await; | ||
| 237 | |||
| 238 | let (rx_stream, usart, _, _) = rx_transfer.free(); | ||
| 239 | |||
| 240 | let remaining_bytes = RSTREAM::get_number_of_transfers() as usize; | ||
| 241 | |||
| 242 | unsafe { | ||
| 243 | (*USART::ptr()).cr1.modify(|_, w| w.idleie().clear_bit()); | ||
| 244 | } | ||
| 245 | self.rx_stream.replace(rx_stream); | ||
| 246 | self.usart.replace(usart); | ||
| 247 | |||
| 248 | Ok(total_bytes - remaining_bytes) | ||
| 249 | } | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | mod private { | ||
| 254 | pub trait Sealed {} | ||
| 255 | } | ||
| 256 | |||
| 257 | pub trait WithInterrupt: private::Sealed { | ||
| 258 | type Interrupt: Interrupt; | ||
| 259 | } | ||
| 260 | |||
| 261 | macro_rules! dma { | ||
| 262 | ($($PER:ident => ($dma:ident, $stream:ident),)+) => { | ||
| 263 | $( | ||
| 264 | impl private::Sealed for dma::$stream<pac::$dma> {} | ||
| 265 | impl WithInterrupt for dma::$stream<pac::$dma> { | ||
| 266 | type Interrupt = interrupt::$PER; | ||
| 267 | } | ||
| 268 | )+ | ||
| 269 | } | ||
| 270 | } | ||
| 271 | |||
| 272 | macro_rules! usart { | ||
| 273 | ($($PER:ident => ($usart:ident),)+) => { | ||
| 274 | $( | ||
| 275 | impl private::Sealed for pac::$usart {} | ||
| 276 | impl WithInterrupt for pac::$usart { | ||
| 277 | type Interrupt = interrupt::$PER; | ||
| 278 | } | ||
| 279 | )+ | ||
| 280 | } | ||
| 281 | } | ||
| 282 | |||
| 283 | dma! { | ||
| 284 | DMA2_STREAM0 => (DMA2, Stream0), | ||
| 285 | DMA2_STREAM1 => (DMA2, Stream1), | ||
| 286 | DMA2_STREAM2 => (DMA2, Stream2), | ||
| 287 | DMA2_STREAM3 => (DMA2, Stream3), | ||
| 288 | DMA2_STREAM4 => (DMA2, Stream4), | ||
| 289 | DMA2_STREAM5 => (DMA2, Stream5), | ||
| 290 | DMA2_STREAM6 => (DMA2, Stream6), | ||
| 291 | DMA2_STREAM7 => (DMA2, Stream7), | ||
| 292 | DMA1_STREAM0 => (DMA1, Stream0), | ||
| 293 | DMA1_STREAM1 => (DMA1, Stream1), | ||
| 294 | DMA1_STREAM2 => (DMA1, Stream2), | ||
| 295 | DMA1_STREAM3 => (DMA1, Stream3), | ||
| 296 | DMA1_STREAM4 => (DMA1, Stream4), | ||
| 297 | DMA1_STREAM5 => (DMA1, Stream5), | ||
| 298 | DMA1_STREAM6 => (DMA1, Stream6), | ||
| 299 | } | ||
| 300 | |||
| 301 | #[cfg(any(feature = "stm32f401", feature = "stm32f410", feature = "stm32f411",))] | ||
| 302 | usart! { | ||
| 303 | USART1 => (USART1), | ||
| 304 | USART2 => (USART2), | ||
| 305 | USART6 => (USART6), | ||
| 306 | } | ||
| 307 | |||
| 308 | #[cfg(any(feature = "stm32f405", feature = "stm32f407"))] | ||
| 309 | usart! { | ||
| 310 | USART1 => (USART1), | ||
| 311 | USART2 => (USART2), | ||
| 312 | USART3 => (USART3), | ||
| 313 | USART6 => (USART6), | ||
| 314 | |||
| 315 | UART4 => (UART4), | ||
| 316 | UART5 => (UART5), | ||
| 317 | } | ||
| 318 | |||
| 319 | #[cfg(feature = "stm32f412")] | ||
| 320 | usart! { | ||
| 321 | USART1 => (USART1), | ||
| 322 | USART2 => (USART2), | ||
| 323 | USART3 => (USART3), | ||
| 324 | USART6 => (USART6), | ||
| 325 | } | ||
| 326 | |||
| 327 | #[cfg(feature = "stm32f413")] | ||
| 328 | usart! { | ||
| 329 | USART1 => (USART1), | ||
| 330 | USART2 => (USART2), | ||
| 331 | USART3 => (USART3), | ||
| 332 | USART6 => (USART6), | ||
| 333 | USART7 => (USART7), | ||
| 334 | USART8 => (USART8), | ||
| 335 | |||
| 336 | UART5 => (UART5), | ||
| 337 | UART9 => (UART9), | ||
| 338 | UART10 => (UART10), | ||
| 339 | } | ||
| 340 | |||
| 341 | #[cfg(any( | ||
| 342 | feature = "stm32f427", | ||
| 343 | feature = "stm32f429", | ||
| 344 | feature = "stm32f446", | ||
| 345 | feature = "stm32f469" | ||
| 346 | ))] | ||
| 347 | usart! { | ||
| 348 | USART1 => (USART1), | ||
| 349 | USART2 => (USART2), | ||
| 350 | USART3 => (USART3), | ||
| 351 | USART6 => (USART6), | ||
| 352 | |||
| 353 | UART4 => (UART4), | ||
| 354 | UART5 => (UART5), | ||
| 355 | // UART7 => (UART7), | ||
| 356 | // UART8 => (UART8), | ||
| 357 | } | ||
diff --git a/embassy-stm32/src/f4/spi.rs b/embassy-stm32/src/f4/spi.rs deleted file mode 100644 index 65bf7287a..000000000 --- a/embassy-stm32/src/f4/spi.rs +++ /dev/null | |||
| @@ -1,475 +0,0 @@ | |||
| 1 | //! Async SPI | ||
| 2 | |||
| 3 | use embassy::time; | ||
| 4 | |||
| 5 | use core::{future::Future, marker::PhantomData, mem, ops::Deref, pin::Pin, ptr}; | ||
| 6 | use embassy::{interrupt::Interrupt, traits::spi::FullDuplex, util::InterruptFuture}; | ||
| 7 | use nb; | ||
| 8 | |||
| 9 | pub use crate::hal::spi::{Mode, Phase, Polarity}; | ||
| 10 | use crate::hal::{ | ||
| 11 | bb, dma, | ||
| 12 | dma::config::DmaConfig, | ||
| 13 | dma::traits::{Channel, DMASet, PeriAddress, Stream}, | ||
| 14 | dma::{MemoryToPeripheral, PeripheralToMemory, Transfer}, | ||
| 15 | rcc::Clocks, | ||
| 16 | spi::Pins, | ||
| 17 | time::Hertz, | ||
| 18 | }; | ||
| 19 | use crate::interrupt; | ||
| 20 | use crate::pac; | ||
| 21 | use futures::future; | ||
| 22 | |||
| 23 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| 24 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 25 | #[non_exhaustive] | ||
| 26 | pub enum Error { | ||
| 27 | TxBufferTooLong, | ||
| 28 | RxBufferTooLong, | ||
| 29 | Overrun, | ||
| 30 | ModeFault, | ||
| 31 | Crc, | ||
| 32 | } | ||
| 33 | |||
| 34 | fn read_sr<T: Instance>(spi: &T) -> nb::Result<u8, Error> { | ||
| 35 | let sr = spi.sr.read(); | ||
| 36 | Err(if sr.ovr().bit_is_set() { | ||
| 37 | nb::Error::Other(Error::Overrun) | ||
| 38 | } else if sr.modf().bit_is_set() { | ||
| 39 | nb::Error::Other(Error::ModeFault) | ||
| 40 | } else if sr.crcerr().bit_is_set() { | ||
| 41 | nb::Error::Other(Error::Crc) | ||
| 42 | } else if sr.rxne().bit_is_set() { | ||
| 43 | // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows | ||
| 44 | // reading a half-word) | ||
| 45 | return Ok(unsafe { ptr::read_volatile(&spi.dr as *const _ as *const u8) }); | ||
| 46 | } else { | ||
| 47 | nb::Error::WouldBlock | ||
| 48 | }) | ||
| 49 | } | ||
| 50 | |||
| 51 | fn write_sr<T: Instance>(spi: &T, byte: u8) -> nb::Result<(), Error> { | ||
| 52 | let sr = spi.sr.read(); | ||
| 53 | Err(if sr.ovr().bit_is_set() { | ||
| 54 | // Read from the DR to clear the OVR bit | ||
| 55 | let _ = spi.dr.read(); | ||
| 56 | nb::Error::Other(Error::Overrun) | ||
| 57 | } else if sr.modf().bit_is_set() { | ||
| 58 | // Write to CR1 to clear MODF | ||
| 59 | spi.cr1.modify(|_r, w| w); | ||
| 60 | nb::Error::Other(Error::ModeFault) | ||
| 61 | } else if sr.crcerr().bit_is_set() { | ||
| 62 | // Clear the CRCERR bit | ||
| 63 | spi.sr.modify(|_r, w| { | ||
| 64 | w.crcerr().clear_bit(); | ||
| 65 | w | ||
| 66 | }); | ||
| 67 | nb::Error::Other(Error::Crc) | ||
| 68 | } else if sr.txe().bit_is_set() { | ||
| 69 | // NOTE(write_volatile) see note above | ||
| 70 | unsafe { ptr::write_volatile(&spi.dr as *const _ as *mut u8, byte) } | ||
| 71 | return Ok(()); | ||
| 72 | } else { | ||
| 73 | nb::Error::WouldBlock | ||
| 74 | }) | ||
| 75 | } | ||
| 76 | |||
| 77 | /// Interface to the Serial peripheral | ||
| 78 | pub struct Spi< | ||
| 79 | SPI: PeriAddress<MemSize = u8> + WithInterrupt, | ||
| 80 | TSTREAM: Stream + WithInterrupt, | ||
| 81 | RSTREAM: Stream + WithInterrupt, | ||
| 82 | CHANNEL: Channel, | ||
| 83 | > { | ||
| 84 | tx_stream: Option<TSTREAM>, | ||
| 85 | rx_stream: Option<RSTREAM>, | ||
| 86 | spi: Option<SPI>, | ||
| 87 | tx_int: TSTREAM::Interrupt, | ||
| 88 | rx_int: RSTREAM::Interrupt, | ||
| 89 | spi_int: SPI::Interrupt, | ||
| 90 | channel: PhantomData<CHANNEL>, | ||
| 91 | } | ||
| 92 | |||
| 93 | impl<SPI, TSTREAM, RSTREAM, CHANNEL> Spi<SPI, TSTREAM, RSTREAM, CHANNEL> | ||
| 94 | where | ||
| 95 | SPI: Instance | ||
| 96 | + PeriAddress<MemSize = u8> | ||
| 97 | + DMASet<TSTREAM, CHANNEL, MemoryToPeripheral> | ||
| 98 | + DMASet<RSTREAM, CHANNEL, PeripheralToMemory> | ||
| 99 | + WithInterrupt, | ||
| 100 | TSTREAM: Stream + WithInterrupt, | ||
| 101 | RSTREAM: Stream + WithInterrupt, | ||
| 102 | CHANNEL: Channel, | ||
| 103 | { | ||
| 104 | // Leaking futures is forbidden! | ||
| 105 | pub unsafe fn new<PINS>( | ||
| 106 | spi: SPI, | ||
| 107 | streams: (TSTREAM, RSTREAM), | ||
| 108 | pins: PINS, | ||
| 109 | tx_int: TSTREAM::Interrupt, | ||
| 110 | rx_int: RSTREAM::Interrupt, | ||
| 111 | spi_int: SPI::Interrupt, | ||
| 112 | mode: Mode, | ||
| 113 | freq: Hertz, | ||
| 114 | clocks: Clocks, | ||
| 115 | ) -> Self | ||
| 116 | where | ||
| 117 | PINS: Pins<SPI>, | ||
| 118 | { | ||
| 119 | let (tx_stream, rx_stream) = streams; | ||
| 120 | |||
| 121 | // let spi1: crate::pac::SPI1 = unsafe { mem::transmute(()) }; | ||
| 122 | // let mut hspi = crate::hal::spi::Spi::spi1( | ||
| 123 | // spi1, | ||
| 124 | // ( | ||
| 125 | // crate::hal::spi::NoSck, | ||
| 126 | // crate::hal::spi::NoMiso, | ||
| 127 | // crate::hal::spi::NoMosi, | ||
| 128 | // ), | ||
| 129 | // mode, | ||
| 130 | // freq, | ||
| 131 | // clocks, | ||
| 132 | // ); | ||
| 133 | |||
| 134 | unsafe { SPI::enable_clock() }; | ||
| 135 | |||
| 136 | let clock = SPI::clock_speed(clocks); | ||
| 137 | |||
| 138 | // disable SS output | ||
| 139 | // spi.cr2 | ||
| 140 | // .write(|w| w.ssoe().clear_bit().rxdmaen().set_bit().txdmaen().set_bit()); | ||
| 141 | spi.cr2.write(|w| w.ssoe().clear_bit()); | ||
| 142 | |||
| 143 | let br = match clock.0 / freq.0 { | ||
| 144 | 0 => unreachable!(), | ||
| 145 | 1..=2 => 0b000, | ||
| 146 | 3..=5 => 0b001, | ||
| 147 | 6..=11 => 0b010, | ||
| 148 | 12..=23 => 0b011, | ||
| 149 | 24..=47 => 0b100, | ||
| 150 | 48..=95 => 0b101, | ||
| 151 | 96..=191 => 0b110, | ||
| 152 | _ => 0b111, | ||
| 153 | }; | ||
| 154 | |||
| 155 | // mstr: master configuration | ||
| 156 | // lsbfirst: MSB first | ||
| 157 | // ssm: enable software slave management (NSS pin free for other uses) | ||
| 158 | // ssi: set nss high = master mode | ||
| 159 | // dff: 8 bit frames | ||
| 160 | // bidimode: 2-line unidirectional | ||
| 161 | // spe: enable the SPI bus | ||
| 162 | spi.cr1.write(|w| { | ||
| 163 | w.cpha() | ||
| 164 | .bit(mode.phase == Phase::CaptureOnSecondTransition) | ||
| 165 | .cpol() | ||
| 166 | .bit(mode.polarity == Polarity::IdleHigh) | ||
| 167 | .mstr() | ||
| 168 | .set_bit() | ||
| 169 | .br() | ||
| 170 | .bits(br) | ||
| 171 | .lsbfirst() | ||
| 172 | .clear_bit() | ||
| 173 | .ssm() | ||
| 174 | .set_bit() | ||
| 175 | .ssi() | ||
| 176 | .set_bit() | ||
| 177 | .rxonly() | ||
| 178 | .clear_bit() | ||
| 179 | .dff() | ||
| 180 | .clear_bit() | ||
| 181 | .bidimode() | ||
| 182 | .clear_bit() | ||
| 183 | .spe() | ||
| 184 | .set_bit() | ||
| 185 | }); | ||
| 186 | |||
| 187 | Self { | ||
| 188 | tx_stream: Some(tx_stream), | ||
| 189 | rx_stream: Some(rx_stream), | ||
| 190 | spi: Some(spi), | ||
| 191 | tx_int: tx_int, | ||
| 192 | rx_int: rx_int, | ||
| 193 | spi_int: spi_int, | ||
| 194 | channel: PhantomData, | ||
| 195 | } | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | impl<SPI, TSTREAM, RSTREAM, CHANNEL> FullDuplex<u8> for Spi<SPI, TSTREAM, RSTREAM, CHANNEL> | ||
| 200 | where | ||
| 201 | SPI: Instance | ||
| 202 | + PeriAddress<MemSize = u8> | ||
| 203 | + DMASet<TSTREAM, CHANNEL, MemoryToPeripheral> | ||
| 204 | + DMASet<RSTREAM, CHANNEL, PeripheralToMemory> | ||
| 205 | + WithInterrupt | ||
| 206 | + 'static, | ||
| 207 | TSTREAM: Stream + WithInterrupt + 'static, | ||
| 208 | RSTREAM: Stream + WithInterrupt + 'static, | ||
| 209 | CHANNEL: Channel + 'static, | ||
| 210 | { | ||
| 211 | type Error = Error; | ||
| 212 | |||
| 213 | type WriteFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | ||
| 214 | type ReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | ||
| 215 | type WriteReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | ||
| 216 | |||
| 217 | fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 218 | #[allow(mutable_transmutes)] | ||
| 219 | let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) }; | ||
| 220 | |||
| 221 | async move { | ||
| 222 | let rx_stream = self.rx_stream.take().unwrap(); | ||
| 223 | let spi = self.spi.take().unwrap(); | ||
| 224 | |||
| 225 | spi.cr2.modify(|_, w| w.errie().set_bit()); | ||
| 226 | |||
| 227 | let mut rx_transfer = Transfer::init( | ||
| 228 | rx_stream, | ||
| 229 | spi, | ||
| 230 | static_buf, | ||
| 231 | None, | ||
| 232 | DmaConfig::default() | ||
| 233 | .transfer_complete_interrupt(true) | ||
| 234 | .memory_increment(true) | ||
| 235 | .double_buffer(false), | ||
| 236 | ); | ||
| 237 | |||
| 238 | let fut = InterruptFuture::new(&mut self.rx_int); | ||
| 239 | let fut_err = InterruptFuture::new(&mut self.spi_int); | ||
| 240 | |||
| 241 | rx_transfer.start(|_spi| {}); | ||
| 242 | future::select(fut, fut_err).await; | ||
| 243 | |||
| 244 | let (rx_stream, spi, _buf, _) = rx_transfer.free(); | ||
| 245 | |||
| 246 | spi.cr2.modify(|_, w| w.errie().clear_bit()); | ||
| 247 | self.rx_stream.replace(rx_stream); | ||
| 248 | self.spi.replace(spi); | ||
| 249 | |||
| 250 | Ok(()) | ||
| 251 | } | ||
| 252 | } | ||
| 253 | |||
| 254 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 255 | #[allow(mutable_transmutes)] | ||
| 256 | let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) }; | ||
| 257 | |||
| 258 | async move { | ||
| 259 | let tx_stream = self.tx_stream.take().unwrap(); | ||
| 260 | let spi = self.spi.take().unwrap(); | ||
| 261 | |||
| 262 | // let mut tx_transfer = Transfer::init( | ||
| 263 | // tx_stream, | ||
| 264 | // spi, | ||
| 265 | // static_buf, | ||
| 266 | // None, | ||
| 267 | // DmaConfig::default() | ||
| 268 | // .transfer_complete_interrupt(true) | ||
| 269 | // .memory_increment(true) | ||
| 270 | // .double_buffer(false), | ||
| 271 | // ); | ||
| 272 | // | ||
| 273 | // let fut = InterruptFuture::new(&mut self.tx_int); | ||
| 274 | // | ||
| 275 | // tx_transfer.start(|_spi| {}); | ||
| 276 | // fut.await; | ||
| 277 | |||
| 278 | // let (tx_stream, spi, _buf, _) = tx_transfer.free(); | ||
| 279 | |||
| 280 | for i in 0..(static_buf.len() - 1) { | ||
| 281 | let byte = static_buf[i]; | ||
| 282 | nb::block!(write_sr(&spi, byte)); | ||
| 283 | } | ||
| 284 | |||
| 285 | self.tx_stream.replace(tx_stream); | ||
| 286 | self.spi.replace(spi); | ||
| 287 | |||
| 288 | Ok(()) | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | fn read_write<'a>( | ||
| 293 | &'a mut self, | ||
| 294 | read_buf: &'a mut [u8], | ||
| 295 | write_buf: &'a [u8], | ||
| 296 | ) -> Self::WriteReadFuture<'a> { | ||
| 297 | #[allow(mutable_transmutes)] | ||
| 298 | let write_static_buf: &'static mut [u8] = unsafe { mem::transmute(write_buf) }; | ||
| 299 | let read_static_buf: &'static mut [u8] = unsafe { mem::transmute(read_buf) }; | ||
| 300 | |||
| 301 | async move { | ||
| 302 | let tx_stream = self.tx_stream.take().unwrap(); | ||
| 303 | let rx_stream = self.rx_stream.take().unwrap(); | ||
| 304 | let spi_tx = self.spi.take().unwrap(); | ||
| 305 | let spi_rx: SPI = unsafe { mem::transmute_copy(&spi_tx) }; | ||
| 306 | |||
| 307 | spi_rx | ||
| 308 | .cr2 | ||
| 309 | .modify(|_, w| w.errie().set_bit().txeie().set_bit().rxneie().set_bit()); | ||
| 310 | |||
| 311 | // let mut tx_transfer = Transfer::init( | ||
| 312 | // tx_stream, | ||
| 313 | // spi_tx, | ||
| 314 | // write_static_buf, | ||
| 315 | // None, | ||
| 316 | // DmaConfig::default() | ||
| 317 | // .transfer_complete_interrupt(true) | ||
| 318 | // .memory_increment(true) | ||
| 319 | // .double_buffer(false), | ||
| 320 | // ); | ||
| 321 | // | ||
| 322 | // let mut rx_transfer = Transfer::init( | ||
| 323 | // rx_stream, | ||
| 324 | // spi_rx, | ||
| 325 | // read_static_buf, | ||
| 326 | // None, | ||
| 327 | // DmaConfig::default() | ||
| 328 | // .transfer_complete_interrupt(true) | ||
| 329 | // .memory_increment(true) | ||
| 330 | // .double_buffer(false), | ||
| 331 | // ); | ||
| 332 | // | ||
| 333 | // let tx_fut = InterruptFuture::new(&mut self.tx_int); | ||
| 334 | // let rx_fut = InterruptFuture::new(&mut self.rx_int); | ||
| 335 | // let rx_fut_err = InterruptFuture::new(&mut self.spi_int); | ||
| 336 | // | ||
| 337 | // rx_transfer.start(|_spi| {}); | ||
| 338 | // tx_transfer.start(|_spi| {}); | ||
| 339 | // | ||
| 340 | // time::Timer::after(time::Duration::from_millis(500)).await; | ||
| 341 | // | ||
| 342 | // // tx_fut.await; | ||
| 343 | // // future::select(rx_fut, rx_fut_err).await; | ||
| 344 | // | ||
| 345 | // let (rx_stream, spi_rx, _buf, _) = rx_transfer.free(); | ||
| 346 | // let (tx_stream, _, _buf, _) = tx_transfer.free(); | ||
| 347 | |||
| 348 | for i in 0..(read_static_buf.len() - 1) { | ||
| 349 | let byte = write_static_buf[i]; | ||
| 350 | loop { | ||
| 351 | let fut = InterruptFuture::new(&mut self.spi_int); | ||
| 352 | match write_sr(&spi_tx, byte) { | ||
| 353 | Ok(()) => break, | ||
| 354 | _ => {} | ||
| 355 | } | ||
| 356 | fut.await; | ||
| 357 | } | ||
| 358 | |||
| 359 | loop { | ||
| 360 | let fut = InterruptFuture::new(&mut self.spi_int); | ||
| 361 | match read_sr(&spi_tx) { | ||
| 362 | Ok(byte) => { | ||
| 363 | read_static_buf[i] = byte; | ||
| 364 | break; | ||
| 365 | } | ||
| 366 | _ => {} | ||
| 367 | } | ||
| 368 | fut.await; | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | spi_rx.cr2.modify(|_, w| { | ||
| 373 | w.errie() | ||
| 374 | .clear_bit() | ||
| 375 | .txeie() | ||
| 376 | .clear_bit() | ||
| 377 | .rxneie() | ||
| 378 | .clear_bit() | ||
| 379 | }); | ||
| 380 | self.rx_stream.replace(rx_stream); | ||
| 381 | self.tx_stream.replace(tx_stream); | ||
| 382 | self.spi.replace(spi_rx); | ||
| 383 | |||
| 384 | Ok(()) | ||
| 385 | } | ||
| 386 | } | ||
| 387 | } | ||
| 388 | |||
| 389 | mod private { | ||
| 390 | pub trait Sealed {} | ||
| 391 | } | ||
| 392 | |||
| 393 | pub trait WithInterrupt: private::Sealed { | ||
| 394 | type Interrupt: Interrupt; | ||
| 395 | } | ||
| 396 | |||
| 397 | pub trait Instance: Deref<Target = pac::spi1::RegisterBlock> + private::Sealed { | ||
| 398 | unsafe fn enable_clock(); | ||
| 399 | fn clock_speed(clocks: Clocks) -> Hertz; | ||
| 400 | } | ||
| 401 | |||
| 402 | macro_rules! dma { | ||
| 403 | ($($PER:ident => ($dma:ident, $stream:ident),)+) => { | ||
| 404 | $( | ||
| 405 | impl private::Sealed for dma::$stream<pac::$dma> {} | ||
| 406 | impl WithInterrupt for dma::$stream<pac::$dma> { | ||
| 407 | type Interrupt = interrupt::$PER; | ||
| 408 | } | ||
| 409 | )+ | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 413 | macro_rules! spi { | ||
| 414 | ($($PER:ident => ($SPI:ident, $pclkX:ident, $apbXenr:ident, $en:expr),)+) => { | ||
| 415 | $( | ||
| 416 | impl private::Sealed for pac::$SPI {} | ||
| 417 | impl Instance for pac::$SPI { | ||
| 418 | unsafe fn enable_clock() { | ||
| 419 | const EN_BIT: u8 = $en; | ||
| 420 | // NOTE(unsafe) self reference will only be used for atomic writes with no side effects. | ||
| 421 | let rcc = &(*pac::RCC::ptr()); | ||
| 422 | // Enable clock. | ||
| 423 | bb::set(&rcc.$apbXenr, EN_BIT); | ||
| 424 | // Stall the pipeline to work around erratum 2.1.13 (DM00037591) | ||
| 425 | cortex_m::asm::dsb(); | ||
| 426 | } | ||
| 427 | |||
| 428 | fn clock_speed(clocks: Clocks) -> Hertz { | ||
| 429 | clocks.$pclkX() | ||
| 430 | } | ||
| 431 | } | ||
| 432 | impl WithInterrupt for pac::$SPI { | ||
| 433 | type Interrupt = interrupt::$PER; | ||
| 434 | } | ||
| 435 | )+ | ||
| 436 | } | ||
| 437 | } | ||
| 438 | |||
| 439 | dma! { | ||
| 440 | DMA2_STREAM0 => (DMA2, Stream0), | ||
| 441 | DMA2_STREAM1 => (DMA2, Stream1), | ||
| 442 | DMA2_STREAM2 => (DMA2, Stream2), | ||
| 443 | DMA2_STREAM3 => (DMA2, Stream3), | ||
| 444 | DMA2_STREAM4 => (DMA2, Stream4), | ||
| 445 | DMA2_STREAM5 => (DMA2, Stream5), | ||
| 446 | DMA2_STREAM6 => (DMA2, Stream6), | ||
| 447 | DMA2_STREAM7 => (DMA2, Stream7), | ||
| 448 | DMA1_STREAM0 => (DMA1, Stream0), | ||
| 449 | DMA1_STREAM1 => (DMA1, Stream1), | ||
| 450 | DMA1_STREAM2 => (DMA1, Stream2), | ||
| 451 | DMA1_STREAM3 => (DMA1, Stream3), | ||
| 452 | DMA1_STREAM4 => (DMA1, Stream4), | ||
| 453 | DMA1_STREAM5 => (DMA1, Stream5), | ||
| 454 | DMA1_STREAM6 => (DMA1, Stream6), | ||
| 455 | } | ||
| 456 | |||
| 457 | #[cfg(any( | ||
| 458 | feature = "stm32f401", | ||
| 459 | feature = "stm32f410", | ||
| 460 | feature = "stm32f411", | ||
| 461 | feature = "stm32f446", | ||
| 462 | ))] | ||
| 463 | spi! { | ||
| 464 | SPI1 => (SPI1, pclk2, apb2enr, 12), | ||
| 465 | SPI2 => (SPI2, pclk1, apb2enr, 14), | ||
| 466 | // SPI6 => (SPI6, pclk2, apb2enr, 21), | ||
| 467 | SPI4 => (SPI3, pclk2, apb2enr, 13), | ||
| 468 | // SPI5 => (SPI3, pclk2, apb2enr, 20), | ||
| 469 | } | ||
| 470 | |||
| 471 | #[cfg(any(feature = "stm32f405", feature = "stm32f407"))] | ||
| 472 | spi! { | ||
| 473 | SPI1 => (SPI1, pclk2, apb2enr, 12), | ||
| 474 | SPI3 => (SPI3, pclk1, apb2enr, 15), | ||
| 475 | } | ||
diff --git a/embassy-stm32/src/interrupt.rs b/embassy-stm32/src/interrupt.rs deleted file mode 100644 index 214327300..000000000 --- a/embassy-stm32/src/interrupt.rs +++ /dev/null | |||
| @@ -1,59 +0,0 @@ | |||
| 1 | use core::sync::atomic::{compiler_fence, Ordering}; | ||
| 2 | |||
| 3 | use crate::pac::NVIC_PRIO_BITS; | ||
| 4 | |||
| 5 | // Re-exports | ||
| 6 | pub use cortex_m::interrupt::{CriticalSection, Mutex}; | ||
| 7 | pub use embassy::interrupt::{declare, take, Interrupt}; | ||
| 8 | |||
| 9 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | ||
| 10 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 11 | #[repr(u8)] | ||
| 12 | pub enum Priority { | ||
| 13 | Level0 = 0, | ||
| 14 | Level1 = 1, | ||
| 15 | Level2 = 2, | ||
| 16 | Level3 = 3, | ||
| 17 | Level4 = 4, | ||
| 18 | Level5 = 5, | ||
| 19 | Level6 = 6, | ||
| 20 | Level7 = 7, | ||
| 21 | Level8 = 8, | ||
| 22 | Level9 = 9, | ||
| 23 | Level10 = 10, | ||
| 24 | Level11 = 11, | ||
| 25 | Level12 = 12, | ||
| 26 | Level13 = 13, | ||
| 27 | Level14 = 14, | ||
| 28 | Level15 = 15, | ||
| 29 | } | ||
| 30 | |||
| 31 | impl From<u8> for Priority { | ||
| 32 | fn from(priority: u8) -> Self { | ||
| 33 | match priority >> (8 - NVIC_PRIO_BITS) { | ||
| 34 | 0 => Self::Level0, | ||
| 35 | 1 => Self::Level1, | ||
| 36 | 2 => Self::Level2, | ||
| 37 | 3 => Self::Level3, | ||
| 38 | 4 => Self::Level4, | ||
| 39 | 5 => Self::Level5, | ||
| 40 | 6 => Self::Level6, | ||
| 41 | 7 => Self::Level7, | ||
| 42 | 8 => Self::Level8, | ||
| 43 | 9 => Self::Level9, | ||
| 44 | 10 => Self::Level10, | ||
| 45 | 11 => Self::Level11, | ||
| 46 | 12 => Self::Level12, | ||
| 47 | 13 => Self::Level13, | ||
| 48 | 14 => Self::Level14, | ||
| 49 | 15 => Self::Level15, | ||
| 50 | _ => unreachable!(), | ||
| 51 | } | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | impl From<Priority> for u8 { | ||
| 56 | fn from(p: Priority) -> Self { | ||
| 57 | (p as u8) << (8 - NVIC_PRIO_BITS) | ||
| 58 | } | ||
| 59 | } | ||
diff --git a/embassy-stm32/src/rtc.rs b/embassy-stm32/src/rtc.rs deleted file mode 100644 index b1abba325..000000000 --- a/embassy-stm32/src/rtc.rs +++ /dev/null | |||
| @@ -1,504 +0,0 @@ | |||
| 1 | use crate::hal::bb; | ||
| 2 | use crate::hal::rcc::Clocks; | ||
| 3 | use core::cell::Cell; | ||
| 4 | use core::convert::TryInto; | ||
| 5 | use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; | ||
| 6 | |||
| 7 | use embassy::interrupt::InterruptExt; | ||
| 8 | use embassy::time::{Clock, TICKS_PER_SECOND}; | ||
| 9 | |||
| 10 | use crate::interrupt; | ||
| 11 | use crate::interrupt::{CriticalSection, Interrupt, Mutex}; | ||
| 12 | |||
| 13 | // RTC timekeeping works with something we call "periods", which are time intervals | ||
| 14 | // of 2^15 ticks. The RTC counter value is 16 bits, so one "overflow cycle" is 2 periods. | ||
| 15 | // | ||
| 16 | // A `period` count is maintained in parallel to the RTC hardware `counter`, like this: | ||
| 17 | // - `period` and `counter` start at 0 | ||
| 18 | // - `period` is incremented on overflow (at counter value 0) | ||
| 19 | // - `period` is incremented "midway" between overflows (at counter value 0x8000) | ||
| 20 | // | ||
| 21 | // Therefore, when `period` is even, counter is in 0..0x7FFF. When odd, counter is in 0x8000..0xFFFF | ||
| 22 | // This allows for now() to return the correct value even if it races an overflow. | ||
| 23 | // | ||
| 24 | // To get `now()`, `period` is read first, then `counter` is read. If the counter value matches | ||
| 25 | // the expected range for the `period` parity, we're done. If it doesn't, this means that | ||
| 26 | // a new period start has raced us between reading `period` and `counter`, so we assume the `counter` value | ||
| 27 | // corresponds to the next period. | ||
| 28 | // | ||
| 29 | // `period` is a 32bit integer, so It overflows on 2^32 * 2^15 / 32768 seconds of uptime, which is 136 years. | ||
| 30 | fn calc_now(period: u32, counter: u16) -> u64 { | ||
| 31 | ((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64) | ||
| 32 | } | ||
| 33 | |||
| 34 | struct AlarmState { | ||
| 35 | timestamp: Cell<u64>, | ||
| 36 | callback: Cell<Option<(fn(*mut ()), *mut ())>>, | ||
| 37 | } | ||
| 38 | |||
| 39 | impl AlarmState { | ||
| 40 | fn new() -> Self { | ||
| 41 | Self { | ||
| 42 | timestamp: Cell::new(u64::MAX), | ||
| 43 | callback: Cell::new(None), | ||
| 44 | } | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | // TODO: This is sometimes wasteful, try to find a better way | ||
| 49 | const ALARM_COUNT: usize = 3; | ||
| 50 | |||
| 51 | /// RTC timer that can be used by the executor and to set alarms. | ||
| 52 | /// | ||
| 53 | /// It can work with Timers 2, 3, 4, 5, 9 and 12. Timers 9 and 12 only have one alarm available, | ||
| 54 | /// while the others have three each. | ||
| 55 | /// This timer works internally with a unit of 2^15 ticks, which means that if a call to | ||
| 56 | /// [`embassy::time::Clock::now`] is blocked for that amount of ticks the returned value will be | ||
| 57 | /// wrong (an old value). The current default tick rate is 32768 ticks per second. | ||
| 58 | pub struct RTC<T: Instance> { | ||
| 59 | rtc: T, | ||
| 60 | irq: T::Interrupt, | ||
| 61 | |||
| 62 | /// Number of 2^23 periods elapsed since boot. | ||
| 63 | period: AtomicU32, | ||
| 64 | |||
| 65 | /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled. | ||
| 66 | alarms: Mutex<[AlarmState; ALARM_COUNT]>, | ||
| 67 | |||
| 68 | clocks: Clocks, | ||
| 69 | } | ||
| 70 | |||
| 71 | impl<T: Instance> RTC<T> { | ||
| 72 | pub fn new(rtc: T, irq: T::Interrupt, clocks: Clocks) -> Self { | ||
| 73 | Self { | ||
| 74 | rtc, | ||
| 75 | irq, | ||
| 76 | period: AtomicU32::new(0), | ||
| 77 | alarms: Mutex::new([AlarmState::new(), AlarmState::new(), AlarmState::new()]), | ||
| 78 | clocks, | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | pub fn start(&'static self) { | ||
| 83 | self.rtc.enable_clock(); | ||
| 84 | self.rtc.stop_and_reset(); | ||
| 85 | |||
| 86 | let multiplier = if T::ppre(&self.clocks) == 1 { 1 } else { 2 }; | ||
| 87 | let freq = T::pclk(&self.clocks) * multiplier; | ||
| 88 | let psc = freq / TICKS_PER_SECOND as u32 - 1; | ||
| 89 | let psc: u16 = psc.try_into().unwrap(); | ||
| 90 | |||
| 91 | self.rtc.set_psc_arr(psc, u16::MAX); | ||
| 92 | // Mid-way point | ||
| 93 | self.rtc.set_compare(0, 0x8000); | ||
| 94 | self.rtc.set_compare_interrupt(0, true); | ||
| 95 | |||
| 96 | self.irq.set_handler(|ptr| unsafe { | ||
| 97 | let this = &*(ptr as *const () as *const Self); | ||
| 98 | this.on_interrupt(); | ||
| 99 | }); | ||
| 100 | self.irq.set_handler_context(self as *const _ as *mut _); | ||
| 101 | self.irq.unpend(); | ||
| 102 | self.irq.enable(); | ||
| 103 | |||
| 104 | self.rtc.start(); | ||
| 105 | } | ||
| 106 | |||
| 107 | fn on_interrupt(&self) { | ||
| 108 | if self.rtc.overflow_interrupt_status() { | ||
| 109 | self.rtc.overflow_clear_flag(); | ||
| 110 | self.next_period(); | ||
| 111 | } | ||
| 112 | |||
| 113 | // Half overflow | ||
| 114 | if self.rtc.compare_interrupt_status(0) { | ||
| 115 | self.rtc.compare_clear_flag(0); | ||
| 116 | self.next_period(); | ||
| 117 | } | ||
| 118 | |||
| 119 | for n in 1..=ALARM_COUNT { | ||
| 120 | if self.rtc.compare_interrupt_status(n) { | ||
| 121 | self.rtc.compare_clear_flag(n); | ||
| 122 | interrupt::free(|cs| self.trigger_alarm(n, cs)); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | fn next_period(&self) { | ||
| 128 | interrupt::free(|cs| { | ||
| 129 | let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; | ||
| 130 | let t = (period as u64) << 15; | ||
| 131 | |||
| 132 | for n in 1..=ALARM_COUNT { | ||
| 133 | let alarm = &self.alarms.borrow(cs)[n - 1]; | ||
| 134 | let at = alarm.timestamp.get(); | ||
| 135 | |||
| 136 | let diff = at - t; | ||
| 137 | if diff < 0xc000 { | ||
| 138 | self.rtc.set_compare(n, at as u16); | ||
| 139 | self.rtc.set_compare_interrupt(n, true); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | }) | ||
| 143 | } | ||
| 144 | |||
| 145 | fn trigger_alarm(&self, n: usize, cs: &CriticalSection) { | ||
| 146 | self.rtc.set_compare_interrupt(n, false); | ||
| 147 | |||
| 148 | let alarm = &self.alarms.borrow(cs)[n - 1]; | ||
| 149 | alarm.timestamp.set(u64::MAX); | ||
| 150 | |||
| 151 | // Call after clearing alarm, so the callback can set another alarm. | ||
| 152 | if let Some((f, ctx)) = alarm.callback.get() { | ||
| 153 | f(ctx); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) { | ||
| 158 | interrupt::free(|cs| { | ||
| 159 | let alarm = &self.alarms.borrow(cs)[n - 1]; | ||
| 160 | alarm.callback.set(Some((callback, ctx))); | ||
| 161 | }) | ||
| 162 | } | ||
| 163 | |||
| 164 | fn set_alarm(&self, n: usize, timestamp: u64) { | ||
| 165 | interrupt::free(|cs| { | ||
| 166 | let alarm = &self.alarms.borrow(cs)[n - 1]; | ||
| 167 | alarm.timestamp.set(timestamp); | ||
| 168 | |||
| 169 | let t = self.now(); | ||
| 170 | if timestamp <= t { | ||
| 171 | self.trigger_alarm(n, cs); | ||
| 172 | return; | ||
| 173 | } | ||
| 174 | |||
| 175 | let diff = timestamp - t; | ||
| 176 | if diff < 0xc000 { | ||
| 177 | let safe_timestamp = timestamp.max(t + 3); | ||
| 178 | self.rtc.set_compare(n, safe_timestamp as u16); | ||
| 179 | self.rtc.set_compare_interrupt(n, true); | ||
| 180 | } else { | ||
| 181 | self.rtc.set_compare_interrupt(n, false); | ||
| 182 | } | ||
| 183 | }) | ||
| 184 | } | ||
| 185 | |||
| 186 | pub fn alarm1(&'static self) -> Alarm<T> { | ||
| 187 | Alarm { n: 1, rtc: self } | ||
| 188 | } | ||
| 189 | pub fn alarm2(&'static self) -> Option<Alarm<T>> { | ||
| 190 | if T::REAL_ALARM_COUNT >= 2 { | ||
| 191 | Some(Alarm { n: 2, rtc: self }) | ||
| 192 | } else { | ||
| 193 | None | ||
| 194 | } | ||
| 195 | } | ||
| 196 | pub fn alarm3(&'static self) -> Option<Alarm<T>> { | ||
| 197 | if T::REAL_ALARM_COUNT >= 3 { | ||
| 198 | Some(Alarm { n: 3, rtc: self }) | ||
| 199 | } else { | ||
| 200 | None | ||
| 201 | } | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | impl<T: Instance> embassy::time::Clock for RTC<T> { | ||
| 206 | fn now(&self) -> u64 { | ||
| 207 | let period = self.period.load(Ordering::Relaxed); | ||
| 208 | compiler_fence(Ordering::Acquire); | ||
| 209 | let counter = self.rtc.counter(); | ||
| 210 | calc_now(period, counter) | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | pub struct Alarm<T: Instance> { | ||
| 215 | n: usize, | ||
| 216 | rtc: &'static RTC<T>, | ||
| 217 | } | ||
| 218 | |||
| 219 | impl<T: Instance> embassy::time::Alarm for Alarm<T> { | ||
| 220 | fn set_callback(&self, callback: fn(*mut ()), ctx: *mut ()) { | ||
| 221 | self.rtc.set_alarm_callback(self.n, callback, ctx); | ||
| 222 | } | ||
| 223 | |||
| 224 | fn set(&self, timestamp: u64) { | ||
| 225 | self.rtc.set_alarm(self.n, timestamp); | ||
| 226 | } | ||
| 227 | |||
| 228 | fn clear(&self) { | ||
| 229 | self.rtc.set_alarm(self.n, u64::MAX); | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | mod sealed { | ||
| 234 | pub trait Sealed {} | ||
| 235 | } | ||
| 236 | |||
| 237 | pub trait Instance: sealed::Sealed + Sized + 'static { | ||
| 238 | type Interrupt: Interrupt; | ||
| 239 | const REAL_ALARM_COUNT: usize; | ||
| 240 | |||
| 241 | fn enable_clock(&self); | ||
| 242 | fn set_compare(&self, n: usize, value: u16); | ||
| 243 | fn set_compare_interrupt(&self, n: usize, enable: bool); | ||
| 244 | fn compare_interrupt_status(&self, n: usize) -> bool; | ||
| 245 | fn compare_clear_flag(&self, n: usize); | ||
| 246 | fn overflow_interrupt_status(&self) -> bool; | ||
| 247 | fn overflow_clear_flag(&self); | ||
| 248 | // This method should ensure that the values are really updated before returning | ||
| 249 | fn set_psc_arr(&self, psc: u16, arr: u16); | ||
| 250 | fn stop_and_reset(&self); | ||
| 251 | fn start(&self); | ||
| 252 | fn counter(&self) -> u16; | ||
| 253 | fn ppre(clocks: &Clocks) -> u8; | ||
| 254 | fn pclk(clocks: &Clocks) -> u32; | ||
| 255 | } | ||
| 256 | |||
| 257 | #[allow(unused_macros)] | ||
| 258 | macro_rules! impl_timer { | ||
| 259 | ($module:ident: ($TYPE:ident, $INT:ident, $apbenr:ident, $enrbit:expr, $apbrstr:ident, $rstrbit:expr, $ppre:ident, $pclk: ident), 3) => { | ||
| 260 | mod $module { | ||
| 261 | use super::*; | ||
| 262 | use crate::hal::pac::{$TYPE, RCC}; | ||
| 263 | |||
| 264 | impl sealed::Sealed for $TYPE {} | ||
| 265 | |||
| 266 | impl Instance for $TYPE { | ||
| 267 | type Interrupt = interrupt::$INT; | ||
| 268 | const REAL_ALARM_COUNT: usize = 3; | ||
| 269 | |||
| 270 | fn enable_clock(&self) { | ||
| 271 | // NOTE(unsafe) It will only be used for atomic operations | ||
| 272 | unsafe { | ||
| 273 | let rcc = &*RCC::ptr(); | ||
| 274 | |||
| 275 | bb::set(&rcc.$apbenr, $enrbit); | ||
| 276 | bb::set(&rcc.$apbrstr, $rstrbit); | ||
| 277 | bb::clear(&rcc.$apbrstr, $rstrbit); | ||
| 278 | } | ||
| 279 | } | ||
| 280 | |||
| 281 | fn set_compare(&self, n: usize, value: u16) { | ||
| 282 | // NOTE(unsafe) these registers accept all the range of u16 values | ||
| 283 | match n { | ||
| 284 | 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }), | ||
| 285 | 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }), | ||
| 286 | 2 => self.ccr3.write(|w| unsafe { w.bits(value.into()) }), | ||
| 287 | 3 => self.ccr4.write(|w| unsafe { w.bits(value.into()) }), | ||
| 288 | _ => {} | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | fn set_compare_interrupt(&self, n: usize, enable: bool) { | ||
| 293 | if n > 3 { | ||
| 294 | return; | ||
| 295 | } | ||
| 296 | let bit = n as u8 + 1; | ||
| 297 | unsafe { | ||
| 298 | if enable { | ||
| 299 | bb::set(&self.dier, bit); | ||
| 300 | } else { | ||
| 301 | bb::clear(&self.dier, bit); | ||
| 302 | } | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 306 | fn compare_interrupt_status(&self, n: usize) -> bool { | ||
| 307 | let status = self.sr.read(); | ||
| 308 | match n { | ||
| 309 | 0 => status.cc1if().bit_is_set(), | ||
| 310 | 1 => status.cc2if().bit_is_set(), | ||
| 311 | 2 => status.cc3if().bit_is_set(), | ||
| 312 | 3 => status.cc4if().bit_is_set(), | ||
| 313 | _ => false, | ||
| 314 | } | ||
| 315 | } | ||
| 316 | |||
| 317 | fn compare_clear_flag(&self, n: usize) { | ||
| 318 | if n > 3 { | ||
| 319 | return; | ||
| 320 | } | ||
| 321 | let bit = n as u8 + 1; | ||
| 322 | unsafe { | ||
| 323 | bb::clear(&self.sr, bit); | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | fn overflow_interrupt_status(&self) -> bool { | ||
| 328 | self.sr.read().uif().bit_is_set() | ||
| 329 | } | ||
| 330 | |||
| 331 | fn overflow_clear_flag(&self) { | ||
| 332 | unsafe { | ||
| 333 | bb::clear(&self.sr, 0); | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | fn set_psc_arr(&self, psc: u16, arr: u16) { | ||
| 338 | // NOTE(unsafe) All u16 values are valid | ||
| 339 | self.psc.write(|w| unsafe { w.bits(psc.into()) }); | ||
| 340 | self.arr.write(|w| unsafe { w.bits(arr.into()) }); | ||
| 341 | |||
| 342 | unsafe { | ||
| 343 | // Set URS, generate update, clear URS | ||
| 344 | bb::set(&self.cr1, 2); | ||
| 345 | self.egr.write(|w| w.ug().set_bit()); | ||
| 346 | bb::clear(&self.cr1, 2); | ||
| 347 | } | ||
| 348 | } | ||
| 349 | |||
| 350 | fn stop_and_reset(&self) { | ||
| 351 | unsafe { | ||
| 352 | bb::clear(&self.cr1, 0); | ||
| 353 | } | ||
| 354 | self.cnt.reset(); | ||
| 355 | } | ||
| 356 | |||
| 357 | fn start(&self) { | ||
| 358 | unsafe { bb::set(&self.cr1, 0) } | ||
| 359 | } | ||
| 360 | |||
| 361 | fn counter(&self) -> u16 { | ||
| 362 | self.cnt.read().bits() as u16 | ||
| 363 | } | ||
| 364 | |||
| 365 | fn ppre(clocks: &Clocks) -> u8 { | ||
| 366 | clocks.$ppre() | ||
| 367 | } | ||
| 368 | |||
| 369 | fn pclk(clocks: &Clocks) -> u32 { | ||
| 370 | clocks.$pclk().0 | ||
| 371 | } | ||
| 372 | } | ||
| 373 | } | ||
| 374 | }; | ||
| 375 | |||
| 376 | ($module:ident: ($TYPE:ident, $INT:ident, $apbenr:ident, $enrbit:expr, $apbrstr:ident, $rstrbit:expr, $ppre:ident, $pclk: ident), 1) => { | ||
| 377 | mod $module { | ||
| 378 | use super::*; | ||
| 379 | use crate::hal::pac::{$TYPE, RCC}; | ||
| 380 | |||
| 381 | impl sealed::Sealed for $TYPE {} | ||
| 382 | |||
| 383 | impl Instance for $TYPE { | ||
| 384 | type Interrupt = interrupt::$INT; | ||
| 385 | const REAL_ALARM_COUNT: usize = 1; | ||
| 386 | |||
| 387 | fn enable_clock(&self) { | ||
| 388 | // NOTE(unsafe) It will only be used for atomic operations | ||
| 389 | unsafe { | ||
| 390 | let rcc = &*RCC::ptr(); | ||
| 391 | |||
| 392 | bb::set(&rcc.$apbenr, $enrbit); | ||
| 393 | bb::set(&rcc.$apbrstr, $rstrbit); | ||
| 394 | bb::clear(&rcc.$apbrstr, $rstrbit); | ||
| 395 | } | ||
| 396 | } | ||
| 397 | |||
| 398 | fn set_compare(&self, n: usize, value: u16) { | ||
| 399 | // NOTE(unsafe) these registers accept all the range of u16 values | ||
| 400 | match n { | ||
| 401 | 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }), | ||
| 402 | 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }), | ||
| 403 | _ => {} | ||
| 404 | } | ||
| 405 | } | ||
| 406 | |||
| 407 | fn set_compare_interrupt(&self, n: usize, enable: bool) { | ||
| 408 | if n > 1 { | ||
| 409 | return; | ||
| 410 | } | ||
| 411 | let bit = n as u8 + 1; | ||
| 412 | unsafe { | ||
| 413 | if enable { | ||
| 414 | bb::set(&self.dier, bit); | ||
| 415 | } else { | ||
| 416 | bb::clear(&self.dier, bit); | ||
| 417 | } | ||
| 418 | } | ||
| 419 | } | ||
| 420 | |||
| 421 | fn compare_interrupt_status(&self, n: usize) -> bool { | ||
| 422 | let status = self.sr.read(); | ||
| 423 | match n { | ||
| 424 | 0 => status.cc1if().bit_is_set(), | ||
| 425 | 1 => status.cc2if().bit_is_set(), | ||
| 426 | _ => false, | ||
| 427 | } | ||
| 428 | } | ||
| 429 | |||
| 430 | fn compare_clear_flag(&self, n: usize) { | ||
| 431 | if n > 1 { | ||
| 432 | return; | ||
| 433 | } | ||
| 434 | let bit = n as u8 + 1; | ||
| 435 | unsafe { | ||
| 436 | bb::clear(&self.sr, bit); | ||
| 437 | } | ||
| 438 | } | ||
| 439 | |||
| 440 | fn overflow_interrupt_status(&self) -> bool { | ||
| 441 | self.sr.read().uif().bit_is_set() | ||
| 442 | } | ||
| 443 | |||
| 444 | fn overflow_clear_flag(&self) { | ||
| 445 | unsafe { | ||
| 446 | bb::clear(&self.sr, 0); | ||
| 447 | } | ||
| 448 | } | ||
| 449 | |||
| 450 | fn set_psc_arr(&self, psc: u16, arr: u16) { | ||
| 451 | // NOTE(unsafe) All u16 values are valid | ||
| 452 | self.psc.write(|w| unsafe { w.bits(psc.into()) }); | ||
| 453 | self.arr.write(|w| unsafe { w.bits(arr.into()) }); | ||
| 454 | |||
| 455 | unsafe { | ||
| 456 | // Set URS, generate update, clear URS | ||
| 457 | bb::set(&self.cr1, 2); | ||
| 458 | self.egr.write(|w| w.ug().set_bit()); | ||
| 459 | bb::clear(&self.cr1, 2); | ||
| 460 | } | ||
| 461 | } | ||
| 462 | |||
| 463 | fn stop_and_reset(&self) { | ||
| 464 | unsafe { | ||
| 465 | bb::clear(&self.cr1, 0); | ||
| 466 | } | ||
| 467 | self.cnt.reset(); | ||
| 468 | } | ||
| 469 | |||
| 470 | fn start(&self) { | ||
| 471 | unsafe { bb::set(&self.cr1, 0) } | ||
| 472 | } | ||
| 473 | |||
| 474 | fn counter(&self) -> u16 { | ||
| 475 | self.cnt.read().bits() as u16 | ||
| 476 | } | ||
| 477 | |||
| 478 | fn ppre(clocks: &Clocks) -> u8 { | ||
| 479 | clocks.$ppre() | ||
| 480 | } | ||
| 481 | |||
| 482 | fn pclk(clocks: &Clocks) -> u32 { | ||
| 483 | clocks.$pclk().0 | ||
| 484 | } | ||
| 485 | } | ||
| 486 | } | ||
| 487 | }; | ||
| 488 | } | ||
| 489 | |||
| 490 | #[cfg(not(feature = "stm32f410"))] | ||
| 491 | impl_timer!(tim2: (TIM2, TIM2, apb1enr, 0, apb1rstr, 0, ppre1, pclk1), 3); | ||
| 492 | |||
| 493 | #[cfg(not(feature = "stm32f410"))] | ||
| 494 | impl_timer!(tim3: (TIM3, TIM3, apb1enr, 1, apb1rstr, 1, ppre1, pclk1), 3); | ||
| 495 | |||
| 496 | #[cfg(not(feature = "stm32f410"))] | ||
| 497 | impl_timer!(tim4: (TIM4, TIM4, apb1enr, 2, apb1rstr, 2, ppre1, pclk1), 3); | ||
| 498 | |||
| 499 | impl_timer!(tim5: (TIM5, TIM5, apb1enr, 3, apb1rstr, 3, ppre1, pclk1), 3); | ||
| 500 | |||
| 501 | impl_timer!(tim9: (TIM9, TIM1_BRK_TIM9, apb2enr, 16, apb2rstr, 16, ppre2, pclk2), 1); | ||
| 502 | |||
| 503 | #[cfg(not(any(feature = "stm32f401", feature = "stm32f410", feature = "stm32f411")))] | ||
| 504 | impl_timer!(tim12: (TIM12, TIM8_BRK_TIM12, apb1enr, 6, apb1rstr, 6, ppre1, pclk1), 1); | ||
