Applies the Uarte patch
Applies the Nordic workaround found in the `Uarte` for the nRF9160 and nRF5340 to the `BufferedUarte`.
This commit is contained in:
parent
c574b0eb73
commit
4e7fa52288
@ -22,7 +22,7 @@ use crate::pac;
|
|||||||
use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
|
use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
|
||||||
use crate::timer::Instance as TimerInstance;
|
use crate::timer::Instance as TimerInstance;
|
||||||
use crate::timer::{Frequency, Timer};
|
use crate::timer::{Frequency, Timer};
|
||||||
use crate::uarte::{Config, Instance as UarteInstance};
|
use crate::uarte::{apply_workaround_for_enable_anomaly, Config, Instance as UarteInstance};
|
||||||
|
|
||||||
// Re-export SVD variants to allow user to directly set values
|
// Re-export SVD variants to allow user to directly set values
|
||||||
pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
|
pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
|
||||||
@ -132,6 +132,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
|
|||||||
irq.pend();
|
irq.pend();
|
||||||
|
|
||||||
// Enable UARTE instance
|
// Enable UARTE instance
|
||||||
|
apply_workaround_for_enable_anomaly(&r);
|
||||||
r.enable.write(|w| w.enable().enabled());
|
r.enable.write(|w| w.enable().enabled());
|
||||||
|
|
||||||
// BAUDRATE register values are `baudrate * 2^32 / 16000000`
|
// BAUDRATE register values are `baudrate * 2^32 / 16000000`
|
||||||
|
@ -116,7 +116,7 @@ impl<'d, T: Instance> Uarte<'d, T> {
|
|||||||
irq.enable();
|
irq.enable();
|
||||||
|
|
||||||
// Enable
|
// Enable
|
||||||
Self::apply_workaround_for_enable_anomaly();
|
apply_workaround_for_enable_anomaly(&r);
|
||||||
r.enable.write(|w| w.enable().enabled());
|
r.enable.write(|w| w.enable().enabled());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -124,61 +124,6 @@ impl<'d, T: Instance> Uarte<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(feature = "_nrf9160", feature = "nrf5340")))]
|
|
||||||
fn apply_workaround_for_enable_anomaly() {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(feature = "_nrf9160", feature = "nrf5340"))]
|
|
||||||
fn apply_workaround_for_enable_anomaly() {
|
|
||||||
use core::ops::Deref;
|
|
||||||
|
|
||||||
let r = T::regs();
|
|
||||||
|
|
||||||
// Apply workaround for anomalies:
|
|
||||||
// - nRF9160 - anomaly 23
|
|
||||||
// - nRF5340 - anomaly 44
|
|
||||||
let rxenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x564) as *const u32;
|
|
||||||
let txenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x568) as *const u32;
|
|
||||||
|
|
||||||
// NB Safety: This is taken from Nordic's driver -
|
|
||||||
// https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
|
|
||||||
if unsafe { core::ptr::read_volatile(txenable_reg) } == 1 {
|
|
||||||
r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
|
|
||||||
}
|
|
||||||
|
|
||||||
// NB Safety: This is taken from Nordic's driver -
|
|
||||||
// https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
|
|
||||||
if unsafe { core::ptr::read_volatile(rxenable_reg) } == 1 {
|
|
||||||
r.enable.write(|w| w.enable().enabled());
|
|
||||||
r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
|
|
||||||
|
|
||||||
let mut workaround_succeded = false;
|
|
||||||
// The UARTE is able to receive up to four bytes after the STOPRX task has been triggered.
|
|
||||||
// On lowest supported baud rate (1200 baud), with parity bit and two stop bits configured
|
|
||||||
// (resulting in 12 bits per data byte sent), this may take up to 40 ms.
|
|
||||||
for _ in 0..40000 {
|
|
||||||
// NB Safety: This is taken from Nordic's driver -
|
|
||||||
// https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
|
|
||||||
if unsafe { core::ptr::read_volatile(rxenable_reg) } == 0 {
|
|
||||||
workaround_succeded = true;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// Need to sleep for 1us here
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !workaround_succeded {
|
|
||||||
panic!("Failed to apply workaround for UART");
|
|
||||||
}
|
|
||||||
|
|
||||||
let errors = r.errorsrc.read().bits();
|
|
||||||
// NB Safety: safe to write back the bits we just read to clear them
|
|
||||||
r.errorsrc.write(|w| unsafe { w.bits(errors) });
|
|
||||||
r.enable.write(|w| w.enable().disabled());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_interrupt(_: *mut ()) {
|
fn on_interrupt(_: *mut ()) {
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
let s = T::state();
|
let s = T::state();
|
||||||
@ -330,6 +275,59 @@ impl<'d, T: Instance> Write for Uarte<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(feature = "_nrf9160", feature = "nrf5340")))]
|
||||||
|
pub(in crate) fn apply_workaround_for_enable_anomaly(r: &crate::pac::uarte0::RegisterBlock) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "_nrf9160", feature = "nrf5340"))]
|
||||||
|
pub(in crate) fn apply_workaround_for_enable_anomaly(r: &crate::pac::uarte0::RegisterBlock) {
|
||||||
|
use core::ops::Deref;
|
||||||
|
|
||||||
|
// Apply workaround for anomalies:
|
||||||
|
// - nRF9160 - anomaly 23
|
||||||
|
// - nRF5340 - anomaly 44
|
||||||
|
let rxenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x564) as *const u32;
|
||||||
|
let txenable_reg: *const u32 = ((r.deref() as *const _ as usize) + 0x568) as *const u32;
|
||||||
|
|
||||||
|
// NB Safety: This is taken from Nordic's driver -
|
||||||
|
// https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
|
||||||
|
if unsafe { core::ptr::read_volatile(txenable_reg) } == 1 {
|
||||||
|
r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB Safety: This is taken from Nordic's driver -
|
||||||
|
// https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
|
||||||
|
if unsafe { core::ptr::read_volatile(rxenable_reg) } == 1 {
|
||||||
|
r.enable.write(|w| w.enable().enabled());
|
||||||
|
r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
|
||||||
|
|
||||||
|
let mut workaround_succeded = false;
|
||||||
|
// The UARTE is able to receive up to four bytes after the STOPRX task has been triggered.
|
||||||
|
// On lowest supported baud rate (1200 baud), with parity bit and two stop bits configured
|
||||||
|
// (resulting in 12 bits per data byte sent), this may take up to 40 ms.
|
||||||
|
for _ in 0..40000 {
|
||||||
|
// NB Safety: This is taken from Nordic's driver -
|
||||||
|
// https://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197
|
||||||
|
if unsafe { core::ptr::read_volatile(rxenable_reg) } == 0 {
|
||||||
|
workaround_succeded = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// Need to sleep for 1us here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !workaround_succeded {
|
||||||
|
panic!("Failed to apply workaround for UART");
|
||||||
|
}
|
||||||
|
|
||||||
|
let errors = r.errorsrc.read().bits();
|
||||||
|
// NB Safety: safe to write back the bits we just read to clear them
|
||||||
|
r.errorsrc.write(|w| unsafe { w.bits(errors) });
|
||||||
|
r.enable.write(|w| w.enable().disabled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Interface to an UARTE peripheral that uses an additional timer and two PPI channels,
|
/// Interface to an UARTE peripheral that uses an additional timer and two PPI channels,
|
||||||
/// allowing it to implement the ReadUntilIdle trait.
|
/// allowing it to implement the ReadUntilIdle trait.
|
||||||
pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
|
pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
|
||||||
|
Loading…
Reference in New Issue
Block a user