Hello,
I'm still a beginner at FreeRTOS and I have too much to learn yet. So, I apologize for the simple questions...
I'm playing with my FRDM-KL25Z in KDS and created a new project with KSDK v. 1.3 and Processor Expert to see how a mutex works in FreeRTOS.
I have 6 tasks of same prority level which compete for the same mutex. Between taking and giving the mutex, each task increments a global variable (one different variable for each task).
As far as I know, when a mutex is realeased, it gets available for the next task waiting for it and this task, which just released (gave) the mutex, is blocked as it tries to take the mutex again in its while loop. Am I right?
But, that is not what I see as I debug the code. The variable is incremented several times before it yields to the next task, instead of being incremented just once.
The only way to get a task imediately yielding to another one is adding a "Task_Yield" or a "Time_Delay" after "Semaphore_Give". Curiously, the FRDM-K64F FreeRTOS mutex demo project in KSDK v. 2 puts a Task_Yield after "Semaphore_Give". But, that doesn't make any sense, because it is as if the mutex there is useless.
Why this is happening? Can anybody throw me a light on this please?
Thanks and best regards,
Marco Coelho
Applications Engineer
Siletec Eletronica
Hi, Marco,
Regarding your above code, I do not think the FreeRTOS can guarantee that the variable cont_a only increment only once if all the tasks have the same priority. but if you add taskYIELD(); after the xSemaphoreGive(xMutex);, the OS can guarantee that the the variable cont_a can increment only once, because taskYIELD() can guarantee the task context switching.
BR
Xiangjun Rong
Dear Xiangjun,
I was thinking about it, and it seems to me that when there are several tasks of same priority level, the current running task is only blocked when a blocking function is executed like "Time_Delay" or "Task_Yield". In my case, the current running task gives and takes the same mutex and ends up being blocked by its own timeout. Am I thinking correctly?
Unlike binary semaphores, the mutexes are made available for all the tasks as they are created. Semaphores are made available only if they are given before through "xSemaphoreGive" function and you can give it in a task and take it in another task. Right?
So, this really make semaphores a more efficient way to syncronize tasks, rather than mutexes, since you can combine different semaphores among the tasks to make the syncronization as you need.
I think I got to the point now.
Marco Coelho
Hi, Marco,
I think you have to add the taskYIELD(); after the xSemaphoreGive(xMutex); so that FreeRtos can give up the current task explicitly.
The xSemaphoreGive(xMutex); just means that xMutex variable is in unlock state, the other task blocked with xSemaphoreTake() has opportunity to run, but it does not means OS releases current task necessarily.
Hope it can help you.
BR
Xiangjun Rong
Dear Xiangjun,
Thanks for your attention!
If all the tasks have the same priority level and the current task's code is like that:
while(1){
xSemaphoreTake(xMutex);
cont_a++;
xSemaphoreGive(xMutex);
}
So, the task should increment the variable only once and be blocked as "xSemaphoreTake(xMutex);" is executed. Shouldn't it?
Hi again, David
I just made new tests replacing the mutex with a binary semaphore, but the same problem as I reported above remains.
Hi Marco,
Not an expert with FreeRTOS either but you might want to try using a binary semaphore:
It goes on to say "Binary semaphores and mutexes are very similar but have some subtle differences: Mutexes include a priority inheritance mechanism, binary semaphores do not. This makes binary semaphores the better choice for implementing synchronisation (between tasks or between tasks and an interrupt), and mutexes the better choice for implementing simple mutual exclusion."
Regards,
David
Dear David,
Thanks for your attention again!
That still doesn't make sense to me, because if the mutex has the same features as the binary semaphore. The difference is that the mutex works in priority inheritance scheme, but this doesn't cause any problem at all, because, as the mutex is released (given), the next task waiting for it is supposed to be made active.
I payed a little more attention in debugging and notice the the execution order of the tasks is right: the task which is waiting the mutex the longest is the task which runs. In our case, at the first run time, the task which waits the longest is that which was first created, since all the task are at the same priority level.
But, before yielding to the next task, the variable is incremented several times, that is, it runs in the loop several times, as if it is blocked by timeout and not by the mutex.
I checked it out and I could see the mutex was successfully created in main_task.
Have my code attached for FRDM-KL25Z. It is quite simple.
Marco Coelho