100 microseconds interval

maxciu wrote on Tuesday, November 03, 2015:


I am a relatively new OpenRTOS user and so far I’m amazed by the possibilities it offer you when dealing with a larger embedded project. However, I got into a problem and would like to ask for some advice on the best way to handle it.

I am trying to implement a CAN based communication protocol and part of it is to send streams of CAN messages separated by time intervals of 100uS. It is ok if the interval is a bit longer, but it should never be shorter than 100uS. I am running an ARM Cortex M4F at 120MHz and my OS ticks are set to 1000Hz.

One of the first solutions I thought about was to increase the tick rate to 10kHz and use vTaskDelay(1) to create the intervals, while giving the other tasks a chance to run. However, I’ve read that it’s best to avoid such high tick rates, due to the context switching delays.

A second solution would be to give my task a higher priority and use a while loop to wait for the 100uS interval. However, this would prevent other tasks from running and this could be a real problem if the message sequence is longer.

The third option would be to block the task with a semaphore as soon as it finishes sending a message. The semaphore would be released in a hardware timer ISR after 100uS. However, I wasn’t able to get the task to wake up multiple times during a tick period. I tried using the xSemaphoreGiveFromISR function follwed by a taskYIELD if the woken parameter gets set, but my task was still executed only once per milisecond.

Do you have any ideas about this problem? I feel like there should be a way to get it done nicely, but I am missing something.

Thank you!

rtel wrote on Tuesday, November 03, 2015:

If you are an OpenRTOS customer then you, or one of your colleages, should have a login to the support ticketing system where you can get private support. I would suggest posting your question there.

maxciu wrote on Tuesday, November 03, 2015:

Thanks for the suggestion. We are in the phase of considering if FreeRTOS would fulfill our needs, which is why we do not have a membership yet. It occured to me that the dilema I have might be a limitation of the OS, so I was trying to figure that out first.

Any feedback or ideas would be greatly appreciated.

heinbali01 wrote on Tuesday, November 03, 2015:

Hi Max,

OpenRTOS is outside my expertise, but if you were to implement the above task in FreeRTOS:

I would go for the third option: program one of the TC’s (Timer-Clock).

I tried using the xSemaphoreGiveFromISR function followed by a taskYIELD

Shouldn’t you use a FromISR variant of taskYIELD ? Something like portYIELD_FROM_ISR() ?

if the woken parameter gets set, but my task was still executed only once per millisecond

Strange, it should be able to wake-up much more often between 2 clock ticks. It sounds like the YIELD_FROM_ISR() has not succeeded.

Here is a solution which uses the (cheaper) task notification (although it should work equally well using a semaphore).

void tc_interrupt()
    BaseType_t xHigherPriorityTaskWoken = psFALSE;
	/* Stop further interrupts to avoid time period shorter than 100 us. */
    vTaskNotifyGiveFromISR( xCANTaskHandle, &xHigherPriorityTaskWoken );
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

void vCANTask( void *pvParameter )
    for( ;; )
        /* Program the TC to issue an interrupt after 100 uS. */
        tc_start_interrupt( 100 );
        /* Will be woken-up by the timer-counter.
        ulTaskNotifyTake( pdTRUE, portMAX_DELAY );


maxciu wrote on Tuesday, November 03, 2015:

Hi Hein,

Thanks for your message, that worked like a charm!
I was indeed using the regular taskYIELD instead of its ISR specific version (portEND_SWITCHING_ISR in my case).
Is there a way to rank up your answer?


heinbali01 wrote on Tuesday, November 03, 2015:

that worked like a charm!


Is there a way to rank up your answer?

Haha, there is not.

Remember that most FreeRTOS API calls can not be called from an ISR. That has to do with locking / critical sections, and certain assumptions that the code makes. Quite often your application will just crash if you forget to add the ‘FromISR’ addition.

Look at these couples:

A. xSemaphoreGive( xSemaphore );
B. xSemaphoreGiveFromISR ( xSemaphore, &xHigherPriorityTaskWoken );

A. xTaskNotifyGive( pvTaskHandle );
B. vTaskNotifyGiveFromISR( pvTaskHandle, &xHigherPriorityTaskWoken );

The normal versions will call taskYIELD(). If the API unblocks a higher-priority task, that task will start running before the API call finishes.

The xxxGiveFromISR() functions will never yield. It would be meaningless to yield because they are called from an interrupt. Normally an ISR ends with a short instruction like “iret”. This pops the registers from stack, including the program counter PC, and it returns to the task that was active just before the ISR was called.

Now your ISR makes a task ‘runnable’ and in stead of just returning, it wants the scheduler to check if another task should start running now. That is the function of portYIELD_FROM_ISR().


maxciu wrote on Tuesday, November 03, 2015:


I was actually wondering about the difference between the regular and ISR calls, so thanks a lot for clearing it up for me.

Have a great day