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
|
- Fix rom::crc docs
|
||||||
- Add octal PSRAM support for ESP32-S3 (#610)
|
- Add octal PSRAM support for ESP32-S3 (#610)
|
||||||
- Add MD5 functions from ESP ROM (#618)
|
- Add MD5 functions from ESP ROM (#618)
|
||||||
|
- Add embassy async `read` support for `uart` (#620)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,10 @@ const UART_FIFO_SIZE: u16 = 128;
|
|||||||
|
|
||||||
/// Custom serial error type
|
/// Custom serial error type
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {}
|
pub enum Error {
|
||||||
|
#[cfg(feature = "async")]
|
||||||
|
ReadBufferFull,
|
||||||
|
}
|
||||||
|
|
||||||
/// UART configuration
|
/// UART configuration
|
||||||
pub mod config {
|
pub mod config {
|
||||||
@ -994,11 +997,15 @@ mod asynch {
|
|||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
|
use embassy_futures::select::select;
|
||||||
use embassy_sync::waitqueue::AtomicWaker;
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
use procmacros::interrupt;
|
use procmacros::interrupt;
|
||||||
|
|
||||||
use super::{Error, Instance};
|
use super::{Error, Instance};
|
||||||
use crate::{uart::UART_FIFO_SIZE, Uart};
|
use crate::{
|
||||||
|
uart::{RegisterBlock, UART_FIFO_SIZE},
|
||||||
|
Uart,
|
||||||
|
};
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(all(uart0, uart1, uart2))] {
|
if #[cfg(all(uart0, uart1, uart2))] {
|
||||||
@ -1016,6 +1023,8 @@ mod asynch {
|
|||||||
pub(crate) enum Event {
|
pub(crate) enum Event {
|
||||||
TxDone,
|
TxDone,
|
||||||
TxFiFoEmpty,
|
TxFiFoEmpty,
|
||||||
|
RxFifoFull,
|
||||||
|
RxCmdCharDetected,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct UartFuture<'a, T: Instance> {
|
pub(crate) struct UartFuture<'a, T: Instance> {
|
||||||
@ -1034,6 +1043,14 @@ mod asynch {
|
|||||||
.register_block()
|
.register_block()
|
||||||
.int_ena
|
.int_ena
|
||||||
.modify(|_, w| w.txfifo_empty_int_ena().set_bit()),
|
.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 }
|
Self { event, instance }
|
||||||
@ -1055,6 +1072,20 @@ mod asynch {
|
|||||||
.read()
|
.read()
|
||||||
.txfifo_empty_int_ena()
|
.txfifo_empty_int_ena()
|
||||||
.bit_is_clear(),
|
.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
|
where
|
||||||
T: Instance,
|
T: Instance,
|
||||||
{
|
{
|
||||||
async fn write(&mut self, words: &[u8]) -> Result<(), Error> {
|
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
for chunk in words.chunks(UART_FIFO_SIZE as usize) {
|
let mut read_bytes = 0;
|
||||||
for &byte in chunk {
|
|
||||||
self.write_byte(byte).unwrap() // should never fail
|
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;
|
UartFuture::new(Event::TxFiFoEmpty, self.inner()).await;
|
||||||
}
|
}
|
||||||
Ok(())
|
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)]
|
#[cfg(uart0)]
|
||||||
#[interrupt]
|
#[interrupt]
|
||||||
fn UART0() {
|
fn UART0() {
|
||||||
let uart = unsafe { &*crate::peripherals::UART0::ptr() };
|
let uart = unsafe { &*crate::peripherals::UART0::ptr() };
|
||||||
uart.int_ena.modify(|_, w| {
|
if intr_handler(uart) {
|
||||||
w.txfifo_empty_int_ena()
|
WAKERS[0].wake();
|
||||||
.clear_bit()
|
}
|
||||||
.tx_done_int_ena()
|
|
||||||
.clear_bit()
|
|
||||||
});
|
|
||||||
WAKERS[0].wake();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(uart1)]
|
#[cfg(uart1)]
|
||||||
#[interrupt]
|
#[interrupt]
|
||||||
fn UART1() {
|
fn UART1() {
|
||||||
let uart = unsafe { &*crate::peripherals::UART1::ptr() };
|
let uart = unsafe { &*crate::peripherals::UART1::ptr() };
|
||||||
uart.int_ena.modify(|_, w| {
|
if intr_handler(uart) {
|
||||||
w.txfifo_empty_int_ena()
|
WAKERS[1].wake();
|
||||||
.clear_bit()
|
}
|
||||||
.tx_done_int_ena()
|
|
||||||
.clear_bit()
|
|
||||||
});
|
|
||||||
WAKERS[1].wake();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(uart2)]
|
#[cfg(uart2)]
|
||||||
#[interrupt]
|
#[interrupt]
|
||||||
fn UART2() {
|
fn UART2() {
|
||||||
let uart = unsafe { &*crate::peripherals::UART2::ptr() };
|
let uart = unsafe { &*crate::peripherals::UART2::ptr() };
|
||||||
uart.int_ena.modify(|_, w| {
|
if intr_handler(uart) {
|
||||||
w.txfifo_empty_int_ena()
|
WAKERS[2].wake();
|
||||||
.clear_bit()
|
}
|
||||||
.tx_done_int_ena()
|
|
||||||
.clear_bit()
|
|
||||||
});
|
|
||||||
WAKERS[2].wake();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,7 @@ sha2 = { version = "0.10.6", default-features = false}
|
|||||||
smart-leds = "0.3.0"
|
smart-leds = "0.3.0"
|
||||||
ssd1306 = "0.7.1"
|
ssd1306 = "0.7.1"
|
||||||
static_cell = "1.0.0"
|
static_cell = "1.0.0"
|
||||||
|
heapless = "0.7.16"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt", "vectored", "xtal40mhz"]
|
default = ["rt", "vectored", "xtal40mhz"]
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
//! embassy serial
|
//! embassy serial
|
||||||
//!
|
//!
|
||||||
//! This is an example of running the embassy executor and asynchronously
|
//! This is an example of running the embassy executor and asynchronously
|
||||||
//! writing to a uart.
|
//! writing to and reading from uart
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{with_timeout, Duration};
|
||||||
use esp32_hal::{
|
use esp32_hal::{
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
embassy,
|
embassy,
|
||||||
@ -20,18 +22,79 @@ use esp32_hal::{
|
|||||||
Uart,
|
Uart,
|
||||||
};
|
};
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
|
use esp_hal_common::uart::config::AtCmdConfig;
|
||||||
|
use heapless::Vec;
|
||||||
use static_cell::StaticCell;
|
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]
|
#[embassy_executor::task]
|
||||||
async fn run(mut uart: Uart<'static, UART0>) {
|
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 {
|
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
|
.await
|
||||||
.unwrap();
|
.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)
|
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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")]
|
#[cfg(feature = "embassy-time-timg0")]
|
||||||
embassy::init(&clocks, timer_group0.timer0);
|
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();
|
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}
|
sha2 = { version = "0.10.6", default-features = false}
|
||||||
ssd1306 = "0.7.1"
|
ssd1306 = "0.7.1"
|
||||||
static_cell = "1.0.0"
|
static_cell = "1.0.0"
|
||||||
|
heapless = "0.7.16"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt", "vectored", "xtal40mhz"]
|
default = ["rt", "vectored", "xtal40mhz"]
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
//! embassy serial
|
//! embassy serial
|
||||||
//!
|
//!
|
||||||
//! This is an example of running the embassy executor and asynchronously
|
//! This is an example of running the embassy executor and asynchronously
|
||||||
//! writing to a uart.
|
//! writing to and reading from uart
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{with_timeout, Duration};
|
||||||
use esp32c2_hal::{
|
use esp32c2_hal::{
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
embassy,
|
embassy,
|
||||||
@ -20,18 +22,79 @@ use esp32c2_hal::{
|
|||||||
Uart,
|
Uart,
|
||||||
};
|
};
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
|
use esp_hal_common::uart::config::AtCmdConfig;
|
||||||
|
use heapless::Vec;
|
||||||
use static_cell::StaticCell;
|
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]
|
#[embassy_executor::task]
|
||||||
async fn run(mut uart: Uart<'static, UART0>) {
|
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 {
|
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
|
.await
|
||||||
.unwrap();
|
.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)
|
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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")]
|
#[cfg(feature = "embassy-time-timg0")]
|
||||||
embassy::init(&clocks, timer_group0.timer0);
|
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();
|
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"
|
smart-leds = "0.3.0"
|
||||||
ssd1306 = "0.7.1"
|
ssd1306 = "0.7.1"
|
||||||
static_cell = "1.0.0"
|
static_cell = "1.0.0"
|
||||||
|
heapless = "0.7.16"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
//! embassy serial
|
//! embassy serial
|
||||||
//!
|
//!
|
||||||
//! This is an example of running the embassy executor and asynchronously
|
//! This is an example of running the embassy executor and asynchronously
|
||||||
//! writing to a uart.
|
//! writing to and reading from uart
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{with_timeout, Duration};
|
||||||
use esp32c3_hal::{
|
use esp32c3_hal::{
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
embassy,
|
embassy,
|
||||||
@ -20,18 +22,79 @@ use esp32c3_hal::{
|
|||||||
Uart,
|
Uart,
|
||||||
};
|
};
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
|
use esp_hal_common::uart::config::AtCmdConfig;
|
||||||
|
use heapless::Vec;
|
||||||
use static_cell::StaticCell;
|
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]
|
#[embassy_executor::task]
|
||||||
async fn run(mut uart: Uart<'static, UART0>) {
|
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 {
|
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
|
.await
|
||||||
.unwrap();
|
.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)
|
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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")]
|
#[cfg(feature = "embassy-time-timg0")]
|
||||||
embassy::init(&clocks, timer_group0.timer0);
|
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();
|
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"
|
smart-leds = "0.3.0"
|
||||||
ssd1306 = "0.7.1"
|
ssd1306 = "0.7.1"
|
||||||
static_cell = "1.0.0"
|
static_cell = "1.0.0"
|
||||||
|
heapless = "0.7.16"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
//! embassy serial
|
//! embassy serial
|
||||||
//!
|
//!
|
||||||
//! This is an example of running the embassy executor and asynchronously
|
//! This is an example of running the embassy executor and asynchronously
|
||||||
//! writing to a uart.
|
//! writing to and reading from uart
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{with_timeout, Duration};
|
||||||
use esp32c6_hal::{
|
use esp32c6_hal::{
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
embassy,
|
embassy,
|
||||||
@ -20,18 +22,79 @@ use esp32c6_hal::{
|
|||||||
Uart,
|
Uart,
|
||||||
};
|
};
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
|
use esp_hal_common::uart::config::AtCmdConfig;
|
||||||
|
use heapless::Vec;
|
||||||
use static_cell::StaticCell;
|
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]
|
#[embassy_executor::task]
|
||||||
async fn run(mut uart: Uart<'static, UART0>) {
|
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 {
|
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
|
.await
|
||||||
.unwrap();
|
.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)
|
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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")]
|
#[cfg(feature = "embassy-time-timg0")]
|
||||||
embassy::init(&clocks, timer_group0.timer0);
|
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();
|
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"
|
smart-leds = "0.3.0"
|
||||||
ssd1306 = "0.7.1"
|
ssd1306 = "0.7.1"
|
||||||
static_cell = "1.0.0"
|
static_cell = "1.0.0"
|
||||||
|
heapless = "0.7.16"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
//! embassy serial
|
//! embassy serial
|
||||||
//!
|
//!
|
||||||
//! This is an example of running the embassy executor and asynchronously
|
//! This is an example of running the embassy executor and asynchronously
|
||||||
//! writing to a uart.
|
//! writing to and reading from uart
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{with_timeout, Duration};
|
||||||
use esp32h2_hal::{
|
use esp32h2_hal::{
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
embassy,
|
embassy,
|
||||||
@ -20,18 +22,79 @@ use esp32h2_hal::{
|
|||||||
Uart,
|
Uart,
|
||||||
};
|
};
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
|
use esp_hal_common::uart::config::AtCmdConfig;
|
||||||
|
use heapless::Vec;
|
||||||
use static_cell::StaticCell;
|
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]
|
#[embassy_executor::task]
|
||||||
async fn run(mut uart: Uart<'static, UART0>) {
|
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 {
|
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
|
.await
|
||||||
.unwrap();
|
.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)
|
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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")]
|
#[cfg(feature = "embassy-time-timg0")]
|
||||||
embassy::init(&clocks, timer_group0.timer0);
|
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();
|
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||||
|
|
||||||
|
|||||||
@ -50,6 +50,7 @@ ssd1306 = "0.7.1"
|
|||||||
static_cell = "1.0.0"
|
static_cell = "1.0.0"
|
||||||
usb-device = { version = "0.2.9" }
|
usb-device = { version = "0.2.9" }
|
||||||
usbd-serial = "0.1.1"
|
usbd-serial = "0.1.1"
|
||||||
|
heapless = "0.7.16"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt", "vectored"]
|
default = ["rt", "vectored"]
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
//! embassy serial
|
//! embassy serial
|
||||||
//!
|
//!
|
||||||
//! This is an example of running the embassy executor and asynchronously
|
//! This is an example of running the embassy executor and asynchronously
|
||||||
//! writing to a uart.
|
//! writing to and reading from uart
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{with_timeout, Duration};
|
||||||
use esp32s2_hal::{
|
use esp32s2_hal::{
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
embassy,
|
embassy,
|
||||||
@ -20,18 +22,79 @@ use esp32s2_hal::{
|
|||||||
Uart,
|
Uart,
|
||||||
};
|
};
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
|
use esp_hal_common::uart::config::AtCmdConfig;
|
||||||
|
use heapless::Vec;
|
||||||
use static_cell::StaticCell;
|
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]
|
#[embassy_executor::task]
|
||||||
async fn run(mut uart: Uart<'static, UART0>) {
|
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 {
|
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
|
.await
|
||||||
.unwrap();
|
.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)
|
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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")]
|
#[cfg(feature = "embassy-time-timg0")]
|
||||||
embassy::init(&clocks, timer_group0.timer0);
|
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();
|
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||||
|
|
||||||
|
|||||||
@ -52,6 +52,7 @@ ssd1306 = "0.7.1"
|
|||||||
static_cell = "1.0.0"
|
static_cell = "1.0.0"
|
||||||
usb-device = "0.2.9"
|
usb-device = "0.2.9"
|
||||||
usbd-serial = "0.1.1"
|
usbd-serial = "0.1.1"
|
||||||
|
heapless = "0.7.16"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt", "vectored"]
|
default = ["rt", "vectored"]
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
//! embassy serial
|
//! embassy serial
|
||||||
//!
|
//!
|
||||||
//! This is an example of running the embassy executor and asynchronously
|
//! This is an example of running the embassy executor and asynchronously
|
||||||
//! writing to a uart.
|
//! writing to and reading from uart
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
use embassy_executor::Executor;
|
use embassy_executor::Executor;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{with_timeout, Duration};
|
||||||
use esp32s3_hal::{
|
use esp32s3_hal::{
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
embassy,
|
embassy,
|
||||||
@ -20,18 +22,79 @@ use esp32s3_hal::{
|
|||||||
Uart,
|
Uart,
|
||||||
};
|
};
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
|
use esp_hal_common::uart::config::AtCmdConfig;
|
||||||
|
use heapless::Vec;
|
||||||
use static_cell::StaticCell;
|
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]
|
#[embassy_executor::task]
|
||||||
async fn run(mut uart: Uart<'static, UART0>) {
|
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 {
|
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
|
.await
|
||||||
.unwrap();
|
.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)
|
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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")]
|
#[cfg(feature = "embassy-time-timg0")]
|
||||||
embassy::init(&clocks, timer_group0.timer0);
|
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();
|
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user