I'm using multi-threading on my ESP32. I have created two tasks and pinned them to core 1. With one of them, I get the following error:
E (20426) FreeRTOS: FreeRTOS Task "MeasurementTask" should not return, Aborting now!
abort() was called at PC 0x4008b8f3 on core 1
Backtrace: 0x4008f34c:0x3ffd0a40 0x4008f57d:0x3ffd0a60 0x4008b8f3:0x3ffd0a80
Rebooting...
However, there is no return
statement in my "MeasurementTask" (see code below). What's the issue here?
tracker.cpp
:
#include "tracker.h"
void threadedLoop(void *pvParameters) {
Serial.println("Loop task pinned");
for(;;) {
checkAPTrigger();
mqttLoop();
}
}
void setupTracker() {
Serial.print("Setup start: ");
Serial.println(millis());
Wire.begin();
setup_sensors();
if(setupAP()) {
setupTime();
setupMQTT();
}
Serial.print("Setup done: ");
Serial.println(millis());
Serial.println("Pinning measurement");
TaskHandle_t measureTask;
xTaskCreatePinnedToCore(
takeMeasurement,
"MeasurementTask",
2048,
NULL,
1,
NULL,
ARDUINO_RUNNING_CORE
);
Serial.println("Pinning loop");
TaskHandle_t loopTask;
xTaskCreatePinnedToCore(
threadedLoop,
"LoopTask",
2048,
NULL,
1,
NULL,
ARDUINO_RUNNING_CORE
);
}
void loopTracker() {
//takeMeasurement();
}
void takeMeasurement(void *pvParameters) {
Serial.println("Measurement task pinned");
DynamicJsonDocument root(512);
JsonObject rootObj = root.to<JsonObject>();
read_sensors(rootObj);
if(!(settings.mqttUsed && publishData(rootObj))) {
appendFile("data", root);
}
serializeJsonPretty(root, Serial);
Serial.println("\n---\n");
}
Sketch:
#include <tracker.h>
void setup() {
Serial.begin(115200);
// put your setup code here, to run once:
wm.resetSettings();
setupTracker();
}
void loop() {
// put your main code here, to run repeatedly:
loopTracker();
}
There are quite some files included in the tracker.h
, but I don't believe they're relevant to this problem. Some of the functions used in the takeMeasurement
do have return values, but I never return them in that function itself.
In FreeRTOS, tasks are started with xTaskCreate...
and ended with vTaskDelete
. A task function may not simply "end", this is not allowed.
Put vTaskDelete(NULL);
at the end of the function to gracefully end the task:
void takeMeasurement(void *pvParameters) {
// . . . task code . . .
vTaskDelete(NULL);
}
Having said that, tasks are usually meant to be long-running. For example, the measurement task could be an endless loop that takes the measurement, sleeps for a while, and repeats.