Your text is generally clear, but I’ll provide some grammatical improvements for better readability:
I am using FreeRTOS on Arduino Mega with the Arduino IDE and supported libraries. I am creating a very simple program with two tasks of different priorities. I have the following questions:
- Are the
loop() functions considered as one task with priority zero?
- Do I need to have at least one task in the Ready state for the program to work? I ask this because if I put a
delay() in both the created tasks and delete the
loop() task, then my program runs into an exception. The same thing happens if I include a delay in all the tasks, including the
- Lastly, when I do not include a delay in the lower priority task, it is scheduled over and over again infinitely, not giving a chance to even the higher priority task when it is unblocked after
vTaskDelay(). This seems wrong, as the higher priority task should preempt the lower priority task even if it is continuously active.
PS: Earlier, I have used ESP32 with FreeRTOS, and it never gives an exception even when all the tasks are blocked on a timer. Also, a higher priority task can preempt a continuously running lower priority task when unblocked.
Thanks for any help on this.
I don’t know the Arduino well, but my expectation would be that setup() is called before the scheduler for FreeRTOS is started, and would not be a task.
loop() would be part of a task, and if having it block causes a fault, it may be implemented as an idlehook, and is called from the Idle Task, which is not allowed to block. The idle task is also not allowed to delete itself.
If you are not getting higher priority tasks to run without doing a blocking operation, it may be that your configuration has disabled pre-emption. This creates that sort of issue, but does remove a lot of “races” and timing issues in the code, as you don’t need to worry about task changes which could other wise be almost anywhere.
Can any task be idlehook? As in my case, it is not that I have to specifically not delete loop() or keep it in an unblocked state, but I have to make sure that all but one task should be unblocked.
Also, I checked the FreeRTOSconfig.h file and in that the macro configUSE_PREEMPTION is set as 1, still I am facing the issue with a higher priority task not being able to preempt unless lower priority is blocked. Can there be any other reason?
FreeRTOS creates a specific task to be the “Idle” task, and it has some cleanup responsibilities (if tasks ever delete themselves). FreeRTOS will crash if there ever is a case that it doesn’t have a task to run, the expectation is that this will be the Idle task as a last resort, but if you really NEED your operations called by the IdleHook to block, having another task ready will meet that requirement.
I would double check that the FreeRTOSConfig.h you are looking at is the same file that FreeRTOS is using, one quick check is to put a error in it and see that you get the error when you compile FreeRTOS.
The only reasons I can think of that would keep the preemption from happening are you aren’t getting interrupts to cause the task switch, or your low priority task has turned off scheduling.
Assuming that you are using this library, loop is implemented as idle task hook. So you cannot block (i.e. call vTaskDelay) from loop. Does removing vTaskDelay from loop fix your problem?
Yes, removing vTaskDelay() eliminates the problem of the program crashing. Is there no requirement for an idle task hook on ESP32, as this problem never occurs on ESP?
Also, I still could not figure out why the lower priority task keeps printing(running) and is not preempted unless I give a vTaskDelay() in the task. When I give vTaskDelay() the higher priority task is scheduled.
Idle hook is optional.
This should not happen. Can you share your task creation code and task code?
I reinstalled the RTOS library following your link and now the high-priority task is preempting without the requirement of delay in low priority task.
Thanks for the support.
Thank you for reporting back.