Async serial uart read (#620)
* implement embassy async uart read * Add embassy async read support for uart * changes based on review * fix CI failures * change review #2 * fixed re-opened PR number * changes review no.3 --------- Co-authored-by: Scott Mabin <scott@mabez.dev>
This commit is contained in:
parent
226bdc3038
commit
9f7565440a
@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Fix rom::crc docs
|
||||
- Add octal PSRAM support for ESP32-S3 (#610)
|
||||
- Add MD5 functions from ESP ROM (#618)
|
||||
- Add embassy async `read` support for `uart` (#620)
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@ -19,7 +19,10 @@ const UART_FIFO_SIZE: u16 = 128;
|
||||
|
||||
/// Custom serial error type
|
||||
#[derive(Debug)]
|
||||
pub enum Error {}
|
||||
pub enum Error {
|
||||
#[cfg(feature = "async")]
|
||||
ReadBufferFull,
|
||||
}
|
||||
|
||||
/// UART configuration
|
||||
pub mod config {
|
||||
@ -994,11 +997,15 @@ mod asynch {
|
||||
use core::task::Poll;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use embassy_futures::select::select;
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
use procmacros::interrupt;
|
||||
|
||||
use super::{Error, Instance};
|
||||
use crate::{uart::UART_FIFO_SIZE, Uart};
|
||||
use crate::{
|
||||
uart::{RegisterBlock, UART_FIFO_SIZE},
|
||||
Uart,
|
||||
};
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(all(uart0, uart1, uart2))] {
|
||||
@ -1016,6 +1023,8 @@ mod asynch {
|
||||
pub(crate) enum Event {
|
||||
TxDone,
|
||||
TxFiFoEmpty,
|
||||
RxFifoFull,
|
||||
RxCmdCharDetected,
|
||||
}
|
||||
|
||||
pub(crate) struct UartFuture<'a, T: Instance> {
|
||||
@ -1034,6 +1043,14 @@ mod asynch {
|
||||
.register_block()
|
||||
.int_ena
|
||||
.modify(|_, w| w.txfifo_empty_int_ena().set_bit()),
|
||||
Event::RxFifoFull => instance
|
||||
.register_block()
|
||||
.int_ena
|
||||
.modify(|_, w| w.rxfifo_full_int_ena().set_bit()),
|
||||
Event::RxCmdCharDetected => instance
|
||||
.register_block()
|
||||
.int_ena
|
||||
.modify(|_, w| w.at_cmd_char_det_int_ena().set_bit()),
|
||||
}
|
||||
|
||||
Self { event, instance }
|
||||
@ -1055,6 +1072,20 @@ mod asynch {
|
||||
.read()
|
||||
.txfifo_empty_int_ena()
|
||||
.bit_is_clear(),
|
||||
Event::RxFifoFull => self
|
||||
.instance
|
||||
.register_block()
|
||||
.int_ena
|
||||
.read()
|
||||
.rxfifo_full_int_ena()
|
||||
.bit_is_clear(),
|
||||
Event::RxCmdCharDetected => self
|
||||
.instance
|
||||
.register_block()
|
||||
.int_ena
|
||||
.read()
|
||||
.at_cmd_char_det_int_ena()
|
||||
.bit_is_clear(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1079,11 +1110,42 @@ mod asynch {
|
||||
where
|
||||
T: Instance,
|
||||
{
|
||||
async fn write(&mut self, words: &[u8]) -> Result<(), Error> {
|
||||
for chunk in words.chunks(UART_FIFO_SIZE as usize) {
|
||||
for &byte in chunk {
|
||||
self.write_byte(byte).unwrap() // should never fail
|
||||
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
let mut read_bytes = 0;
|
||||
|
||||
select(
|
||||
UartFuture::new(Event::RxCmdCharDetected, self.inner()),
|
||||
UartFuture::new(Event::RxFifoFull, self.inner()),
|
||||
)
|
||||
.await;
|
||||
|
||||
while let Ok(byte) = self.read_byte() {
|
||||
if read_bytes < buf.len() {
|
||||
buf[read_bytes] = byte;
|
||||
read_bytes += 1;
|
||||
} else {
|
||||
return Err(Error::ReadBufferFull);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(read_bytes)
|
||||
}
|
||||
|
||||
async fn write(&mut self, words: &[u8]) -> Result<(), Error> {
|
||||
let mut offset: usize = 0;
|
||||
loop {
|
||||
let mut next_offset =
|
||||
offset + (UART_FIFO_SIZE - self.uart.get_tx_fifo_count()) as usize;
|
||||
if next_offset > words.len() {
|
||||
next_offset = words.len();
|
||||
}
|
||||
for &byte in &words[offset..next_offset] {
|
||||
self.write_byte(byte).unwrap(); // should never fail
|
||||
}
|
||||
if next_offset == words.len() {
|
||||
break;
|
||||
}
|
||||
offset = next_offset;
|
||||
UartFuture::new(Event::TxFiFoEmpty, self.inner()).await;
|
||||
}
|
||||
Ok(())
|
||||
@ -1111,42 +1173,63 @@ mod asynch {
|
||||
}
|
||||
}
|
||||
|
||||
fn intr_handler(uart: &RegisterBlock) -> bool {
|
||||
let int_ena_val = uart.int_ena.read();
|
||||
let int_raw_val = uart.int_raw.read();
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if int_ena_val.at_cmd_char_det_int_ena().bit_is_set()
|
||||
&& int_raw_val.at_cmd_char_det_int_raw().bit_is_set()
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(uart0)]
|
||||
#[interrupt]
|
||||
fn UART0() {
|
||||
let uart = unsafe { &*crate::peripherals::UART0::ptr() };
|
||||
uart.int_ena.modify(|_, w| {
|
||||
w.txfifo_empty_int_ena()
|
||||
.clear_bit()
|
||||
.tx_done_int_ena()
|
||||
.clear_bit()
|
||||
});
|
||||
WAKERS[0].wake();
|
||||
if intr_handler(uart) {
|
||||
WAKERS[0].wake();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(uart1)]
|
||||
#[interrupt]
|
||||
fn UART1() {
|
||||
let uart = unsafe { &*crate::peripherals::UART1::ptr() };
|
||||
uart.int_ena.modify(|_, w| {
|
||||
w.txfifo_empty_int_ena()
|
||||
.clear_bit()
|
||||
.tx_done_int_ena()
|
||||
.clear_bit()
|
||||
});
|
||||
WAKERS[1].wake();
|
||||
if intr_handler(uart) {
|
||||
WAKERS[1].wake();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(uart2)]
|
||||
#[interrupt]
|
||||
fn UART2() {
|
||||
let uart = unsafe { &*crate::peripherals::UART2::ptr() };
|
||||
uart.int_ena.modify(|_, w| {
|
||||
w.txfifo_empty_int_ena()
|
||||
.clear_bit()
|
||||
.tx_done_int_ena()
|
||||
.clear_bit()
|
||||
});
|
||||
WAKERS[2].wake();
|
||||
if intr_handler(uart) {
|
||||
WAKERS[2].wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,6 +47,7 @@ sha2 = { version = "0.10.6", default-features = false}
|
||||
smart-leds = "0.3.0"
|
||||
ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored", "xtal40mhz"]
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to a uart.
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Executor;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::{with_timeout, Duration};
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
@ -20,18 +22,79 @@ use esp32_hal::{
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_common::uart::config::AtCmdConfig;
|
||||
use heapless::Vec;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 128;
|
||||
// EOT (CTRL-D)
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run(mut uart: Uart<'static, UART0>) {
|
||||
// max message size to receive
|
||||
// leave some extra space for AT-CMD characters
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
// timeout read
|
||||
const READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
let mut rbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
let mut wbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
loop {
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"Hello async write!!!\r\n")
|
||||
if rbuf.is_empty() {
|
||||
embedded_hal_async::serial::Write::write(
|
||||
&mut uart,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
wbuf.clear();
|
||||
write!(&mut wbuf, "\r\n-- received {} bytes --\r\n", rbuf.len()).unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, wbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, rbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||
.await
|
||||
.unwrap();
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
|
||||
// set rbuf full capacity
|
||||
rbuf.resize_default(rbuf.capacity()).ok();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
match with_timeout(READ_TIMEOUT, uart.read(&mut rbuf[offset..])).await {
|
||||
Ok(r) => {
|
||||
if let Ok(len) = r {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
// buffer is full
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Timeout
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +129,9 @@ fn main() -> ! {
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(&clocks, timer_group0.timer0);
|
||||
|
||||
let uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||
|
||||
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
|
||||
@ -42,6 +42,7 @@ lis3dh-async = "0.7.0"
|
||||
sha2 = { version = "0.10.6", default-features = false}
|
||||
ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored", "xtal40mhz"]
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to a uart.
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Executor;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::{with_timeout, Duration};
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
@ -20,18 +22,79 @@ use esp32c2_hal::{
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_common::uart::config::AtCmdConfig;
|
||||
use heapless::Vec;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 128;
|
||||
/// EOT; CTRL-D
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run(mut uart: Uart<'static, UART0>) {
|
||||
// max message size to receive
|
||||
// leave some extra space for AT-CMD characters
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
// timeout read
|
||||
const READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
let mut rbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
let mut wbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
loop {
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"Hello async write!!!\r\n")
|
||||
if rbuf.is_empty() {
|
||||
embedded_hal_async::serial::Write::write(
|
||||
&mut uart,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
wbuf.clear();
|
||||
write!(&mut wbuf, "\r\n-- received {} bytes --\r\n", rbuf.len()).unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, wbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, rbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||
.await
|
||||
.unwrap();
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
|
||||
// set rbuf full capacity
|
||||
rbuf.resize_default(rbuf.capacity()).ok();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
match with_timeout(READ_TIMEOUT, uart.read(&mut rbuf[offset..])).await {
|
||||
Ok(r) => {
|
||||
if let Ok(len) = r {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
// buffer is full
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Timeout
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +129,9 @@ fn main() -> ! {
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(&clocks, timer_group0.timer0);
|
||||
|
||||
let uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||
|
||||
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
|
||||
@ -48,6 +48,7 @@ sha2 = { version = "0.10.6", default-features = false}
|
||||
smart-leds = "0.3.0"
|
||||
ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to a uart.
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Executor;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::{with_timeout, Duration};
|
||||
use esp32c3_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
@ -20,18 +22,79 @@ use esp32c3_hal::{
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_common::uart::config::AtCmdConfig;
|
||||
use heapless::Vec;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 128;
|
||||
// EOT (CTRL-D)
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run(mut uart: Uart<'static, UART0>) {
|
||||
// max message size to receive
|
||||
// leave some extra space for AT-CMD characters
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
// timeout read
|
||||
const READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
let mut rbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
let mut wbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
loop {
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"Hello async write!!!\r\n")
|
||||
if rbuf.is_empty() {
|
||||
embedded_hal_async::serial::Write::write(
|
||||
&mut uart,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
wbuf.clear();
|
||||
write!(&mut wbuf, "\r\n-- received {} bytes --\r\n", rbuf.len()).unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, wbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, rbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||
.await
|
||||
.unwrap();
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
|
||||
// set rbuf full capacity
|
||||
rbuf.resize_default(rbuf.capacity()).ok();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
match with_timeout(READ_TIMEOUT, uart.read(&mut rbuf[offset..])).await {
|
||||
Ok(r) => {
|
||||
if let Ok(len) = r {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
// buffer is full
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Timeout
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +136,9 @@ fn main() -> ! {
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(&clocks, timer_group0.timer0);
|
||||
|
||||
let uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||
|
||||
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
|
||||
@ -49,6 +49,7 @@ sha2 = { version = "0.10.6", default-features = false}
|
||||
smart-leds = "0.3.0"
|
||||
ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to a uart.
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Executor;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::{with_timeout, Duration};
|
||||
use esp32c6_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
@ -20,18 +22,79 @@ use esp32c6_hal::{
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_common::uart::config::AtCmdConfig;
|
||||
use heapless::Vec;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 128;
|
||||
// EOT (CTRL-D)
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run(mut uart: Uart<'static, UART0>) {
|
||||
// max message size to receive
|
||||
// leave some extra space for AT-CMD characters
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
// timeout read
|
||||
const READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
let mut rbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
let mut wbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
loop {
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"Hello async write!!!\r\n")
|
||||
if rbuf.is_empty() {
|
||||
embedded_hal_async::serial::Write::write(
|
||||
&mut uart,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
wbuf.clear();
|
||||
write!(&mut wbuf, "\r\n-- received {} bytes --\r\n", rbuf.len()).unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, wbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, rbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||
.await
|
||||
.unwrap();
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
|
||||
// set rbuf full capacity
|
||||
rbuf.resize_default(rbuf.capacity()).ok();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
match with_timeout(READ_TIMEOUT, uart.read(&mut rbuf[offset..])).await {
|
||||
Ok(r) => {
|
||||
if let Ok(len) = r {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
// buffer is full
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Timeout
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +136,9 @@ fn main() -> ! {
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(&clocks, timer_group0.timer0);
|
||||
|
||||
let uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||
|
||||
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
|
||||
@ -49,6 +49,7 @@ sha2 = { version = "0.10.6", default-features = false}
|
||||
smart-leds = "0.3.0"
|
||||
ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to a uart.
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Executor;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::{with_timeout, Duration};
|
||||
use esp32h2_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
@ -20,18 +22,79 @@ use esp32h2_hal::{
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_common::uart::config::AtCmdConfig;
|
||||
use heapless::Vec;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 128;
|
||||
// EOT (CTRL-D)
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run(mut uart: Uart<'static, UART0>) {
|
||||
// max message size to receive
|
||||
// leave some extra space for AT-CMD characters
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
// timeout read
|
||||
const READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
let mut rbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
let mut wbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
loop {
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"Hello async write!!!\r\n")
|
||||
if rbuf.is_empty() {
|
||||
embedded_hal_async::serial::Write::write(
|
||||
&mut uart,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
wbuf.clear();
|
||||
write!(&mut wbuf, "\r\n-- received {} bytes --\r\n", rbuf.len()).unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, wbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, rbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||
.await
|
||||
.unwrap();
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
|
||||
// set rbuf full capacity
|
||||
rbuf.resize_default(rbuf.capacity()).ok();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
match with_timeout(READ_TIMEOUT, uart.read(&mut rbuf[offset..])).await {
|
||||
Ok(r) => {
|
||||
if let Ok(len) = r {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
// buffer is full
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Timeout
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +136,9 @@ fn main() -> ! {
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(&clocks, timer_group0.timer0);
|
||||
|
||||
let uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||
|
||||
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
|
||||
@ -50,6 +50,7 @@ ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
usb-device = { version = "0.2.9" }
|
||||
usbd-serial = "0.1.1"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored"]
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to a uart.
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Executor;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::{with_timeout, Duration};
|
||||
use esp32s2_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
@ -20,18 +22,79 @@ use esp32s2_hal::{
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_common::uart::config::AtCmdConfig;
|
||||
use heapless::Vec;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 128;
|
||||
// EOT (CTRL-D)
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run(mut uart: Uart<'static, UART0>) {
|
||||
// max message size to receive
|
||||
// leave some extra space for AT-CMD characters
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
// timeout read
|
||||
const READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
let mut rbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
let mut wbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
loop {
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"Hello async write!!!\r\n")
|
||||
if rbuf.is_empty() {
|
||||
embedded_hal_async::serial::Write::write(
|
||||
&mut uart,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
wbuf.clear();
|
||||
write!(&mut wbuf, "\r\n-- received {} bytes --\r\n", rbuf.len()).unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, wbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, rbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||
.await
|
||||
.unwrap();
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
|
||||
// set rbuf full capacity
|
||||
rbuf.resize_default(rbuf.capacity()).ok();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
match with_timeout(READ_TIMEOUT, uart.read(&mut rbuf[offset..])).await {
|
||||
Ok(r) => {
|
||||
if let Ok(len) = r {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
// buffer is full
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Timeout
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +129,9 @@ fn main() -> ! {
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(&clocks, timer_group0.timer0);
|
||||
|
||||
let uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||
|
||||
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
|
||||
@ -52,6 +52,7 @@ ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
usb-device = "0.2.9"
|
||||
usbd-serial = "0.1.1"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored"]
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to a uart.
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Executor;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::{with_timeout, Duration};
|
||||
use esp32s3_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
@ -20,18 +22,79 @@ use esp32s3_hal::{
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_common::uart::config::AtCmdConfig;
|
||||
use heapless::Vec;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 128;
|
||||
// EOT (CTRL-D)
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run(mut uart: Uart<'static, UART0>) {
|
||||
// max message size to receive
|
||||
// leave some extra space for AT-CMD characters
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
// timeout read
|
||||
const READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
let mut rbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
let mut wbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
loop {
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"Hello async write!!!\r\n")
|
||||
if rbuf.is_empty() {
|
||||
embedded_hal_async::serial::Write::write(
|
||||
&mut uart,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
wbuf.clear();
|
||||
write!(&mut wbuf, "\r\n-- received {} bytes --\r\n", rbuf.len()).unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, wbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, rbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||
.await
|
||||
.unwrap();
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
|
||||
// set rbuf full capacity
|
||||
rbuf.resize_default(rbuf.capacity()).ok();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
match with_timeout(READ_TIMEOUT, uart.read(&mut rbuf[offset..])).await {
|
||||
Ok(r) => {
|
||||
if let Ok(len) = r {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
// buffer is full
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Timeout
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +136,9 @@ fn main() -> ! {
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(&clocks, timer_group0.timer0);
|
||||
|
||||
let uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||
|
||||
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user