main: Add UART I/O helpers
This commit is contained in:
parent
7bbb47a844
commit
6604670490
2 changed files with 120 additions and 0 deletions
118
src/main.rs
118
src/main.rs
|
|
@ -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:?}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue