update UART example, update UART HAL

This commit is contained in:
2024-09-26 22:08:17 +02:00
parent ce7a8665a3
commit 60305ef393
20 changed files with 2121 additions and 419 deletions

View File

@ -9,17 +9,12 @@ cortex-m-rt = "0.7"
embedded-hal = "1"
embedded-io = "0.6"
rtt-target = { version = "0.5" }
# Even though we do not use this directly, we need to activate this feature explicitely
# so that RTIC compiles because thumv6 does not have CAS operations natively.
portable-atomic = { version = "1", features = ["unsafe-assume-single-core"]}
panic-rtt-target = { version = "0.1" }
[dependencies.va108xx-hal]
path = "../../va108xx-hal"
[dependencies.vorago-reb1]
path = "../../vorago-reb1"
[dependencies.rtic]
version = "2"
features = ["thumbv6-backend"]
@ -31,3 +26,20 @@ features = ["cortex-m-systick"]
[dependencies.rtic-sync]
version = "1.3"
features = ["defmt-03"]
[dependencies.once_cell]
version = "1"
default-features = false
features = ["critical-section"]
[dependencies.ringbuf]
version = "0.4"
git = "https://github.com/us-irs/ringbuf.git"
branch = "use-portable-atomic-crate"
default-features = false
[dependencies.va108xx-hal]
path = "../../va108xx-hal"
[dependencies.vorago-reb1]
path = "../../vorago-reb1"

View File

@ -10,10 +10,25 @@
#![no_main]
#![no_std]
use once_cell::sync::Lazy;
use ringbuf::StaticRb;
// Larger buffer for TC to be able to hold the possibly large memory write packets.
const RX_RING_BUF_SIZE: usize = 1024;
// Ring buffers to handling variable sized telemetry
static mut RINGBUF: Lazy<StaticRb<u8, RX_RING_BUF_SIZE>> =
Lazy::new(StaticRb::<u8, RX_RING_BUF_SIZE>::default);
#[rtic::app(device = pac, dispatchers = [OC4])]
mod app {
use super::*;
use embedded_io::Write;
use panic_rtt_target as _;
use ringbuf::{
traits::{Observer, Producer},
CachingCons, StaticProd,
};
use rtic_example::SYSCLK_FREQ;
use rtic_sync::make_channel;
use rtt_target::{rprintln, rtt_init_print};
@ -21,18 +36,18 @@ mod app {
gpio::PinsB,
pac,
prelude::*,
uart::{self, IrqCfg, IrqResult, UartWithIrqBase},
uart::{self, IrqCfg, IrqContextTimeoutOrMaxSize, IrqResult, RxWithIrq},
};
#[local]
struct Local {
rx_info_tx: rtic_sync::channel::Sender<'static, RxInfo, 3>,
rx_info_rx: rtic_sync::channel::Receiver<'static, RxInfo, 3>,
data_producer: StaticProd<'static, u8, RX_RING_BUF_SIZE>,
data_consumer: CachingCons<&'static StaticRb<u8, RX_RING_BUF_SIZE>>,
uart_rx: RxWithIrq<pac::Uartb>,
}
#[shared]
struct Shared {
irq_uart: UartWithIrqBase<pac::Uartb>,
rx_buf: [u8; 64],
}
@ -58,18 +73,19 @@ mod app {
let rx = gpiob.pb20.into_funsel_1();
let irq_cfg = IrqCfg::new(pac::interrupt::OC3, true, true);
let (mut irq_uart, _) =
uart::Uart::new(&mut dp.sysconfig, 50.MHz(), dp.uartb, (tx, rx), 115200.Hz())
.into_uart_with_irq(irq_cfg, Some(&mut dp.sysconfig), Some(&mut dp.irqsel))
.downgrade();
irq_uart
.read_fixed_len_using_irq(64, true)
.expect("Read initialization failed");
let irq_uart =
uart::Uart::new(&mut dp.sysconfig, 50.MHz(), dp.uartb, (tx, rx), 115200.Hz());
let (tx, rx) = irq_uart.split();
let rx = rx.into_rx_with_irq(&dp.irqsel, pac::interrupt::OC3);
let context = IrqContextTimeoutOrMaxSize::new(64);
rx.read_fixed_len_or_timeout_based_using_irq(&mut context)
.expect("UART RX init failed");
let (rx_info_tx, rx_info_rx) = make_channel!(RxInfo, 3);
let rx_buf: [u8; 64] = [0; 64];
(
Shared { irq_uart, rx_buf },
Shared { uart_rx, rx_buf },
Local {
rx_info_tx,
rx_info_rx,
@ -87,57 +103,34 @@ mod app {
#[task(
binds = OC3,
shared = [irq_uart, rx_buf],
local = [cnt: u32 = 0, result: IrqResult = IrqResult::new(), rx_info_tx],
shared = [rx_buf],
local = [
uart_rx,
data_producer
],
)]
fn reception_task(cx: reception_task::Context) {
let result = cx.local.result;
let cnt: &mut u32 = cx.local.cnt;
let irq_uart = cx.shared.irq_uart;
let rx_buf = cx.shared.rx_buf;
let (completed, end_idx) = (irq_uart, rx_buf).lock(|irq_uart, rx_buf| {
match irq_uart.irq_handler(result, rx_buf) {
Ok(_) => {
if result.complete() {
// Initiate next transfer immediately
irq_uart
.read_fixed_len_using_irq(64, true)
.expect("Read operation init failed");
let mut end_idx = 0;
for (idx, val) in rx_buf.iter().enumerate() {
if (*val as char) == '\n' {
end_idx = idx;
break;
}
}
(true, end_idx)
} else {
(false, 0)
}
}
Err(e) => {
rprintln!("reception error {:?}", e);
(false, 0)
}
let mut buf: [u8; 16] = [0; 16];
let mut ringbuf_full = false;
let result = cx.local.uart_rx.irq_handler(&mut buf);
if result.bytes_read > 0 && result.errors.is_none() {
if cx.local.data_producer.vacant_len() < result.bytes_read {
ringbuf_full = true;
} else {
cx.local
.data_producer
.push_slice(&buf[0..result.bytes_read]);
}
});
if completed {
rprintln!("counter: {}", cnt);
cx.local
.rx_info_tx
.try_send(RxInfo {
bytes_read: result.bytes_read,
end_idx,
timeout: result.timeout(),
})
.expect("RX queue full");
}
*cnt += 1;
if ringbuf_full {
// Could also drop oldest data, but that would require the consumer to be shared.
rprintln!("buffer full, data was dropped");
}
}
#[task(shared = [irq_uart, rx_buf], local = [rx_info_rx], priority=1)]
async fn reply_handler(cx: reply_handler::Context) {
#[task(shared = [rx_buf], local = [data_consumer], priority=1)]
async fn echo_handler(cx: echo_handler::Context) {
/*
let mut irq_uart = cx.shared.irq_uart;
let mut rx_buf = cx.shared.rx_buf;
loop {
@ -161,5 +154,6 @@ mod app {
}
}
}
*/
}
}