I have been fighting a really annoying bug lately and I must be missing something important here. For context I have set up a esp32 Json websocket server running on core 1 in the Loop(); function and I created a task with the handle Sensors that runs on Core 0 and it updates the sensor data and runs a few timers. Everything was running fine before I added some sanity checks for the sensors but now even when I get rid of the checks Core 0 starts to panic and restart in a loop.
I have confined the problem down to the Task function SensorHandling() that runs on Core 0 but I still can't find the problem. Maybe someone else could take a crack.
Just guesses:
I see, you use a semaphore: but you trigger "yourself": the semaphore you are waiting for - you set also at the end. This looks like an "endless loop".
I could imagine this:
it is a "recursion": the RTOS handles your thread. You fire the xSemaphoreGive(Ticket); and the RTOS will look if need to release a thread potentially waiting for this semaphore. And RTOS sees the "same" thread again, to release.
Even it is still running, possible, that RTOS launches the thread code again, like a nested call. It is recursive at the end: the same thread "calls" itself again, before it has "finished".
You eat up your local variables (the stack). It is like a nested call of the same function again before the previous one has finished (recursion).
The error you get might not be related to root cause, maybe you run out of stack (and overwrite other variables, resulting in a "strange" behavior).
Why do you trigger yourself? Technically your thread runs endless, in a full-speed loop.
What happens if you:
get rid of this xSemaphoreTake(Ticket, portMAX_DELAY);
and also this xSemaphoreGive(Ticket);
it just "triggers itself" to keep running (never waiting), so, keep it as an endless loop (no need to wait, it would not wait anyway)
use just this vTaskDelay(1); (or: osDelay(1); ) in order to give other threads a chance to be scheduled as well
I would imagine: the RTOS calls your thread unlimited times, as nested calls and you run out of local variable space (stack), corrupting other memories.
Triggering yourself with a semaphore is not needed (and actually "strange"): "you" are running already, no need to wait for "yourself".
Or: you delete yourself via vTaskDelete(Sensors); But you fire the xSemaphoreGive(Ticket); still at the end. Maybe, the RTOS cannot find anymore who is waiting for this Semaphore.
The RTOS looks a bit strange to me. Sorry.
But just guesses...
this one is probably killing you too, but can't find source to verify..
calling these begins, destroys, recreates and inits them..
doing that in a forever loop will give you grief..
vTaskDelay(1); should wait 1 ms. So, you would loop every 1 ms.
Personally, using RTOS I would change a bit the thread code:
place all init, e.g. rtc.begin() before the for(;;): this entry of the thread is just executed once (on thread init and start),
the thread keeps looping in the for-loop
use a semaphore to release inside the for-loop (to have a blocking point), but set the semaphore from the "outside" (release by another thread), not releasing itself
if the thread code should run in for-loop, all the time: no need for semaphore, instead use this
vTaskDelay(1); (or osDelay(1)) : this blocks for 1 ms, it gives other threads a chance to be activated
I would also place all variable definitions before the for-loop, not inside the for loop, or: create a block with curly brackets and define local inside the block, but the block will be finished, the local variables released before the thread loops back
Manuals about semaphores state:
"The correct use of a semaphore is for signaling from one task to another. A mutex is meant to be taken and released, always in that order, by each task that uses the shared resource it protects. By contrast, tasks that use semaphores either signal or wait—not both."
You do both in the same task, assuming this is an issue.