aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Strygin <[email protected]>2021-12-26 18:04:07 +0300
committerNikita Strygin <[email protected]>2021-12-26 18:13:19 +0300
commit6b08c70273b977b9e2d025281c051830307d0902 (patch)
treedfc2cc57e1f27cc7d16b889fda327a4e52a2769f
parent23c16903dbd9ff26e930760a0fa5cb39488f8a97 (diff)
Port buffered uart to v1 stm32 hardware
- No DMA - Create clear_interrupt_flag function to handle differences between v1 and v2 hardware
-rw-r--r--embassy-stm32/src/usart/mod.rs75
1 files changed, 54 insertions, 21 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index b51a728c0..a93bd2daf 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -245,9 +245,7 @@ where
245 } 245 }
246} 246}
247 247
248#[cfg(usart_v2)]
249pub use buffered::*; 248pub use buffered::*;
250#[cfg(usart_v2)]
251mod buffered { 249mod buffered {
252 use atomic_polyfill::{compiler_fence, Ordering}; 250 use atomic_polyfill::{compiler_fence, Ordering};
253 use core::pin::Pin; 251 use core::pin::Pin;
@@ -323,39 +321,30 @@ mod buffered {
323 fn on_rx(&mut self) { 321 fn on_rx(&mut self) {
324 let r = self.uart.inner.regs(); 322 let r = self.uart.inner.regs();
325 unsafe { 323 unsafe {
326 let sr = r.isr().read(); 324 let sr = sr(r).read();
325 // TODO: do we want to handle interrupts the same way on v1 hardware?
327 if sr.pe() { 326 if sr.pe() {
328 r.icr().write(|w| { 327 clear_interrupt_flag(r, InterruptFlag::PE);
329 w.set_pe(true);
330 });
331 trace!("Parity error"); 328 trace!("Parity error");
332 } else if sr.fe() { 329 } else if sr.fe() {
333 r.icr().write(|w| { 330 clear_interrupt_flag(r, InterruptFlag::FE);
334 w.set_fe(true);
335 });
336 trace!("Framing error"); 331 trace!("Framing error");
337 } else if sr.ne() { 332 } else if sr.ne() {
338 r.icr().write(|w| { 333 clear_interrupt_flag(r, InterruptFlag::NE);
339 w.set_ne(true);
340 });
341 trace!("Noise error"); 334 trace!("Noise error");
342 } else if sr.ore() { 335 } else if sr.ore() {
343 r.icr().write(|w| { 336 clear_interrupt_flag(r, InterruptFlag::ORE);
344 w.set_ore(true);
345 });
346 trace!("Overrun error"); 337 trace!("Overrun error");
347 } else if sr.rxne() { 338 } else if sr.rxne() {
348 let buf = self.rx.push_buf(); 339 let buf = self.rx.push_buf();
349 if buf.is_empty() { 340 if buf.is_empty() {
350 self.rx_waker.wake(); 341 self.rx_waker.wake();
351 } else { 342 } else {
352 buf[0] = r.rdr().read().0 as u8; 343 buf[0] = rdr(r).read_volatile();
353 self.rx.push(1); 344 self.rx.push(1);
354 } 345 }
355 } else if sr.idle() { 346 } else if sr.idle() {
356 r.icr().write(|w| { 347 clear_interrupt_flag(r, InterruptFlag::IDLE);
357 w.set_idle(true);
358 });
359 self.rx_waker.wake(); 348 self.rx_waker.wake();
360 }; 349 };
361 } 350 }
@@ -364,13 +353,13 @@ mod buffered {
364 fn on_tx(&mut self) { 353 fn on_tx(&mut self) {
365 let r = self.uart.inner.regs(); 354 let r = self.uart.inner.regs();
366 unsafe { 355 unsafe {
367 if r.isr().read().txe() { 356 if sr(r).read().txe() {
368 let buf = self.tx.pop_buf(); 357 let buf = self.tx.pop_buf();
369 if !buf.is_empty() { 358 if !buf.is_empty() {
370 r.cr1().modify(|w| { 359 r.cr1().modify(|w| {
371 w.set_txeie(true); 360 w.set_txeie(true);
372 }); 361 });
373 r.tdr().write_value(regs::Dr(buf[0].into())); 362 tdr(r).write_volatile(buf[0].into());
374 self.tx.pop(1); 363 self.tx.pop(1);
375 self.tx_waker.wake(); 364 self.tx_waker.wake();
376 } else { 365 } else {
@@ -480,11 +469,32 @@ fn rdr(r: crate::pac::usart::Usart) -> *mut u8 {
480 r.dr().ptr() as _ 469 r.dr().ptr() as _
481} 470}
482 471
472enum InterruptFlag {
473 PE,
474 FE,
475 NE,
476 ORE,
477 IDLE,
478}
479
483#[cfg(usart_v1)] 480#[cfg(usart_v1)]
484fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::pac::common::RW> { 481fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::pac::common::RW> {
485 r.sr() 482 r.sr()
486} 483}
487 484
485#[cfg(usart_v1)]
486fn clear_interrupt_flag(r: crate::pac::usart::Usart, _flag: InterruptFlag) {
487 // This bit is set by hardware when noise is detected on a received frame. It is cleared by a
488 // software sequence (an read to the USART_SR register followed by a read to the
489 // USART_DR register).
490
491 // this is the same as what st's HAL does on v1 hardware
492 unsafe {
493 r.sr().read();
494 r.dr().read();
495 }
496}
497
488#[cfg(usart_v2)] 498#[cfg(usart_v2)]
489fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { 499fn tdr(r: crate::pac::usart::Usart) -> *mut u8 {
490 r.tdr().ptr() as _ 500 r.tdr().ptr() as _
@@ -500,6 +510,29 @@ fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Ixr, crate::
500 r.isr() 510 r.isr()
501} 511}
502 512
513#[cfg(usart_v2)]
514#[inline]
515fn clear_interrupt_flag(r: crate::pac::usart::Usart, flag: InterruptFlag) {
516 // v2 has a separate register for clearing flags (nice)
517 match flag {
518 InterruptFlag::PE => r.icr().write(|w| {
519 w.set_pe(true);
520 }),
521 InterruptFlag::FE => r.icr().write(|w| {
522 w.set_fe(true);
523 }),
524 InterruptFlag::NE => r.icr().write(|w| {
525 w.set_ne(true);
526 }),
527 InterruptFlag::ORE => r.icr().write(|w| {
528 w.set_ore(true);
529 }),
530 InterruptFlag::IDLE => r.icr().write(|w| {
531 w.set_idle(true);
532 }),
533 }
534}
535
503pub(crate) mod sealed { 536pub(crate) mod sealed {
504 use super::*; 537 use super::*;
505 538