diff options
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 73 |
1 files changed, 52 insertions, 21 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index b51a728c0..3567746cf 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)] | ||
| 249 | pub use buffered::*; | 248 | pub use buffered::*; |
| 250 | #[cfg(usart_v2)] | ||
| 251 | mod buffered { | 249 | mod 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,30 @@ fn rdr(r: crate::pac::usart::Usart) -> *mut u8 { | |||
| 480 | r.dr().ptr() as _ | 469 | r.dr().ptr() as _ |
| 481 | } | 470 | } |
| 482 | 471 | ||
| 472 | enum InterruptFlag { | ||
| 473 | PE, | ||
| 474 | FE, | ||
| 475 | NE, | ||
| 476 | ORE, | ||
| 477 | IDLE, | ||
| 478 | } | ||
| 479 | |||
| 483 | #[cfg(usart_v1)] | 480 | #[cfg(usart_v1)] |
| 484 | fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::pac::common::RW> { | 481 | fn 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)] | ||
| 486 | unsafe fn 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 | r.sr().read(); | ||
| 493 | r.dr().read(); | ||
| 494 | } | ||
| 495 | |||
| 488 | #[cfg(usart_v2)] | 496 | #[cfg(usart_v2)] |
| 489 | fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { | 497 | fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { |
| 490 | r.tdr().ptr() as _ | 498 | r.tdr().ptr() as _ |
| @@ -500,6 +508,29 @@ fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Ixr, crate:: | |||
| 500 | r.isr() | 508 | r.isr() |
| 501 | } | 509 | } |
| 502 | 510 | ||
| 511 | #[cfg(usart_v2)] | ||
| 512 | #[inline] | ||
| 513 | unsafe fn clear_interrupt_flag(r: crate::pac::usart::Usart, flag: InterruptFlag) { | ||
| 514 | // v2 has a separate register for clearing flags (nice) | ||
| 515 | match flag { | ||
| 516 | InterruptFlag::PE => r.icr().write(|w| { | ||
| 517 | w.set_pe(true); | ||
| 518 | }), | ||
| 519 | InterruptFlag::FE => r.icr().write(|w| { | ||
| 520 | w.set_fe(true); | ||
| 521 | }), | ||
| 522 | InterruptFlag::NE => r.icr().write(|w| { | ||
| 523 | w.set_ne(true); | ||
| 524 | }), | ||
| 525 | InterruptFlag::ORE => r.icr().write(|w| { | ||
| 526 | w.set_ore(true); | ||
| 527 | }), | ||
| 528 | InterruptFlag::IDLE => r.icr().write(|w| { | ||
| 529 | w.set_idle(true); | ||
| 530 | }), | ||
| 531 | } | ||
| 532 | } | ||
| 533 | |||
| 503 | pub(crate) mod sealed { | 534 | pub(crate) mod sealed { |
| 504 | use super::*; | 535 | use super::*; |
| 505 | 536 | ||
