diff --git a/.vscode/settings.json b/.vscode/settings.json index 1b3e550c8..f43b437ba 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -23,6 +23,12 @@ ], "[toml]": { - "editor.formatOnSave": false + "editor.formatOnSave": false, + }, + "[markdown]": { + "editor.formatOnSave": false, + }, + "[jsonc]": { + "editor.formatOnSave": false, } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c3ca4331..c01991cc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/esp-hal-common/src/uart.rs b/esp-hal-common/src/uart.rs index 57a5c54e5..57accd61b 100644 --- a/esp-hal-common/src/uart.rs +++ b/esp-hal-common/src/uart.rs @@ -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 { + 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)] diff --git a/esp32-hal/examples/embassy_serial.rs b/esp32-hal/examples/embassy_serial.rs index 40d1031b4..9af6f1a42 100644 --- a/esp32-hal/examples/embassy_serial.rs +++ b/esp32-hal/examples/embassy_serial.rs @@ -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) { + 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) { const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16; - let mut rbuf: Vec = 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(); } diff --git a/esp32c2-hal/Cargo.toml b/esp32c2-hal/Cargo.toml index 7f231b4e5..d9fdf414d 100644 --- a/esp32c2-hal/Cargo.toml +++ b/esp32c2-hal/Cargo.toml @@ -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"] diff --git a/esp32c2-hal/examples/embassy_serial.rs b/esp32c2-hal/examples/embassy_serial.rs index 910d31046..3e2e85223 100644 --- a/esp32c2-hal/examples/embassy_serial.rs +++ b/esp32c2-hal/examples/embassy_serial.rs @@ -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) { + 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) { const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16; - let mut rbuf: Vec = 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(); } diff --git a/esp32c3-hal/Cargo.toml b/esp32c3-hal/Cargo.toml index 8afcc0825..fa5242892 100644 --- a/esp32c3-hal/Cargo.toml +++ b/esp32c3-hal/Cargo.toml @@ -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"] diff --git a/esp32c3-hal/examples/embassy_serial.rs b/esp32c3-hal/examples/embassy_serial.rs index cb52e208f..79f493a09 100644 --- a/esp32c3-hal/examples/embassy_serial.rs +++ b/esp32c3-hal/examples/embassy_serial.rs @@ -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) { + 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) { const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16; - let mut rbuf: Vec = 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(); } diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index 51a391bd9..bae49abb6 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -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"] diff --git a/esp32c6-hal/examples/embassy_serial.rs b/esp32c6-hal/examples/embassy_serial.rs index d2080e4cd..378a75b21 100644 --- a/esp32c6-hal/examples/embassy_serial.rs +++ b/esp32c6-hal/examples/embassy_serial.rs @@ -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) { + 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) { const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16; - let mut rbuf: Vec = 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(); } diff --git a/esp32h2-hal/Cargo.toml b/esp32h2-hal/Cargo.toml index 42dc5ab8d..7e46594ce 100644 --- a/esp32h2-hal/Cargo.toml +++ b/esp32h2-hal/Cargo.toml @@ -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"] diff --git a/esp32h2-hal/examples/embassy_serial.rs b/esp32h2-hal/examples/embassy_serial.rs index 7522dd7ad..dd0ad91ca 100644 --- a/esp32h2-hal/examples/embassy_serial.rs +++ b/esp32h2-hal/examples/embassy_serial.rs @@ -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) { + 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) { const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16; - let mut rbuf: Vec = 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(); } diff --git a/esp32s2-hal/examples/embassy_serial.rs b/esp32s2-hal/examples/embassy_serial.rs index e543f6fae..915bf494c 100644 --- a/esp32s2-hal/examples/embassy_serial.rs +++ b/esp32s2-hal/examples/embassy_serial.rs @@ -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) { + 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) { const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16; - let mut rbuf: Vec = 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(); } diff --git a/esp32s3-hal/examples/embassy_serial.rs b/esp32s3-hal/examples/embassy_serial.rs index 788774dd3..53746767c 100644 --- a/esp32s3-hal/examples/embassy_serial.rs +++ b/esp32s3-hal/examples/embassy_serial.rs @@ -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) { + 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) { const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16; - let mut rbuf: Vec = 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(); }