diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-03-28 22:41:45 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-03-29 00:58:58 +0200 |
| commit | 3a18373828577e5e9d06e9f5c108376fef32fe18 (patch) | |
| tree | 3712adfb3061029914bc63a47231beebf49b9c2f | |
| parent | 00e5f3035219656823ec7a2451f4ebae6802e1b8 (diff) | |
nrf/uarte: update BufferedUarte to new APi
| -rw-r--r-- | embassy-nrf-examples/src/bin/buffered_uart.rs | 80 | ||||
| -rw-r--r-- | embassy-nrf/Cargo.toml | 16 | ||||
| -rw-r--r-- | embassy-nrf/src/buffered_uarte.rs | 287 | ||||
| -rw-r--r-- | embassy-nrf/src/lib.rs | 11 |
4 files changed, 173 insertions, 221 deletions
diff --git a/embassy-nrf-examples/src/bin/buffered_uart.rs b/embassy-nrf-examples/src/bin/buffered_uart.rs index c70171280..80b24d2ba 100644 --- a/embassy-nrf-examples/src/bin/buffered_uart.rs +++ b/embassy-nrf-examples/src/bin/buffered_uart.rs | |||
| @@ -7,54 +7,49 @@ | |||
| 7 | 7 | ||
| 8 | #[path = "../example_common.rs"] | 8 | #[path = "../example_common.rs"] |
| 9 | mod example_common; | 9 | mod example_common; |
| 10 | use core::mem; | ||
| 11 | |||
| 12 | use embassy_nrf::gpio::NoPin; | ||
| 10 | use example_common::*; | 13 | use example_common::*; |
| 11 | 14 | ||
| 12 | use cortex_m_rt::entry; | 15 | use cortex_m_rt::entry; |
| 13 | use defmt::panic; | 16 | use defmt::panic; |
| 14 | use futures::pin_mut; | 17 | use futures::pin_mut; |
| 15 | use nrf52840_hal as hal; | 18 | use nrf52840_hal::clocks; |
| 16 | use nrf52840_hal::gpio; | ||
| 17 | 19 | ||
| 18 | use embassy::executor::{task, Executor}; | 20 | use embassy::executor::{task, Executor}; |
| 19 | use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; | 21 | use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; |
| 20 | use embassy::util::Forever; | 22 | use embassy::util::{Forever, Steal}; |
| 21 | use embassy_nrf::buffered_uarte; | 23 | use embassy_nrf::{buffered_uarte::BufferedUarte, interrupt, peripherals, rtc, uarte, Peripherals}; |
| 22 | use embassy_nrf::interrupt; | ||
| 23 | |||
| 24 | static mut TX_BUFFER: [u8; 4096] = [0; 4096]; | ||
| 25 | static mut RX_BUFFER: [u8; 4096] = [0; 4096]; | ||
| 26 | 24 | ||
| 27 | #[task] | 25 | #[task] |
| 28 | async fn run() { | 26 | async fn run() { |
| 29 | let p = unwrap!(embassy_nrf::pac::Peripherals::take()); | 27 | let p = unsafe { Peripherals::steal() }; |
| 30 | |||
| 31 | let port0 = gpio::p0::Parts::new(p.P0); | ||
| 32 | |||
| 33 | let pins = buffered_uarte::Pins { | ||
| 34 | rxd: port0.p0_08.into_floating_input().degrade(), | ||
| 35 | txd: port0 | ||
| 36 | .p0_06 | ||
| 37 | .into_push_pull_output(gpio::Level::Low) | ||
| 38 | .degrade(), | ||
| 39 | cts: None, | ||
| 40 | rts: None, | ||
| 41 | }; | ||
| 42 | 28 | ||
| 43 | let ppi = hal::ppi::Parts::new(p.PPI); | 29 | let mut config = uarte::Config::default(); |
| 30 | config.parity = uarte::Parity::EXCLUDED; | ||
| 31 | config.baudrate = uarte::Baudrate::BAUD115200; | ||
| 32 | |||
| 33 | let mut tx_buffer = [0u8; 4096]; | ||
| 34 | let mut rx_buffer = [0u8; 4096]; | ||
| 44 | 35 | ||
| 45 | let irq = interrupt::take!(UARTE0_UART0); | 36 | let irq = interrupt::take!(UARTE0_UART0); |
| 46 | let u = buffered_uarte::BufferedUarte::new( | 37 | let u = unsafe { |
| 47 | p.UARTE0, | 38 | BufferedUarte::new( |
| 48 | p.TIMER0, | 39 | p.UARTE0, |
| 49 | ppi.ppi0, | 40 | p.TIMER0, |
| 50 | ppi.ppi1, | 41 | p.PPI_CH0, |
| 51 | irq, | 42 | p.PPI_CH1, |
| 52 | unsafe { &mut RX_BUFFER }, | 43 | irq, |
| 53 | unsafe { &mut TX_BUFFER }, | 44 | p.P0_08, |
| 54 | pins, | 45 | p.P0_06, |
| 55 | buffered_uarte::Parity::EXCLUDED, | 46 | NoPin, |
| 56 | buffered_uarte::Baudrate::BAUD115200, | 47 | NoPin, |
| 57 | ); | 48 | config, |
| 49 | &mut rx_buffer, | ||
| 50 | &mut tx_buffer, | ||
| 51 | ) | ||
| 52 | }; | ||
| 58 | pin_mut!(u); | 53 | pin_mut!(u); |
| 59 | 54 | ||
| 60 | info!("uarte initialized!"); | 55 | info!("uarte initialized!"); |
| @@ -80,13 +75,30 @@ async fn run() { | |||
| 80 | } | 75 | } |
| 81 | } | 76 | } |
| 82 | 77 | ||
| 78 | static RTC: Forever<rtc::RTC<peripherals::RTC1>> = Forever::new(); | ||
| 79 | static ALARM: Forever<rtc::Alarm<peripherals::RTC1>> = Forever::new(); | ||
| 83 | static EXECUTOR: Forever<Executor> = Forever::new(); | 80 | static EXECUTOR: Forever<Executor> = Forever::new(); |
| 84 | 81 | ||
| 85 | #[entry] | 82 | #[entry] |
| 86 | fn main() -> ! { | 83 | fn main() -> ! { |
| 87 | info!("Hello World!"); | 84 | info!("Hello World!"); |
| 88 | 85 | ||
| 86 | let p = unwrap!(embassy_nrf::Peripherals::take()); | ||
| 87 | |||
| 88 | clocks::Clocks::new(unsafe { mem::transmute(()) }) | ||
| 89 | .enable_ext_hfosc() | ||
| 90 | .set_lfclk_src_external(clocks::LfOscConfiguration::NoExternalNoBypass) | ||
| 91 | .start_lfclk(); | ||
| 92 | |||
| 93 | let rtc = RTC.put(rtc::RTC::new(p.RTC1, interrupt::take!(RTC1))); | ||
| 94 | rtc.start(); | ||
| 95 | |||
| 96 | unsafe { embassy::time::set_clock(rtc) }; | ||
| 97 | |||
| 98 | let alarm = ALARM.put(rtc.alarm0()); | ||
| 89 | let executor = EXECUTOR.put(Executor::new()); | 99 | let executor = EXECUTOR.put(Executor::new()); |
| 100 | executor.set_alarm(alarm); | ||
| 101 | |||
| 90 | executor.run(|spawner| { | 102 | executor.run(|spawner| { |
| 91 | unwrap!(spawner.spawn(run())); | 103 | unwrap!(spawner.spawn(run())); |
| 92 | }); | 104 | }); |
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index f26e892d3..3ab2c60bd 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml | |||
| @@ -11,11 +11,11 @@ defmt-info = [ ] | |||
| 11 | defmt-warn = [ ] | 11 | defmt-warn = [ ] |
| 12 | defmt-error = [ ] | 12 | defmt-error = [ ] |
| 13 | 13 | ||
| 14 | 52810 = ["nrf52810-pac", "nrf52810-hal"] | 14 | 52810 = ["nrf52810-pac"] |
| 15 | 52811 = ["nrf52811-pac"] #, "nrf52811-hal"] | 15 | 52811 = ["nrf52811-pac"] |
| 16 | 52832 = ["nrf52832-pac", "nrf52832-hal"] | 16 | 52832 = ["nrf52832-pac"] |
| 17 | 52833 = ["nrf52833-pac", "nrf52833-hal"] | 17 | 52833 = ["nrf52833-pac"] |
| 18 | 52840 = ["nrf52840-pac", "nrf52840-hal"] | 18 | 52840 = ["nrf52840-pac"] |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | [dependencies] | 21 | [dependencies] |
| @@ -36,9 +36,3 @@ nrf52811-pac = { version = "0.9.1", optional = true } | |||
| 36 | nrf52832-pac = { version = "0.9.0", optional = true } | 36 | nrf52832-pac = { version = "0.9.0", optional = true } |
| 37 | nrf52833-pac = { version = "0.9.0", optional = true } | 37 | nrf52833-pac = { version = "0.9.0", optional = true } |
| 38 | nrf52840-pac = { version = "0.9.0", optional = true } | 38 | nrf52840-pac = { version = "0.9.0", optional = true } |
| 39 | |||
| 40 | nrf52810-hal = { version = "0.12.1", optional = true } | ||
| 41 | #nrf52811-hal = { version = "0.12.1", optional = true } # doesn't exist yet | ||
| 42 | nrf52832-hal = { version = "0.12.1", optional = true } | ||
| 43 | nrf52833-hal = { version = "0.12.1", optional = true } | ||
| 44 | nrf52840-hal = { version = "0.12.1", optional = true } | ||
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 6cc5f1322..702ccde0e 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs | |||
| @@ -1,30 +1,24 @@ | |||
| 1 | //! HAL interface to the UARTE peripheral | ||
| 2 | //! | ||
| 3 | //! See product specification: | ||
| 4 | //! | ||
| 5 | //! - nrf52832: Section 35 | ||
| 6 | //! - nrf52840: Section 6.34 | ||
| 7 | use core::cmp::min; | 1 | use core::cmp::min; |
| 8 | use core::mem; | 2 | use core::mem; |
| 9 | use core::ops::Deref; | ||
| 10 | use core::pin::Pin; | 3 | use core::pin::Pin; |
| 11 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 12 | use core::task::{Context, Poll}; | 5 | use core::task::{Context, Poll}; |
| 13 | use embassy::interrupt::InterruptExt; | 6 | use embassy::interrupt::InterruptExt; |
| 14 | use embassy::io::{AsyncBufRead, AsyncWrite, Result}; | 7 | use embassy::io::{AsyncBufRead, AsyncWrite, Result}; |
| 15 | use embassy::util::WakerRegistration; | 8 | use embassy::util::{PeripheralBorrow, WakerRegistration}; |
| 16 | use embassy_extras::low_power_wait_until; | ||
| 17 | use embassy_extras::peripheral::{PeripheralMutex, PeripheralState}; | 9 | use embassy_extras::peripheral::{PeripheralMutex, PeripheralState}; |
| 18 | use embassy_extras::ring_buffer::RingBuffer; | 10 | use embassy_extras::ring_buffer::RingBuffer; |
| 19 | use embedded_hal::digital::v2::OutputPin; | 11 | use embassy_extras::{low_power_wait_until, unborrow}; |
| 20 | 12 | ||
| 21 | use crate::fmt::*; | 13 | use crate::fmt::{panic, *}; |
| 22 | use crate::hal::ppi::ConfigurablePpi; | 14 | use crate::gpio::sealed::Pin as _; |
| 23 | use crate::interrupt::{self, Interrupt}; | 15 | use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin}; |
| 24 | use crate::pac; | 16 | use crate::pac; |
| 17 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | ||
| 18 | use crate::timer::Instance as TimerInstance; | ||
| 19 | use crate::uarte::{Config, Instance as UarteInstance}; | ||
| 25 | 20 | ||
| 26 | // Re-export SVD variants to allow user to directly set values | 21 | // Re-export SVD variants to allow user to directly set values |
| 27 | pub use crate::hal::uarte::Pins; | ||
| 28 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; | 22 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; |
| 29 | 23 | ||
| 30 | #[derive(Copy, Clone, Debug, PartialEq)] | 24 | #[derive(Copy, Clone, Debug, PartialEq)] |
| @@ -39,17 +33,17 @@ enum TxState { | |||
| 39 | Transmitting(usize), | 33 | Transmitting(usize), |
| 40 | } | 34 | } |
| 41 | 35 | ||
| 42 | struct State<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> { | 36 | struct State<'d, U: UarteInstance, T: TimerInstance> { |
| 43 | uarte: U, | 37 | uarte: U, |
| 44 | timer: T, | 38 | timer: T, |
| 45 | ppi_channel_1: P1, | 39 | _ppi_ch1: Ppi<'d, AnyConfigurableChannel>, |
| 46 | ppi_channel_2: P2, | 40 | _ppi_ch2: Ppi<'d, AnyConfigurableChannel>, |
| 47 | 41 | ||
| 48 | rx: RingBuffer<'a>, | 42 | rx: RingBuffer<'d>, |
| 49 | rx_state: RxState, | 43 | rx_state: RxState, |
| 50 | rx_waker: WakerRegistration, | 44 | rx_waker: WakerRegistration, |
| 51 | 45 | ||
| 52 | tx: RingBuffer<'a>, | 46 | tx: RingBuffer<'d>, |
| 53 | tx_state: TxState, | 47 | tx_state: TxState, |
| 54 | tx_waker: WakerRegistration, | 48 | tx_waker: WakerRegistration, |
| 55 | } | 49 | } |
| @@ -62,115 +56,112 @@ struct State<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: Configu | |||
| 62 | /// are disabled before using `Uarte`. See product specification: | 56 | /// are disabled before using `Uarte`. See product specification: |
| 63 | /// - nrf52832: Section 15.2 | 57 | /// - nrf52832: Section 15.2 |
| 64 | /// - nrf52840: Section 6.1.2 | 58 | /// - nrf52840: Section 6.1.2 |
| 65 | pub struct BufferedUarte< | 59 | pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> { |
| 66 | 'a, | 60 | inner: PeripheralMutex<State<'d, U, T>>, |
| 67 | U: Instance, | ||
| 68 | T: TimerInstance, | ||
| 69 | P1: ConfigurablePpi, | ||
| 70 | P2: ConfigurablePpi, | ||
| 71 | > { | ||
| 72 | inner: PeripheralMutex<State<'a, U, T, P1, P2>>, | ||
| 73 | } | 61 | } |
| 74 | 62 | ||
| 75 | impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> | 63 | impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { |
| 76 | BufferedUarte<'a, U, T, P1, P2> | 64 | /// unsafe: may not leak self or futures |
| 77 | { | 65 | pub unsafe fn new( |
| 78 | pub fn new( | 66 | uarte: impl PeripheralBorrow<Target = U> + 'd, |
| 79 | uarte: U, | 67 | timer: impl PeripheralBorrow<Target = T> + 'd, |
| 80 | timer: T, | 68 | ppi_ch1: impl PeripheralBorrow<Target = impl ConfigurableChannel> + 'd, |
| 81 | mut ppi_channel_1: P1, | 69 | ppi_ch2: impl PeripheralBorrow<Target = impl ConfigurableChannel> + 'd, |
| 82 | mut ppi_channel_2: P2, | 70 | irq: impl PeripheralBorrow<Target = U::Interrupt> + 'd, |
| 83 | irq: U::Interrupt, | 71 | rxd: impl PeripheralBorrow<Target = impl GpioPin> + 'd, |
| 84 | rx_buffer: &'a mut [u8], | 72 | txd: impl PeripheralBorrow<Target = impl GpioPin> + 'd, |
| 85 | tx_buffer: &'a mut [u8], | 73 | cts: impl PeripheralBorrow<Target = impl GpioOptionalPin> + 'd, |
| 86 | mut pins: Pins, | 74 | rts: impl PeripheralBorrow<Target = impl GpioOptionalPin> + 'd, |
| 87 | parity: Parity, | 75 | config: Config, |
| 88 | baudrate: Baudrate, | 76 | rx_buffer: &'d mut [u8], |
| 77 | tx_buffer: &'d mut [u8], | ||
| 89 | ) -> Self { | 78 | ) -> Self { |
| 90 | // Select pins | 79 | unborrow!(uarte, timer, ppi_ch1, ppi_ch2, irq, rxd, txd, cts, rts); |
| 91 | uarte.psel.rxd.write(|w| { | ||
| 92 | unsafe { w.bits(pins.rxd.psel_bits()) }; | ||
| 93 | w.connect().connected() | ||
| 94 | }); | ||
| 95 | pins.txd.set_high().unwrap(); | ||
| 96 | uarte.psel.txd.write(|w| { | ||
| 97 | unsafe { w.bits(pins.txd.psel_bits()) }; | ||
| 98 | w.connect().connected() | ||
| 99 | }); | ||
| 100 | 80 | ||
| 101 | // Optional pins | 81 | let r = uarte.regs(); |
| 102 | uarte.psel.cts.write(|w| { | 82 | let rt = timer.regs(); |
| 103 | if let Some(ref pin) = pins.cts { | ||
| 104 | unsafe { w.bits(pin.psel_bits()) }; | ||
| 105 | w.connect().connected() | ||
| 106 | } else { | ||
| 107 | w.connect().disconnected() | ||
| 108 | } | ||
| 109 | }); | ||
| 110 | 83 | ||
| 111 | uarte.psel.rts.write(|w| { | 84 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); |
| 112 | if let Some(ref pin) = pins.rts { | 85 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); |
| 113 | unsafe { w.bits(pin.psel_bits()) }; | ||
| 114 | w.connect().connected() | ||
| 115 | } else { | ||
| 116 | w.connect().disconnected() | ||
| 117 | } | ||
| 118 | }); | ||
| 119 | 86 | ||
| 120 | // Enable UARTE instance | 87 | txd.set_high(); |
| 121 | uarte.enable.write(|w| w.enable().enabled()); | 88 | txd.conf().write(|w| w.dir().output().drive().h0h1()); |
| 89 | r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); | ||
| 122 | 90 | ||
| 123 | // Enable interrupts | 91 | if let Some(pin) = rts.pin_mut() { |
| 124 | uarte.intenset.write(|w| w.endrx().set().endtx().set()); | 92 | pin.set_high(); |
| 93 | pin.conf().write(|w| w.dir().output().drive().h0h1()); | ||
| 94 | } | ||
| 95 | r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); | ||
| 96 | |||
| 97 | if let Some(pin) = cts.pin_mut() { | ||
| 98 | pin.conf().write(|w| w.input().connect().drive().h0h1()); | ||
| 99 | } | ||
| 100 | r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); | ||
| 101 | |||
| 102 | r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); | ||
| 103 | r.config.write(|w| w.parity().variant(config.parity)); | ||
| 125 | 104 | ||
| 126 | // Configure | 105 | // Configure |
| 127 | let hardware_flow_control = pins.rts.is_some() && pins.cts.is_some(); | 106 | let hardware_flow_control = match (rts.pin().is_some(), cts.pin().is_some()) { |
| 128 | uarte | 107 | (false, false) => false, |
| 129 | .config | 108 | (true, true) => true, |
| 130 | .write(|w| w.hwfc().bit(hardware_flow_control).parity().variant(parity)); | 109 | _ => panic!("RTS and CTS pins must be either both set or none set."), |
| 110 | }; | ||
| 111 | r.config.write(|w| { | ||
| 112 | w.hwfc().bit(hardware_flow_control); | ||
| 113 | w.parity().variant(config.parity); | ||
| 114 | w | ||
| 115 | }); | ||
| 116 | r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); | ||
| 131 | 117 | ||
| 132 | // Configure frequency | 118 | // Enable interrupts |
| 133 | uarte.baudrate.write(|w| w.baudrate().variant(baudrate)); | 119 | r.intenset.write(|w| w.endrx().set().endtx().set()); |
| 134 | 120 | ||
| 135 | // Disable the irq, let the Registration enable it when everything is set up. | 121 | // Disable the irq, let the Registration enable it when everything is set up. |
| 136 | irq.disable(); | 122 | irq.disable(); |
| 137 | irq.pend(); | 123 | irq.pend(); |
| 138 | 124 | ||
| 125 | // Enable UARTE instance | ||
| 126 | r.enable.write(|w| w.enable().enabled()); | ||
| 127 | |||
| 139 | // BAUDRATE register values are `baudrate * 2^32 / 16000000` | 128 | // BAUDRATE register values are `baudrate * 2^32 / 16000000` |
| 140 | // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values | 129 | // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values |
| 141 | // | 130 | // |
| 142 | // We want to stop RX if line is idle for 2 bytes worth of time | 131 | // We want to stop RX if line is idle for 2 bytes worth of time |
| 143 | // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit) | 132 | // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit) |
| 144 | // This gives us the amount of 16M ticks for 20 bits. | 133 | // This gives us the amount of 16M ticks for 20 bits. |
| 145 | let timeout = 0x8000_0000 / (baudrate as u32 / 40); | 134 | let timeout = 0x8000_0000 / (config.baudrate as u32 / 40); |
| 146 | 135 | ||
| 147 | timer.tasks_stop.write(|w| unsafe { w.bits(1) }); | 136 | rt.tasks_stop.write(|w| unsafe { w.bits(1) }); |
| 148 | timer.bitmode.write(|w| w.bitmode()._32bit()); | 137 | rt.bitmode.write(|w| w.bitmode()._32bit()); |
| 149 | timer.prescaler.write(|w| unsafe { w.prescaler().bits(0) }); | 138 | rt.prescaler.write(|w| unsafe { w.prescaler().bits(0) }); |
| 150 | timer.cc[0].write(|w| unsafe { w.bits(timeout) }); | 139 | rt.cc[0].write(|w| unsafe { w.bits(timeout) }); |
| 151 | timer.mode.write(|w| w.mode().timer()); | 140 | rt.mode.write(|w| w.mode().timer()); |
| 152 | timer.shorts.write(|w| { | 141 | rt.shorts.write(|w| { |
| 153 | w.compare0_clear().set_bit(); | 142 | w.compare0_clear().set_bit(); |
| 154 | w.compare0_stop().set_bit(); | 143 | w.compare0_stop().set_bit(); |
| 155 | w | 144 | w |
| 156 | }); | 145 | }); |
| 157 | 146 | ||
| 158 | ppi_channel_1.set_event_endpoint(&uarte.events_rxdrdy); | 147 | let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable()); |
| 159 | ppi_channel_1.set_task_endpoint(&timer.tasks_clear); | 148 | ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy)); |
| 160 | ppi_channel_1.set_fork_task_endpoint(&timer.tasks_start); | 149 | ppi_ch1.set_task(Task::from_reg(&rt.tasks_clear)); |
| 161 | ppi_channel_1.enable(); | 150 | ppi_ch1.set_fork_task(Task::from_reg(&rt.tasks_start)); |
| 151 | ppi_ch1.enable(); | ||
| 162 | 152 | ||
| 163 | ppi_channel_2.set_event_endpoint(&timer.events_compare[0]); | 153 | let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable()); |
| 164 | ppi_channel_2.set_task_endpoint(&uarte.tasks_stoprx); | 154 | ppi_ch2.set_event(Event::from_reg(&rt.events_compare[0])); |
| 165 | ppi_channel_2.enable(); | 155 | ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx)); |
| 156 | ppi_ch2.enable(); | ||
| 166 | 157 | ||
| 167 | BufferedUarte { | 158 | BufferedUarte { |
| 168 | inner: PeripheralMutex::new( | 159 | inner: PeripheralMutex::new( |
| 169 | State { | 160 | State { |
| 170 | uarte, | 161 | uarte, |
| 171 | timer, | 162 | timer, |
| 172 | ppi_channel_1, | 163 | _ppi_ch1: ppi_ch1, |
| 173 | ppi_channel_2, | 164 | _ppi_ch2: ppi_ch2, |
| 174 | 165 | ||
| 175 | rx: RingBuffer::new(rx_buffer), | 166 | rx: RingBuffer::new(rx_buffer), |
| 176 | rx_state: RxState::Idle, | 167 | rx_state: RxState::Idle, |
| @@ -187,25 +178,23 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 187 | 178 | ||
| 188 | pub fn set_baudrate(self: Pin<&mut Self>, baudrate: Baudrate) { | 179 | pub fn set_baudrate(self: Pin<&mut Self>, baudrate: Baudrate) { |
| 189 | self.inner().with(|state, _irq| { | 180 | self.inner().with(|state, _irq| { |
| 181 | let r = state.uarte.regs(); | ||
| 182 | let rt = state.timer.regs(); | ||
| 183 | |||
| 190 | let timeout = 0x8000_0000 / (baudrate as u32 / 40); | 184 | let timeout = 0x8000_0000 / (baudrate as u32 / 40); |
| 191 | state.timer.cc[0].write(|w| unsafe { w.bits(timeout) }); | 185 | rt.cc[0].write(|w| unsafe { w.bits(timeout) }); |
| 192 | state.timer.tasks_clear.write(|w| unsafe { w.bits(1) }); | 186 | rt.tasks_clear.write(|w| unsafe { w.bits(1) }); |
| 193 | 187 | ||
| 194 | state | 188 | r.baudrate.write(|w| w.baudrate().variant(baudrate)); |
| 195 | .uarte | ||
| 196 | .baudrate | ||
| 197 | .write(|w| w.baudrate().variant(baudrate)); | ||
| 198 | }); | 189 | }); |
| 199 | } | 190 | } |
| 200 | 191 | ||
| 201 | fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State<'a, U, T, P1, P2>>> { | 192 | fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State<'d, U, T>>> { |
| 202 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } | 193 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } |
| 203 | } | 194 | } |
| 204 | } | 195 | } |
| 205 | 196 | ||
| 206 | impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> AsyncBufRead | 197 | impl<'d, U: UarteInstance, T: TimerInstance> AsyncBufRead for BufferedUarte<'d, U, T> { |
| 207 | for BufferedUarte<'a, U, T, P1, P2> | ||
| 208 | { | ||
| 209 | fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { | 198 | fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { |
| 210 | let mut inner = self.inner(); | 199 | let mut inner = self.inner(); |
| 211 | inner.as_mut().register_interrupt(); | 200 | inner.as_mut().register_interrupt(); |
| @@ -242,9 +231,7 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 242 | } | 231 | } |
| 243 | } | 232 | } |
| 244 | 233 | ||
| 245 | impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> AsyncWrite | 234 | impl<'d, U: UarteInstance, T: TimerInstance> AsyncWrite for BufferedUarte<'d, U, T> { |
| 246 | for BufferedUarte<'a, U, T, P1, P2> | ||
| 247 | { | ||
| 248 | fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { | 235 | fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { |
| 249 | let mut inner = self.inner(); | 236 | let mut inner = self.inner(); |
| 250 | inner.as_mut().register_interrupt(); | 237 | inner.as_mut().register_interrupt(); |
| @@ -276,32 +263,36 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 276 | } | 263 | } |
| 277 | } | 264 | } |
| 278 | 265 | ||
| 279 | impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> Drop | 266 | impl<'a, U: UarteInstance, T: TimerInstance> Drop for State<'a, U, T> { |
| 280 | for State<'a, U, T, P1, P2> | ||
| 281 | { | ||
| 282 | fn drop(&mut self) { | 267 | fn drop(&mut self) { |
| 283 | self.timer.tasks_stop.write(|w| unsafe { w.bits(1) }); | 268 | let r = self.uarte.regs(); |
| 269 | let rt = self.timer.regs(); | ||
| 270 | |||
| 271 | // TODO this probably deadlocks. do like Uarte instead. | ||
| 272 | |||
| 273 | rt.tasks_stop.write(|w| unsafe { w.bits(1) }); | ||
| 284 | if let RxState::Receiving = self.rx_state { | 274 | if let RxState::Receiving = self.rx_state { |
| 285 | self.uarte.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | 275 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
| 286 | } | 276 | } |
| 287 | if let TxState::Transmitting(_) = self.tx_state { | 277 | if let TxState::Transmitting(_) = self.tx_state { |
| 288 | self.uarte.tasks_stoptx.write(|w| unsafe { w.bits(1) }); | 278 | r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); |
| 289 | } | 279 | } |
| 290 | if let RxState::Receiving = self.rx_state { | 280 | if let RxState::Receiving = self.rx_state { |
| 291 | low_power_wait_until(|| self.uarte.events_endrx.read().bits() == 1); | 281 | low_power_wait_until(|| r.events_endrx.read().bits() == 1); |
| 292 | } | 282 | } |
| 293 | if let TxState::Transmitting(_) = self.tx_state { | 283 | if let TxState::Transmitting(_) = self.tx_state { |
| 294 | low_power_wait_until(|| self.uarte.events_endtx.read().bits() == 1); | 284 | low_power_wait_until(|| r.events_endtx.read().bits() == 1); |
| 295 | } | 285 | } |
| 296 | } | 286 | } |
| 297 | } | 287 | } |
| 298 | 288 | ||
| 299 | impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> PeripheralState | 289 | impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for State<'a, U, T> { |
| 300 | for State<'a, U, T, P1, P2> | ||
| 301 | { | ||
| 302 | type Interrupt = U::Interrupt; | 290 | type Interrupt = U::Interrupt; |
| 303 | fn on_interrupt(&mut self) { | 291 | fn on_interrupt(&mut self) { |
| 304 | trace!("irq: start"); | 292 | trace!("irq: start"); |
| 293 | let r = self.uarte.regs(); | ||
| 294 | let rt = self.timer.regs(); | ||
| 295 | |||
| 305 | loop { | 296 | loop { |
| 306 | match self.rx_state { | 297 | match self.rx_state { |
| 307 | RxState::Idle => { | 298 | RxState::Idle => { |
| @@ -313,11 +304,11 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 313 | self.rx_state = RxState::Receiving; | 304 | self.rx_state = RxState::Receiving; |
| 314 | 305 | ||
| 315 | // Set up the DMA read | 306 | // Set up the DMA read |
| 316 | self.uarte.rxd.ptr.write(|w| | 307 | r.rxd.ptr.write(|w| |
| 317 | // The PTR field is a full 32 bits wide and accepts the full range | 308 | // The PTR field is a full 32 bits wide and accepts the full range |
| 318 | // of values. | 309 | // of values. |
| 319 | unsafe { w.ptr().bits(buf.as_ptr() as u32) }); | 310 | unsafe { w.ptr().bits(buf.as_ptr() as u32) }); |
| 320 | self.uarte.rxd.maxcnt.write(|w| | 311 | r.rxd.maxcnt.write(|w| |
| 321 | // We're giving it the length of the buffer, so no danger of | 312 | // We're giving it the length of the buffer, so no danger of |
| 322 | // accessing invalid memory. We have verified that the length of the | 313 | // accessing invalid memory. We have verified that the length of the |
| 323 | // buffer fits in an `u8`, so the cast to `u8` is also fine. | 314 | // buffer fits in an `u8`, so the cast to `u8` is also fine. |
| @@ -328,7 +319,7 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 328 | trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len()); | 319 | trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len()); |
| 329 | 320 | ||
| 330 | // Start UARTE Receive transaction | 321 | // Start UARTE Receive transaction |
| 331 | self.uarte.tasks_startrx.write(|w| | 322 | r.tasks_startrx.write(|w| |
| 332 | // `1` is a valid value to write to task registers. | 323 | // `1` is a valid value to write to task registers. |
| 333 | unsafe { w.bits(1) }); | 324 | unsafe { w.bits(1) }); |
| 334 | } | 325 | } |
| @@ -336,14 +327,14 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 336 | } | 327 | } |
| 337 | RxState::Receiving => { | 328 | RxState::Receiving => { |
| 338 | trace!(" irq_rx: in state receiving"); | 329 | trace!(" irq_rx: in state receiving"); |
| 339 | if self.uarte.events_endrx.read().bits() != 0 { | 330 | if r.events_endrx.read().bits() != 0 { |
| 340 | self.timer.tasks_stop.write(|w| unsafe { w.bits(1) }); | 331 | rt.tasks_stop.write(|w| unsafe { w.bits(1) }); |
| 341 | 332 | ||
| 342 | let n: usize = self.uarte.rxd.amount.read().amount().bits() as usize; | 333 | let n: usize = r.rxd.amount.read().amount().bits() as usize; |
| 343 | trace!(" irq_rx: endrx {:?}", n); | 334 | trace!(" irq_rx: endrx {:?}", n); |
| 344 | self.rx.push(n); | 335 | self.rx.push(n); |
| 345 | 336 | ||
| 346 | self.uarte.events_endrx.reset(); | 337 | r.events_endrx.reset(); |
| 347 | 338 | ||
| 348 | self.rx_waker.wake(); | 339 | self.rx_waker.wake(); |
| 349 | self.rx_state = RxState::Idle; | 340 | self.rx_state = RxState::Idle; |
| @@ -364,11 +355,11 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 364 | self.tx_state = TxState::Transmitting(buf.len()); | 355 | self.tx_state = TxState::Transmitting(buf.len()); |
| 365 | 356 | ||
| 366 | // Set up the DMA write | 357 | // Set up the DMA write |
| 367 | self.uarte.txd.ptr.write(|w| | 358 | r.txd.ptr.write(|w| |
| 368 | // The PTR field is a full 32 bits wide and accepts the full range | 359 | // The PTR field is a full 32 bits wide and accepts the full range |
| 369 | // of values. | 360 | // of values. |
| 370 | unsafe { w.ptr().bits(buf.as_ptr() as u32) }); | 361 | unsafe { w.ptr().bits(buf.as_ptr() as u32) }); |
| 371 | self.uarte.txd.maxcnt.write(|w| | 362 | r.txd.maxcnt.write(|w| |
| 372 | // We're giving it the length of the buffer, so no danger of | 363 | // We're giving it the length of the buffer, so no danger of |
| 373 | // accessing invalid memory. We have verified that the length of the | 364 | // accessing invalid memory. We have verified that the length of the |
| 374 | // buffer fits in an `u8`, so the cast to `u8` is also fine. | 365 | // buffer fits in an `u8`, so the cast to `u8` is also fine. |
| @@ -378,7 +369,7 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 378 | unsafe { w.maxcnt().bits(buf.len() as _) }); | 369 | unsafe { w.maxcnt().bits(buf.len() as _) }); |
| 379 | 370 | ||
| 380 | // Start UARTE Transmit transaction | 371 | // Start UARTE Transmit transaction |
| 381 | self.uarte.tasks_starttx.write(|w| | 372 | r.tasks_starttx.write(|w| |
| 382 | // `1` is a valid value to write to task registers. | 373 | // `1` is a valid value to write to task registers. |
| 383 | unsafe { w.bits(1) }); | 374 | unsafe { w.bits(1) }); |
| 384 | } | 375 | } |
| @@ -386,8 +377,8 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 386 | } | 377 | } |
| 387 | TxState::Transmitting(n) => { | 378 | TxState::Transmitting(n) => { |
| 388 | trace!(" irq_tx: in state Transmitting"); | 379 | trace!(" irq_tx: in state Transmitting"); |
| 389 | if self.uarte.events_endtx.read().bits() != 0 { | 380 | if r.events_endtx.read().bits() != 0 { |
| 390 | self.uarte.events_endtx.reset(); | 381 | r.events_endtx.reset(); |
| 391 | 382 | ||
| 392 | trace!(" irq_tx: endtx {:?}", n); | 383 | trace!(" irq_tx: endtx {:?}", n); |
| 393 | self.tx.pop(n); | 384 | self.tx.pop(n); |
| @@ -402,37 +393,3 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 402 | trace!("irq: end"); | 393 | trace!("irq: end"); |
| 403 | } | 394 | } |
| 404 | } | 395 | } |
| 405 | |||
| 406 | mod sealed { | ||
| 407 | pub trait Instance {} | ||
| 408 | |||
| 409 | impl Instance for crate::pac::UARTE0 {} | ||
| 410 | #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] | ||
| 411 | impl Instance for crate::pac::UARTE1 {} | ||
| 412 | |||
| 413 | pub trait TimerInstance {} | ||
| 414 | impl TimerInstance for crate::pac::TIMER0 {} | ||
| 415 | impl TimerInstance for crate::pac::TIMER1 {} | ||
| 416 | impl TimerInstance for crate::pac::TIMER2 {} | ||
| 417 | } | ||
| 418 | |||
| 419 | pub trait Instance: Deref<Target = pac::uarte0::RegisterBlock> + sealed::Instance { | ||
| 420 | type Interrupt: Interrupt; | ||
| 421 | } | ||
| 422 | |||
| 423 | impl Instance for pac::UARTE0 { | ||
| 424 | type Interrupt = interrupt::UARTE0_UART0; | ||
| 425 | } | ||
| 426 | |||
| 427 | #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] | ||
| 428 | impl Instance for pac::UARTE1 { | ||
| 429 | type Interrupt = interrupt::UARTE1; | ||
| 430 | } | ||
| 431 | |||
| 432 | pub trait TimerInstance: | ||
| 433 | Deref<Target = pac::timer0::RegisterBlock> + sealed::TimerInstance | ||
| 434 | { | ||
| 435 | } | ||
| 436 | impl TimerInstance for crate::pac::TIMER0 {} | ||
| 437 | impl TimerInstance for crate::pac::TIMER1 {} | ||
| 438 | impl TimerInstance for crate::pac::TIMER2 {} | ||
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 67ff9dc31..042050d2f 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs | |||
| @@ -40,17 +40,6 @@ pub use nrf52833_pac as pac; | |||
| 40 | #[cfg(feature = "52840")] | 40 | #[cfg(feature = "52840")] |
| 41 | pub use nrf52840_pac as pac; | 41 | pub use nrf52840_pac as pac; |
| 42 | 42 | ||
| 43 | #[cfg(feature = "52810")] | ||
| 44 | pub use nrf52810_hal as hal; | ||
| 45 | #[cfg(feature = "52811")] | ||
| 46 | pub use nrf52811_hal as hal; | ||
| 47 | #[cfg(feature = "52832")] | ||
| 48 | pub use nrf52832_hal as hal; | ||
| 49 | #[cfg(feature = "52833")] | ||
| 50 | pub use nrf52833_hal as hal; | ||
| 51 | #[cfg(feature = "52840")] | ||
| 52 | pub use nrf52840_hal as hal; | ||
| 53 | |||
| 54 | /// Length of Nordic EasyDMA differs for MCUs | 43 | /// Length of Nordic EasyDMA differs for MCUs |
| 55 | #[cfg(any( | 44 | #[cfg(any( |
| 56 | feature = "52810", | 45 | feature = "52810", |
