Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

Block task waiting for flag change

Posted by Ella on December 1, 2012
Hi,
What is the best way to block task waiting for bit change. In my specific case I want to wait for RX_DONE flag from UART. So actually I want to block while( !(RS_STATUS & RX_DONE) ).

1. I understand that I can write an Interrupt handler and use a semaphore to block/unblock task
2. I can make polling

But I would prefer the scheduler to poll for RS_DONE bit without context switch. (This is what I've done in my own OS used on 8-bit AVRs). Now I'm starting to work with STM32 ARM Core. I've read FreeRTOS documentation and did not find a way to block task waiting for bit set/cleared or value zero/non zero. Not sure it is possible at all in Free RTOS but I think such feature can be very efficient for non time critical events like UART for example (when processing can be relatively slow considering huge difference between baud rate and FreeRTOS tick).

3. Last option that come to my mind is to implement semaphore for blocking and poll for bits in Idle Task giving a semaphore to unblock waiting tasks. This will prevent context switch to blocked task for polling and considering the fact that IdleTask is running anyway there would be no extra context switches at all.

What do you think?


RE: Block task waiting for flag change

Posted by Dave on December 1, 2012
The normal way is to signal the task from an interrupt.

How can an RTOS know about a bit change in a register it knows nothing of unless it polled the register itself? If the RTOS is going to poll the register then the application may as well poll the register. If you really want a function that does nothing but poll an address waiting for a bit to change then you could easily write your own function that took the register address and the bit mask as parameters.

RE: Block task waiting for flag change

Posted by Richard Damon on December 1, 2012
The proper way to detect this sort of I/O change in a program with any sort of real time requirements (which would be why you are using a Real Time Operating System) is to us an interrupt handler. This way you find out about the event very shortly after it occurs and not possibly 10-100ms after the event occurs if you place it somehow into the tic processing.

Specifying the details of HOW the RTOS is to detect the change is not a trivial matter, as the word size of the access may be important, which bits to look at need to be specified, and maybe something else needs to be do to make it work, so it really requires that in general you will need to provide a piece of code to the kernel to run the test, at which point it is simpler, and not that much less efficient, to just have the task do the test itself and wait in a loop doing the test and a vTaskDelay(1).

RE: Block task waiting for flag change

Posted by Ella on December 2, 2012
Got your replies. In general I agree with you except one thing. The difference between polling task and polling inside RTOS (actually it will be inside scheduler) is an extra context switch to the polling task.

In my own RTOS I had a fields in task state table that provided me an option to block task on bit/byte/word change. Scheduler was checking for required condition. It is not that complex as all you need is a number of flags, address(es) and compare values or bit mask.
Actually semaphores queues are something similar. Both are polled by in scheduler. And context switch is made only if required condition is reached.
There is an option to have a hook in scheduler to let user provide it's own function that will decide weather unblock task or not.
Anyway if it does not exist there is nothing to do. Maybe in future someone will think about it and will implement something.

Well I do not like to have an Interrupt in cases when it is not really required. In my project I must deal with a number of UARTs running at 9600 that gives about 1ms per byte.
> This way you find out about the event very shortly after it occurs and not possibly 10-100ms after the event occurs
>if you place it somehow into the tic processing.
On a CPU running at 120MHz I can definitely get latency less then 0.1ms or less. So polling is not so bad I think. Also I still keep in mind an idea of having polling in idle task.

RE: Block task waiting for flag change

Posted by Richard on December 2, 2012
“Actually semaphores queues are something similar. Both are polled by in scheduler.”


That is not how semaphores work at all. The scheduler does not poll anything. Context switch times would be unacceptably long if it did.

Regards.

RE: Block task waiting for flag change

Posted by Ella on December 2, 2012
Anyway at some point scheduler takes decision of passing the task from suspended to running state. I'd like to have a hook at the point of this decision where I could check my own conditions and return a reply to scheduler about my own decision.

Otherwise I can only use interrupts or poll from task itself. I do not want to write interrupt handler at all. I do not care a bout few extra ms latency. Poling is also a costly.

RE: Block task waiting for flag change

Posted by Richard Damon on December 2, 2012
"On a CPU running at 120MHz I can definitely get latency less then 0.1ms or less. So polling is not so bad I think. Also I still keep in mind an idea of having polling in idle task."

Doing the polling in the idle task means that BY DEFINITION the detection is considered the lowest priority event in your system and if ANY task is using the CPU, you will not detect the event. If not done in the idle task, then it would be on the timer tick, and that should normally be a relatively low frequency or you are wasting a lot of CPU power as every timer tick causes a full context switch to run the scheduler.

Also, Interrupts are NOT something to avoid if they provide information about events that you need to process, they are your friend. You will lose less CPU power processing the interrupt than you will lose in you poll loop and the changes you need to do to make sure the polling happens in a timely manner.

The difficulty in specify a polling method to the scheduler comes in the multi-platform support. For some uses, the read might NEED to be done as an 8 bit read, and doing a 16 or 32 bit read would not work, for others it might need to be 16 bit, and others it might need to be 32 bit. Should the API also support 64 bits?, how about 128? While for a give machine it may be obvious what sizes to support, FreeRTOS is a multi platform system which tries to provide the SAME API to all machines.

Then what happens if to read a port value another port needs to be set first? (not unheard of for some machines). At that point you really start to need to call back to user code to do the check.

Note that FreeRTOS does support hooks that allow you to add this sort of check in either the idle loop or the timer tick, so you could add the "polling" test and signal the task if the hardware can not generate an interrupt for what you want to test.

Richard said, semaphores/queue are NOT polled. The act of putting data/signaling that object causes it to see if a scheduling event should happen THEN, not waiting for a "polling" cycle.

RE: Block task waiting for flag change

Posted by Richard Damon on December 2, 2012
znatok,
The scheduler does NOT go down the list of tasks that are suspended trying to figure which ones are to become ready. Tasks which block are placed on lists of things that will activate them, either by time expiring or an object activated. Only when the specified event happens does the task wake up. A task that is suspended is ignored by the scheduler until something makes a call to unsuspend the task.

RE: Block task waiting for flag change

Posted by woops_ on December 2, 2012
“I'd like to have a hook at the point of this decision where I could check my own conditions and return a reply to scheduler about my own decision.”


You can assign a function to every task. See http://www.freertos.org/xTaskGetApplicationTaskTag.html. You can also have hooks on task in and task out. See the trace macros. I dont think it helps you because what are you going to do if you find the task is still polling? If the RTOS decides to select your task and the hook says no then the scheduler has to select another task. I mean it happens after the task is selected not before. So you are no better off than doing the polling in the task, for example

while( bitNotSet ){
taskYIELD();
}

When the rtos runs the task the task immediately yields to another. This happens after the task is selected as well so is no better or worse than the rtos doing it. It will be a problem if the task is not the lowest priority, then you would need vTaskDelay(1) instead of yield but you get bad resolution.

RE: Block task waiting for flag change

Posted by Ella on December 2, 2012
"Note that FreeRTOS does support hooks that allow you to add this sort of check in either the idle loop or the timer tick, so you could add the "polling" test and signal the task if the hardware can not generate an interrupt for what you want to test."

Did not see it in API document I've purchased. Can you help me to find it.


"Also, Interrupts are NOT something to avoid if they provide information about events that you need to process, they are your friend. You will lose less CPU power processing the interrupt than you will lose in you poll loop and the changes you need to do to make sure the polling happens in a timely manner."

In my situation I have a number of low latency events that has to and actually are processed in interrupts. And another events that are not latency critical. If I would process non critical events in interrupts I can prevent critical events from being processed at time. (I know I can use interrupt priorities and nesting interrupts but it is not always possible). So I think it is a waste of time to use interrupt handler just to release semaphore for non time critical events. Also consider that interrupt handlers written in C are not so efficient. Writing handler in assembler in case it is not required not a best idea.


RE: Block task waiting for flag change

Posted by Ella on December 2, 2012
> You can assign a function to every task. See http://www.freertos.org/xTaskGetApplicationTaskTag.html.
Not sure how tags should help me.

OK. I get your point. Scheduler is no going over task list deciding which task to run but instead it takes next task from ready to run list. So actually I need to prevent task from being putted into ready list. In my case event that will put my task into ready list is timer tick. So I need a hook to timer tick processing just before kernel decides to put task into ready list. Ideally would be something like this:

int hook()
{
if( flag $ bit )
return 0; /* OK to run task */
else
return SOME_TIME_TO_CONTINUE_WAIT;
}

task()
{
set_hook ( hook );
while(1)
{
vTaskDelay( SOME_TIME )

/* Process Event */
}

After SOME_TIME has passed tick handler will attempt to put task into running list and here it should ask hook if it should be done or not. If hook return 0 task will be placed into run list. Otherwise task should delay more SOME_TIME_TO_CONTINUE_WAIT ticks.

RE: Block task waiting for flag change

Posted by Richard Damon on December 2, 2012
> In my situation I have a number of low latency events that has to and actually are processed in interrupts. And another events that are not latency critical. If I would process non critical events in interrupts I can prevent critical events from being processed at time. (I know I can use interrupt priorities and nesting interrupts but it is not always possible). So I think it is a waste of time to use interrupt handler just to release semaphore for non time critical events. Also consider that interrupt handlers written in C are not so efficient. Writing handler in assembler in case it is not required not a best idea.

Interrupt handlers should NOT "process" events, but record and signal. They do the minimum needed to satisfy the hardware condition and then pass off the rest of the processing to a task that will run in priority order. An interrupt handler in a RTOS situation shouldn't take more than a few microseconds to get the information and then return. If you really look at timing, the signal a semaphore and return is really the best option. The "inefficiency" of C in this case isn't significant.

If you really have events that can't tolerate the microseconds of delay, then you NEED to use nested interrupts, as you are going to get that sort of delay just from the timer interrupt.

For your case above, I would have the task not stop on a vTaskDelay() but wait on a semaphore. Then it the vApplicationTickHook (after adding #define configUSE_TICK_HOOK 1 in your config file) test the bit and if set signal the semaphore with xSemaphoreGiveFromISR(). (I actually would use an interrupt routine triggered by the bit if possible).


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS