rtic-rs / rtic

Real-Time Interrupt-driven Concurrency (RTIC) framework for ARM Cortex-M microcontrollers

Home Page:https://rtic.rs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Software/Hardware Task interfaction with RTIC v2

robamu opened this issue · comments

Hello,

I am trying to migrate a project to RTIC v2.
I managed to make everything compile now, but I am looking for a way to replace a feature which is not there anymore.
I have a serial UART ISR handler function like this:

    #[task(binds = USART2_EXTI26, shared = [rx_transfer, tx_transfer])]
    fn serial_isr(mut cx: serial_isr::Context) {
        /* ... Some stuff ... */
        // serial_tx_handler::spawn_after(MsDuration::from_ticks(
        // MIN_DELAY_BETWEEN_TX_PACKETS_MS.into(),
        //))
        //.unwrap();
        // TODO: We actually need the delay here.. how do we do this?
        serial_tx_handler::spawn().ok();
    }

I want to spawn a regular software task from that ISR after a delay. My understanding is that I still need to keep the ISR as short as possible, so I do not want to delay there. What is the cleanest or intended way to do this with RTIC v2?

One option I considered was to simply put a delay as the first thing in my serial_tx_handler at the start. If that delay is to be optional, I could share something like a boolean inside the shared tx_transfer struct. Is this a viable way or are there better alternatives?

A solution which compiles ( I can't test it because of unrelated linker errors):

    #[task(
        shared = [tx_transfer],
    )]
    async fn serial_tx_handler(mut cx: serial_tx_handler::Context, init_delay_ms: u32) {
        Systick::delay(init_delay_ms.millis()).await;
        ...
    }

then I call serial_tx_handler::spawn(0) in my init and serial_tx_handler::spawn(20) in my ISR.

While it was possible to spawn the task inside the ISR, this is not really a valid approach anymore because all software tasks are running inside a loop now. This means that I do not spawn the task inside the ISR anymore but modify a shared state machine to notify the software task of task completion. The software task will then simply run at a higher frequency while it is waiting for the transfer completion. An example or explanation inside the documentation might still be useful, I think the general flow or starting a DMA/Interrupt driven transfer inside a software task, waiting for completion via a hardware task/interrupt, and post-completion handling inside a software taks is something common for embedded systems.