From 6695bf0f21065960d6e83f2248fc6ad9a8ffa528 Mon Sep 17 00:00:00 2001 From: Timo Kröger Date: Wed, 23 Dec 2020 16:18:29 +0100 Subject: Low power UART driver --- examples/src/bin/buffered_uart.rs | 84 ++++++++++++++++++++++++++ examples/src/bin/uart.rs | 121 +++++++++++++++++++++++--------------- 2 files changed, 156 insertions(+), 49 deletions(-) create mode 100644 examples/src/bin/buffered_uart.rs (limited to 'examples/src') diff --git a/examples/src/bin/buffered_uart.rs b/examples/src/bin/buffered_uart.rs new file mode 100644 index 000000000..6e15fbcfa --- /dev/null +++ b/examples/src/bin/buffered_uart.rs @@ -0,0 +1,84 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +#[path = "../example_common.rs"] +mod example_common; +use example_common::*; + +use cortex_m_rt::entry; +use defmt::panic; +use futures::pin_mut; +use nrf52840_hal::gpio; + +use embassy::executor::{task, Executor}; +use embassy::io::{AsyncBufRead, AsyncBufReadExt, AsyncWrite, AsyncWriteExt}; +use embassy::util::Forever; +use embassy_nrf::buffered_uarte; +use embassy_nrf::interrupt; + +#[task] +async fn run() { + let p = unwrap!(embassy_nrf::pac::Peripherals::take()); + + let port0 = gpio::p0::Parts::new(p.P0); + + let pins = buffered_uarte::Pins { + rxd: port0.p0_08.into_floating_input().degrade(), + txd: port0 + .p0_06 + .into_push_pull_output(gpio::Level::Low) + .degrade(), + cts: None, + rts: None, + }; + + let irq = interrupt::take!(UARTE0_UART0); + let u = buffered_uarte::BufferedUarte::new( + p.UARTE0, + irq, + pins, + buffered_uarte::Parity::EXCLUDED, + buffered_uarte::Baudrate::BAUD115200, + ); + pin_mut!(u); + + info!("uarte initialized!"); + + unwrap!(u.write_all(b"Hello!\r\n").await); + info!("wrote hello in uart!"); + + // Simple demo, reading 8-char chunks and echoing them back reversed. + loop { + info!("reading..."); + let mut buf = [0u8; 8]; + unwrap!(u.read_exact(&mut buf).await); + info!("read done, got {:[u8]}", buf); + + // Reverse buf + for i in 0..4 { + let tmp = buf[i]; + buf[i] = buf[7 - i]; + buf[7 - i] = tmp; + } + + info!("writing..."); + unwrap!(u.write_all(&buf).await); + info!("write done"); + } +} + +static EXECUTOR: Forever = Forever::new(); + +#[entry] +fn main() -> ! { + info!("Hello World!"); + + let executor = EXECUTOR.put(Executor::new(cortex_m::asm::sev)); + unwrap!(executor.spawn(run())); + + loop { + executor.run(); + cortex_m::asm::wfe(); + } +} diff --git a/examples/src/bin/uart.rs b/examples/src/bin/uart.rs index 6e15fbcfa..107936686 100644 --- a/examples/src/bin/uart.rs +++ b/examples/src/bin/uart.rs @@ -8,74 +8,97 @@ use example_common::*; use cortex_m_rt::entry; use defmt::panic; -use futures::pin_mut; -use nrf52840_hal::gpio; - use embassy::executor::{task, Executor}; -use embassy::io::{AsyncBufRead, AsyncBufReadExt, AsyncWrite, AsyncWriteExt}; +use embassy::time::{Duration, Timer}; use embassy::util::Forever; -use embassy_nrf::buffered_uarte; -use embassy_nrf::interrupt; +use embassy_nrf::{interrupt, pac, rtc, uarte}; +use futures::future::{select, Either}; +use nrf52840_hal::clocks; +use nrf52840_hal::gpio; #[task] -async fn run() { - let p = unwrap!(embassy_nrf::pac::Peripherals::take()); - - let port0 = gpio::p0::Parts::new(p.P0); - - let pins = buffered_uarte::Pins { - rxd: port0.p0_08.into_floating_input().degrade(), - txd: port0 - .p0_06 - .into_push_pull_output(gpio::Level::Low) - .degrade(), - cts: None, - rts: None, - }; - - let irq = interrupt::take!(UARTE0_UART0); - let u = buffered_uarte::BufferedUarte::new( - p.UARTE0, - irq, - pins, - buffered_uarte::Parity::EXCLUDED, - buffered_uarte::Baudrate::BAUD115200, - ); - pin_mut!(u); - +async fn run(mut uart: uarte::Uarte) { info!("uarte initialized!"); - unwrap!(u.write_all(b"Hello!\r\n").await); + // Message must be in SRAM + let mut buf = [0; 8]; + buf.copy_from_slice(b"Hello!\r\n"); + + uart.send(&buf).await; info!("wrote hello in uart!"); - // Simple demo, reading 8-char chunks and echoing them back reversed. + info!("reading..."); loop { - info!("reading..."); - let mut buf = [0u8; 8]; - unwrap!(u.read_exact(&mut buf).await); - info!("read done, got {:[u8]}", buf); - - // Reverse buf - for i in 0..4 { - let tmp = buf[i]; - buf[i] = buf[7 - i]; - buf[7 - i] = tmp; + let received = match select( + uart.receive(&mut buf), + Timer::after(Duration::from_millis(10)), + ) + .await + { + Either::Left((buf, _)) => buf, + Either::Right((_, read)) => { + let (buf, n) = read.stop().await; + &buf[..n] + } + }; + + if received.len() > 0 { + info!("read done, got {:[u8]}", received); + + // Echo back received data + uart.send(received).await; } - - info!("writing..."); - unwrap!(u.write_all(&buf).await); - info!("write done"); } } +static RTC: Forever> = Forever::new(); +static ALARM: Forever> = Forever::new(); static EXECUTOR: Forever = Forever::new(); #[entry] fn main() -> ! { info!("Hello World!"); - let executor = EXECUTOR.put(Executor::new(cortex_m::asm::sev)); - unwrap!(executor.spawn(run())); + let p = unwrap!(embassy_nrf::pac::Peripherals::take()); + + clocks::Clocks::new(p.CLOCK) + .enable_ext_hfosc() + .set_lfclk_src_external(clocks::LfOscConfiguration::NoExternalNoBypass) + .start_lfclk(); + + let rtc = RTC.put(rtc::RTC::new(p.RTC1, interrupt::take!(RTC1))); + rtc.start(); + + unsafe { embassy::time::set_clock(rtc) }; + + let alarm = ALARM.put(rtc.alarm0()); + let executor = EXECUTOR.put(Executor::new_with_alarm(alarm, cortex_m::asm::sev)); + + // Init UART + let port0 = gpio::p0::Parts::new(p.P0); + + let pins = uarte::Pins { + rxd: port0.p0_08.into_floating_input().degrade(), + txd: port0 + .p0_06 + .into_push_pull_output(gpio::Level::Low) + .degrade(), + cts: None, + rts: None, + }; + + // NOTE(unsafe): Safe becasue we do not use `mem::forget` anywhere. + let uart = unsafe { + uarte::Uarte::new( + p.UARTE0, + interrupt::take!(UARTE0_UART0), + pins, + uarte::Parity::EXCLUDED, + uarte::Baudrate::BAUD115200, + ) + }; + + unwrap!(executor.spawn(run(uart))); loop { executor.run(); -- cgit