0
0
Fork 0

main: Add UART I/O helpers

This commit is contained in:
Jannik Beyerstedt 2026-07-26 21:40:55 +02:00 committed by Jannik Beyerstedt
commit 6604670490
2 changed files with 120 additions and 0 deletions

View file

@ -53,6 +53,8 @@ const OWN_STATION_TYPE: ItsStationType = ItsStationType::Cyclist;
const OWN_VEHICLE_WIDTH: u8 = 5; // in 10cm steps!
#[cfg(feature = "cam_tx")]
const OWN_VEHICLE_LENGTH: u16 = 20; // in 10cm steps!
#[cfg(feature = "_uart")]
const SERIAL_FIFO_SIZE_THLD: u8 = 100; // hardware has max. 128 byte
// This creates a default app-descriptor required by the esp-idf bootloader.
// For more information see: <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description>
@ -61,6 +63,11 @@ esp_bootloader_esp_idf::esp_app_desc!();
#[cfg(feature = "gnss")]
static GNSS_UPDATE: Mutex<RefCell<Option<applogic::GnssFix>>> = Mutex::new(RefCell::new(None));
static WIFI_RX_QUEUE: Mutex<RefCell<Option<ArrayQueue<Vec<u8>>>>> = Mutex::new(RefCell::new(None));
#[cfg(feature = "_uart")]
static UART_RX_BUF: Mutex<RefCell<Option<Vec<u8>>>> = Mutex::new(RefCell::new(None));
#[cfg(feature = "_uart")]
static SERIAL: Mutex<RefCell<Option<esp_hal::uart::Uart<'static, esp_hal::Blocking>>>> =
Mutex::new(RefCell::new(None));
#[allow(
clippy::large_stack_frames,
@ -192,6 +199,25 @@ async fn main(spawner: Spawner) -> ! {
loop {
embassy_time::Timer::after(embassy_time::Duration::from_millis(1)).await;
#[cfg(feature = "_uart")]
{
let mut new_data = None;
critical_section::with(|cs| {
let mut buf_rc = UART_RX_BUF.borrow(cs).borrow_mut();
// unwrap is fine b/c we stored something in it before
let buf = buf_rc.as_mut().unwrap();
// we move the buffer to new_data to do the processing outside of the critical section lock
if !buf.is_empty() {
new_data = Some(core::mem::take(buf));
}
});
if let Some(data) = new_data {
warn!("TODO: New UART data: {data:x?}");
}
}
#[cfg(feature = "gnss")]
{
let mut new_position = false;
@ -573,3 +599,95 @@ where
{
error!("graphics failed: {error:?}");
}
#[cfg(feature = "_uart")]
/// Configures UART0 with an interrupt handler and saves it to `SERIAL`
fn setup_uart0(
baud: u32,
cmd_char: Option<u8>,
gpio12: esp_hal::peripherals::GPIO12<'static>,
gpio11: esp_hal::peripherals::GPIO11<'static>,
uart0: esp_hal::peripherals::UART0<'static>,
handler: esp_hal::interrupt::InterruptHandler,
) -> Result<(), alloc::string::String> {
critical_section::with(|cs| {
UART_RX_BUF
.borrow(cs)
.replace(Some(alloc::vec::Vec::with_capacity(255)));
});
let mut uart = esp_hal::uart::Uart::new(
uart0,
esp_hal::uart::Config::default()
.with_baudrate(baud)
.with_rx(
esp_hal::uart::RxConfig::default()
.with_fifo_full_threshold(u16::from(SERIAL_FIFO_SIZE_THLD))
.with_timeout(50),
),
)
.map_err(|err| alloc::format!("UART0 config error: {err}"))?
.with_rx(gpio12)
.with_tx(gpio11);
if let Some(char) = cmd_char {
uart.set_at_cmd(
esp_hal::uart::AtCmdConfig::default()
.with_cmd_char(char)
.with_char_num(1)
.with_pre_idle_count(0) // command start can be right after other data
.with_post_idle_count(0) // we don't expect a gap between the command start and subsequent text
.with_gap_timeout(5), // needs to be >0 to work
);
}
uart.set_interrupt_handler(handler);
uart.listen(
esp_hal::uart::UartInterrupt::AtCmd
| esp_hal::uart::UartInterrupt::RxTimeout
| esp_hal::uart::UartInterrupt::RxFifoFull, // just to be save
);
critical_section::with(|cs| SERIAL.borrow_ref_mut(cs).replace(uart));
Ok(())
}
#[cfg(feature = "_uart")]
#[esp_hal::handler]
fn serial_handler() {
critical_section::with(|cs| {
let mut serial = SERIAL.borrow_ref_mut(cs);
let mut uart_buf = UART_RX_BUF.borrow_ref_mut(cs);
if let (Some(serial), Some(uart_buf)) = (serial.as_mut(), uart_buf.as_mut()) {
let mut buf = [0u8; SERIAL_FIFO_SIZE_THLD as usize];
match serial.read_buffered(&mut buf) {
Ok(0) => {}
Ok(len) => {
uart_buf.extend_from_slice(&buf[..len]);
}
Err(err) => error!("Failed to read from UART: {err}"),
}
serial.clear_interrupts(
esp_hal::uart::UartInterrupt::RxFifoFull
| esp_hal::uart::UartInterrupt::RxTimeout
| esp_hal::uart::UartInterrupt::AtCmd,
);
}
});
}
#[cfg(feature = "_uart")]
fn send_uart0(data: &[u8]) {
critical_section::with(|cs| {
let mut serial = SERIAL.borrow_ref_mut(cs);
if let Some(serial) = serial.as_mut()
&& let Err(err) = serial.write(data)
{
error!("Failed to write to UART: {err:?}");
}
});
}