stm32: update stm32-metapac.
This commit is contained in:
@ -19,68 +19,64 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
|
||||
let state = T::buffered_state();
|
||||
|
||||
// RX
|
||||
unsafe {
|
||||
let sr = sr(r).read();
|
||||
// On v1 & v2, reading DR clears the rxne, error and idle interrupt
|
||||
// flags. Keep this close to the SR read to reduce the chance of a
|
||||
// flag being set in-between.
|
||||
let dr = if sr.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr.ore() || sr.idle()) {
|
||||
Some(rdr(r).read_volatile())
|
||||
let sr_val = sr(r).read();
|
||||
// On v1 & v2, reading DR clears the rxne, error and idle interrupt
|
||||
// flags. Keep this close to the SR read to reduce the chance of a
|
||||
// flag being set in-between.
|
||||
let dr = if sr_val.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr_val.ore() || sr_val.idle()) {
|
||||
Some(rdr(r).read_volatile())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
clear_interrupt_flags(r, sr_val);
|
||||
|
||||
if sr_val.pe() {
|
||||
warn!("Parity error");
|
||||
}
|
||||
if sr_val.fe() {
|
||||
warn!("Framing error");
|
||||
}
|
||||
if sr_val.ne() {
|
||||
warn!("Noise error");
|
||||
}
|
||||
if sr_val.ore() {
|
||||
warn!("Overrun error");
|
||||
}
|
||||
if sr_val.rxne() {
|
||||
let mut rx_writer = state.rx_buf.writer();
|
||||
let buf = rx_writer.push_slice();
|
||||
if !buf.is_empty() {
|
||||
buf[0] = dr.unwrap();
|
||||
rx_writer.push_done(1);
|
||||
} else {
|
||||
None
|
||||
};
|
||||
clear_interrupt_flags(r, sr);
|
||||
|
||||
if sr.pe() {
|
||||
warn!("Parity error");
|
||||
}
|
||||
if sr.fe() {
|
||||
warn!("Framing error");
|
||||
}
|
||||
if sr.ne() {
|
||||
warn!("Noise error");
|
||||
}
|
||||
if sr.ore() {
|
||||
warn!("Overrun error");
|
||||
}
|
||||
if sr.rxne() {
|
||||
let mut rx_writer = state.rx_buf.writer();
|
||||
let buf = rx_writer.push_slice();
|
||||
if !buf.is_empty() {
|
||||
buf[0] = dr.unwrap();
|
||||
rx_writer.push_done(1);
|
||||
} else {
|
||||
// FIXME: Should we disable any further RX interrupts when the buffer becomes full.
|
||||
}
|
||||
|
||||
if state.rx_buf.is_full() {
|
||||
state.rx_waker.wake();
|
||||
}
|
||||
// FIXME: Should we disable any further RX interrupts when the buffer becomes full.
|
||||
}
|
||||
|
||||
if sr.idle() {
|
||||
if state.rx_buf.is_full() {
|
||||
state.rx_waker.wake();
|
||||
}
|
||||
}
|
||||
|
||||
if sr_val.idle() {
|
||||
state.rx_waker.wake();
|
||||
}
|
||||
|
||||
// TX
|
||||
unsafe {
|
||||
if sr(r).read().txe() {
|
||||
let mut tx_reader = state.tx_buf.reader();
|
||||
let buf = tx_reader.pop_slice();
|
||||
if !buf.is_empty() {
|
||||
r.cr1().modify(|w| {
|
||||
w.set_txeie(true);
|
||||
});
|
||||
tdr(r).write_volatile(buf[0].into());
|
||||
tx_reader.pop_done(1);
|
||||
state.tx_waker.wake();
|
||||
} else {
|
||||
// Disable interrupt until we have something to transmit again
|
||||
r.cr1().modify(|w| {
|
||||
w.set_txeie(false);
|
||||
});
|
||||
}
|
||||
if sr(r).read().txe() {
|
||||
let mut tx_reader = state.tx_buf.reader();
|
||||
let buf = tx_reader.pop_slice();
|
||||
if !buf.is_empty() {
|
||||
r.cr1().modify(|w| {
|
||||
w.set_txeie(true);
|
||||
});
|
||||
tdr(r).write_volatile(buf[0].into());
|
||||
tx_reader.pop_done(1);
|
||||
state.tx_waker.wake();
|
||||
} else {
|
||||
// Disable interrupt until we have something to transmit again
|
||||
r.cr1().modify(|w| {
|
||||
w.set_txeie(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -150,14 +146,12 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
unsafe {
|
||||
rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
|
||||
cts.set_as_af(cts.af_num(), AFType::Input);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_rtse(true);
|
||||
w.set_ctse(true);
|
||||
});
|
||||
}
|
||||
rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
|
||||
cts.set_as_af(cts.af_num(), AFType::Input);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_rtse(true);
|
||||
w.set_ctse(true);
|
||||
});
|
||||
|
||||
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||
}
|
||||
@ -178,12 +172,10 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
unsafe {
|
||||
de.set_as_af(de.af_num(), AFType::OutputPushPull);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_dem(true);
|
||||
});
|
||||
}
|
||||
de.set_as_af(de.af_num(), AFType::OutputPushPull);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_dem(true);
|
||||
});
|
||||
|
||||
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
|
||||
}
|
||||
@ -205,22 +197,18 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
||||
unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
|
||||
|
||||
let r = T::regs();
|
||||
unsafe {
|
||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||
}
|
||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||
|
||||
configure(r, &config, T::frequency(), T::KIND, true, true);
|
||||
|
||||
unsafe {
|
||||
r.cr1().modify(|w| {
|
||||
#[cfg(lpuart_v2)]
|
||||
w.set_fifoen(true);
|
||||
r.cr1().modify(|w| {
|
||||
#[cfg(lpuart_v2)]
|
||||
w.set_fifoen(true);
|
||||
|
||||
w.set_rxneie(true);
|
||||
w.set_idleie(true);
|
||||
});
|
||||
}
|
||||
w.set_rxneie(true);
|
||||
w.set_idleie(true);
|
||||
});
|
||||
|
||||
T::Interrupt::unpend();
|
||||
unsafe { T::Interrupt::enable() };
|
||||
|
@ -36,35 +36,31 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
|
||||
let r = T::regs();
|
||||
let s = T::state();
|
||||
|
||||
let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) };
|
||||
let (sr, cr1, cr3) = (sr(r).read(), r.cr1().read(), r.cr3().read());
|
||||
|
||||
let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
|
||||
if has_errors {
|
||||
// clear all interrupts and DMA Rx Request
|
||||
unsafe {
|
||||
r.cr1().modify(|w| {
|
||||
// disable RXNE interrupt
|
||||
w.set_rxneie(false);
|
||||
// disable parity interrupt
|
||||
w.set_peie(false);
|
||||
// disable idle line interrupt
|
||||
w.set_idleie(false);
|
||||
});
|
||||
r.cr3().modify(|w| {
|
||||
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||
w.set_eie(false);
|
||||
// disable DMA Rx Request
|
||||
w.set_dmar(false);
|
||||
});
|
||||
}
|
||||
r.cr1().modify(|w| {
|
||||
// disable RXNE interrupt
|
||||
w.set_rxneie(false);
|
||||
// disable parity interrupt
|
||||
w.set_peie(false);
|
||||
// disable idle line interrupt
|
||||
w.set_idleie(false);
|
||||
});
|
||||
r.cr3().modify(|w| {
|
||||
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||
w.set_eie(false);
|
||||
// disable DMA Rx Request
|
||||
w.set_dmar(false);
|
||||
});
|
||||
} else if cr1.idleie() && sr.idle() {
|
||||
// IDLE detected: no more data will come
|
||||
unsafe {
|
||||
r.cr1().modify(|w| {
|
||||
// disable idle line detection
|
||||
w.set_idleie(false);
|
||||
});
|
||||
}
|
||||
r.cr1().modify(|w| {
|
||||
// disable idle line detection
|
||||
w.set_idleie(false);
|
||||
});
|
||||
} else if cr1.rxneie() {
|
||||
// We cannot check the RXNE flag as it is auto-cleared by the DMA controller
|
||||
|
||||
@ -205,12 +201,10 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
unsafe {
|
||||
cts.set_as_af(cts.af_num(), AFType::Input);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_ctse(true);
|
||||
});
|
||||
}
|
||||
cts.set_as_af(cts.af_num(), AFType::Input);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_ctse(true);
|
||||
});
|
||||
Self::new_inner(peri, tx, tx_dma, config)
|
||||
}
|
||||
|
||||
@ -224,9 +218,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
||||
|
||||
let r = T::regs();
|
||||
|
||||
unsafe {
|
||||
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||
}
|
||||
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||
|
||||
configure(r, &config, T::frequency(), T::KIND, false, true);
|
||||
|
||||
@ -245,11 +237,9 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
||||
{
|
||||
let ch = &mut self.tx_dma;
|
||||
let request = ch.request();
|
||||
unsafe {
|
||||
T::regs().cr3().modify(|reg| {
|
||||
reg.set_dmat(true);
|
||||
});
|
||||
}
|
||||
T::regs().cr3().modify(|reg| {
|
||||
reg.set_dmat(true);
|
||||
});
|
||||
// If we don't assign future to a variable, the data register pointer
|
||||
// is held across an await and makes the future non-Send.
|
||||
let transfer = unsafe { Transfer::new_write(ch, request, buffer, tdr(T::regs()), Default::default()) };
|
||||
@ -258,21 +248,17 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
|
||||
}
|
||||
|
||||
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||
unsafe {
|
||||
let r = T::regs();
|
||||
for &b in buffer {
|
||||
while !sr(r).read().txe() {}
|
||||
tdr(r).write_volatile(b);
|
||||
}
|
||||
let r = T::regs();
|
||||
for &b in buffer {
|
||||
while !sr(r).read().txe() {}
|
||||
unsafe { tdr(r).write_volatile(b) };
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn blocking_flush(&mut self) -> Result<(), Error> {
|
||||
unsafe {
|
||||
let r = T::regs();
|
||||
while !sr(r).read().tc() {}
|
||||
}
|
||||
let r = T::regs();
|
||||
while !sr(r).read().tc() {}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -305,12 +291,10 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
unsafe {
|
||||
rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_rtse(true);
|
||||
});
|
||||
}
|
||||
rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_rtse(true);
|
||||
});
|
||||
|
||||
Self::new_inner(peri, rx, rx_dma, config)
|
||||
}
|
||||
@ -325,9 +309,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
|
||||
let r = T::regs();
|
||||
|
||||
unsafe {
|
||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||
}
|
||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||
|
||||
configure(r, &config, T::frequency(), T::KIND, true, false);
|
||||
|
||||
@ -347,7 +329,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
}
|
||||
|
||||
#[cfg(any(usart_v1, usart_v2))]
|
||||
unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> {
|
||||
fn check_rx_flags(&mut self) -> Result<bool, Error> {
|
||||
let r = T::regs();
|
||||
loop {
|
||||
// Handle all buffered error flags.
|
||||
@ -380,7 +362,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
}
|
||||
|
||||
#[cfg(any(usart_v3, usart_v4))]
|
||||
unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> {
|
||||
fn check_rx_flags(&mut self) -> Result<bool, Error> {
|
||||
let r = T::regs();
|
||||
let sr = r.isr().read();
|
||||
if sr.pe() {
|
||||
@ -410,22 +392,18 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
|
||||
pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
|
||||
let r = T::regs();
|
||||
unsafe {
|
||||
if self.check_rx_flags()? {
|
||||
Ok(rdr(r).read_volatile())
|
||||
} else {
|
||||
Err(nb::Error::WouldBlock)
|
||||
}
|
||||
if self.check_rx_flags()? {
|
||||
Ok(unsafe { rdr(r).read_volatile() })
|
||||
} else {
|
||||
Err(nb::Error::WouldBlock)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||
unsafe {
|
||||
let r = T::regs();
|
||||
for b in buffer {
|
||||
while !self.check_rx_flags()? {}
|
||||
*b = rdr(r).read_volatile();
|
||||
}
|
||||
let r = T::regs();
|
||||
for b in buffer {
|
||||
while !self.check_rx_flags()? {}
|
||||
unsafe { *b = rdr(r).read_volatile() }
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -451,23 +429,20 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
let on_drop = OnDrop::new(move || {
|
||||
// defmt::trace!("Clear all USART interrupts and DMA Read Request");
|
||||
// clear all interrupts and DMA Rx Request
|
||||
// SAFETY: only clears Rx related flags
|
||||
unsafe {
|
||||
r.cr1().modify(|w| {
|
||||
// disable RXNE interrupt
|
||||
w.set_rxneie(false);
|
||||
// disable parity interrupt
|
||||
w.set_peie(false);
|
||||
// disable idle line interrupt
|
||||
w.set_idleie(false);
|
||||
});
|
||||
r.cr3().modify(|w| {
|
||||
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||
w.set_eie(false);
|
||||
// disable DMA Rx Request
|
||||
w.set_dmar(false);
|
||||
});
|
||||
}
|
||||
r.cr1().modify(|w| {
|
||||
// disable RXNE interrupt
|
||||
w.set_rxneie(false);
|
||||
// disable parity interrupt
|
||||
w.set_peie(false);
|
||||
// disable idle line interrupt
|
||||
w.set_idleie(false);
|
||||
});
|
||||
r.cr3().modify(|w| {
|
||||
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||
w.set_eie(false);
|
||||
// disable DMA Rx Request
|
||||
w.set_dmar(false);
|
||||
});
|
||||
});
|
||||
|
||||
let ch = &mut self.rx_dma;
|
||||
@ -480,78 +455,74 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
// future which will complete when DMA Read request completes
|
||||
let transfer = unsafe { Transfer::new_read(ch, request, rdr(T::regs()), buffer, Default::default()) };
|
||||
|
||||
// SAFETY: The only way we might have a problem is using split rx and tx
|
||||
// here we only modify or read Rx related flags, interrupts and DMA channel
|
||||
unsafe {
|
||||
// clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer
|
||||
if !self.detect_previous_overrun {
|
||||
let sr = sr(r).read();
|
||||
// This read also clears the error and idle interrupt flags on v1.
|
||||
rdr(r).read_volatile();
|
||||
clear_interrupt_flags(r, sr);
|
||||
// clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer
|
||||
if !self.detect_previous_overrun {
|
||||
let sr = sr(r).read();
|
||||
// This read also clears the error and idle interrupt flags on v1.
|
||||
unsafe { rdr(r).read_volatile() };
|
||||
clear_interrupt_flags(r, sr);
|
||||
}
|
||||
|
||||
r.cr1().modify(|w| {
|
||||
// disable RXNE interrupt
|
||||
w.set_rxneie(false);
|
||||
// enable parity interrupt if not ParityNone
|
||||
w.set_peie(w.pce());
|
||||
});
|
||||
|
||||
r.cr3().modify(|w| {
|
||||
// enable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||
w.set_eie(true);
|
||||
// enable DMA Rx Request
|
||||
w.set_dmar(true);
|
||||
});
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
// In case of errors already pending when reception started, interrupts may have already been raised
|
||||
// and lead to reception abortion (Overrun error for instance). In such a case, all interrupts
|
||||
// have been disabled in interrupt handler and DMA Rx Request has been disabled.
|
||||
|
||||
let cr3 = r.cr3().read();
|
||||
|
||||
if !cr3.dmar() {
|
||||
// something went wrong
|
||||
// because the only way to get this flag cleared is to have an interrupt
|
||||
|
||||
// DMA will be stopped when transfer is dropped
|
||||
|
||||
let sr = sr(r).read();
|
||||
// This read also clears the error and idle interrupt flags on v1.
|
||||
unsafe { rdr(r).read_volatile() };
|
||||
clear_interrupt_flags(r, sr);
|
||||
|
||||
if sr.pe() {
|
||||
return Err(Error::Parity);
|
||||
}
|
||||
if sr.fe() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
if sr.ne() {
|
||||
return Err(Error::Noise);
|
||||
}
|
||||
if sr.ore() {
|
||||
return Err(Error::Overrun);
|
||||
}
|
||||
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
if enable_idle_line_detection {
|
||||
// clear idle flag
|
||||
let sr = sr(r).read();
|
||||
// This read also clears the error and idle interrupt flags on v1.
|
||||
unsafe { rdr(r).read_volatile() };
|
||||
clear_interrupt_flags(r, sr);
|
||||
|
||||
// enable idle interrupt
|
||||
r.cr1().modify(|w| {
|
||||
// disable RXNE interrupt
|
||||
w.set_rxneie(false);
|
||||
// enable parity interrupt if not ParityNone
|
||||
w.set_peie(w.pce());
|
||||
w.set_idleie(true);
|
||||
});
|
||||
|
||||
r.cr3().modify(|w| {
|
||||
// enable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||
w.set_eie(true);
|
||||
// enable DMA Rx Request
|
||||
w.set_dmar(true);
|
||||
});
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
// In case of errors already pending when reception started, interrupts may have already been raised
|
||||
// and lead to reception abortion (Overrun error for instance). In such a case, all interrupts
|
||||
// have been disabled in interrupt handler and DMA Rx Request has been disabled.
|
||||
|
||||
let cr3 = r.cr3().read();
|
||||
|
||||
if !cr3.dmar() {
|
||||
// something went wrong
|
||||
// because the only way to get this flag cleared is to have an interrupt
|
||||
|
||||
// DMA will be stopped when transfer is dropped
|
||||
|
||||
let sr = sr(r).read();
|
||||
// This read also clears the error and idle interrupt flags on v1.
|
||||
rdr(r).read_volatile();
|
||||
clear_interrupt_flags(r, sr);
|
||||
|
||||
if sr.pe() {
|
||||
return Err(Error::Parity);
|
||||
}
|
||||
if sr.fe() {
|
||||
return Err(Error::Framing);
|
||||
}
|
||||
if sr.ne() {
|
||||
return Err(Error::Noise);
|
||||
}
|
||||
if sr.ore() {
|
||||
return Err(Error::Overrun);
|
||||
}
|
||||
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
if enable_idle_line_detection {
|
||||
// clear idle flag
|
||||
let sr = sr(r).read();
|
||||
// This read also clears the error and idle interrupt flags on v1.
|
||||
rdr(r).read_volatile();
|
||||
clear_interrupt_flags(r, sr);
|
||||
|
||||
// enable idle interrupt
|
||||
r.cr1().modify(|w| {
|
||||
w.set_idleie(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
@ -562,15 +533,11 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
||||
|
||||
s.rx_waker.register(cx.waker());
|
||||
|
||||
// SAFETY: read only and we only use Rx related flags
|
||||
let sr = unsafe { sr(r).read() };
|
||||
let sr = sr(r).read();
|
||||
|
||||
// SAFETY: only clears Rx related flags
|
||||
unsafe {
|
||||
// This read also clears the error and idle interrupt flags on v1.
|
||||
rdr(r).read_volatile();
|
||||
clear_interrupt_flags(r, sr);
|
||||
}
|
||||
// This read also clears the error and idle interrupt flags on v1.
|
||||
unsafe { rdr(r).read_volatile() };
|
||||
clear_interrupt_flags(r, sr);
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
@ -677,14 +644,12 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
unsafe {
|
||||
rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
|
||||
cts.set_as_af(cts.af_num(), AFType::Input);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_rtse(true);
|
||||
w.set_ctse(true);
|
||||
});
|
||||
}
|
||||
rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
|
||||
cts.set_as_af(cts.af_num(), AFType::Input);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_rtse(true);
|
||||
w.set_ctse(true);
|
||||
});
|
||||
Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
|
||||
}
|
||||
|
||||
@ -704,12 +669,10 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
unsafe {
|
||||
de.set_as_af(de.af_num(), AFType::OutputPushPull);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_dem(true);
|
||||
});
|
||||
}
|
||||
de.set_as_af(de.af_num(), AFType::OutputPushPull);
|
||||
T::regs().cr3().write(|w| {
|
||||
w.set_dem(true);
|
||||
});
|
||||
Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
|
||||
}
|
||||
|
||||
@ -725,10 +688,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||
|
||||
let r = T::regs();
|
||||
|
||||
unsafe {
|
||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||
}
|
||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||
|
||||
configure(r, &config, T::frequency(), T::KIND, true, true);
|
||||
|
||||
@ -847,11 +808,9 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
|
||||
if div * 2 >= brr_min && kind == Kind::Uart && !cfg!(usart_v1) {
|
||||
over8 = true;
|
||||
let div = div as u32;
|
||||
unsafe {
|
||||
r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07)));
|
||||
#[cfg(usart_v4)]
|
||||
r.presc().write(|w| w.set_prescaler(_presc_val));
|
||||
}
|
||||
r.brr().write_value(regs::Brr(((div << 1) & !0xF) | (div & 0x07)));
|
||||
#[cfg(usart_v4)]
|
||||
r.presc().write(|w| w.set_prescaler(_presc_val));
|
||||
found = Some(div);
|
||||
break;
|
||||
}
|
||||
@ -860,11 +819,9 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
|
||||
|
||||
if div < brr_max {
|
||||
let div = div as u32;
|
||||
unsafe {
|
||||
r.brr().write_value(regs::Brr(div));
|
||||
#[cfg(usart_v4)]
|
||||
r.presc().write(|w| w.set_prescaler(_presc_val));
|
||||
}
|
||||
r.brr().write_value(regs::Brr(div));
|
||||
#[cfg(usart_v4)]
|
||||
r.presc().write(|w| w.set_prescaler(_presc_val));
|
||||
found = Some(div);
|
||||
break;
|
||||
}
|
||||
@ -883,44 +840,42 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
|
||||
pclk_freq.0 / div
|
||||
);
|
||||
|
||||
unsafe {
|
||||
r.cr2().write(|w| {
|
||||
w.set_stop(match config.stop_bits {
|
||||
StopBits::STOP0P5 => vals::Stop::STOP0P5,
|
||||
StopBits::STOP1 => vals::Stop::STOP1,
|
||||
StopBits::STOP1P5 => vals::Stop::STOP1P5,
|
||||
StopBits::STOP2 => vals::Stop::STOP2,
|
||||
});
|
||||
r.cr2().write(|w| {
|
||||
w.set_stop(match config.stop_bits {
|
||||
StopBits::STOP0P5 => vals::Stop::STOP0P5,
|
||||
StopBits::STOP1 => vals::Stop::STOP1,
|
||||
StopBits::STOP1P5 => vals::Stop::STOP1P5,
|
||||
StopBits::STOP2 => vals::Stop::STOP2,
|
||||
});
|
||||
r.cr1().write(|w| {
|
||||
// enable uart
|
||||
w.set_ue(true);
|
||||
// enable transceiver
|
||||
w.set_te(enable_tx);
|
||||
// enable receiver
|
||||
w.set_re(enable_rx);
|
||||
// configure word size
|
||||
w.set_m0(if config.parity != Parity::ParityNone {
|
||||
vals::M0::BIT9
|
||||
} else {
|
||||
vals::M0::BIT8
|
||||
});
|
||||
// configure parity
|
||||
w.set_pce(config.parity != Parity::ParityNone);
|
||||
w.set_ps(match config.parity {
|
||||
Parity::ParityOdd => vals::Ps::ODD,
|
||||
Parity::ParityEven => vals::Ps::EVEN,
|
||||
_ => vals::Ps::EVEN,
|
||||
});
|
||||
#[cfg(not(usart_v1))]
|
||||
w.set_over8(vals::Over8(over8 as _));
|
||||
});
|
||||
r.cr1().write(|w| {
|
||||
// enable uart
|
||||
w.set_ue(true);
|
||||
// enable transceiver
|
||||
w.set_te(enable_tx);
|
||||
// enable receiver
|
||||
w.set_re(enable_rx);
|
||||
// configure word size
|
||||
w.set_m0(if config.parity != Parity::ParityNone {
|
||||
vals::M0::BIT9
|
||||
} else {
|
||||
vals::M0::BIT8
|
||||
});
|
||||
// configure parity
|
||||
w.set_pce(config.parity != Parity::ParityNone);
|
||||
w.set_ps(match config.parity {
|
||||
Parity::ParityOdd => vals::Ps::ODD,
|
||||
Parity::ParityEven => vals::Ps::EVEN,
|
||||
_ => vals::Ps::EVEN,
|
||||
});
|
||||
|
||||
#[cfg(not(usart_v1))]
|
||||
r.cr3().modify(|w| {
|
||||
w.set_onebit(config.assume_noise_free);
|
||||
});
|
||||
}
|
||||
w.set_over8(vals::Over8(over8 as _));
|
||||
});
|
||||
|
||||
#[cfg(not(usart_v1))]
|
||||
r.cr3().modify(|w| {
|
||||
w.set_onebit(config.assume_noise_free);
|
||||
});
|
||||
}
|
||||
|
||||
mod eh02 {
|
||||
@ -1111,12 +1066,12 @@ use self::sealed::Kind;
|
||||
|
||||
#[cfg(any(usart_v1, usart_v2))]
|
||||
fn tdr(r: crate::pac::usart::Usart) -> *mut u8 {
|
||||
r.dr().ptr() as _
|
||||
r.dr().as_ptr() as _
|
||||
}
|
||||
|
||||
#[cfg(any(usart_v1, usart_v2))]
|
||||
fn rdr(r: crate::pac::usart::Usart) -> *mut u8 {
|
||||
r.dr().ptr() as _
|
||||
r.dr().as_ptr() as _
|
||||
}
|
||||
|
||||
#[cfg(any(usart_v1, usart_v2))]
|
||||
@ -1126,18 +1081,18 @@ fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::p
|
||||
|
||||
#[cfg(any(usart_v1, usart_v2))]
|
||||
#[allow(unused)]
|
||||
unsafe fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) {
|
||||
fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) {
|
||||
// On v1 the flags are cleared implicitly by reads and writes to DR.
|
||||
}
|
||||
|
||||
#[cfg(any(usart_v3, usart_v4))]
|
||||
fn tdr(r: Regs) -> *mut u8 {
|
||||
r.tdr().ptr() as _
|
||||
r.tdr().as_ptr() as _
|
||||
}
|
||||
|
||||
#[cfg(any(usart_v3, usart_v4))]
|
||||
fn rdr(r: Regs) -> *mut u8 {
|
||||
r.rdr().ptr() as _
|
||||
r.rdr().as_ptr() as _
|
||||
}
|
||||
|
||||
#[cfg(any(usart_v3, usart_v4))]
|
||||
@ -1147,7 +1102,7 @@ fn sr(r: Regs) -> crate::pac::common::Reg<regs::Isr, crate::pac::common::R> {
|
||||
|
||||
#[cfg(any(usart_v3, usart_v4))]
|
||||
#[allow(unused)]
|
||||
unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) {
|
||||
fn clear_interrupt_flags(r: Regs, sr: regs::Isr) {
|
||||
r.icr().write(|w| *w = regs::Icr(sr.0));
|
||||
}
|
||||
|
||||
@ -1214,7 +1169,7 @@ macro_rules! impl_usart {
|
||||
type Interrupt = crate::interrupt::typelevel::$irq;
|
||||
|
||||
fn regs() -> Regs {
|
||||
Regs(crate::pac::$inst.0)
|
||||
unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) }
|
||||
}
|
||||
|
||||
fn state() -> &'static crate::usart::sealed::State {
|
||||
|
@ -59,23 +59,20 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
|
||||
|
||||
let r = T::regs();
|
||||
// clear all interrupts and DMA Rx Request
|
||||
// SAFETY: only clears Rx related flags
|
||||
unsafe {
|
||||
r.cr1().modify(|w| {
|
||||
// disable RXNE interrupt
|
||||
w.set_rxneie(false);
|
||||
// enable parity interrupt if not ParityNone
|
||||
w.set_peie(w.pce());
|
||||
// enable idle line interrupt
|
||||
w.set_idleie(true);
|
||||
});
|
||||
r.cr3().modify(|w| {
|
||||
// enable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||
w.set_eie(true);
|
||||
// enable DMA Rx Request
|
||||
w.set_dmar(true);
|
||||
});
|
||||
}
|
||||
r.cr1().modify(|w| {
|
||||
// disable RXNE interrupt
|
||||
w.set_rxneie(false);
|
||||
// enable parity interrupt if not ParityNone
|
||||
w.set_peie(w.pce());
|
||||
// enable idle line interrupt
|
||||
w.set_idleie(true);
|
||||
});
|
||||
r.cr3().modify(|w| {
|
||||
// enable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||
w.set_eie(true);
|
||||
// enable DMA Rx Request
|
||||
w.set_dmar(true);
|
||||
});
|
||||
}
|
||||
|
||||
/// Stop uart background receive
|
||||
@ -84,23 +81,20 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
|
||||
|
||||
let r = T::regs();
|
||||
// clear all interrupts and DMA Rx Request
|
||||
// SAFETY: only clears Rx related flags
|
||||
unsafe {
|
||||
r.cr1().modify(|w| {
|
||||
// disable RXNE interrupt
|
||||
w.set_rxneie(false);
|
||||
// disable parity interrupt
|
||||
w.set_peie(false);
|
||||
// disable idle line interrupt
|
||||
w.set_idleie(false);
|
||||
});
|
||||
r.cr3().modify(|w| {
|
||||
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||
w.set_eie(false);
|
||||
// disable DMA Rx Request
|
||||
w.set_dmar(false);
|
||||
});
|
||||
}
|
||||
r.cr1().modify(|w| {
|
||||
// disable RXNE interrupt
|
||||
w.set_rxneie(false);
|
||||
// disable parity interrupt
|
||||
w.set_peie(false);
|
||||
// disable idle line interrupt
|
||||
w.set_idleie(false);
|
||||
});
|
||||
r.cr3().modify(|w| {
|
||||
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
|
||||
w.set_eie(false);
|
||||
// disable DMA Rx Request
|
||||
w.set_dmar(false);
|
||||
});
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
}
|
||||
@ -117,8 +111,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
|
||||
let r = T::regs();
|
||||
|
||||
// Start background receive if it was not already started
|
||||
// SAFETY: read only
|
||||
match unsafe { r.cr3().read().dmar() } {
|
||||
match r.cr3().read().dmar() {
|
||||
false => self.start()?,
|
||||
_ => {}
|
||||
};
|
||||
@ -213,19 +206,17 @@ fn check_for_errors(s: Sr) -> Result<(), Error> {
|
||||
|
||||
/// Clear IDLE and return the Sr register
|
||||
fn clear_idle_flag(r: Regs) -> Sr {
|
||||
unsafe {
|
||||
// SAFETY: read only and we only use Rx related flags
|
||||
// SAFETY: read only and we only use Rx related flags
|
||||
|
||||
let sr = sr(r).read();
|
||||
let sr = sr(r).read();
|
||||
|
||||
// This read also clears the error and idle interrupt flags on v1.
|
||||
rdr(r).read_volatile();
|
||||
clear_interrupt_flags(r, sr);
|
||||
// This read also clears the error and idle interrupt flags on v1.
|
||||
unsafe { rdr(r).read_volatile() };
|
||||
clear_interrupt_flags(r, sr);
|
||||
|
||||
r.cr1().modify(|w| w.set_idleie(true));
|
||||
r.cr1().modify(|w| w.set_idleie(true));
|
||||
|
||||
sr
|
||||
}
|
||||
sr
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||
|
Reference in New Issue
Block a user