Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example uart_loopback does not compile. TX buffer managment in Uart is broken sending garbage characters. #408

Open
joeatbayes opened this issue Apr 20, 2024 · 1 comment

Comments

@joeatbayes
Copy link

joeatbayes commented Apr 20, 2024

The example https://github.com/esp-rs/esp-idf-hal/blob/master/examples/uart_loopback.rs fails to compile due to a missing import. I adapted it to my needs and fixed a couple errors so it both compiles and provides proper response when tested with linux screen.

As shown below the two commented lines to uart.write() and uart_wait_tx_done() end up causing 1 character followed by 10 garbage characters. When the write is replaced with write_nb() which does not use the uart tx buffer it works correctly.

I would greatly appreciate the proper esp_idf_hal example code to reset the watchdog timer at the bottom of the loop so I can remove the sleep_ms(15). I know that we can do this with async or threads but what I really want here is a demonstration of a fast polling loop. I find they scale better and provide more predictable timing than spawning a bunch of threads.

### Results working copied from linux screen correctly echoing keys hit from linux screen connected as uart device on other end

abcdefghijklmnopaewwabcdefghijklmnopabcdefg

### Results copied from linux screen when the write() is used instead of write_nb()

�������������b����������c�555555555�MMMMMMMMMM���555555555�����������e�555555555�����������e������������d����������f�55555555��55555555555555�������i����������j����������k����������l����������m����������n�55555555��SSSSSSSSSSSSSS����������������aSSSSSSSSSSSSSS
                    ��555555555쪪��������c�555555555�����������a�55555555��555555555������������a����������b�55555555��MMMMMMMMMMMMMm��555555555�����������a�555555555�SSSSSSSSSSSS������������d����������e55555555555555�����������g�555555555�������iSSSSSSSSSSSS�����������k�555555555�55555555555������������n����������o�555555555����������

Source that works correctly

//! Non Blocking fast poll Uart RS485 1/2 duplex echo for RS485 style transciever
//! test
//!
//! Folowing pins are used:
//! TX    GPIO43
//! RX    GPIO44
//!//!
//! This example transfers data via UART.
//! Connect TX and RX pins to see the outgoing data is read as incoming data.
//! Echo characters sent from terminal such as linux screen. 
#![allow(unused_imports)]
#![allow(dead_code)]

use anyhow::Result;
use esp_idf_hal::delay::NON_BLOCK;
use esp_idf_hal::gpio;
use esp_idf_hal::gpio::PinDriver;
use esp_idf_hal::delay::Delay;
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::prelude::*;
use esp_idf_hal::uart::*;
use esp_idf_sys;
// TODO:  Figure out how to make WDT work esp_idf_hal https://github.com/esp-rs/esp-hal/blob/main/examples/src/bin/watchdog.rs
// Until then disable WDT in menu config

fn main() -> anyhow::Result<()> {
    esp_idf_hal::sys::link_patches();
    let peripherals = Peripherals::take()?;

    let tx = peripherals.pins.gpio43;
    let rx = peripherals.pins.gpio44;
    let led_pin = peripherals.pins.gpio11;
    let rs_48_en_pin = peripherals.pins.gpio21;
    let delay: Delay = Default::default();
    let mut led = PinDriver::output(led_pin)?;
    let mut rs48_enable = PinDriver::output(rs_48_en_pin)?;

    println!("Starting UART loopback test");
    let config = config::Config::new().baudrate(Hertz(115_200));
    let uart = UartDriver::new(
        peripherals.uart1,
        tx,
        rx,
        Option::<gpio::Gpio0>::None,
        Option::<gpio::Gpio1>::None,
        &config,
    )?;
    
    loop {
        let mut buf = [0_u8; 1];        
        uart.read(&mut buf, NON_BLOCK)?;
        // we know read will return a 0 in buf 
        // when nothing is available so we ignore 
        if buf[0] != 0 {            
          println!("Written 0xaa, read {:?} {:?} 0x{:02x}", buf[0] as char, buf[0],buf[0]);
          rs48_enable.set_high()?;
          delay.delay_us(150); // need to allow transceiver time to enter active mode

          // Calling Write directly causes mutliple garbage characters to 
          // be sent.  I think the uart is not properly managing it's buffer.
          //uart.write(&buf)?;
          //uart.wait_tx_done(150);

          uart.write_nb(&mut buf)?;          
          delay.delay_ms(1);
          //buf[0] = 0;                    
          rs48_enable.set_low()?;
          led.toggle()?;
        }
        // Only need this delay because watchdog fires otherwise
        delay.delay_ms(18); // TODO: TO RESET WATCHDOG IN TIGHT LOOP LIKE THIS USING esp_idf_hal

        // TODO: DO SOME OTHER WORK SINCE WE ARE NO LONGER BLOCKING
        // ON DATA IN UART AVAILABILITY
                
    }
}

### Cargo for this file

[package]
name = "ex-uart-non-block-rs485"
version = "0.1.0"
authors = ["joe ellsworth [email protected]"]
edition = "2021"
resolver = "2"
rust-version = "1.71"

[profile.release]
opt-level = "s"

[profile.dev]
debug = true # Symbols are nice and they don't increase the size on Flash
opt-level = "z"

[features]
default = ["std", "embassy", "esp-idf-svc/native"]

pio = ["esp-idf-svc/pio"]
std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"]
alloc = ["esp-idf-svc/alloc"]
nightly = ["esp-idf-svc/nightly"]
experimental = ["esp-idf-svc/experimental"]
embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"]

[dependencies]
log = { version = "0.4", default-features = false }
esp-idf-svc = { version = "0.48", default-features = false }
esp-idf-hal = "0.43.1"
anyhow = "1.0.82"
esp-idf-sys = "0.34.1"

[build-dependencies]
embuild = "0.31.3"



@joeatbayes
Copy link
Author

jesse how do I tell what should be filed here or over in esp-rs. This is the second one of my issues you had to move.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Todo
Development

No branches or pull requests

1 participant