How to reduce event delivery time

saraballi wrote on Thursday, March 26, 2015:

Hi, I have a requirement to perform an operation within 80us of receiving an interrupt. The ISR when triggered will post an event and once the event is delivered to the waiting task, it has to perform the operation within 80us. This is the only task in the system.
I see that there is a delay in this event delivery by about 4-5 microseconds with FreeRTOS as compared to a NO-RTOS scenario. This fails the next operation which has to start within 80us.
Is there a way to speed up the event delivery?
I am using this on LPC1769 (Cortex M3) and have already used portYIELD_FROM_ISR() after xEventGroupSetBitsFromISR() in the ISR.


davedoors wrote on Thursday, March 26, 2015:

5 microseconds is only a small percentage of your 80 microsecond deadline. Even if you could drop it to 2 microseconds its not going to make much different to your overall timing. Are you sure you are targeting the right area in your optimization?

xEventGroupSetBitsFromISR() is going to be the slowest method you could use because it needs a switch to the timer task, then a switch to your app task. This way will be much faster

heinbali01 wrote on Friday, March 27, 2015:

Hi Santosh,

Same thoughts as Dave: you might want to compare different ways of setting an event from your ISR:

BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue,
    eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );

BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore,
    BaseType_t *pxHigherPriorityTaskWoken );

Dave is right that event’s are less useful/efficient when used from an interrupt:

BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
    const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );

Event-groups are very efficient and handy when used among different tasks. Like Queue’s, they can have many “givers” and many “takers”, each with different priorities.
FreeRTOS+TCP uses Event-groups to implement API calls (and more). As soon as an API call has been handled by the library, an event bit will be set to wake-up the caller.

And of course, you’ll have to avoid long-lasting critical sections, during which your ISR is disabled (and thus delayed).

Is your task always in a blocked state? Or is it doing other things as well?

Flash versus SRAM: The LPC1769 has a fast internal flash. I don’t know if moving the ISR code to SRAM would still make it faster. You could give it a try.

I think that you will get the latency down to below 1 uS.


saraballi wrote on Sunday, April 05, 2015:

Thank you Dave and Hein for your responses. While I will try to use direct task notification APIs, increasing the configTICK_RATE_HZ from 1K to 2K has given the desired performance. In the system we have this one external interrupt that is delivering the events to the high priority task. Other tasks in the system will be of lower priority and will interact with this high priority task and not with any external components.
In this situation, is increasing configTICK_RATE_HZ a good option and what are the pitfalls if any?

rtel wrote on Sunday, April 05, 2015:

is increasing configTICK_RATE_HZ a good option

In general terms it is not recommended to have such a high tick
frequency because it means more time will be spent processing tick
interrupts - but like all things it is very much dependent on the
application being created.


richard_damon wrote on Sunday, April 05, 2015:

In my opinion if raising configTICK_RATE_HZ is helping, something is misconfigured. The response time to switch to a new task has nothing to do with the tick rate unless some interrupt is unblocking a task and then not activating the scheduler, leaving it to the tick hook to do the switch.

The needed tick rate is controlled by the precision needed in timeouts and delays, which I find rarely are as tight as 1 ms.

saraballi wrote on Monday, April 06, 2015:

Hi Richard, W.r.t the configuration, I guess it is configured right. With ConfigAssert turned ON I dont see any warnings. Is there anything else I should look at?
I have only this task in the system running at priority 2. The timer daemon task is set to priority 1.

On using direct task notification APIs instead of xEventGroupSetBitsFromISR, I see it consistently keeps looping within the for (;:wink: loop of portTASK_FUNCTION() function and the control never returns to my task.
Any particular reason for this?


rtel wrote on Monday, April 06, 2015:

Are you clearing the interrupt in the ISR? If you don’t clear the
interrupt then it is likely the interrupt is continuously being re-entered.

saraballi wrote on Monday, April 06, 2015:

Yes. The interrupt is cleared in the ISR