I am new to FreeRTOS and to this forum, and I do not know, if I am right here with the problem.
But I am found a problem.
I create tasks and suspend them all right after creation.
If there are only two tasks, first is suspendet, and second one unsuspends the first one, everything is ok.
But if I create three tasks, first two are suspendet, and in a third one unsuspends the two first taks, then there is an error.
And it happens after creating the second task, and on trying to suspend this. And the error occurs in a vTaskSwitchContext function, at line 1629 (version 6.1.1 of FreeRTOS) when the variable uxTopReadyPriority is overrolling without to check it.
I did add the check, if it is == 0, then break the while loop, and the program goes further.
I create tasks and suspend them all right after creation.
Are you creating then suspending before the scheduler has started or after the scheduler has started?
Are the tasks suspending themselves, or being suspended by another task. What are the relative priorities of the tasks?
If there are only two tasks, first is suspendet, and second one unsuspends the first one, everything is ok.
The first is suspended, then unsuspended by the second, it works……so the first starts running once it has been unsuspended. Ok.
But if I create three tasks, first two are suspendet, and in a third one unsuspends the two first taks, then there is an error.
So task one and task two are in the suspended state (do they suspend themselves? is the scheduler already running when this happens? Are you sure they are actually suspended?)
And it happens after creating the second task, and on trying to suspend this. And the error occurs in a vTaskSwitchContext function, at line 1629 (version 6.1.1 of FreeRTOS) when the variable uxTopReadyPriority is overrolling without to check it.
Can you provide a very simple/basic example to help me understand the scenario you are describing?
I got this problem of the underflowing of uxTopReadyPriority value (i.e the value of uxTopReadyPriority became negative and kept decrementing)
In the end I used a work around by:
1) Creating all tasks that runs in the system.
2) Create a TaskSuspender Task and set it to the highest priority (this Task is meant to be the first Task to run and will suspend all other Tasks). At the end of this Task, suspend itself by invoking vTaskSuspend(NULL);
3) Invoke vTaskStartScheduler();
This lets the TaskSuspender suspend all other Tasks before anything happens and the IDLE Task will be running.
This lets the TaskSuspender suspend all other Tasks before anything happens and the IDLE Task will be running.
Hope it help.
Not really. My questions were intended to allow me to try and replicate the problem, and see if there is a problem. I cannot look at the issue, assist you, or comment until you answer the questions or provide me with the code.
Apologies tacadia - in my last reply I was assuming posts 1 and 4 in this thread were from the same person. I have just realised they are not.
With regards to suspending tasks before the scheduler has been started, which from the posted code it looks like tacadia is doing - it is good to know that it is working fine in V7. The ability to do that was only introduced in V6.1.0, so, if previously, you were using a version earlier than that, then I would not expect it to have worked.
richardbarry: Hey no worries (: Just glad to be able to help (:
masteralexei:
I’m not in my lab to do the code walks and tests for now, but my suspicion is 2 folds:
(1) ensure that your vMainTask is really the first one that is running. For an absolute certainty, raise vMainTask’s priority to be higher than that of the other 2 Tasks.
(2) Ensure that you have enough xHeap space for memory allocation of the Tasks as well as enough Task stack space. During a context switch, the context of the Task will be pushed onto the Task Stack. You can check your memory map for this (:
1. Well, the priority are the same by all three tasks. But after creation of first two, they are immediately suspended (Scheduler is not yet runung).
Only the last one is not suspended. I think, that if the task suspended, it will not be running, even if the task has a higher priority.
So. And as I have seen, the last created task started as first one, if all tasks are having the same priority. Or am I wrong here?
2. I think that 10 MegaBytes of Heap are enough for tree tasks
And one more,
The bug occurs BEFORE the scheduler stared, but during the call of vTaskSuspend for the second one in my example.
the last, third task is even not yet created. That means, that there is already one task created and suspended, and another task created too, and is to suspend.
Ok - I have just had a look at this, and can confirm that there is a bug. Here is the tracker I have just opened which documents a simple work around for the time being. Thanks for bringing this to my attention - and congratulations for finding the first genuine bug in absolutely ages and ages! This relates to a piece of code that was only added recently, and highlights a case that, obviously, was not tested satisfactorily.
In the function vTaskSuspend(), if you replace the line (this is from FreeRTOS V7.x.x, and V6.x.x will probably not have the ‘U’ after the ‘1’):
/* The scheduler is not running, but the task that was pointed
to by pxCurrentTCB has just been suspended and pxCurrentTCB
must be adjusted to point to a different task. */
if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1U )
with the following code:
/* The scheduler is not running, but the task that was pointed
to by pxCurrentTCB has just been suspended and pxCurrentTCB
must be adjusted to point to a different task. */
if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
…then you should find the problem fixed. Please let me know if you still have a problem after this change.
After made the changes, that you suggest, it works!
But I think, that it still would be nice to have that check in “while” loop in vTaskSwitchContext function. So it is safer, I think.
But I think, that it still would be nice to have that check in “while” loop in vTaskSwitchContext function. So it is safer, I think.
That code runs very often and has to be optimised, otherwise people will complain, a lot. Also, having that check in would have simply hidden the problem that you found - two wrongs making a right as it were, or at least appearing to.
FreeRTOS V7.0.0 does however have an assert in the loop thus:
Richard,
This discussion brought up a thought for me. Currently FreeRTOS creates the idle task last, and failure to create that is fatal to starting the OS. It appears that there may also be parts of the code that assume that there is always some task to be scheduled. Would it make sense to change the creation of the idle task from the last task created to the first?
This would mean that starting the schedule is much less apt to fail, and a failure to create the idle task could be reported as a failure to create the first user task. It would also make the condition of always being a task ready to run true once any task is created, as opposed to only true once the system is stated.
If you go back far enough in the history I think (from memory) the idle task used to be created when the first task was created. It was later changed to instead be created when the scheduler was started. I can’t remember why now, it was many years ago. The reason might be given in the change log, but it probably pre-dates the current SVN repository.
Only very recent versions of FreeRTOS have had the ability to suspend a task before the scheduler is started - the ability was added due to multiple requests from users. When the scheduler is running there must always be a task ready to schedule (hence the idle task must never block), but prior to the introduction of this new ability there was not the same requirement before the scheduler was started.
This is a follow up on our issues presented in this thread.
I have done the patch as you’ve suggested and yes, it doesn’t hang anymore. When I did more tests, I found out that the issue in the original code that causes the uxTopReadyPriority to underflow will arise from the following sequence of execution:
When Task2 is created, uxCurrentNumberOfTasks has incremented to 2. However, with the old code, of:
/* The scheduler is not running, but the task that was pointed
to by pxCurrentTCB has just been suspended and pxCurrentTCB
must be adjusted to point to a different task. */
if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1U )
{
/* No other tasks are defined, so set pxCurrentTCB back to
NULL so when the next task is created pxCurrentTCB will
be set to point to it no matter what its relative priority
is. */
pxCurrentTCB = NULL;
}
else
{
vTaskSwitchContext();
}
This causes the vTaskSwitchContext() to be invoked. When this happens, the while loop code: