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.