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
This commit is contained in:
Scott Mabin 2023-10-25 18:25:25 +01:00 committed by GitHub
parent a24eff9bf9
commit 94a07da47b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 245 additions and 175 deletions

View File

@ -23,6 +23,12 @@
],
"[toml]": {
"editor.formatOnSave": false
"editor.formatOnSave": false,
},
"[markdown]": {
"editor.formatOnSave": false,
},
"[jsonc]": {
"editor.formatOnSave": false,
}
}

View File

@ -45,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Xtensa targets: Use ESP32Reset - not Reset (#823)
- Examples should now work with the `defmt` feature (#810)
- Fixed a race condition causing SpiDma to stop working unexpectedly (#869)
- Fixed async uart serial, and updated the embassy_serial examples (#871).
### Removed

View File

@ -61,8 +61,6 @@ const UART_FIFO_SIZE: u16 = 128;
pub enum Error {
InvalidArgument,
#[cfg(feature = "async")]
ReadBufferFull,
#[cfg(feature = "async")]
RxFifoOvf,
}
@ -854,6 +852,8 @@ pub trait Instance {
.set_bit()
.rxfifo_tout_int_clr()
.set_bit()
.at_cmd_char_det_int_clr()
.set_bit()
});
Self::register_block().int_ena.write(|w| {
@ -863,6 +863,8 @@ pub trait Instance {
.clear_bit()
.rxfifo_tout_int_ena()
.clear_bit()
.at_cmd_char_det_int_ena()
.clear_bit()
});
}
@ -1374,8 +1376,6 @@ mod asynch {
/// - `buf` buffer slice to write the bytes into
///
/// # Errors
/// - `Err(ReadBufferFull)` if provided buffer slice is not enough to
/// copy all avaialble bytes. Increase buffer slice length.
/// - `Err(RxFifoOvf)` when MCU Rx Fifo Overflow interrupt is triggered.
/// To avoid this error, call this function more often.
/// - `Err(Error::ReadNoConfig)` if neither `set_rx_fifo_full_threshold`
@ -1448,8 +1448,6 @@ mod asynch {
/// - `buf` buffer slice to write the bytes into
///
/// # Errors
/// - `Err(ReadBufferFull)` if provided buffer slice is not enough to
/// copy all avaialble bytes. Increase buffer slice length.
/// - `Err(RxFifoOvf)` when MCU Rx Fifo Overflow interrupt is triggered.
/// To avoid this error, call this function more often.
/// - `Err(Error::ReadNoConfig)` if neither `set_rx_fifo_full_threshold`
@ -1459,6 +1457,10 @@ mod asynch {
/// When succesfull, returns the number of bytes written to
/// buf
async fn read_async(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
if buf.len() == 0 {
return Ok(0);
}
let mut read_bytes = 0;
if self.at_cmd_config.is_some() {
@ -1487,7 +1489,7 @@ mod asynch {
buf[read_bytes] = byte;
read_bytes += 1;
} else {
return Err(Error::ReadBufferFull);
break;
}
}
@ -1540,20 +1542,25 @@ mod asynch {
}
fn intr_handler(uart: &RegisterBlock) -> bool {
let int_ena_val = uart.int_ena.read();
let int_raw_val = uart.int_raw.read();
let int_ena_val = uart.int_ena.read();
let mut wake = false;
if int_ena_val.txfifo_empty_int_ena().bit_is_set()
&& int_raw_val.txfifo_empty_int_raw().bit_is_set()
{
uart.int_ena.write(|w| w.txfifo_empty_int_ena().clear_bit());
return true;
uart.int_clr.write(|w| w.txfifo_empty_int_clr().set_bit());
uart.int_ena
.modify(|_, w| w.txfifo_empty_int_ena().clear_bit());
wake = true;
}
if int_ena_val.tx_done_int_ena().bit_is_set() && int_raw_val.tx_done_int_raw().bit_is_set()
{
uart.int_ena.write(|w| w.tx_done_int_ena().clear_bit());
return true;
uart.int_clr.write(|w| w.tx_done_int_clr().set_bit());
uart.int_ena.modify(|_, w| w.tx_done_int_ena().clear_bit());
wake = true;
}
if int_ena_val.at_cmd_char_det_int_ena().bit_is_set()
@ -1562,27 +1569,29 @@ mod asynch {
uart.int_clr
.write(|w| w.at_cmd_char_det_int_clr().set_bit());
uart.int_ena
.write(|w| w.at_cmd_char_det_int_ena().clear_bit());
return true;
.modify(|_, w| w.at_cmd_char_det_int_ena().clear_bit());
wake = true;
}
if int_ena_val.rxfifo_full_int_ena().bit_is_set()
&& int_raw_val.rxfifo_full_int_raw().bit_is_set()
{
uart.int_clr.write(|w| w.rxfifo_full_int_clr().set_bit());
uart.int_ena.write(|w| w.rxfifo_full_int_ena().clear_bit());
return true;
uart.int_ena
.modify(|_, w| w.rxfifo_full_int_ena().clear_bit());
wake = true;
}
if int_ena_val.rxfifo_ovf_int_ena().bit_is_set()
&& int_raw_val.rxfifo_ovf_int_raw().bit_is_set()
{
uart.int_clr.write(|w| w.rxfifo_ovf_int_clr().set_bit());
uart.int_ena.write(|w| w.rxfifo_ovf_int_ena().clear_bit());
return true;
uart.int_ena
.modify(|_, w| w.rxfifo_ovf_int_ena().clear_bit());
wake = true;
}
false
wake
}
#[cfg(uart0)]

View File

@ -8,18 +8,18 @@
#![feature(type_alias_impl_trait)]
use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
use esp32_hal::{
clock::ClockControl,
embassy::{self},
embassy,
interrupt,
peripherals::{Interrupt, Peripherals, UART0},
prelude::*,
timer::TimerGroup,
Uart,
};
use esp_backtrace as _;
use esp_hal_common::uart::{config::AtCmdConfig, UartRx, UartTx};
use heapless::Vec;
use static_cell::make_static;
// rx_fifo_full_threshold
const READ_BUF_SIZE: usize = 64;
@ -27,8 +27,8 @@ const READ_BUF_SIZE: usize = 64;
const AT_CMD: u8 = 0x04;
#[embassy_executor::task]
async fn writer(mut tx: UartTx<'static, UART0>) {
esp_println::println!("writing...");
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",
@ -36,27 +36,30 @@ async fn writer(mut tx: UartTx<'static, UART0>) {
.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>) {
esp_println::println!("reading...");
// max message size to receive
// leave some extra space for AT-CMD characters
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: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
let mut rbuf: [u8; MAX_BUFFER_SIZE] = [0u8; MAX_BUFFER_SIZE];
let mut offset = 0;
while let Ok(len) = embedded_io_async::Read::read(&mut rx, &mut rbuf[offset..]).await {
offset += len;
if offset == 0 {
rbuf.truncate(0);
break;
}
// if set_at_cmd is used than stop reading
if len < READ_BUF_SIZE {
rbuf.truncate(offset);
break;
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),
}
}
}
@ -68,8 +71,17 @@ async fn main(spawner: Spawner) {
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
embassy::init(&clocks, timer_group0.timer0);
#[cfg(feature = "embassy-time-systick")]
embassy::init(
&clocks,
esp32_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
);
#[cfg(feature = "embassy-time-timg0")]
{
let timer_group0 = esp32_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));
@ -80,6 +92,8 @@ async fn main(spawner: Spawner) {
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
spawner.spawn(reader(rx)).ok();
spawner.spawn(writer(tx)).ok();
let signal = &*make_static!(Signal::new());
spawner.spawn(reader(rx, &signal)).ok();
spawner.spawn(writer(tx, &signal)).ok();
}

View File

@ -47,6 +47,7 @@ crypto-bigint = {version = "0.5.1", default-features = false }
elliptic-curve = {version = "0.13.4", default-features = false, features = ["sec1"] }
p192 = {version = "0.13.0", default-features = false, features = ["arithmetic"] }
p256 = {version = "0.13.2", default-features = false, features = ["arithmetic"] }
embassy-sync = "0.2.0"
[features]
default = ["rt", "vectored", "xtal-40mhz"]

View File

@ -8,6 +8,7 @@
#![feature(type_alias_impl_trait)]
use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
use esp32c2_hal::{
clock::ClockControl,
embassy,
@ -18,7 +19,7 @@ use esp32c2_hal::{
};
use esp_backtrace as _;
use esp_hal_common::uart::{config::AtCmdConfig, UartRx, UartTx};
use heapless::Vec;
use static_cell::make_static;
// rx_fifo_full_threshold
const READ_BUF_SIZE: usize = 64;
@ -26,8 +27,8 @@ const READ_BUF_SIZE: usize = 64;
const AT_CMD: u8 = 0x04;
#[embassy_executor::task]
async fn writer(mut tx: UartTx<'static, UART0>) {
esp_println::println!("writing...");
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",
@ -35,27 +36,30 @@ async fn writer(mut tx: UartTx<'static, UART0>) {
.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>) {
esp_println::println!("reading...");
// max message size to receive
// leave some extra space for AT-CMD characters
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: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
let mut rbuf: [u8; MAX_BUFFER_SIZE] = [0u8; MAX_BUFFER_SIZE];
let mut offset = 0;
while let Ok(len) = embedded_io_async::Read::read(&mut rx, &mut rbuf[offset..]).await {
offset += len;
if offset == 0 {
rbuf.truncate(0);
break;
}
// if set_at_cmd is used than stop reading
if len < READ_BUF_SIZE {
rbuf.truncate(offset);
break;
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),
}
}
}
@ -74,10 +78,10 @@ async fn main(spawner: Spawner) {
);
#[cfg(feature = "embassy-time-timg0")]
embassy::init(
&clocks,
esp32c2_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks).timer0,
);
{
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));
@ -88,6 +92,8 @@ async fn main(spawner: Spawner) {
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
spawner.spawn(reader(rx)).ok();
spawner.spawn(writer(tx)).ok();
let signal = &*make_static!(Signal::new());
spawner.spawn(reader(rx, &signal)).ok();
spawner.spawn(writer(tx, &signal)).ok();
}

View File

@ -50,6 +50,7 @@ sha2 = { version = "0.10.7", default-features = false }
smart-leds = "0.3.0"
ssd1306 = "0.8.1"
static_cell = { version = "1.2.0", features = ["nightly"] }
embassy-sync = "0.2.0"
[features]
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]

View File

@ -8,6 +8,7 @@
#![feature(type_alias_impl_trait)]
use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
use esp32c3_hal::{
clock::ClockControl,
embassy,
@ -18,7 +19,7 @@ use esp32c3_hal::{
};
use esp_backtrace as _;
use esp_hal_common::uart::{config::AtCmdConfig, UartRx, UartTx};
use heapless::Vec;
use static_cell::make_static;
// rx_fifo_full_threshold
const READ_BUF_SIZE: usize = 64;
@ -26,8 +27,8 @@ const READ_BUF_SIZE: usize = 64;
const AT_CMD: u8 = 0x04;
#[embassy_executor::task]
async fn writer(mut tx: UartTx<'static, UART0>) {
esp_println::println!("writing...");
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",
@ -35,27 +36,30 @@ async fn writer(mut tx: UartTx<'static, UART0>) {
.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>) {
esp_println::println!("reading...");
// max message size to receive
// leave some extra space for AT-CMD characters
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: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
let mut rbuf: [u8; MAX_BUFFER_SIZE] = [0u8; MAX_BUFFER_SIZE];
let mut offset = 0;
while let Ok(len) = embedded_io_async::Read::read(&mut rx, &mut rbuf[offset..]).await {
offset += len;
if offset == 0 {
rbuf.truncate(0);
break;
}
// if set_at_cmd is used than stop reading
if len < READ_BUF_SIZE {
rbuf.truncate(offset);
break;
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),
}
}
}
@ -74,10 +78,10 @@ async fn main(spawner: Spawner) {
);
#[cfg(feature = "embassy-time-timg0")]
embassy::init(
&clocks,
esp32c3_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks).timer0,
);
{
let timer_group0 = esp32c3_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));
@ -88,6 +92,8 @@ async fn main(spawner: Spawner) {
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
spawner.spawn(reader(rx)).ok();
spawner.spawn(writer(tx)).ok();
let signal = &*make_static!(Signal::new());
spawner.spawn(reader(rx, &signal)).ok();
spawner.spawn(writer(tx, &signal)).ok();
}

View File

@ -53,6 +53,7 @@ hex-literal = "0"
elliptic-curve = {version = "0.13.4", default-features = false, features = ["sec1"] }
p192 = {version = "0.13.0", default-features = false, features = ["arithmetic"] }
p256 = {version = "0.13.2", default-features = false, features = ["arithmetic"] }
embassy-sync = "0.2.0"
[features]
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]

View File

@ -8,6 +8,7 @@
#![feature(type_alias_impl_trait)]
use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
use esp32c6_hal::{
clock::ClockControl,
embassy,
@ -18,7 +19,7 @@ use esp32c6_hal::{
};
use esp_backtrace as _;
use esp_hal_common::uart::{config::AtCmdConfig, UartRx, UartTx};
use heapless::Vec;
use static_cell::make_static;
// rx_fifo_full_threshold
const READ_BUF_SIZE: usize = 64;
@ -26,8 +27,8 @@ const READ_BUF_SIZE: usize = 64;
const AT_CMD: u8 = 0x04;
#[embassy_executor::task]
async fn writer(mut tx: UartTx<'static, UART0>) {
esp_println::println!("writing...");
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",
@ -35,33 +36,36 @@ async fn writer(mut tx: UartTx<'static, UART0>) {
.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>) {
esp_println::println!("reading...");
// max message size to receive
// leave some extra space for AT-CMD characters
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: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
let mut rbuf: [u8; MAX_BUFFER_SIZE] = [0u8; MAX_BUFFER_SIZE];
let mut offset = 0;
while let Ok(len) = embedded_io_async::Read::read(&mut rx, &mut rbuf[offset..]).await {
offset += len;
if offset == 0 {
rbuf.truncate(0);
break;
}
// if set_at_cmd is used than stop reading
if len < READ_BUF_SIZE {
rbuf.truncate(offset);
break;
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) -> ! {
async fn main(spawner: Spawner) {
esp_println::println!("Init!");
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
@ -88,6 +92,8 @@ async fn main(spawner: Spawner) -> ! {
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
spawner.spawn(reader(rx)).ok();
spawner.spawn(writer(tx)).ok();
let signal = &*make_static!(Signal::new());
spawner.spawn(reader(rx, &signal)).ok();
spawner.spawn(writer(tx, &signal)).ok();
}

View File

@ -53,6 +53,7 @@ hex-literal = "0"
elliptic-curve = {version = "0.13.4", default-features = false, features = ["sec1"] }
p192 = {version = "0.13.0", default-features = false, features = ["arithmetic"] }
p256 = {version = "0.13.2", default-features = false, features = ["arithmetic"] }
embassy-sync = "0.2.0"
[features]
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]

View File

@ -8,6 +8,7 @@
#![feature(type_alias_impl_trait)]
use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
use esp32h2_hal::{
clock::ClockControl,
embassy,
@ -18,7 +19,7 @@ use esp32h2_hal::{
};
use esp_backtrace as _;
use esp_hal_common::uart::{config::AtCmdConfig, UartRx, UartTx};
use heapless::Vec;
use static_cell::make_static;
// rx_fifo_full_threshold
const READ_BUF_SIZE: usize = 64;
@ -26,8 +27,8 @@ const READ_BUF_SIZE: usize = 64;
const AT_CMD: u8 = 0x04;
#[embassy_executor::task]
async fn writer(mut tx: UartTx<'static, UART0>) {
esp_println::println!("writing...");
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",
@ -35,27 +36,30 @@ async fn writer(mut tx: UartTx<'static, UART0>) {
.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>) {
esp_println::println!("reading...");
// max message size to receive
// leave some extra space for AT-CMD characters
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: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
let mut rbuf: [u8; MAX_BUFFER_SIZE] = [0u8; MAX_BUFFER_SIZE];
let mut offset = 0;
while let Ok(len) = embedded_io_async::Read::read(&mut rx, &mut rbuf[offset..]).await {
offset += len;
if offset == 0 {
rbuf.truncate(0);
break;
}
// if set_at_cmd is used than stop reading
if len < READ_BUF_SIZE {
rbuf.truncate(offset);
break;
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),
}
}
}
@ -88,6 +92,8 @@ async fn main(spawner: Spawner) {
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
spawner.spawn(reader(rx)).ok();
spawner.spawn(writer(tx)).ok();
let signal = &*make_static!(Signal::new());
spawner.spawn(reader(rx, &signal)).ok();
spawner.spawn(writer(tx, &signal)).ok();
}

View File

@ -8,9 +8,10 @@
#![feature(type_alias_impl_trait)]
use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
use esp32s2_hal::{
clock::ClockControl,
embassy::{self},
embassy,
interrupt,
peripherals::{Interrupt, Peripherals, UART0},
prelude::*,
@ -18,7 +19,7 @@ use esp32s2_hal::{
};
use esp_backtrace as _;
use esp_hal_common::uart::{config::AtCmdConfig, UartRx, UartTx};
use heapless::Vec;
use static_cell::make_static;
// rx_fifo_full_threshold
const READ_BUF_SIZE: usize = 64;
@ -26,8 +27,8 @@ const READ_BUF_SIZE: usize = 64;
const AT_CMD: u8 = 0x04;
#[embassy_executor::task]
async fn writer(mut tx: UartTx<'static, UART0>) {
esp_println::println!("writing...");
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",
@ -35,27 +36,30 @@ async fn writer(mut tx: UartTx<'static, UART0>) {
.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>) {
esp_println::println!("reading...");
// max message size to receive
// leave some extra space for AT-CMD characters
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: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
let mut rbuf: [u8; MAX_BUFFER_SIZE] = [0u8; MAX_BUFFER_SIZE];
let mut offset = 0;
while let Ok(len) = embedded_io_async::Read::read(&mut rx, &mut rbuf[offset..]).await {
offset += len;
if offset == 0 {
rbuf.truncate(0);
break;
}
// if set_at_cmd is used than stop reading
if len < READ_BUF_SIZE {
rbuf.truncate(offset);
break;
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),
}
}
}
@ -88,6 +92,8 @@ async fn main(spawner: Spawner) {
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
spawner.spawn(reader(rx)).ok();
spawner.spawn(writer(tx)).ok();
let signal = &*make_static!(Signal::new());
spawner.spawn(reader(rx, &signal)).ok();
spawner.spawn(writer(tx, &signal)).ok();
}

View File

@ -8,9 +8,10 @@
#![feature(type_alias_impl_trait)]
use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
use esp32s3_hal::{
clock::ClockControl,
embassy::{self},
embassy,
interrupt,
peripherals::{Interrupt, Peripherals, UART0},
prelude::*,
@ -18,7 +19,7 @@ use esp32s3_hal::{
};
use esp_backtrace as _;
use esp_hal_common::uart::{config::AtCmdConfig, UartRx, UartTx};
use heapless::Vec;
use static_cell::make_static;
// rx_fifo_full_threshold
const READ_BUF_SIZE: usize = 64;
@ -26,8 +27,8 @@ const READ_BUF_SIZE: usize = 64;
const AT_CMD: u8 = 0x04;
#[embassy_executor::task]
async fn writer(mut tx: UartTx<'static, UART0>) {
esp_println::println!("writing...");
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",
@ -35,27 +36,30 @@ async fn writer(mut tx: UartTx<'static, UART0>) {
.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>) {
esp_println::println!("reading...");
// max message size to receive
// leave some extra space for AT-CMD characters
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: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
let mut rbuf: [u8; MAX_BUFFER_SIZE] = [0u8; MAX_BUFFER_SIZE];
let mut offset = 0;
while let Ok(len) = embedded_io_async::Read::read(&mut rx, &mut rbuf[offset..]).await {
offset += len;
if offset == 0 {
rbuf.truncate(0);
break;
}
// if set_at_cmd is used than stop reading
if len < READ_BUF_SIZE {
rbuf.truncate(offset);
break;
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),
}
}
}
@ -88,6 +92,8 @@ async fn main(spawner: Spawner) {
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
spawner.spawn(reader(rx)).ok();
spawner.spawn(writer(tx)).ok();
let signal = &*make_static!(Signal::new());
spawner.spawn(reader(rx, &signal)).ok();
spawner.spawn(writer(tx, &signal)).ok();
}