diff options
| -rw-r--r-- | embassy-stm32/src/can/fdcan.rs | 413 | ||||
| -rw-r--r-- | tests/stm32/src/bin/can.rs | 8 | ||||
| -rw-r--r-- | tests/stm32/src/bin/can_common.rs | 9 | ||||
| -rw-r--r-- | tests/stm32/src/bin/fdcan.rs | 4 |
4 files changed, 258 insertions, 176 deletions
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index 81ceb06aa..b772a3ca0 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs | |||
| @@ -3,6 +3,7 @@ use core::future::poll_fn; | |||
| 3 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 4 | use core::task::Poll; | 4 | use core::task::Poll; |
| 5 | 5 | ||
| 6 | use embassy_hal_internal::interrupt::InterruptExt; | ||
| 6 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 7 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 8 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 8 | use embassy_sync::channel::{Channel, DynamicReceiver, DynamicSender}; | 9 | use embassy_sync::channel::{Channel, DynamicReceiver, DynamicSender}; |
| @@ -40,7 +41,7 @@ pub struct IT0InterruptHandler<T: Instance> { | |||
| 40 | // We use IT0 for everything currently | 41 | // We use IT0 for everything currently |
| 41 | impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0InterruptHandler<T> { | 42 | impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0InterruptHandler<T> { |
| 42 | unsafe fn on_interrupt() { | 43 | unsafe fn on_interrupt() { |
| 43 | let regs = T::regs(); | 44 | let regs = T::registers().regs; |
| 44 | 45 | ||
| 45 | let ir = regs.ir().read(); | 46 | let ir = regs.ir().read(); |
| 46 | 47 | ||
| @@ -140,22 +141,13 @@ pub enum OperatingMode { | |||
| 140 | //TestMode, | 141 | //TestMode, |
| 141 | } | 142 | } |
| 142 | 143 | ||
| 143 | /// FDCAN Configuration instance instance | ||
| 144 | /// Create instance of this first | ||
| 145 | pub struct CanConfigurator<'d, T: Instance> { | ||
| 146 | config: crate::can::fd::config::FdCanConfig, | ||
| 147 | /// Reference to internals. | ||
| 148 | instance: FdcanInstance<'d, T>, | ||
| 149 | properties: Properties<T>, | ||
| 150 | } | ||
| 151 | |||
| 152 | fn calc_ns_per_timer_tick<T: Instance>(mode: crate::can::fd::config::FrameTransmissionConfig) -> u64 { | 144 | fn calc_ns_per_timer_tick<T: Instance>(mode: crate::can::fd::config::FrameTransmissionConfig) -> u64 { |
| 153 | match mode { | 145 | match mode { |
| 154 | // Use timestamp from Rx FIFO to adjust timestamp reported to user | 146 | // Use timestamp from Rx FIFO to adjust timestamp reported to user |
| 155 | crate::can::fd::config::FrameTransmissionConfig::ClassicCanOnly => { | 147 | crate::can::fd::config::FrameTransmissionConfig::ClassicCanOnly => { |
| 156 | let freq = T::frequency(); | 148 | let freq = T::frequency(); |
| 157 | let prescale: u64 = | 149 | let prescale: u64 = ({ T::registers().regs.nbtp().read().nbrp() } + 1) as u64 |
| 158 | ({ T::regs().nbtp().read().nbrp() } + 1) as u64 * ({ T::regs().tscc().read().tcp() } + 1) as u64; | 150 | * ({ T::registers().regs.tscc().read().tcp() } + 1) as u64; |
| 159 | 1_000_000_000 as u64 / (freq.0 as u64 * prescale) | 151 | 1_000_000_000 as u64 / (freq.0 as u64 * prescale) |
| 160 | } | 152 | } |
| 161 | // For VBR this is too hard because the FDCAN timer switches clock rate you need to configure to use | 153 | // For VBR this is too hard because the FDCAN timer switches clock rate you need to configure to use |
| @@ -164,6 +156,18 @@ fn calc_ns_per_timer_tick<T: Instance>(mode: crate::can::fd::config::FrameTransm | |||
| 164 | } | 156 | } |
| 165 | } | 157 | } |
| 166 | 158 | ||
| 159 | /// FDCAN Configuration instance instance | ||
| 160 | /// Create instance of this first | ||
| 161 | pub struct CanConfigurator<'d, T: Instance> { | ||
| 162 | config: crate::can::fd::config::FdCanConfig, | ||
| 163 | info: &'static Info, | ||
| 164 | state: &'static State, | ||
| 165 | /// Reference to internals. | ||
| 166 | _instance: FdcanInstance<'d, T>, | ||
| 167 | properties: Properties, | ||
| 168 | periph_clock: crate::time::Hertz, | ||
| 169 | } | ||
| 170 | |||
| 167 | impl<'d, T: Instance> CanConfigurator<'d, T> { | 171 | impl<'d, T: Instance> CanConfigurator<'d, T> { |
| 168 | /// Creates a new Fdcan instance, keeping the peripheral in sleep mode. | 172 | /// Creates a new Fdcan instance, keeping the peripheral in sleep mode. |
| 169 | /// You must call [Fdcan::enable_non_blocking] to use the peripheral. | 173 | /// You must call [Fdcan::enable_non_blocking] to use the peripheral. |
| @@ -196,16 +200,18 @@ impl<'d, T: Instance> CanConfigurator<'d, T> { | |||
| 196 | T::IT1Interrupt::unpend(); // Not unsafe | 200 | T::IT1Interrupt::unpend(); // Not unsafe |
| 197 | T::IT1Interrupt::enable(); | 201 | T::IT1Interrupt::enable(); |
| 198 | } | 202 | } |
| 199 | |||
| 200 | Self { | 203 | Self { |
| 201 | config, | 204 | config, |
| 202 | instance: FdcanInstance(peri), | 205 | info: T::info(), |
| 203 | properties: Properties::new(), | 206 | state: T::state(), |
| 207 | _instance: FdcanInstance(peri), | ||
| 208 | properties: Properties::new(T::info()), | ||
| 209 | periph_clock: T::frequency(), | ||
| 204 | } | 210 | } |
| 205 | } | 211 | } |
| 206 | 212 | ||
| 207 | /// Get driver properties | 213 | /// Get driver properties |
| 208 | pub fn properties(&self) -> &Properties<T> { | 214 | pub fn properties(&self) -> &Properties { |
| 209 | &self.properties | 215 | &self.properties |
| 210 | } | 216 | } |
| 211 | 217 | ||
| @@ -221,7 +227,7 @@ impl<'d, T: Instance> CanConfigurator<'d, T> { | |||
| 221 | 227 | ||
| 222 | /// Configures the bit timings calculated from supplied bitrate. | 228 | /// Configures the bit timings calculated from supplied bitrate. |
| 223 | pub fn set_bitrate(&mut self, bitrate: u32) { | 229 | pub fn set_bitrate(&mut self, bitrate: u32) { |
| 224 | let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap(); | 230 | let bit_timing = util::calc_can_timings(self.periph_clock, bitrate).unwrap(); |
| 225 | 231 | ||
| 226 | let nbtr = crate::can::fd::config::NominalBitTiming { | 232 | let nbtr = crate::can::fd::config::NominalBitTiming { |
| 227 | sync_jump_width: bit_timing.sync_jump_width, | 233 | sync_jump_width: bit_timing.sync_jump_width, |
| @@ -234,7 +240,7 @@ impl<'d, T: Instance> CanConfigurator<'d, T> { | |||
| 234 | 240 | ||
| 235 | /// Configures the bit timings for VBR data calculated from supplied bitrate. This also sets confit to allow can FD and VBR | 241 | /// Configures the bit timings for VBR data calculated from supplied bitrate. This also sets confit to allow can FD and VBR |
| 236 | pub fn set_fd_data_bitrate(&mut self, bitrate: u32, transceiver_delay_compensation: bool) { | 242 | pub fn set_fd_data_bitrate(&mut self, bitrate: u32, transceiver_delay_compensation: bool) { |
| 237 | let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap(); | 243 | let bit_timing = util::calc_can_timings(self.periph_clock, bitrate).unwrap(); |
| 238 | // Note, used existing calcluation for normal(non-VBR) bitrate, appears to work for 250k/1M | 244 | // Note, used existing calcluation for normal(non-VBR) bitrate, appears to work for 250k/1M |
| 239 | let nbtr = crate::can::fd::config::DataBitTiming { | 245 | let nbtr = crate::can::fd::config::DataBitTiming { |
| 240 | transceiver_delay_compensation, | 246 | transceiver_delay_compensation, |
| @@ -248,62 +254,68 @@ impl<'d, T: Instance> CanConfigurator<'d, T> { | |||
| 248 | } | 254 | } |
| 249 | 255 | ||
| 250 | /// Start in mode. | 256 | /// Start in mode. |
| 251 | pub fn start(self, mode: OperatingMode) -> Can<'d, T> { | 257 | pub fn start(self, mode: OperatingMode) -> Can<'d> { |
| 252 | let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(self.config.frame_transmit); | 258 | let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(self.config.frame_transmit); |
| 253 | critical_section::with(|_| unsafe { | 259 | critical_section::with(|_| { |
| 254 | T::mut_state().ns_per_timer_tick = ns_per_timer_tick; | 260 | let state = self.state as *const State; |
| 261 | unsafe { | ||
| 262 | let mut_state = state as *mut State; | ||
| 263 | (*mut_state).ns_per_timer_tick = ns_per_timer_tick; | ||
| 264 | } | ||
| 255 | }); | 265 | }); |
| 256 | T::registers().into_mode(self.config, mode); | 266 | T::registers().into_mode(self.config, mode); |
| 257 | let ret = Can { | 267 | Can { |
| 258 | config: self.config, | 268 | config: self.config, |
| 259 | instance: self.instance, | 269 | info: self.info, |
| 270 | state: self.state, | ||
| 271 | instance: T::info().regs.regs, | ||
| 260 | _mode: mode, | 272 | _mode: mode, |
| 261 | properties: self.properties, | 273 | properties: Properties::new(T::info()), |
| 262 | }; | 274 | } |
| 263 | ret | ||
| 264 | } | 275 | } |
| 265 | 276 | ||
| 266 | /// Start, entering mode. Does same as start(mode) | 277 | /// Start, entering mode. Does same as start(mode) |
| 267 | pub fn into_normal_mode(self) -> Can<'d, T> { | 278 | pub fn into_normal_mode(self) -> Can<'d> { |
| 268 | self.start(OperatingMode::NormalOperationMode) | 279 | self.start(OperatingMode::NormalOperationMode) |
| 269 | } | 280 | } |
| 270 | 281 | ||
| 271 | /// Start, entering mode. Does same as start(mode) | 282 | /// Start, entering mode. Does same as start(mode) |
| 272 | pub fn into_internal_loopback_mode(self) -> Can<'d, T> { | 283 | pub fn into_internal_loopback_mode(self) -> Can<'d> { |
| 273 | self.start(OperatingMode::InternalLoopbackMode) | 284 | self.start(OperatingMode::InternalLoopbackMode) |
| 274 | } | 285 | } |
| 275 | 286 | ||
| 276 | /// Start, entering mode. Does same as start(mode) | 287 | /// Start, entering mode. Does same as start(mode) |
| 277 | pub fn into_external_loopback_mode(self) -> Can<'d, T> { | 288 | pub fn into_external_loopback_mode(self) -> Can<'d> { |
| 278 | self.start(OperatingMode::ExternalLoopbackMode) | 289 | self.start(OperatingMode::ExternalLoopbackMode) |
| 279 | } | 290 | } |
| 280 | } | 291 | } |
| 281 | 292 | ||
| 282 | /// FDCAN Instance | 293 | /// FDCAN Instance |
| 283 | pub struct Can<'d, T: Instance> { | 294 | pub struct Can<'d> { |
| 284 | config: crate::can::fd::config::FdCanConfig, | 295 | config: crate::can::fd::config::FdCanConfig, |
| 285 | /// Reference to internals. | 296 | info: &'static Info, |
| 286 | instance: FdcanInstance<'d, T>, | 297 | state: &'static State, |
| 298 | instance: &'d crate::pac::can::Fdcan, | ||
| 287 | _mode: OperatingMode, | 299 | _mode: OperatingMode, |
| 288 | properties: Properties<T>, | 300 | properties: Properties, |
| 289 | } | 301 | } |
| 290 | 302 | ||
| 291 | impl<'d, T: Instance> Can<'d, T> { | 303 | impl<'d> Can<'d> { |
| 292 | /// Get driver properties | 304 | /// Get driver properties |
| 293 | pub fn properties(&self) -> &Properties<T> { | 305 | pub fn properties(&self) -> &Properties { |
| 294 | &self.properties | 306 | &self.properties |
| 295 | } | 307 | } |
| 296 | 308 | ||
| 297 | /// Flush one of the TX mailboxes. | 309 | /// Flush one of the TX mailboxes. |
| 298 | pub async fn flush(&self, idx: usize) { | 310 | pub async fn flush(&self, idx: usize) { |
| 299 | poll_fn(|cx| { | 311 | poll_fn(|cx| { |
| 300 | T::state().tx_mode.register(cx.waker()); | 312 | self.state.tx_mode.register(cx.waker()); |
| 301 | 313 | ||
| 302 | if idx > 3 { | 314 | if idx > 3 { |
| 303 | panic!("Bad mailbox"); | 315 | panic!("Bad mailbox"); |
| 304 | } | 316 | } |
| 305 | let idx = 1 << idx; | 317 | let idx = 1 << idx; |
| 306 | if !T::regs().txbrp().read().trp(idx) { | 318 | if !self.info.regs.regs.txbrp().read().trp(idx) { |
| 307 | return Poll::Ready(()); | 319 | return Poll::Ready(()); |
| 308 | } | 320 | } |
| 309 | 321 | ||
| @@ -317,12 +329,12 @@ impl<'d, T: Instance> Can<'d, T> { | |||
| 317 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 329 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 318 | /// transmitted, then tries again. | 330 | /// transmitted, then tries again. |
| 319 | pub async fn write(&mut self, frame: &Frame) -> Option<Frame> { | 331 | pub async fn write(&mut self, frame: &Frame) -> Option<Frame> { |
| 320 | T::state().tx_mode.write::<T>(frame).await | 332 | self.state.tx_mode.write(self.info, frame).await |
| 321 | } | 333 | } |
| 322 | 334 | ||
| 323 | /// Returns the next received message frame | 335 | /// Returns the next received message frame |
| 324 | pub async fn read(&mut self) -> Result<Envelope, BusError> { | 336 | pub async fn read(&mut self) -> Result<Envelope, BusError> { |
| 325 | T::state().rx_mode.read_classic::<T>().await | 337 | self.state.rx_mode.read_classic(self.info, self.state).await |
| 326 | } | 338 | } |
| 327 | 339 | ||
| 328 | /// Queues the message to be sent but exerts backpressure. If a lower-priority | 340 | /// Queues the message to be sent but exerts backpressure. If a lower-priority |
| @@ -330,58 +342,61 @@ impl<'d, T: Instance> Can<'d, T> { | |||
| 330 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 342 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 331 | /// transmitted, then tries again. | 343 | /// transmitted, then tries again. |
| 332 | pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> { | 344 | pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> { |
| 333 | T::state().tx_mode.write_fd::<T>(frame).await | 345 | self.state.tx_mode.write_fd(self.info, frame).await |
| 334 | } | 346 | } |
| 335 | 347 | ||
| 336 | /// Returns the next received message frame | 348 | /// Returns the next received message frame |
| 337 | pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> { | 349 | pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> { |
| 338 | T::state().rx_mode.read_fd::<T>().await | 350 | self.state.rx_mode.read_fd(self.info, self.state).await |
| 339 | } | 351 | } |
| 340 | 352 | ||
| 341 | /// Split instance into separate portions: Tx(write), Rx(read), common properties | 353 | /// Split instance into separate portions: Tx(write), Rx(read), common properties |
| 342 | pub fn split(self) -> (CanTx<'d, T>, CanRx<'d, T>, Properties<T>) { | 354 | pub fn split(self) -> (CanTx<'d>, CanRx<'d>, Properties) { |
| 343 | ( | 355 | ( |
| 344 | CanTx { | 356 | CanTx { |
| 357 | info: self.info, | ||
| 358 | state: self.state, | ||
| 345 | config: self.config, | 359 | config: self.config, |
| 346 | _instance: self.instance, | 360 | _instance: self.instance, |
| 347 | _mode: self._mode, | 361 | _mode: self._mode, |
| 348 | }, | 362 | }, |
| 349 | CanRx { | 363 | CanRx { |
| 350 | _instance1: PhantomData::<T>, | 364 | info: self.info, |
| 351 | _instance2: T::regs(), | 365 | state: self.state, |
| 366 | _instance: self.instance, | ||
| 352 | _mode: self._mode, | 367 | _mode: self._mode, |
| 353 | }, | 368 | }, |
| 354 | self.properties, | 369 | self.properties, |
| 355 | ) | 370 | ) |
| 356 | } | 371 | } |
| 357 | |||
| 358 | /// Join split rx and tx portions back together | 372 | /// Join split rx and tx portions back together |
| 359 | pub fn join(tx: CanTx<'d, T>, rx: CanRx<'d, T>) -> Self { | 373 | pub fn join(tx: CanTx<'d>, rx: CanRx<'d>) -> Self { |
| 360 | Can { | 374 | Can { |
| 361 | config: tx.config, | 375 | config: tx.config, |
| 362 | //_instance2: T::regs(), | 376 | info: tx.info, |
| 377 | state: tx.state, | ||
| 363 | instance: tx._instance, | 378 | instance: tx._instance, |
| 364 | _mode: rx._mode, | 379 | _mode: rx._mode, |
| 365 | properties: Properties::new(), | 380 | properties: Properties::new(tx.info), |
| 366 | } | 381 | } |
| 367 | } | 382 | } |
| 368 | 383 | ||
| 369 | /// Return a buffered instance of driver without CAN FD support. User must supply Buffers | 384 | /// Return a buffered instance of driver without CAN FD support. User must supply Buffers |
| 370 | pub fn buffered<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>( | 385 | pub fn buffered<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>( |
| 371 | &self, | 386 | self, |
| 372 | tx_buf: &'static mut TxBuf<TX_BUF_SIZE>, | 387 | tx_buf: &'static mut TxBuf<TX_BUF_SIZE>, |
| 373 | rxb: &'static mut RxBuf<RX_BUF_SIZE>, | 388 | rxb: &'static mut RxBuf<RX_BUF_SIZE>, |
| 374 | ) -> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> { | 389 | ) -> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { |
| 375 | BufferedCan::new(PhantomData::<T>, T::regs(), self._mode, tx_buf, rxb) | 390 | BufferedCan::new(self.info, self.state, self.info.regs.regs, self._mode, tx_buf, rxb) |
| 376 | } | 391 | } |
| 377 | 392 | ||
| 378 | /// Return a buffered instance of driver with CAN FD support. User must supply Buffers | 393 | /// Return a buffered instance of driver with CAN FD support. User must supply Buffers |
| 379 | pub fn buffered_fd<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>( | 394 | pub fn buffered_fd<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>( |
| 380 | &self, | 395 | self, |
| 381 | tx_buf: &'static mut TxFdBuf<TX_BUF_SIZE>, | 396 | tx_buf: &'static mut TxFdBuf<TX_BUF_SIZE>, |
| 382 | rxb: &'static mut RxFdBuf<RX_BUF_SIZE>, | 397 | rxb: &'static mut RxFdBuf<RX_BUF_SIZE>, |
| 383 | ) -> BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> { | 398 | ) -> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { |
| 384 | BufferedCanFd::new(PhantomData::<T>, T::regs(), self._mode, tx_buf, rxb) | 399 | BufferedCanFd::new(self.info, self.state, self.info.regs.regs, self._mode, tx_buf, rxb) |
| 385 | } | 400 | } |
| 386 | } | 401 | } |
| 387 | 402 | ||
| @@ -392,52 +407,57 @@ pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result< | |||
| 392 | pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>; | 407 | pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>; |
| 393 | 408 | ||
| 394 | /// Buffered FDCAN Instance | 409 | /// Buffered FDCAN Instance |
| 395 | pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { | 410 | pub struct BufferedCan<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { |
| 396 | _instance1: PhantomData<T>, | 411 | info: &'static Info, |
| 397 | _instance2: &'d crate::pac::can::Fdcan, | 412 | state: &'static State, |
| 413 | _instance: &'d crate::pac::can::Fdcan, | ||
| 398 | _mode: OperatingMode, | 414 | _mode: OperatingMode, |
| 399 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, | 415 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, |
| 400 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, | 416 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, |
| 401 | properties: Properties<T>, | 417 | properties: Properties, |
| 402 | } | 418 | } |
| 403 | 419 | ||
| 404 | impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | 420 | impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { |
| 405 | BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> | ||
| 406 | { | ||
| 407 | fn new( | 421 | fn new( |
| 408 | _instance1: PhantomData<T>, | 422 | info: &'static Info, |
| 409 | _instance2: &'d crate::pac::can::Fdcan, | 423 | state: &'static State, |
| 424 | _instance: &'d crate::pac::can::Fdcan, | ||
| 410 | _mode: OperatingMode, | 425 | _mode: OperatingMode, |
| 411 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, | 426 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, |
| 412 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, | 427 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, |
| 413 | ) -> Self { | 428 | ) -> Self { |
| 414 | BufferedCan { | 429 | BufferedCan { |
| 415 | _instance1, | 430 | info, |
| 416 | _instance2, | 431 | state, |
| 432 | _instance, | ||
| 417 | _mode, | 433 | _mode, |
| 418 | tx_buf, | 434 | tx_buf, |
| 419 | rx_buf, | 435 | rx_buf, |
| 420 | properties: Properties::new(), | 436 | properties: Properties::new(info), |
| 421 | } | 437 | } |
| 422 | .setup() | 438 | .setup() |
| 423 | } | 439 | } |
| 424 | 440 | ||
| 425 | /// Get driver properties | 441 | /// Get driver properties |
| 426 | pub fn properties(&self) -> &Properties<T> { | 442 | pub fn properties(&self) -> &Properties { |
| 427 | &self.properties | 443 | &self.properties |
| 428 | } | 444 | } |
| 429 | 445 | ||
| 430 | fn setup(self) -> Self { | 446 | fn setup(self) -> Self { |
| 431 | // We don't want interrupts being processed while we change modes. | 447 | // We don't want interrupts being processed while we change modes. |
| 432 | critical_section::with(|_| unsafe { | 448 | critical_section::with(|_| { |
| 433 | let rx_inner = super::common::ClassicBufferedRxInner { | 449 | let rx_inner = super::common::ClassicBufferedRxInner { |
| 434 | rx_sender: self.rx_buf.sender().into(), | 450 | rx_sender: self.rx_buf.sender().into(), |
| 435 | }; | 451 | }; |
| 436 | let tx_inner = super::common::ClassicBufferedTxInner { | 452 | let tx_inner = super::common::ClassicBufferedTxInner { |
| 437 | tx_receiver: self.tx_buf.receiver().into(), | 453 | tx_receiver: self.tx_buf.receiver().into(), |
| 438 | }; | 454 | }; |
| 439 | T::mut_state().rx_mode = RxMode::ClassicBuffered(rx_inner); | 455 | let state = self.state as *const State; |
| 440 | T::mut_state().tx_mode = TxMode::ClassicBuffered(tx_inner); | 456 | unsafe { |
| 457 | let mut_state = state as *mut State; | ||
| 458 | (*mut_state).rx_mode = RxMode::ClassicBuffered(rx_inner); | ||
| 459 | (*mut_state).tx_mode = TxMode::ClassicBuffered(tx_inner); | ||
| 460 | } | ||
| 441 | }); | 461 | }); |
| 442 | self | 462 | self |
| 443 | } | 463 | } |
| @@ -445,7 +465,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 445 | /// Async write frame to TX buffer. | 465 | /// Async write frame to TX buffer. |
| 446 | pub async fn write(&mut self, frame: Frame) { | 466 | pub async fn write(&mut self, frame: Frame) { |
| 447 | self.tx_buf.send(frame).await; | 467 | self.tx_buf.send(frame).await; |
| 448 | T::IT0Interrupt::pend(); // Wake for Tx | 468 | self.info.interrupt0.pend(); // Wake for Tx |
| 469 | //T::IT0Interrupt::pend(); // Wake for Tx | ||
| 449 | } | 470 | } |
| 450 | 471 | ||
| 451 | /// Async read frame from RX buffer. | 472 | /// Async read frame from RX buffer. |
| @@ -457,7 +478,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 457 | pub fn writer(&self) -> BufferedCanSender { | 478 | pub fn writer(&self) -> BufferedCanSender { |
| 458 | BufferedCanSender { | 479 | BufferedCanSender { |
| 459 | tx_buf: self.tx_buf.sender().into(), | 480 | tx_buf: self.tx_buf.sender().into(), |
| 460 | waker: T::IT0Interrupt::pend, | 481 | waker: self.info.tx_waker, |
| 461 | } | 482 | } |
| 462 | } | 483 | } |
| 463 | 484 | ||
| @@ -467,13 +488,15 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 467 | } | 488 | } |
| 468 | } | 489 | } |
| 469 | 490 | ||
| 470 | impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop | 491 | impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { |
| 471 | for BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> | ||
| 472 | { | ||
| 473 | fn drop(&mut self) { | 492 | fn drop(&mut self) { |
| 474 | critical_section::with(|_| unsafe { | 493 | critical_section::with(|_| { |
| 475 | T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | 494 | let state = self.state as *const State; |
| 476 | T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | 495 | unsafe { |
| 496 | let mut_state = state as *mut State; | ||
| 497 | (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 498 | (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 499 | } | ||
| 477 | }); | 500 | }); |
| 478 | } | 501 | } |
| 479 | } | 502 | } |
| @@ -484,16 +507,6 @@ pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Resul | |||
| 484 | /// User supplied buffer for TX buffering | 507 | /// User supplied buffer for TX buffering |
| 485 | pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; | 508 | pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; |
| 486 | 509 | ||
| 487 | /// Buffered FDCAN Instance | ||
| 488 | pub struct BufferedCanFd<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { | ||
| 489 | _instance1: PhantomData<T>, | ||
| 490 | _instance2: &'d crate::pac::can::Fdcan, | ||
| 491 | _mode: OperatingMode, | ||
| 492 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, | ||
| 493 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, | ||
| 494 | properties: Properties<T>, | ||
| 495 | } | ||
| 496 | |||
| 497 | /// Sender that can be used for sending CAN frames. | 510 | /// Sender that can be used for sending CAN frames. |
| 498 | #[derive(Copy, Clone)] | 511 | #[derive(Copy, Clone)] |
| 499 | pub struct BufferedFdCanSender { | 512 | pub struct BufferedFdCanSender { |
| @@ -524,43 +537,58 @@ impl BufferedFdCanSender { | |||
| 524 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 537 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 525 | pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<FdEnvelope, BusError>>; | 538 | pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<FdEnvelope, BusError>>; |
| 526 | 539 | ||
| 527 | impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | 540 | /// Buffered FDCAN Instance |
| 528 | BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> | 541 | pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { |
| 529 | { | 542 | info: &'static Info, |
| 543 | state: &'static State, | ||
| 544 | _instance: &'d crate::pac::can::Fdcan, | ||
| 545 | _mode: OperatingMode, | ||
| 546 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, | ||
| 547 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, | ||
| 548 | properties: Properties, | ||
| 549 | } | ||
| 550 | |||
| 551 | impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { | ||
| 530 | fn new( | 552 | fn new( |
| 531 | _instance1: PhantomData<T>, | 553 | info: &'static Info, |
| 532 | _instance2: &'d crate::pac::can::Fdcan, | 554 | state: &'static State, |
| 555 | _instance: &'d crate::pac::can::Fdcan, | ||
| 533 | _mode: OperatingMode, | 556 | _mode: OperatingMode, |
| 534 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, | 557 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, |
| 535 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, | 558 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, |
| 536 | ) -> Self { | 559 | ) -> Self { |
| 537 | BufferedCanFd { | 560 | BufferedCanFd { |
| 538 | _instance1, | 561 | info, |
| 539 | _instance2, | 562 | state, |
| 563 | _instance, | ||
| 540 | _mode, | 564 | _mode, |
| 541 | tx_buf, | 565 | tx_buf, |
| 542 | rx_buf, | 566 | rx_buf, |
| 543 | properties: Properties::new(), | 567 | properties: Properties::new(info), |
| 544 | } | 568 | } |
| 545 | .setup() | 569 | .setup() |
| 546 | } | 570 | } |
| 547 | 571 | ||
| 548 | /// Get driver properties | 572 | /// Get driver properties |
| 549 | pub fn properties(&self) -> &Properties<T> { | 573 | pub fn properties(&self) -> &Properties { |
| 550 | &self.properties | 574 | &self.properties |
| 551 | } | 575 | } |
| 552 | 576 | ||
| 553 | fn setup(self) -> Self { | 577 | fn setup(self) -> Self { |
| 554 | // We don't want interrupts being processed while we change modes. | 578 | // We don't want interrupts being processed while we change modes. |
| 555 | critical_section::with(|_| unsafe { | 579 | critical_section::with(|_| { |
| 556 | let rx_inner = super::common::FdBufferedRxInner { | 580 | let rx_inner = super::common::FdBufferedRxInner { |
| 557 | rx_sender: self.rx_buf.sender().into(), | 581 | rx_sender: self.rx_buf.sender().into(), |
| 558 | }; | 582 | }; |
| 559 | let tx_inner = super::common::FdBufferedTxInner { | 583 | let tx_inner = super::common::FdBufferedTxInner { |
| 560 | tx_receiver: self.tx_buf.receiver().into(), | 584 | tx_receiver: self.tx_buf.receiver().into(), |
| 561 | }; | 585 | }; |
| 562 | T::mut_state().rx_mode = RxMode::FdBuffered(rx_inner); | 586 | let state = self.state as *const State; |
| 563 | T::mut_state().tx_mode = TxMode::FdBuffered(tx_inner); | 587 | unsafe { |
| 588 | let mut_state = state as *mut State; | ||
| 589 | (*mut_state).rx_mode = RxMode::FdBuffered(rx_inner); | ||
| 590 | (*mut_state).tx_mode = TxMode::FdBuffered(tx_inner); | ||
| 591 | } | ||
| 564 | }); | 592 | }); |
| 565 | self | 593 | self |
| 566 | } | 594 | } |
| @@ -568,7 +596,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 568 | /// Async write frame to TX buffer. | 596 | /// Async write frame to TX buffer. |
| 569 | pub async fn write(&mut self, frame: FdFrame) { | 597 | pub async fn write(&mut self, frame: FdFrame) { |
| 570 | self.tx_buf.send(frame).await; | 598 | self.tx_buf.send(frame).await; |
| 571 | T::IT0Interrupt::pend(); // Wake for Tx | 599 | self.info.interrupt0.pend(); // Wake for Tx |
| 600 | //T::IT0Interrupt::pend(); // Wake for Tx | ||
| 572 | } | 601 | } |
| 573 | 602 | ||
| 574 | /// Async read frame from RX buffer. | 603 | /// Async read frame from RX buffer. |
| @@ -580,7 +609,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 580 | pub fn writer(&self) -> BufferedFdCanSender { | 609 | pub fn writer(&self) -> BufferedFdCanSender { |
| 581 | BufferedFdCanSender { | 610 | BufferedFdCanSender { |
| 582 | tx_buf: self.tx_buf.sender().into(), | 611 | tx_buf: self.tx_buf.sender().into(), |
| 583 | waker: T::IT0Interrupt::pend, | 612 | waker: self.info.tx_waker, |
| 584 | } | 613 | } |
| 585 | } | 614 | } |
| 586 | 615 | ||
| @@ -590,38 +619,55 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 590 | } | 619 | } |
| 591 | } | 620 | } |
| 592 | 621 | ||
| 593 | impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop | 622 | impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { |
| 594 | for BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> | ||
| 595 | { | ||
| 596 | fn drop(&mut self) { | 623 | fn drop(&mut self) { |
| 597 | critical_section::with(|_| unsafe { | 624 | critical_section::with(|_| { |
| 598 | T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | 625 | let state = self.state as *const State; |
| 599 | T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | 626 | unsafe { |
| 627 | let mut_state = state as *mut State; | ||
| 628 | (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 629 | (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 630 | } | ||
| 600 | }); | 631 | }); |
| 601 | } | 632 | } |
| 602 | } | 633 | } |
| 603 | 634 | ||
| 604 | /// FDCAN Rx only Instance | 635 | /// FDCAN Rx only Instance |
| 605 | pub struct CanRx<'d, T: Instance> { | 636 | pub struct CanRx<'d> { |
| 606 | _instance1: PhantomData<T>, | 637 | info: &'static Info, |
| 607 | _instance2: &'d crate::pac::can::Fdcan, | 638 | state: &'static State, |
| 639 | _instance: &'d crate::pac::can::Fdcan, | ||
| 608 | _mode: OperatingMode, | 640 | _mode: OperatingMode, |
| 609 | } | 641 | } |
| 610 | 642 | ||
| 643 | impl<'d> CanRx<'d> { | ||
| 644 | /// Returns the next received message frame | ||
| 645 | pub async fn read(&mut self) -> Result<Envelope, BusError> { | ||
| 646 | self.state.rx_mode.read_classic(&self.info, &self.state).await | ||
| 647 | } | ||
| 648 | |||
| 649 | /// Returns the next received message frame | ||
| 650 | pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> { | ||
| 651 | self.state.rx_mode.read_fd(&self.info, &self.state).await | ||
| 652 | } | ||
| 653 | } | ||
| 654 | |||
| 611 | /// FDCAN Tx only Instance | 655 | /// FDCAN Tx only Instance |
| 612 | pub struct CanTx<'d, T: Instance> { | 656 | pub struct CanTx<'d> { |
| 657 | info: &'static Info, | ||
| 658 | state: &'static State, | ||
| 613 | config: crate::can::fd::config::FdCanConfig, | 659 | config: crate::can::fd::config::FdCanConfig, |
| 614 | _instance: FdcanInstance<'d, T>, //(PeripheralRef<'a, T>); | 660 | _instance: &'d crate::pac::can::Fdcan, |
| 615 | _mode: OperatingMode, | 661 | _mode: OperatingMode, |
| 616 | } | 662 | } |
| 617 | 663 | ||
| 618 | impl<'c, 'd, T: Instance> CanTx<'d, T> { | 664 | impl<'c, 'd> CanTx<'d> { |
| 619 | /// Queues the message to be sent but exerts backpressure. If a lower-priority | 665 | /// Queues the message to be sent but exerts backpressure. If a lower-priority |
| 620 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames | 666 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames |
| 621 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 667 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 622 | /// transmitted, then tries again. | 668 | /// transmitted, then tries again. |
| 623 | pub async fn write(&mut self, frame: &Frame) -> Option<Frame> { | 669 | pub async fn write(&mut self, frame: &Frame) -> Option<Frame> { |
| 624 | T::state().tx_mode.write::<T>(frame).await | 670 | self.state.tx_mode.write(self.info, frame).await |
| 625 | } | 671 | } |
| 626 | 672 | ||
| 627 | /// Queues the message to be sent but exerts backpressure. If a lower-priority | 673 | /// Queues the message to be sent but exerts backpressure. If a lower-priority |
| @@ -629,19 +675,7 @@ impl<'c, 'd, T: Instance> CanTx<'d, T> { | |||
| 629 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 675 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 630 | /// transmitted, then tries again. | 676 | /// transmitted, then tries again. |
| 631 | pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> { | 677 | pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> { |
| 632 | T::state().tx_mode.write_fd::<T>(frame).await | 678 | self.state.tx_mode.write_fd(self.info, frame).await |
| 633 | } | ||
| 634 | } | ||
| 635 | |||
| 636 | impl<'c, 'd, T: Instance> CanRx<'d, T> { | ||
| 637 | /// Returns the next received message frame | ||
| 638 | pub async fn read(&mut self) -> Result<Envelope, BusError> { | ||
| 639 | T::state().rx_mode.read_classic::<T>().await | ||
| 640 | } | ||
| 641 | |||
| 642 | /// Returns the next received message frame | ||
| 643 | pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> { | ||
| 644 | T::state().rx_mode.read_fd::<T>().await | ||
| 645 | } | 679 | } |
| 646 | } | 680 | } |
| 647 | 681 | ||
| @@ -662,7 +696,7 @@ impl RxMode { | |||
| 662 | } | 696 | } |
| 663 | 697 | ||
| 664 | fn on_interrupt<T: Instance>(&self, fifonr: usize) { | 698 | fn on_interrupt<T: Instance>(&self, fifonr: usize) { |
| 665 | T::regs().ir().write(|w| w.set_rfn(fifonr, true)); | 699 | T::registers().regs.ir().write(|w| w.set_rfn(fifonr, true)); |
| 666 | match self { | 700 | match self { |
| 667 | RxMode::NonBuffered(waker) => { | 701 | RxMode::NonBuffered(waker) => { |
| 668 | waker.wake(); | 702 | waker.wake(); |
| @@ -696,7 +730,6 @@ impl RxMode { | |||
| 696 | } | 730 | } |
| 697 | } | 731 | } |
| 698 | 732 | ||
| 699 | //async fn read_classic<T: Instance>(&self) -> Result<Envelope, BusError> { | ||
| 700 | fn try_read_fd<T: Instance>(&self) -> Option<Result<FdEnvelope, BusError>> { | 733 | fn try_read_fd<T: Instance>(&self) -> Option<Result<FdEnvelope, BusError>> { |
| 701 | if let Some((frame, ts)) = T::registers().read(0) { | 734 | if let Some((frame, ts)) = T::registers().read(0) { |
| 702 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | 735 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); |
| @@ -712,14 +745,18 @@ impl RxMode { | |||
| 712 | } | 745 | } |
| 713 | } | 746 | } |
| 714 | 747 | ||
| 715 | fn read<T: Instance, F: CanHeader>(&self) -> Option<Result<(F, Timestamp), BusError>> { | 748 | fn read<F: CanHeader>( |
| 716 | if let Some((msg, ts)) = T::registers().read(0) { | 749 | &self, |
| 717 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | 750 | info: &'static Info, |
| 751 | state: &'static State, | ||
| 752 | ) -> Option<Result<(F, Timestamp), BusError>> { | ||
| 753 | if let Some((msg, ts)) = info.regs.read(0) { | ||
| 754 | let ts = info.calc_timestamp(state.ns_per_timer_tick, ts); | ||
| 718 | Some(Ok((msg, ts))) | 755 | Some(Ok((msg, ts))) |
| 719 | } else if let Some((msg, ts)) = T::registers().read(1) { | 756 | } else if let Some((msg, ts)) = info.regs.read(1) { |
| 720 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | 757 | let ts = info.calc_timestamp(state.ns_per_timer_tick, ts); |
| 721 | Some(Ok((msg, ts))) | 758 | Some(Ok((msg, ts))) |
| 722 | } else if let Some(err) = T::registers().curr_error() { | 759 | } else if let Some(err) = info.regs.curr_error() { |
| 723 | // TODO: this is probably wrong | 760 | // TODO: this is probably wrong |
| 724 | Some(Err(err)) | 761 | Some(Err(err)) |
| 725 | } else { | 762 | } else { |
| @@ -727,11 +764,16 @@ impl RxMode { | |||
| 727 | } | 764 | } |
| 728 | } | 765 | } |
| 729 | 766 | ||
| 730 | async fn read_async<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> { | 767 | async fn read_async<F: CanHeader>( |
| 731 | poll_fn(|cx| { | 768 | &self, |
| 732 | T::state().err_waker.register(cx.waker()); | 769 | info: &'static Info, |
| 770 | state: &'static State, | ||
| 771 | ) -> Result<(F, Timestamp), BusError> { | ||
| 772 | //let _ = self.read::<F>(info, state); | ||
| 773 | poll_fn(move |cx| { | ||
| 774 | state.err_waker.register(cx.waker()); | ||
| 733 | self.register(cx.waker()); | 775 | self.register(cx.waker()); |
| 734 | match self.read::<T, _>() { | 776 | match self.read::<_>(info, state) { |
| 735 | Some(result) => Poll::Ready(result), | 777 | Some(result) => Poll::Ready(result), |
| 736 | None => Poll::Pending, | 778 | None => Poll::Pending, |
| 737 | } | 779 | } |
| @@ -739,15 +781,15 @@ impl RxMode { | |||
| 739 | .await | 781 | .await |
| 740 | } | 782 | } |
| 741 | 783 | ||
| 742 | async fn read_classic<T: Instance>(&self) -> Result<Envelope, BusError> { | 784 | async fn read_classic(&self, info: &'static Info, state: &'static State) -> Result<Envelope, BusError> { |
| 743 | match self.read_async::<T, _>().await { | 785 | match self.read_async::<_>(info, state).await { |
| 744 | Ok((frame, ts)) => Ok(Envelope { ts, frame }), | 786 | Ok((frame, ts)) => Ok(Envelope { ts, frame }), |
| 745 | Err(e) => Err(e), | 787 | Err(e) => Err(e), |
| 746 | } | 788 | } |
| 747 | } | 789 | } |
| 748 | 790 | ||
| 749 | async fn read_fd<T: Instance>(&self) -> Result<FdEnvelope, BusError> { | 791 | async fn read_fd(&self, info: &'static Info, state: &'static State) -> Result<FdEnvelope, BusError> { |
| 750 | match self.read_async::<T, _>().await { | 792 | match self.read_async::<_>(info, state).await { |
| 751 | Ok((frame, ts)) => Ok(FdEnvelope { ts, frame }), | 793 | Ok((frame, ts)) => Ok(FdEnvelope { ts, frame }), |
| 752 | Err(e) => Err(e), | 794 | Err(e) => Err(e), |
| 753 | } | 795 | } |
| @@ -776,11 +818,11 @@ impl TxMode { | |||
| 776 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames | 818 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames |
| 777 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 819 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 778 | /// transmitted, then tries again. | 820 | /// transmitted, then tries again. |
| 779 | async fn write_generic<T: Instance, F: embedded_can::Frame + CanHeader>(&self, frame: &F) -> Option<F> { | 821 | async fn write_generic<F: embedded_can::Frame + CanHeader>(&self, info: &'static Info, frame: &F) -> Option<F> { |
| 780 | poll_fn(|cx| { | 822 | poll_fn(|cx| { |
| 781 | self.register(cx.waker()); | 823 | self.register(cx.waker()); |
| 782 | 824 | ||
| 783 | if let Ok(dropped) = T::registers().write(frame) { | 825 | if let Ok(dropped) = info.regs.write(frame) { |
| 784 | return Poll::Ready(dropped); | 826 | return Poll::Ready(dropped); |
| 785 | } | 827 | } |
| 786 | 828 | ||
| @@ -795,68 +837,70 @@ impl TxMode { | |||
| 795 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames | 837 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames |
| 796 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 838 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 797 | /// transmitted, then tries again. | 839 | /// transmitted, then tries again. |
| 798 | async fn write<T: Instance>(&self, frame: &Frame) -> Option<Frame> { | 840 | async fn write(&self, info: &'static Info, frame: &Frame) -> Option<Frame> { |
| 799 | self.write_generic::<T, _>(frame).await | 841 | self.write_generic::<_>(info, frame).await |
| 800 | } | 842 | } |
| 801 | 843 | ||
| 802 | /// Queues the message to be sent but exerts backpressure. If a lower-priority | 844 | /// Queues the message to be sent but exerts backpressure. If a lower-priority |
| 803 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames | 845 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames |
| 804 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 846 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 805 | /// transmitted, then tries again. | 847 | /// transmitted, then tries again. |
| 806 | async fn write_fd<T: Instance>(&self, frame: &FdFrame) -> Option<FdFrame> { | 848 | async fn write_fd(&self, info: &'static Info, frame: &FdFrame) -> Option<FdFrame> { |
| 807 | self.write_generic::<T, _>(frame).await | 849 | self.write_generic::<_>(info, frame).await |
| 808 | } | 850 | } |
| 809 | } | 851 | } |
| 810 | 852 | ||
| 811 | /// Common driver properties, including filters and error counters | 853 | /// Common driver properties, including filters and error counters |
| 812 | pub struct Properties<T> { | 854 | pub struct Properties { |
| 855 | info: &'static Info, | ||
| 813 | // phantom pointer to ensure !Sync | 856 | // phantom pointer to ensure !Sync |
| 814 | instance: PhantomData<*const T>, | 857 | //instance: PhantomData<*const T>, |
| 815 | } | 858 | } |
| 816 | 859 | ||
| 817 | impl<T: Instance> Properties<T> { | 860 | impl Properties { |
| 818 | fn new() -> Self { | 861 | fn new(info: &'static Info) -> Self { |
| 819 | Self { | 862 | Self { |
| 820 | instance: Default::default(), | 863 | info, |
| 864 | //instance: Default::default(), | ||
| 821 | } | 865 | } |
| 822 | } | 866 | } |
| 823 | 867 | ||
| 824 | /// Set a standard address CAN filter in the specified slot in FDCAN memory. | 868 | /// Set a standard address CAN filter in the specified slot in FDCAN memory. |
| 825 | #[inline] | 869 | #[inline] |
| 826 | pub fn set_standard_filter(&self, slot: StandardFilterSlot, filter: StandardFilter) { | 870 | pub fn set_standard_filter(&self, slot: StandardFilterSlot, filter: StandardFilter) { |
| 827 | T::registers().msg_ram_mut().filters.flssa[slot as usize].activate(filter); | 871 | self.info.regs.msg_ram_mut().filters.flssa[slot as usize].activate(filter); |
| 828 | } | 872 | } |
| 829 | 873 | ||
| 830 | /// Set the full array of standard address CAN filters in FDCAN memory. | 874 | /// Set the full array of standard address CAN filters in FDCAN memory. |
| 831 | /// Overwrites all standard address filters in memory. | 875 | /// Overwrites all standard address filters in memory. |
| 832 | pub fn set_standard_filters(&self, filters: &[StandardFilter; STANDARD_FILTER_MAX as usize]) { | 876 | pub fn set_standard_filters(&self, filters: &[StandardFilter; STANDARD_FILTER_MAX as usize]) { |
| 833 | for (i, f) in filters.iter().enumerate() { | 877 | for (i, f) in filters.iter().enumerate() { |
| 834 | T::registers().msg_ram_mut().filters.flssa[i].activate(*f); | 878 | self.info.regs.msg_ram_mut().filters.flssa[i].activate(*f); |
| 835 | } | 879 | } |
| 836 | } | 880 | } |
| 837 | 881 | ||
| 838 | /// Set an extended address CAN filter in the specified slot in FDCAN memory. | 882 | /// Set an extended address CAN filter in the specified slot in FDCAN memory. |
| 839 | #[inline] | 883 | #[inline] |
| 840 | pub fn set_extended_filter(&self, slot: ExtendedFilterSlot, filter: ExtendedFilter) { | 884 | pub fn set_extended_filter(&self, slot: ExtendedFilterSlot, filter: ExtendedFilter) { |
| 841 | T::registers().msg_ram_mut().filters.flesa[slot as usize].activate(filter); | 885 | self.info.regs.msg_ram_mut().filters.flesa[slot as usize].activate(filter); |
| 842 | } | 886 | } |
| 843 | 887 | ||
| 844 | /// Set the full array of extended address CAN filters in FDCAN memory. | 888 | /// Set the full array of extended address CAN filters in FDCAN memory. |
| 845 | /// Overwrites all extended address filters in memory. | 889 | /// Overwrites all extended address filters in memory. |
| 846 | pub fn set_extended_filters(&self, filters: &[ExtendedFilter; EXTENDED_FILTER_MAX as usize]) { | 890 | pub fn set_extended_filters(&self, filters: &[ExtendedFilter; EXTENDED_FILTER_MAX as usize]) { |
| 847 | for (i, f) in filters.iter().enumerate() { | 891 | for (i, f) in filters.iter().enumerate() { |
| 848 | T::registers().msg_ram_mut().filters.flesa[i].activate(*f); | 892 | self.info.regs.msg_ram_mut().filters.flesa[i].activate(*f); |
| 849 | } | 893 | } |
| 850 | } | 894 | } |
| 851 | 895 | ||
| 852 | /// Get the CAN RX error counter | 896 | /// Get the CAN RX error counter |
| 853 | pub fn rx_error_count(&self) -> u8 { | 897 | pub fn rx_error_count(&self) -> u8 { |
| 854 | T::regs().ecr().read().rec() | 898 | self.info.regs.regs.ecr().read().rec() |
| 855 | } | 899 | } |
| 856 | 900 | ||
| 857 | /// Get the CAN TX error counter | 901 | /// Get the CAN TX error counter |
| 858 | pub fn tx_error_count(&self) -> u8 { | 902 | pub fn tx_error_count(&self) -> u8 { |
| 859 | T::regs().ecr().read().tec() | 903 | self.info.regs.regs.ecr().read().tec() |
| 860 | } | 904 | } |
| 861 | 905 | ||
| 862 | /// Get the current bus error mode | 906 | /// Get the current bus error mode |
| @@ -864,7 +908,7 @@ impl<T: Instance> Properties<T> { | |||
| 864 | // This read will clear LEC and DLEC. This is not ideal, but protocol | 908 | // This read will clear LEC and DLEC. This is not ideal, but protocol |
| 865 | // error reporting in this driver should have a big ol' FIXME on it | 909 | // error reporting in this driver should have a big ol' FIXME on it |
| 866 | // anyway! | 910 | // anyway! |
| 867 | let psr = T::regs().psr().read(); | 911 | let psr = self.info.regs.regs.psr().read(); |
| 868 | match (psr.bo(), psr.ep()) { | 912 | match (psr.bo(), psr.ep()) { |
| 869 | (false, false) => BusErrorMode::ErrorActive, | 913 | (false, false) => BusErrorMode::ErrorActive, |
| 870 | (false, true) => BusErrorMode::ErrorPassive, | 914 | (false, true) => BusErrorMode::ErrorPassive, |
| @@ -892,10 +936,37 @@ impl State { | |||
| 892 | } | 936 | } |
| 893 | } | 937 | } |
| 894 | 938 | ||
| 939 | struct Info { | ||
| 940 | regs: Registers, | ||
| 941 | interrupt0: crate::interrupt::Interrupt, | ||
| 942 | _interrupt1: crate::interrupt::Interrupt, | ||
| 943 | tx_waker: fn(), | ||
| 944 | } | ||
| 945 | |||
| 946 | impl Info { | ||
| 947 | #[cfg(feature = "time")] | ||
| 948 | fn calc_timestamp(&self, ns_per_timer_tick: u64, ts_val: u16) -> Timestamp { | ||
| 949 | let now_embassy = embassy_time::Instant::now(); | ||
| 950 | if ns_per_timer_tick == 0 { | ||
| 951 | return now_embassy; | ||
| 952 | } | ||
| 953 | let cantime = { self.regs.regs.tscv().read().tsc() }; | ||
| 954 | let delta = cantime.overflowing_sub(ts_val).0 as u64; | ||
| 955 | let ns = ns_per_timer_tick * delta as u64; | ||
| 956 | now_embassy - embassy_time::Duration::from_nanos(ns) | ||
| 957 | } | ||
| 958 | |||
| 959 | #[cfg(not(feature = "time"))] | ||
| 960 | fn calc_timestamp(&self, _ns_per_timer_tick: u64, ts_val: u16) -> Timestamp { | ||
| 961 | ts_val | ||
| 962 | } | ||
| 963 | } | ||
| 964 | |||
| 895 | trait SealedInstance { | 965 | trait SealedInstance { |
| 896 | const MSG_RAM_OFFSET: usize; | 966 | const MSG_RAM_OFFSET: usize; |
| 897 | 967 | ||
| 898 | fn regs() -> &'static crate::pac::can::Fdcan; | 968 | fn info() -> &'static Info; |
| 969 | //fn regs() -> &'static crate::pac::can::Fdcan; | ||
| 899 | fn registers() -> crate::can::fd::peripheral::Registers; | 970 | fn registers() -> crate::can::fd::peripheral::Registers; |
| 900 | fn state() -> &'static State; | 971 | fn state() -> &'static State; |
| 901 | unsafe fn mut_state() -> &'static mut State; | 972 | unsafe fn mut_state() -> &'static mut State; |
| @@ -915,12 +986,20 @@ pub trait Instance: SealedInstance + RccPeripheral + 'static { | |||
| 915 | pub struct FdcanInstance<'a, T>(PeripheralRef<'a, T>); | 986 | pub struct FdcanInstance<'a, T>(PeripheralRef<'a, T>); |
| 916 | 987 | ||
| 917 | macro_rules! impl_fdcan { | 988 | macro_rules! impl_fdcan { |
| 918 | ($inst:ident, $msg_ram_inst:ident, $msg_ram_offset:literal) => { | 989 | ($inst:ident, |
| 990 | //$irq0:ident, $irq1:ident, | ||
| 991 | $msg_ram_inst:ident, $msg_ram_offset:literal) => { | ||
| 919 | impl SealedInstance for peripherals::$inst { | 992 | impl SealedInstance for peripherals::$inst { |
| 920 | const MSG_RAM_OFFSET: usize = $msg_ram_offset; | 993 | const MSG_RAM_OFFSET: usize = $msg_ram_offset; |
| 921 | 994 | ||
| 922 | fn regs() -> &'static crate::pac::can::Fdcan { | 995 | fn info() -> &'static Info { |
| 923 | &crate::pac::$inst | 996 | static INFO: Info = Info { |
| 997 | regs: Registers{regs: &crate::pac::$inst, msgram: &crate::pac::$msg_ram_inst, msg_ram_offset: $msg_ram_offset}, | ||
| 998 | interrupt0: crate::_generated::peripheral_interrupts::$inst::IT0::IRQ, | ||
| 999 | _interrupt1: crate::_generated::peripheral_interrupts::$inst::IT1::IRQ, | ||
| 1000 | tx_waker: crate::_generated::peripheral_interrupts::$inst::IT0::pend, | ||
| 1001 | }; | ||
| 1002 | &INFO | ||
| 924 | } | 1003 | } |
| 925 | fn registers() -> Registers { | 1004 | fn registers() -> Registers { |
| 926 | Registers{regs: &crate::pac::$inst, msgram: &crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET} | 1005 | Registers{regs: &crate::pac::$inst, msgram: &crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET} |
| @@ -939,7 +1018,7 @@ macro_rules! impl_fdcan { | |||
| 939 | if ns_per_timer_tick == 0 { | 1018 | if ns_per_timer_tick == 0 { |
| 940 | return now_embassy; | 1019 | return now_embassy; |
| 941 | } | 1020 | } |
| 942 | let cantime = { Self::regs().tscv().read().tsc() }; | 1021 | let cantime = { Self::registers().regs.tscv().read().tsc() }; |
| 943 | let delta = cantime.overflowing_sub(ts_val).0 as u64; | 1022 | let delta = cantime.overflowing_sub(ts_val).0 as u64; |
| 944 | let ns = ns_per_timer_tick * delta as u64; | 1023 | let ns = ns_per_timer_tick * delta as u64; |
| 945 | now_embassy - embassy_time::Duration::from_nanos(ns) | 1024 | now_embassy - embassy_time::Duration::from_nanos(ns) |
diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs index 551764458..004b1a729 100644 --- a/tests/stm32/src/bin/can.rs +++ b/tests/stm32/src/bin/can.rs | |||
| @@ -9,9 +9,7 @@ use common::*; | |||
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_stm32::bind_interrupts; | 10 | use embassy_stm32::bind_interrupts; |
| 11 | use embassy_stm32::can::filter::Mask32; | 11 | use embassy_stm32::can::filter::Mask32; |
| 12 | use embassy_stm32::can::{ | 12 | use embassy_stm32::can::{Fifo, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler}; |
| 13 | Can, Fifo, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler, | ||
| 14 | }; | ||
| 15 | use embassy_stm32::gpio::{Input, Pull}; | 13 | use embassy_stm32::gpio::{Input, Pull}; |
| 16 | use embassy_stm32::peripherals::CAN1; | 14 | use embassy_stm32::peripherals::CAN1; |
| 17 | use embassy_time::Duration; | 15 | use embassy_time::Duration; |
| @@ -20,6 +18,10 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 20 | mod can_common; | 18 | mod can_common; |
| 21 | use can_common::*; | 19 | use can_common::*; |
| 22 | 20 | ||
| 21 | type Can<'d> = embassy_stm32::can::Can<'d, embassy_stm32::peripherals::CAN1>; | ||
| 22 | type CanTx<'d> = embassy_stm32::can::CanTx<'d, embassy_stm32::peripherals::CAN1>; | ||
| 23 | type CanRx<'d> = embassy_stm32::can::CanRx<'d, embassy_stm32::peripherals::CAN1>; | ||
| 24 | |||
| 23 | bind_interrupts!(struct Irqs { | 25 | bind_interrupts!(struct Irqs { |
| 24 | CAN1_RX0 => Rx0InterruptHandler<CAN1>; | 26 | CAN1_RX0 => Rx0InterruptHandler<CAN1>; |
| 25 | CAN1_RX1 => Rx1InterruptHandler<CAN1>; | 27 | CAN1_RX1 => Rx1InterruptHandler<CAN1>; |
diff --git a/tests/stm32/src/bin/can_common.rs b/tests/stm32/src/bin/can_common.rs index 4b39269cc..fbfbcdc21 100644 --- a/tests/stm32/src/bin/can_common.rs +++ b/tests/stm32/src/bin/can_common.rs | |||
| @@ -8,7 +8,8 @@ pub struct TestOptions { | |||
| 8 | pub max_buffered: u8, | 8 | pub max_buffered: u8, |
| 9 | } | 9 | } |
| 10 | 10 | ||
| 11 | pub async fn run_can_tests<'d, T: can::Instance>(can: &mut can::Can<'d, T>, options: &TestOptions) { | 11 | pub async fn run_can_tests<'d>(can: &mut crate::Can<'d>, options: &TestOptions) { |
| 12 | //pub async fn run_can_tests<'d, T: can::Instance>(can: &mut can::Can<'d, T>, options: &TestOptions) { | ||
| 12 | let mut i: u8 = 0; | 13 | let mut i: u8 = 0; |
| 13 | loop { | 14 | loop { |
| 14 | //let tx_frame = can::frame::Frame::new_standard(0x123, &[i, 0x12 as u8, 0x34 as u8, 0x56 as u8, 0x78 as u8, 0x9A as u8, 0xBC as u8 ]).unwrap(); | 15 | //let tx_frame = can::frame::Frame::new_standard(0x123, &[i, 0x12 as u8, 0x34 as u8, 0x56 as u8, 0x78 as u8, 0x9A as u8, 0xBC as u8 ]).unwrap(); |
| @@ -79,11 +80,7 @@ pub async fn run_can_tests<'d, T: can::Instance>(can: &mut can::Can<'d, T>, opti | |||
| 79 | } | 80 | } |
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | pub async fn run_split_can_tests<'d, T: can::Instance>( | 83 | pub async fn run_split_can_tests<'d>(tx: &mut crate::CanTx<'d>, rx: &mut crate::CanRx<'d>, options: &TestOptions) { |
| 83 | tx: &mut can::CanTx<'d, T>, | ||
| 84 | rx: &mut can::CanRx<'d, T>, | ||
| 85 | options: &TestOptions, | ||
| 86 | ) { | ||
| 87 | for i in 0..options.max_buffered { | 84 | for i in 0..options.max_buffered { |
| 88 | // Try filling up the RX FIFO0 buffers | 85 | // Try filling up the RX FIFO0 buffers |
| 89 | //let tx_frame = if 0 != (i & 0x01) { | 86 | //let tx_frame = if 0 != (i & 0x01) { |
diff --git a/tests/stm32/src/bin/fdcan.rs b/tests/stm32/src/bin/fdcan.rs index 20bd3f7e3..8534f92e8 100644 --- a/tests/stm32/src/bin/fdcan.rs +++ b/tests/stm32/src/bin/fdcan.rs | |||
| @@ -15,6 +15,10 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 15 | mod can_common; | 15 | mod can_common; |
| 16 | use can_common::*; | 16 | use can_common::*; |
| 17 | 17 | ||
| 18 | type Can<'d> = can::Can<'d>; | ||
| 19 | type CanTx<'d> = can::CanTx<'d>; | ||
| 20 | type CanRx<'d> = can::CanRx<'d>; | ||
| 21 | |||
| 18 | bind_interrupts!(struct Irqs2 { | 22 | bind_interrupts!(struct Irqs2 { |
| 19 | FDCAN2_IT0 => can::IT0InterruptHandler<FDCAN2>; | 23 | FDCAN2_IT0 => can::IT0InterruptHandler<FDCAN2>; |
| 20 | FDCAN2_IT1 => can::IT1InterruptHandler<FDCAN2>; | 24 | FDCAN2_IT1 => can::IT1InterruptHandler<FDCAN2>; |
