esp-rs / esp-hal

no_std Hardware Abstraction Layers for ESP32 microcontrollers
https://docs.esp-rs.org/esp-hal/
Apache License 2.0
667 stars 189 forks source link

Embassy_serial can't transmit a package more than 128bytes #1564

Closed cvbni closed 2 weeks ago

cvbni commented 3 months ago

I debug on embassy_serial example,and I fund a question: The "set_rx_fifo_full_threshold" in esp32-c2 can set to 0x1FF(511),but the UART_FIFO_SIZE is 128,

I changed the UART_FIFO_SIZE to 256 in uart.rs file,but it not work

I want to transmit package more than 128bytes. Any help ,thanks!!!

MabezDev commented 3 months ago

Have you actually tried transmitting more than 128 bytes? set_rx_fifo_full_threshold has nothing to do with transmission. write_async should handle the chunking already.

cvbni commented 3 months ago

Have you actually tried transmitting more than 128 bytes? set_rx_fifo_full_threshold has nothing to do with transmission. write_async should handle the chunking already.

Sorry I didn't make it clear. What I mean by this is that UART can't receive more than 128bytes of data

    let mut uart0 = Uart::new_async(peripherals.UART0, &clocks);
    uart0.set_at_cmd(AtCmdConfig::new(None, None, None, 0x04, None));
    uart0.set_rx_fifo_full_threshold(256 as u16).unwrap();//510
    uart0.set_rx_timeout(Some(8)).unwrap();

    let (mut tx0, mut rx0) = uart0.split();
    match select(
        pin!(async move {
            let mut buf = [0u8; 512];
            loop {
                let r = match embedded_io_async::Read::read(&mut rx0, &mut buf[2..]).await {
                    Ok(len) => len,
                    Err(_) => 0 as usize,
                };
                println!("read {} bytes", r);
                println!("read {:?} bytes", &buf[..r]);
                buf[1] = (r & 0xff) as u8;
                buf[0] = ((r >> 8) & 0xff) as u8;
                CH0.send(buf).await;
            }
        }),
        pin!(async move {
            loop {
                println!("\nHello world! Second");
                let buf = CH0.receive().await;
                let b0 = buf[0] as usize;
                let b1 = buf[1] as usize;
                let w = b1 + (b0 << 8);
                println!("b0 {b0} b1 {b1}");
                //println!("{:?}", &buf[2..(w+2)]);//b"Hello async serial\r\n"
                tx0.write_async(&buf[2..(w + 2)]).await.unwrap();
            }
        }),
    )
    .await
    {
        Either::First(_a) => {}
        Either::Second(_b) => {}
    }

not work here,if i send more than 128bytes data from PC uart tool.

                let r = match embedded_io_async::Read::read(&mut rx0, &mut buf[2..]).await {
                    Ok(len) => len,
                    Err(_) => 0 as usize,
                };
                println!("read {} bytes", r);
                println!("read {:?} bytes", &buf[..r]);
MabezDev commented 3 months ago

What I mean by this is that UART can't receive more than 128bytes of data

When you say this, can you be more clear about "can't receive"? Do you mean in one go? Does the data show up with more calls to read()? What baudrate? Any errors?

Ideally a simple and small reproducible repo would help us figure out what's going on.

cvbni commented 3 months ago

i send 128 hexs 0001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607

It can receive,like this

72 65 61 64 20 31 32 38 20 62 79 74 65 73 0A 

62 30 20 30 20 62 31 20 31 32 38 0A 

00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 05 06 07 08 09 00 01 02 03 04 0A 

48 65 6C 6C 6F 20 77 6F 72 6C 64 21 20 53 65 63 6F 6E 64 0A 6C 64 21 20 53 65 63 6F 6E 64 0A 

show in ascii

read 128 bytes

b0 0 b1 128



when i send 129 hex 000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708

it can' receive,like this

72 65 61 64 20 30 20 62 79 74 65 73 0A 

62 30 20 30 20 62 31 20 30 0A 

0A 

48 65 6C 6C 6F 20 77 6F 72 6C 64 21 20 53 65 63 6F 6E 64 0A 

show in ascii

read 0 bytes

b0 0 b1 0

Hello world! Second
MabezDev commented 3 months ago

Could you provide a minimal reproduction repo so we can attempt to fix it?

cvbni commented 3 months ago

Could you provide a minimal reproduction repo so we can attempt to fix it?

cargo.toml

[package]
name = "c2ntd"
version = "0.1.0"
authors = ["cvbnix"]
edition = "2021"
license = "MIT OR Apache-2.0"

