esp-hal/esp32c2-hal/examples/embassy_serial.rs
Scott Mabin 94a07da47b
Fix Async UART (#871)
* Fix Async UART

The uart handler was `writing` to the enable register instead of
`modify`, which meant any wake would see the cleared enabled bit and
think the event had occurred. This wasn't seen before the split of uart
because it was only possible to listen to one thing at a time.

This PR also removes the ReadBufferFull error in favour of returning the
max bytes in the buffer.

The serial examples has been updated to actually have some cross task
communication.

* changelog

* fix dev deps
2023-10-25 10:25:25 -07:00

100 lines
3.0 KiB
Rust

//! embassy serial
//!
//! This is an example of running the embassy executor and asynchronously
//! writing to and reading from uart
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
use esp32c2_hal::{
clock::ClockControl,
embassy,
interrupt,
peripherals::{Interrupt, Peripherals, UART0},
prelude::*,
Uart,
};
use esp_backtrace as _;
use esp_hal_common::uart::{config::AtCmdConfig, UartRx, UartTx};
use static_cell::make_static;
// rx_fifo_full_threshold
const READ_BUF_SIZE: usize = 64;
// EOT (CTRL-D)
const AT_CMD: u8 = 0x04;
#[embassy_executor::task]
async fn writer(mut tx: UartTx<'static, UART0>, signal: &'static Signal<NoopRawMutex, usize>) {
use core::fmt::Write;
embedded_io_async::Write::write(
&mut tx,
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
)
.await
.unwrap();
embedded_io_async::Write::flush(&mut tx).await.unwrap();
loop {
let bytes_read = signal.wait().await;
signal.reset();
write!(&mut tx, "\r\n-- received {} bytes --\r\n", bytes_read).unwrap();
embedded_io_async::Write::flush(&mut tx).await.unwrap();
}
}
#[embassy_executor::task]
async fn reader(mut rx: UartRx<'static, UART0>, signal: &'static Signal<NoopRawMutex, usize>) {
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
let mut rbuf: [u8; MAX_BUFFER_SIZE] = [0u8; MAX_BUFFER_SIZE];
let mut offset = 0;
loop {
let r = embedded_io_async::Read::read(&mut rx, &mut rbuf[offset..]).await;
match r {
Ok(len) => {
offset += len;
esp_println::println!("Read: {len}, data: {:?}", &rbuf[..offset]);
offset = 0;
signal.signal(len);
}
Err(e) => esp_println::println!("RX Error: {:?}", e),
}
}
}
#[main]
async fn main(spawner: Spawner) {
esp_println::println!("Init!");
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
#[cfg(feature = "embassy-time-systick")]
embassy::init(
&clocks,
esp32c2_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
);
#[cfg(feature = "embassy-time-timg0")]
{
let timer_group0 = esp32c2_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timer_group0.timer0);
}
let mut uart0 = Uart::new(peripherals.UART0, &clocks);
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
uart0
.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16)
.unwrap();
let (tx, rx) = uart0.split();
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
let signal = &*make_static!(Signal::new());
spawner.spawn(reader(rx, &signal)).ok();
spawner.spawn(writer(tx, &signal)).ok();
}