4
votes

Using:

  • Stm32F10x, F2xx, F4xx
  • FreeRtos 8.1.1
  • gcc-arm-none-eabi-4_8-2014q2

I have an ISR which must run with high interrupt priority, so that's forbidden to call FreeRtos Api from within this ISR (see here and here).

In some cases these ISR detects conditions, for which a sleeping FreeRtos task should be waked up with at least possible latency.

Normally (if the ISR was allowed to call FreeRtos Api because of enough low priority) I would use a queue or semaphore to solve this.

But how to realize that with a high priority ISR?

My current interims approach is like this (briefly outlined):

volatile int flag = 0;

void XYZ_IRQHandler() {
    if (someCondition)
        flag = 1
}

void FreeRtosTaskFunction(void* parameters) {
    for (;;) {
        if (flag == 1)
            doSomething();
        vTaskDelay(1);  // sleep 10ms (tick frequency is 100Hz)
    }
}

But this approach has the disadvantages:

  • Latency (from setting the flag in ISR until task wakeup) to is up to 1 FreeRtos tick.
  • Need to poll the flag (waste of cpu cycles).

Any suggestions to solve this in a better way, especially with less latency?

2

2 Answers

2
votes

I have an idea, although not tested seems like it should work.

I am assuming that your ISR is a high priority because it needs an extremely low latency to do something unaffected by other interrupts (i.e., take a measurement at an exact time), and the task should be done quickly, but isn't quite as critical (i.e., transmit or display the value).

In your high-priority ISR, perform the timing-critical function, and then trigger a low-priority internal interrupt.

When the high-priority ISR is complete, (as well as any others pending), the low-priority ISR will be called. This can then call the FreeRTOS API and initiate the task with no further delay.

0
votes

The solution is to use FreeRTOS Task notification.

Your task will pend, then resume/awaken right away upon the ISR event.