xTaskNotifyGive() - feasible with 1 microsecond timer ISR?

Hello,

I have a timer ISR that is generating 1 microsecond “ticks”, this is used for time-dependant events in certain functions. This is working fine, but the code in the function blocks on the timer ISR count variable reaching a certain value (actually, decrementing to zero having started at the required delay value).

I would like to replace these with either direct task notifications or semaphores, to remove the blocking that is burning unnecessary CPU cycles.

My question is, is this feasible given that the interrupt is firing every 1 microsecond? Will the overhead be too much?

thanks
Nick

I think it depends on your processor frequency, but in common uC applications where uC runs slower than 100 MHz, 1 MHz interrupt firing rate is extreme even without an RTOS. What is your application? Maybe there can be another way.

Processor core frequency is 600 MHz (iMX.RT), peripherals obvs. much slower than this. One microsecond interrupt works fine without an RTOS (minimal jitter) - in fact we could go faster, but we don’t need to.

Application is reading data from a slow peripheral, which only needs to be done infrequently (say every 10 seconds.) Reading from the peripheral is slow (hundreds of milliseconds, with several sequential steps required). But despite the above, we need the reading from the peripheral to be reliable and robust. The application also has other, faster tasks running (e.g. TCP/IP stack.)

thanks,

From your description it is not clear why you need a 1us interrupt. What is it doing? Why does it need that resolution?

It’s sampling/driving data from/to an external onewire interface. Normally, you might be able to use the UART hardware peripheral for that but for other reasons that’s not possible here.

And an edge-triggered IRQ with hi-resolution time stamping is also not an option ?
Software sampling a serial interface is really not the optimal solution…
But if there is no other way, unfortunately you have to live with that and burn a good share of the power of your pretty fast MCU for this job.
Good luck !

Hello Nick,

I guess your 1us timer ISR of software onewire driver doesn’t need to call FreeRTOS API every 1us. Is it right? And can iMX.RT use higher priority interrupt than configMAX_SYSCALL_INTERRUPT_PRIORITY?

If so, how about the following method? (I am doing similar method with 32MHz 16bit MCU and 2Mbps RX UART (i.e. almost 5us interrupt interval ) and FreeRTOS. (But it is an RTOS Demo, not a real application…))

(1) Configure your 1us timer interrupt priority higher than configMAX_SYSCALL_INTERRUPT_PRIORITY.
(1’) i.e. ISR for this interrupt cannot call any FreeRTOS API.
(1’’) and this ISR isn’t disturbed by any FreeRTOS’s critical sections
(2) Reserve one interrupt which can be triggered by software.
(3) Configure above software interrupt priority lower than configMAX_SYSCALL_INTERRUPT_PRIORITY.
(3’) i.e. ISR for this interrupt can call FreeRTOS API ending with ‘FromISR’.
(4) When onewire communication finish , trigger the reserved software interrupt from ISR of 1us timer interrupt.
(5) Then ISR of the reserved software interrupt call FreeRTOS’ vTaskNotifyGiveFromISR().

Best regards,
NoMaY

I think these are great solutions, both from @hs2, and from @NoMaY-jp, thank you!

I also implemented “soft” UART’s, using the same methods. The ISR would only register the input values of the input pins, along with a time-stamp.

And for sending data, it will set a PIO during each ISR.

But as for performance, a real, hard-wired USART is preferred. Think also of the maximum deviations, the tolerance.

Adding an update on this: I found a way to get this working using the hardware UART peripheral, rather than software sampling/polling. The timing is a little awkward, and you have to change the baud rate a couple times to get the correct timing but it seems to work OK. An old Maxim app note I found helped.

This means I can use the UART receive interrupt, and the main task can block on receiving queue data from the ISR - much better!

But this does lead onto a follow up question that is more to do with freeRTOS. What is the recommended method for receiving data from multiple ISR’s into one common calling task? The reason for this is we have multiple serial interfaces, and the interface in-use is passed as an argument into the “transmit” task. But there is a separate receive ISR for each interface. I would like not to have the split the sending task up into 3 x separate tasks (the only difference between them is the serial interface #, otherwise they are identical). Is there a way? The current implementation uses queues, but the intention was to replace that with direct task notifications.

thanks!
-Nick

The main options I would see are either:

  • have all 3 sources send into a single Queue (which wouldn’t work if multiple might be active at the same time)

  • Have each ISR send its data into a unique buffer (Queue or just a simple ram line buffer) and if using a Queue, use a QueueSet to wait in the task, or with the ram line buffer use direct to task, with each ISR setting a different bit so the task knows which buffer(s) to process.

I’ve used a simple ring buffer with a associated notification (bit) matching Richards 2nd option.

Thanks both.

Serial interface accesses are always sequential and so a single queue approach seems to be working just fine.