diff --git a/examples/rtic/src/bin/uart-echo-rtic.rs b/examples/rtic/src/bin/uart-echo-rtic.rs index 6127467..98e8e4f 100644 --- a/examples/rtic/src/bin/uart-echo-rtic.rs +++ b/examples/rtic/src/bin/uart-echo-rtic.rs @@ -1,12 +1,7 @@ //! More complex UART application //! //! 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 -//! 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. +//! a non-blocking way. All received data will be sent back to the sender. #![no_main] #![no_std] @@ -26,37 +21,29 @@ mod app { use embedded_io::Write; use panic_rtt_target as _; use ringbuf::{ - traits::{Observer, Producer}, + traits::{Consumer, Observer, Producer, SplitRef}, CachingCons, StaticProd, }; use rtic_example::SYSCLK_FREQ; - use rtic_sync::make_channel; + use rtic_monotonics::Monotonic; use rtt_target::{rprintln, rtt_init_print}; use va108xx_hal::{ gpio::PinsB, pac, prelude::*, - uart::{self, IrqCfg, IrqContextTimeoutOrMaxSize, IrqResult, RxWithIrq}, + uart::{self, RxWithIrq, Tx}, }; #[local] struct Local { data_producer: StaticProd<'static, u8, RX_RING_BUF_SIZE>, data_consumer: CachingCons<&'static StaticRb>, - uart_rx: RxWithIrq, + rx: RxWithIrq, + tx: Tx, } #[shared] - struct Shared { - rx_buf: [u8; 64], - } - - #[derive(Debug, Copy, Clone)] - struct RxInfo { - pub bytes_read: usize, - pub end_idx: usize, - pub timeout: bool, - } + struct Shared {} rtic_monotonics::systick_monotonic!(Mono, 1_000); @@ -72,23 +59,21 @@ mod app { let tx = gpiob.pb21.into_funsel_1(); let rx = gpiob.pb20.into_funsel_1(); - let irq_cfg = IrqCfg::new(pac::interrupt::OC3, true, true); 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 mut 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"); + rx.start(); - let (rx_info_tx, rx_info_rx) = make_channel!(RxInfo, 3); - let rx_buf: [u8; 64] = [0; 64]; + let (data_producer, data_consumer) = unsafe { RINGBUF.split_ref() }; ( - Shared { uart_rx, rx_buf }, + Shared {}, Local { - rx_info_tx, - rx_info_rx, + data_producer, + data_consumer, + rx, + tx, }, ) } @@ -103,16 +88,16 @@ mod app { #[task( binds = OC3, - shared = [rx_buf], + shared = [], local = [ - uart_rx, + rx, data_producer ], )] fn reception_task(cx: reception_task::Context) { let mut buf: [u8; 16] = [0; 16]; 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 cx.local.data_producer.vacant_len() < result.bytes_read { 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) { - /* - let mut irq_uart = cx.shared.irq_uart; - let mut rx_buf = cx.shared.rx_buf; loop { - match cx.local.rx_info_rx.recv().await { - Ok(rx_info) => { - rprintln!("reception success, {} bytes read", rx_info.bytes_read); - if rx_info.timeout { - rprintln!("timeout occurred"); - } - rx_buf.lock(|rx_buf| { - let string = core::str::from_utf8(&rx_buf[0..rx_info.end_idx]) - .expect("Invalid string format"); - rprintln!("read string: {}", string); - irq_uart.lock(|uart| { - writeln!(uart.uart, "{}", string).expect("Sending reply failed"); - }); - }); - } - Err(e) => { - rprintln!("error receiving RX info: {:?}", e); - } - } + let bytes_to_read = cx.local.data_consumer.occupied_len(); + let actual_read_bytes = cx + .local + .data_consumer + .pop_slice(&mut cx.local.buf[0..bytes_to_read]); + cx.local + .tx + .write_all(&cx.local.buf[0..actual_read_bytes]) + .expect("Failed to write to TX"); + Mono::delay(50.millis()).await; } - */ } } diff --git a/vscode/launch.json b/vscode/launch.json index eb3034e..77cffe3 100644 --- a/vscode/launch.json +++ b/vscode/launch.json @@ -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", "request": "launch", @@ -428,4 +452,4 @@ } }, ] -} \ No newline at end of file +} diff --git a/vscode/tasks.json b/vscode/tasks.json index 314629e..e5c297e 100644 --- a/vscode/tasks.json +++ b/vscode/tasks.json @@ -122,13 +122,13 @@ } }, { - "label": "rust: cargo build uart irq", + "label": "uart-echo-rtic-example", "type": "shell", "command": "~/.cargo/bin/cargo", // note: full path to the cargo "args": [ "build", "--bin", - "uart-rtic", + "uart-echo-rtic", ], "group": { "kind": "build",