Maybe a long shot, but what happens if you take out the calls to
printf()? Fist just from ‘other task’, which may get deleted before all
the output has been output (depending on how printf() is implemented),
and second removing printf() from all tasks.
Disabling all Prints from all over the code didn’t help. I am using Segger RTT for prints. So I disabled it all together. It seems there is something special about deleting that first ever task.
If I kill that dummy task as well (along with other_task), I see the problem again. So it seems one of those tasks created in the beginning must stay in the task list.
I think RTT is just the output method. Did you actually comment out the
calls to printf()? Otherwise it will make little difference to the
libraries being called by printf(), and the stack used by printf(), in
order to prepare the string that will be output.
In the printf function, I just returned without calling any functions thus effectively bypassing any calls to the functions. Individually commenting out each print statment would be a lot of statements to comment out…
Something like:
int p_printf(const char *format, ...)
{
return 0;
if (xSemaphoreTake(printf_mutex, 3000) == pdFALSE) {
return -1;
}
va_list args;
va_start(args, format);
int loglen = vsnprintf(LOG_BUFFER, LOG_BUFFER_SIZE, format, args);
va_end(args);
int ret = SEGGER_RTT_Write(0, LOG_BUFFER, loglen);
xSemaphoreGive(printf_mutex);
return ret;
}
**If dummy taks isblocked for more than twice the expiry time of the fastest timer, the GPIO interrupts will cause all timers to start expiring sooner than the scheduled expiry.
**
One thing to note that may help. If a timer is due to expire every
10ms, and it is blocked from running for 30ms, then it will execute 3
times in quick succession to ‘catch up’ with where it should have been.
That can make it look like all of a sudden it is running too quickly -
whereas in reality, once it is caught up with itself, it will return to
its proper frequency.
I don’t think that is what is happening in this case, so just something
to be aware of.
There has to be atleast one task in the Running state. If all tasks are blocked, GPIO interrupts will cause timers to start expiring before the scheduled time
I removed the dummy task I created and I put a loop at the end of the inittask so that the init task never ends. This fixes the problem because now I have at least one task (inittask) which is in Runnign state while all others are in blocked state.
This is what changed at the end of the inittask:
// vTaskDelete(NULL); <--- Commented this so this task doesn't end
while (1) { <--- Kept it running for ever
vTaskDelay(10);
}
} /*end of inittask*/
I am testing it now to make sure it stands the test of time… I will let it run for a while.
Interesting. So if it exectues three times in a succession, all the logic around it will execute three times as well. That would be a disaster for some applications.
Also, will a GPIO interrupt cause the timer to be blocked for the duration of the ISR execution causing the above behavior?
Interesting. So if it exectues three times in a succession, all the
logic around it will execute three times as well. That would be a
disaster for some applications.
Likewise it would be a disaster for some applications if it is supposed
to execute three times within a given period and in fact it only
executes once. Or if it missed its deadline by a single tick, so opted
not to execute. Executing exactly the required number of times seems
the best option.
Also, will a GPIO interrupt cause the timer to be blocked?
Only if the interrupt too a verrrrry long time to execute, or if the
interrupt was not cleared properly so was continuously being re-entered.
It looks like your interrupt is being cleared - assuming the code in
your post is correct - though.
There is ALWAYS a task in the ready to run state, as the Idle task that is automatically created will never block (and if you enable the idle hook, you must not block in it).
Your inittask above isn’t in the ‘Running’ state for most of its time, as it is blocked with vTaskDelay().
A task that deletes itself will have its final clean up defered to being done in the idle task.
Some thoughts that pop up:
Are you using the idle hook?
Are you using tickless idle? Having a task aways ready to wake up soon can block going into tickless idle, and if tickless idle isn’t setup right, it could throw off your time base.
WFI stopps the processor until an interrupt comes. This can save power. It shouldn’t normally cause issues, as if you are in the idle task, there isn’t anything else to do, but wait for some interrupt.
The possible issue with tickless idle is that something isn’t configured right. In tickless idle, if the kernal sees that nothing will be needed to be done for awhile, it reconfigures the system to stop interrupting every tick, but to go to sleep for a longer period of time, until an interrupt occurs or that long period of time expires. If it gets woken up by an interrupt, it then needs to figure out approximately how much time has expired by looking at the timer it setup and then advance time by that much. This process is NOT exact, and there can be some time slipage, and I think the tick hook may get called repeatedly (if you are using the tick hook, you may not want to use tickless idle). If you have some of the hardware configured differently than FreeRTOS is expecting, this time estimate could be off more signficantly.