[dependencies]
esp-backtrace = { version = "0.11.0", features = [
    "esp32c2",
    "exception-handler",
    "panic-handler",
    "println",
] }
esp-hal = { version = "0.17.0", features = [
    "esp32c2",
    "async",
    "embassy",
    "embassy-executor-thread",
    "embassy-time-timg0",
] }
esp-println = { version = "0.9.0", features = ["esp32c2", "log", "uart"] }
log = { version = "0.4.20" }
esp-alloc = { version = "0.3.0" }
embedded-svc = { version = "0.27.1", default-features = false, features = [] }
#embedded-io = "0.6.1"
embedded-io-async = "0.6.1"
esp-wifi = { version = "0.5.0", features = [
    "esp32c2",
    #"phy-enable-usb",
    "utils",
    #"wifi",
    "ble",
    "dump-packets",
    "async",
] }
heapless = { version = "0.8.0", default-features = false }
smoltcp = { version = "0.11.0", default-features = false, features = [
    "medium-ethernet",
    "proto-dhcpv4",
    "proto-igmp",
    "proto-ipv4",
    "socket-dhcpv4",
    "socket-icmp",
    "socket-raw",
    "socket-tcp",
    "socket-udp",
] }
#embassy-executor = { version = "0.5.0", features = ["task-arena-size-40960","integrated-timers",] }

embassy-executor = { version = "0.5.0", features = ["integrated-timers"] }
embassy-time = "0.3.0"
embassy-sync = "0.5.0"
embassy-futures = "0.1.1"

[profile.dev]
# Rust debug is too slow. 
# For debug builds always builds with some optimization
opt-level = "s"
[profile.release]
codegen-units = 1        # LLVM can perform better optimizations using a single thread
debug = 2
debug-assertions = false
incremental = false
lto = 'fat'
opt-level = 's'
overflow-checks = false

main.rs

#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#![feature(async_closure)]

use core::pin::pin;
use embassy_executor::Spawner;
use embassy_futures::select::{select, Either};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel;
//use embassy_time::Timer;
use esp_backtrace as _;
use esp_hal::{
    clock::ClockControl,
    embassy,
    peripherals::Peripherals,
    prelude::*,
    timer::TimerGroup,
    uart::{config::AtCmdConfig, Uart}, //, UartRx, UartTx
};
extern crate alloc;
use core::mem::MaybeUninit;
use esp_println::println;
static CH0: Channel<CriticalSectionRawMutex, [u8; 512], 1> = Channel::new();
#[global_allocator]
static ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();

fn init_heap() {
    const HEAP_SIZE: usize = 32 * 1024;
    static mut HEAP: MaybeUninit<[u8; HEAP_SIZE]> = MaybeUninit::uninit();
    unsafe {
        ALLOCATOR.init(HEAP.as_mut_ptr() as *mut u8, HEAP_SIZE);
    }
}

#[main]
async fn main(_spawner: Spawner) {
    let peripherals = Peripherals::take();
    let system = peripherals.SYSTEM.split();
    let clocks = ClockControl::max(system.clock_control).freeze();
    let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
    embassy::init(&clocks, timg0);
    init_heap();
    let mut uart0 = Uart::new_async(peripherals.UART0, &clocks);
    uart0.set_at_cmd(AtCmdConfig::new(None, None, None, 0x04, None));
    uart0.set_rx_fifo_full_threshold(256 as u16).unwrap(); //510
    uart0.set_rx_timeout(Some(8)).unwrap();

    let (mut tx0, mut rx0) = uart0.split();

    match select(
        pin!(async move {
            let mut buf = [0u8; 512];
            loop {
                let r = match embedded_io_async::Read::read(&mut rx0, &mut buf[2..]).await {
                    Ok(len) => {
                        println!("read {} bytes", len);
                        len
                    }
                    Err(e) => {
                        println!("read err! {:?} ", e);
                        0 as usize
                    }
                };
                buf[1] = (r & 0xff) as u8;
                buf[0] = ((r >> 8) & 0xff) as u8;
                CH0.send(buf).await;
            }
        }),
        pin!(async move {
            loop {
                println!("\n");
                let buf = CH0.receive().await;
                let b0 = buf[0] as usize;
                let b1 = buf[1] as usize;
                let w = b1 + (b0 << 8);
                println!("print b0 {b0} b1 {b1}");
                tx0.write_async(&buf[2..(w + 2)]).await.unwrap();
            }
        }),
    )
    .await
    {
        Either::First(_a) => {}
        Either::Second(_b) => {}
    }
}
cvbni commented 3 months ago

0001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607 send the 128bytes data by hex

show in hex 图片 show in ascii

图片

00010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809

send the 130bytes data by hex

show in hex 图片

show in ascii 图片

bjoernQ commented 3 months ago

I can reproduce your results but your example should work if you set the rx-fifo-full-threshold to 128 (or less) but you will receive data in multiple chunks.

In theory the UARTs can be configured in a more flexible way regarding their usage of UART RAM:

image

We currently don't support that but that's the reason why the thresholds are 8 bit.

cvbni commented 3 months ago

OK, I understand, thanks, I will modify my program to adapt to 128 byte slices

MabezDev commented 2 weeks ago

I believe setting a rx_fifo_full_threshold less than 128 (the current configured fifo size) so that you can drain the FIFO before it fills up.

As you have a work around, I will close this for now.