updated UART echo RTIC example

This commit is contained in:
Robin Müller 2024-09-27 10:31:04 +02:00
parent 60305ef393
commit f7ff74940a
Signed by: muellerr
GPG Key ID: A649FB78196E3849
3 changed files with 60 additions and 60 deletions

View File

@ -1,12 +1,7 @@
//! More complex UART application //! More complex UART application
//! //!
//! Uses the IRQ capabilities of the VA10820 peripheral and the RTIC framework to poll the UART in //! Uses the IRQ capabilities of the VA10820 peripheral and the RTIC framework to poll the UART in
//! a non-blocking way. You can send variably sized strings to the VA10820 which will be echoed //! a non-blocking way. All received data will be sent back to the sender.
//! back to the sender.
//!
//! This script was tested with an Arduino Due. You can find the test script in the
//! [`/test/DueSerialTest`](https://egit.irs.uni-stuttgart.de/rust/va108xx-hal/src/branch/main/test/DueSerialTest)
//! folder.
#![no_main] #![no_main]
#![no_std] #![no_std]
@ -26,37 +21,29 @@ mod app {
use embedded_io::Write; use embedded_io::Write;
use panic_rtt_target as _; use panic_rtt_target as _;
use ringbuf::{ use ringbuf::{
traits::{Observer, Producer}, traits::{Consumer, Observer, Producer, SplitRef},
CachingCons, StaticProd, CachingCons, StaticProd,
}; };
use rtic_example::SYSCLK_FREQ; use rtic_example::SYSCLK_FREQ;
use rtic_sync::make_channel; use rtic_monotonics::Monotonic;
use rtt_target::{rprintln, rtt_init_print}; use rtt_target::{rprintln, rtt_init_print};
use va108xx_hal::{ use va108xx_hal::{
gpio::PinsB, gpio::PinsB,
pac, pac,
prelude::*, prelude::*,
uart::{self, IrqCfg, IrqContextTimeoutOrMaxSize, IrqResult, RxWithIrq}, uart::{self, RxWithIrq, Tx},
}; };
#[local] #[local]
struct Local { struct Local {
data_producer: StaticProd<'static, u8, RX_RING_BUF_SIZE>, data_producer: StaticProd<'static, u8, RX_RING_BUF_SIZE>,
data_consumer: CachingCons<&'static StaticRb<u8, RX_RING_BUF_SIZE>>, data_consumer: CachingCons<&'static StaticRb<u8, RX_RING_BUF_SIZE>>,
uart_rx: RxWithIrq<pac::Uartb>, rx: RxWithIrq<pac::Uartb>,
tx: Tx<pac::Uartb>,
} }
#[shared] #[shared]
struct Shared { struct Shared {}
rx_buf: [u8; 64],
}
#[derive(Debug, Copy, Clone)]
struct RxInfo {
pub bytes_read: usize,
pub end_idx: usize,
pub timeout: bool,
}
rtic_monotonics::systick_monotonic!(Mono, 1_000); rtic_monotonics::systick_monotonic!(Mono, 1_000);
@ -72,23 +59,21 @@ mod app {
let tx = gpiob.pb21.into_funsel_1(); let tx = gpiob.pb21.into_funsel_1();
let rx = gpiob.pb20.into_funsel_1(); let rx = gpiob.pb20.into_funsel_1();
let irq_cfg = IrqCfg::new(pac::interrupt::OC3, true, true);
let irq_uart = let irq_uart =
uart::Uart::new(&mut dp.sysconfig, 50.MHz(), dp.uartb, (tx, rx), 115200.Hz()); uart::Uart::new(&mut dp.sysconfig, 50.MHz(), dp.uartb, (tx, rx), 115200.Hz());
let (tx, rx) = irq_uart.split(); let (tx, rx) = irq_uart.split();
let rx = rx.into_rx_with_irq(&dp.irqsel, pac::interrupt::OC3); let mut rx = rx.into_rx_with_irq(&dp.irqsel, pac::interrupt::OC3);
let context = IrqContextTimeoutOrMaxSize::new(64); rx.start();
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 (data_producer, data_consumer) = unsafe { RINGBUF.split_ref() };
let rx_buf: [u8; 64] = [0; 64];
( (
Shared { uart_rx, rx_buf }, Shared {},
Local { Local {
rx_info_tx, data_producer,
rx_info_rx, data_consumer,
rx,
tx,
}, },
) )
} }
@ -103,16 +88,16 @@ mod app {
#[task( #[task(
binds = OC3, binds = OC3,
shared = [rx_buf], shared = [],
local = [ local = [
uart_rx, rx,
data_producer data_producer
], ],
)] )]
fn reception_task(cx: reception_task::Context) { fn reception_task(cx: reception_task::Context) {
let mut buf: [u8; 16] = [0; 16]; let mut buf: [u8; 16] = [0; 16];
let mut ringbuf_full = false; let mut ringbuf_full = false;
let result = cx.local.uart_rx.irq_handler(&mut buf); let result = cx.local.rx.irq_handler(&mut buf);
if result.bytes_read > 0 && result.errors.is_none() { if result.bytes_read > 0 && result.errors.is_none() {
if cx.local.data_producer.vacant_len() < result.bytes_read { if cx.local.data_producer.vacant_len() < result.bytes_read {
ringbuf_full = true; ringbuf_full = true;
@ -128,32 +113,23 @@ mod app {
} }
} }
#[task(shared = [rx_buf], local = [data_consumer], priority=1)] #[task(shared = [], local = [
buf: [u8; RX_RING_BUF_SIZE] = [0; RX_RING_BUF_SIZE],
data_consumer,
tx
], priority=1)]
async fn echo_handler(cx: echo_handler::Context) { 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 { loop {
match cx.local.rx_info_rx.recv().await { let bytes_to_read = cx.local.data_consumer.occupied_len();
Ok(rx_info) => { let actual_read_bytes = cx
rprintln!("reception success, {} bytes read", rx_info.bytes_read); .local
if rx_info.timeout { .data_consumer
rprintln!("timeout occurred"); .pop_slice(&mut cx.local.buf[0..bytes_to_read]);
} cx.local
rx_buf.lock(|rx_buf| { .tx
let string = core::str::from_utf8(&rx_buf[0..rx_info.end_idx]) .write_all(&cx.local.buf[0..actual_read_bytes])
.expect("Invalid string format"); .expect("Failed to write to TX");
rprintln!("read string: {}", string); Mono::delay(50.millis()).await;
irq_uart.lock(|uart| {
writeln!(uart.uart, "{}", string).expect("Sending reply failed");
});
});
}
Err(e) => {
rprintln!("error receiving RX info: {:?}", e);
} }
} }
} }
*/
}
}

