I’m trying to use C++ objects as tasks and am having trouble getting member data passed into a new instance.
For example I have a button monitor that reports presses to a seat manager but none of the instance variables populate inside my task loop.
Edit: this is code for an ESP32 with their implementation of FreeRTOS.
Here’s the base class for a task object
class TaskBase {
public:
TaskBase(const char* name, UBaseType_t priority, configSTACK_DEPTH_TYPE stackDepth=configMINIMAL_STACK_SIZE) {
xTaskCreate(&taskLoop, name, stackDepth, this, priority, &handle);
}
protected:
virtual void task() = 0;
private:
TaskHandle_t handle;
static void taskLoop(void* param) {
TaskBase* obj = const_cast<TaskBase*>(static_cast<const TaskBase*>(param));
obj->task();
}
};
A button monitor derived from it
class ButtonMonitor : public TaskBase {
public:
ButtonMonitor( uint8_t pin,
QueueHandle_t queue,
touch_value_t capThreshold = 40000,
const char* name = "Button Monitor",
UBaseType_t priority = PRIO_MEDIUM,
configSTACK_DEPTH_TYPE stackDepth = 2000 );
protected:
void task();
private:
static const TickType_t xDebounceDuration = pdMS_TO_TICKS(50);
static const TickType_t xLongPressDuration = pdMS_TO_TICKS(700);
static const TickType_t xPressDuration = pdMS_TO_TICKS(250);
static const TickType_t xSequentialTapDuration = pdMS_TO_TICKS(250);
static const TickType_t xWaitDuration = pdMS_TO_TICKS(20);
uint8_t _pin;
touch_value_t _capThreshold;
QueueHandle_t _sendQueue;
};
Button monitor implementation
ButtonMonitor::ButtonMonitor( uint8_t pin,
QueueHandle_t queue,
touch_value_t capThreshold,
const char* name,
UBaseType_t priority,
configSTACK_DEPTH_TYPE stackDepth ) :
TaskBase( name, priority, stackDepth ), _pin(pin), _sendQueue(queue), _capThreshold(capThreshold) {
}
void ButtonMonitor::task() {
log_i("pin %d", _pin);
log_i("cap threshold %d", _capThreshold);
while(1) {
// FIXME use _pin and _capThreshold
bCurrPressed = touchRead(10) > 40000;
// a bunch of correctly working button code
log_i("Queue %d Seat %2d Touches %d", _sendQueue, sensorData.seat, sensorData.reading);
xQueueSend(_sendQueue, &sensorData, portMAX_DELAY);
// more button code
vTaskDelay(20); // FIXME use xWaitDuration
}
}
main (edited for clarity)
void setup() {
SemaphoreHandle_t xBoardStateChangedSemaphore = xSemaphoreCreateBinary();
QueueHandle_t xSeatManagerReceiveQueue = xQueueCreate(2, sizeof(SensorData_t));
vTaskDelay(500);
ButtonMonitor b( 10, xSeatManagerReceiveQueue, 40000 );
log_i("Button monitor go");
vTaskDelay(500);
SeatManager s( xSeatManagerReceiveQueue, xBoardStateChangedSemaphore );
log_i("Seat manager go");
}
Run log
[ 95][I][esp32-hal-psram.c:96] psramInit(): PSRAM enabled
[ 1100][I][main.cpp:16] setup(): Blarkey Blark & The Blunky Funch in the house!!!!
o 1600][I][mutton_monitor.cpp[: 1 71]6 0t0a]s[kI(])[:b uptitno n1_0m
t␀i
or.cpp:17] task(): pin 10
[ 1600][I][button_monitor.cpp:18] task(): cap threshold 40000
[ 2100][I][main.cpp:27] setup(): Seat manager go
[ 3764][I][button_monitor.cpp:81] task(): Queue 0 Seat 0 Touches 2
assert failed: xQueueGenericSend queue.c:820 (pxQueue)
Backtrace: 0x40377332:0x3fcec880 0x4037aab5:0x3fcec8a0 0x403803d1:0x3fcec8c0 0x4037b2e3:0x3fcec9f0 0x420017cb:0x3fceca30 0x4201f649:0x3fceca80
#0 0x40377332:0x3fcec880 in panic_abort at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_system/panic.c:408
#1 0x4037aab5:0x3fcec8a0 in esp_system_abort at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_system/esp_system.c:137
#2 0x403803d1:0x3fcec8c0 in __assert_func at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/newlib/assert.c:85
#3 0x4037b2e3:0x3fcec9f0 in xQueueGenericSend at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/queue.c:821 (discriminator 2)
#4 0x420017cb:0x3fceca30 in ButtonMonitor::task() at src/button_monitor.cpp:82
#5 0x4201f649:0x3fceca80 in TaskBase::taskLoop(void*) at src/task_base.h:33
As you can see, the log shows the ButtonManager instance correctly assigns _pin and _capThreshold but when I reference them in the while loop I get zeros instead. The panic happens when writing data to the queue.
Seems I’m missing some variable scope concept here. Any suggestions? Thanks.