aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/Cargo.toml1
-rw-r--r--embassy-stm32/src/can/bxcan.rs176
2 files changed, 101 insertions, 76 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 5d4b26a36..4e29bb32f 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -69,7 +69,6 @@ cfg-if = "1.0.0"
69embedded-io = { version = "0.4.0", features = ["async"], optional = true } 69embedded-io = { version = "0.4.0", features = ["async"], optional = true }
70chrono = { version = "^0.4", default-features = false, optional = true} 70chrono = { version = "^0.4", default-features = false, optional = true}
71bit_field = "0.10.2" 71bit_field = "0.10.2"
72heapless = { version = "0.7.5", default-features = false }
73 72
74[dev-dependencies] 73[dev-dependencies]
75critical-section = { version = "1.1", features = ["std"] } 74critical-section = { version = "1.1", features = ["std"] }
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index 734efdc02..8ae1dcb94 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -1,17 +1,73 @@
1use core::future::poll_fn; 1use core::future::poll_fn;
2use core::marker::PhantomData;
2use core::ops::{Deref, DerefMut}; 3use core::ops::{Deref, DerefMut};
3use core::task::Poll; 4use core::task::Poll;
4 5
5pub use bxcan; 6pub use bxcan;
6use bxcan::{Data, ExtendedId, Frame, Id, StandardId}; 7use bxcan::{Data, ExtendedId, Frame, Id, StandardId};
8use embassy_cortex_m::interrupt::Interrupt;
7use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_common::{into_ref, PeripheralRef};
10use futures::FutureExt;
8 11
9use crate::gpio::sealed::AFType; 12use crate::gpio::sealed::AFType;
10use crate::interrupt::InterruptExt; 13use crate::interrupt::InterruptExt;
11use crate::pac::can::vals::{Lec, RirIde}; 14use crate::pac::can::vals::{Lec, RirIde};
12use crate::rcc::RccPeripheral; 15use crate::rcc::RccPeripheral;
13use crate::time::Hertz; 16use crate::time::Hertz;
14use crate::{peripherals, Peripheral}; 17use crate::{interrupt, peripherals, Peripheral};
18
19/// Interrupt handler.
20pub struct TxInterruptHandler<T: Instance> {
21 _phantom: PhantomData<T>,
22}
23
24impl<T: Instance> interrupt::Handler<T::TXInterrupt> for TxInterruptHandler<T> {
25 unsafe fn on_interrupt() {
26 T::regs().tsr().write(|v| {
27 v.set_rqcp(0, true);
28 v.set_rqcp(1, true);
29 v.set_rqcp(2, true);
30 });
31
32 T::state().tx_waker.wake();
33 }
34}
35
36pub struct Rx0InterruptHandler<T: Instance> {
37 _phantom: PhantomData<T>,
38}
39
40impl<T: Instance> interrupt::Handler<T::RX0Interrupt> for Rx0InterruptHandler<T> {
41 unsafe fn on_interrupt() {
42 Can::<T>::receive_fifo(RxFifo::Fifo0);
43 }
44}
45
46pub struct Rx1InterruptHandler<T: Instance> {
47 _phantom: PhantomData<T>,
48}
49
50impl<T: Instance> interrupt::Handler<T::RX1Interrupt> for Rx1InterruptHandler<T> {
51 unsafe fn on_interrupt() {
52 Can::<T>::receive_fifo(RxFifo::Fifo1);
53 }
54}
55
56pub struct SceInterruptHandler<T: Instance> {
57 _phantom: PhantomData<T>,
58}
59
60impl<T: Instance> interrupt::Handler<T::SCEInterrupt> for SceInterruptHandler<T> {
61 unsafe fn on_interrupt() {
62 let msr = T::regs().msr();
63 let msr_val = msr.read();
64
65 if msr_val.erri() {
66 msr.modify(|v| v.set_erri(true));
67 T::state().err_waker.wake();
68 }
69 }
70}
15 71
16pub struct Can<'d, T: Instance> { 72pub struct Can<'d, T: Instance> {
17 can: bxcan::Can<BxcanInstance<'d, T>>, 73 can: bxcan::Can<BxcanInstance<'d, T>>,
@@ -64,12 +120,13 @@ impl<'d, T: Instance> Can<'d, T> {
64 peri: impl Peripheral<P = T> + 'd, 120 peri: impl Peripheral<P = T> + 'd,
65 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 121 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
66 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 122 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
67 tx_irq: impl Peripheral<P = T::TXInterrupt> + 'd, 123 _irqs: impl interrupt::Binding<T::TXInterrupt, TxInterruptHandler<T>>
68 rx0_irq: impl Peripheral<P = T::RX0Interrupt> + 'd, 124 + interrupt::Binding<T::RX0Interrupt, Rx0InterruptHandler<T>>
69 rx1_irq: impl Peripheral<P = T::RX1Interrupt> + 'd, 125 + interrupt::Binding<T::RX1Interrupt, Rx1InterruptHandler<T>>
70 sce_irq: impl Peripheral<P = T::SCEInterrupt> + 'd, 126 + interrupt::Binding<T::SCEInterrupt, SceInterruptHandler<T>>
127 + 'd,
71 ) -> Self { 128 ) -> Self {
72 into_ref!(peri, rx, tx, tx_irq, rx0_irq, rx1_irq, sce_irq); 129 into_ref!(peri, rx, tx);
73 130
74 unsafe { 131 unsafe {
75 rx.set_as_af(rx.af_num(), AFType::Input); 132 rx.set_as_af(rx.af_num(), AFType::Input);
@@ -79,21 +136,19 @@ impl<'d, T: Instance> Can<'d, T> {
79 T::enable(); 136 T::enable();
80 T::reset(); 137 T::reset();
81 138
82 tx_irq.unpend(); 139 unsafe {
83 tx_irq.set_handler(Self::tx_interrupt); 140 T::TXInterrupt::steal().unpend();
84 tx_irq.enable(); 141 T::TXInterrupt::steal().enable();
85 142
86 rx0_irq.unpend(); 143 T::RX0Interrupt::steal().unpend();
87 rx0_irq.set_handler(Self::rx0_interrupt); 144 T::RX0Interrupt::steal().enable();
88 rx0_irq.enable();
89 145
90 rx1_irq.unpend(); 146 T::RX1Interrupt::steal().unpend();
91 rx1_irq.set_handler(Self::rx1_interrupt); 147 T::RX1Interrupt::steal().enable();
92 rx1_irq.enable();
93 148
94 sce_irq.unpend(); 149 T::SCEInterrupt::steal().unpend();
95 sce_irq.set_handler(Self::sce_interrupt); 150 T::SCEInterrupt::steal().enable();
96 sce_irq.enable(); 151 }
97 152
98 let can = bxcan::Can::builder(BxcanInstance(peri)).leave_disabled(); 153 let can = bxcan::Can::builder(BxcanInstance(peri)).leave_disabled();
99 Self { can } 154 Self { can }
@@ -133,12 +188,11 @@ impl<'d, T: Instance> Can<'d, T> {
133 188
134 pub async fn receive_frame_or_error(&mut self) -> FrameOrError { 189 pub async fn receive_frame_or_error(&mut self) -> FrameOrError {
135 poll_fn(|cx| { 190 poll_fn(|cx| {
136 if let Some(frame) = T::state().rx_queue.dequeue() { 191 if let Poll::Ready(frame) = T::state().rx_queue.recv().poll_unpin(cx) {
137 return Poll::Ready(FrameOrError::Frame(frame)); 192 return Poll::Ready(FrameOrError::Frame(frame));
138 } else if let Some(err) = self.curr_error() { 193 } else if let Some(err) = self.curr_error() {
139 return Poll::Ready(FrameOrError::Error(err)); 194 return Poll::Ready(FrameOrError::Error(err));
140 } 195 }
141 T::state().rx_waker.register(cx.waker());
142 T::state().err_waker.register(cx.waker()); 196 T::state().err_waker.register(cx.waker());
143 Poll::Pending 197 Poll::Pending
144 }) 198 })
@@ -159,69 +213,42 @@ impl<'d, T: Instance> Can<'d, T> {
159 None 213 None
160 } 214 }
161 215
162 unsafe fn sce_interrupt(_: *mut ()) {
163 let msr = T::regs().msr();
164 let msr_val = msr.read();
165
166 if msr_val.erri() {
167 msr.modify(|v| v.set_erri(true));
168 T::state().err_waker.wake();
169 return;
170 }
171 }
172
173 unsafe fn tx_interrupt(_: *mut ()) {
174 T::regs().tsr().write(|v| {
175 v.set_rqcp(0, true);
176 v.set_rqcp(1, true);
177 v.set_rqcp(2, true);
178 });
179 T::state().tx_waker.wake();
180 }
181
182 unsafe fn rx0_interrupt(_: *mut ()) {
183 Self::receive_fifo(RxFifo::Fifo0);
184 }
185
186 unsafe fn rx1_interrupt(_: *mut ()) {
187 Self::receive_fifo(RxFifo::Fifi1);
188 }
189
190 unsafe fn receive_fifo(fifo: RxFifo) { 216 unsafe fn receive_fifo(fifo: RxFifo) {
191 let state = T::state(); 217 let state = T::state();
192 let regs = T::regs(); 218 let regs = T::regs();
193 let fifo_idx = match fifo { 219 let fifo_idx = match fifo {
194 RxFifo::Fifo0 => 0usize, 220 RxFifo::Fifo0 => 0usize,
195 RxFifo::Fifi1 => 1usize, 221 RxFifo::Fifo1 => 1usize,
196 }; 222 };
197 let rfr = regs.rfr(fifo_idx); 223 let rfr = regs.rfr(fifo_idx);
198 let fifo = regs.rx(fifo_idx); 224 let fifo = regs.rx(fifo_idx);
199 225
200 // If there are no pending messages, there is nothing to do 226 loop {
201 if rfr.read().fmp() == 0 { 227 // If there are no pending messages, there is nothing to do
202 return; 228 if rfr.read().fmp() == 0 {
203 } 229 return;
230 }
204 231
205 let rir = fifo.rir().read(); 232 let rir = fifo.rir().read();
206 let id = if rir.ide() == RirIde::STANDARD { 233 let id = if rir.ide() == RirIde::STANDARD {
207 Id::from(StandardId::new_unchecked(rir.stid())) 234 Id::from(StandardId::new_unchecked(rir.stid()))
208 } else { 235 } else {
209 Id::from(ExtendedId::new_unchecked(rir.exid())) 236 Id::from(ExtendedId::new_unchecked(rir.exid()))
210 }; 237 };
211 let data_len = fifo.rdtr().read().dlc() as usize; 238 let data_len = fifo.rdtr().read().dlc() as usize;
212 let mut data: [u8; 8] = [0; 8]; 239 let mut data: [u8; 8] = [0; 8];
213 data[0..4].copy_from_slice(&fifo.rdlr().read().0.to_ne_bytes()); 240 data[0..4].copy_from_slice(&fifo.rdlr().read().0.to_ne_bytes());
214 data[4..8].copy_from_slice(&fifo.rdhr().read().0.to_ne_bytes()); 241 data[4..8].copy_from_slice(&fifo.rdhr().read().0.to_ne_bytes());
215 242
216 let frame = Frame::new_data(id, Data::new(&data[0..data_len]).unwrap()); 243 let frame = Frame::new_data(id, Data::new(&data[0..data_len]).unwrap());
217 244
218 rfr.modify(|v| v.set_rfom(true)); 245 rfr.modify(|v| v.set_rfom(true));
219 246
220 match state.rx_queue.enqueue(frame) { 247 /*
221 Ok(_) => {} 248 NOTE: consensus was reached that if rx_queue is full, packets should be dropped
222 Err(_) => defmt::error!("RX queue overflow"), 249 */
250 let _ = state.rx_queue.try_send(frame);
223 } 251 }
224 state.rx_waker.wake();
225 } 252 }
226 253
227 pub fn calc_bxcan_timings(periph_clock: Hertz, can_bitrate: u32) -> Option<u32> { 254 pub fn calc_bxcan_timings(periph_clock: Hertz, can_bitrate: u32) -> Option<u32> {
@@ -318,7 +345,7 @@ impl<'d, T: Instance> Can<'d, T> {
318 345
319enum RxFifo { 346enum RxFifo {
320 Fifo0, 347 Fifo0,
321 Fifi1, 348 Fifo1,
322} 349}
323 350
324impl<'d, T: Instance> Drop for Can<'d, T> { 351impl<'d, T: Instance> Drop for Can<'d, T> {
@@ -345,23 +372,22 @@ impl<'d, T: Instance> DerefMut for Can<'d, T> {
345} 372}
346 373
347pub(crate) mod sealed { 374pub(crate) mod sealed {
375 use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
376 use embassy_sync::channel::Channel;
348 use embassy_sync::waitqueue::AtomicWaker; 377 use embassy_sync::waitqueue::AtomicWaker;
349 use heapless::mpmc::Q8;
350 378
351 pub struct State { 379 pub struct State {
352 pub tx_waker: AtomicWaker, 380 pub tx_waker: AtomicWaker,
353 pub rx_waker: AtomicWaker,
354 pub err_waker: AtomicWaker, 381 pub err_waker: AtomicWaker,
355 pub rx_queue: Q8<bxcan::Frame>, 382 pub rx_queue: Channel<CriticalSectionRawMutex, bxcan::Frame, 32>,
356 } 383 }
357 384
358 impl State { 385 impl State {
359 pub const fn new() -> Self { 386 pub const fn new() -> Self {
360 Self { 387 Self {
361 tx_waker: AtomicWaker::new(), 388 tx_waker: AtomicWaker::new(),
362 rx_waker: AtomicWaker::new(),
363 err_waker: AtomicWaker::new(), 389 err_waker: AtomicWaker::new(),
364 rx_queue: Q8::new(), 390 rx_queue: Channel::new(),
365 } 391 }
366 } 392 }
367 } 393 }