View File

@ -222,6 +222,30 @@
] ]
} }
}, },
{
"type": "cortex-debug",
"request": "launch",
"name": "UART Echo with RTIC",
"servertype": "jlink",
"cwd": "${workspaceRoot}",
"device": "Cortex-M0",
"svdFile": "./va108xx/svd/va108xx-base.svd.patched",
"preLaunchTask": "uart-echo-rtic-example",
"executable": "${workspaceFolder}/target/thumbv6m-none-eabi/debug/uart-echo-rtic",
"interface": "jtag",
"runToEntryPoint": "main",
"rttConfig": {
"enabled": true,
"address": "auto",
"decoders": [
{
"port": 0,
"timestamp": true,
"type": "console"
}
]
}
},
{ {
"type": "cortex-debug", "type": "cortex-debug",
"request": "launch", "request": "launch",

View File

@ -122,13 +122,13 @@
} }
}, },
{ {
"label": "rust: cargo build uart irq", "label": "uart-echo-rtic-example",
"type": "shell", "type": "shell",
"command": "~/.cargo/bin/cargo", // note: full path to the cargo "command": "~/.cargo/bin/cargo", // note: full path to the cargo
"args": [ "args": [
"build", "build",
"--bin", "--bin",
"uart-rtic", "uart-echo-rtic",
], ],
"group": { "group": {
"kind": "build", "kind": "build",