C++ freertos 在获取信号量失败后从 subclass 调用基 class 的重写函数
C++ freertos Call overriden function of base class from subclass after getting semaphore failes
我正在尝试创建一个包含信号量的基 class 并等待它可以获取信号量,然后调用派生 class 中的函数。 (我想有许多不同的基础 classes 来实现不同的功能,但它们都应该在获取信号量后才执行此功能。
我对freertos不是很熟悉,所以我想错误可能与此有关。
我做了一些尝试,但到目前为止没有成功。
基本代码如下:
基地class:
class CommandMode{
public:
CommandMode(xSemaphoreHandle* smphr_calc_steps);
virtual ~CommandMode(){};
virtual int GetNextState()=0;
protected:
static void TSK_CalcSteps(void* params);
xSemaphoreHandle* smphr_calc_steps;
virtual void CalculateSteps(){};
};
CommandMode::CommandMode(xSemaphoreHandle* smphr_calc_steps):smphr_calc_steps(smphr_calc_steps){
xTaskCreate(&TSK_CalcSteps, "output data calc", 2048, this, 1, NULL);
}
void CommandMode::TSK_CalcSteps(void* params){
CommandMode* cm = (CommandMode*) params;
while(true){
//force reevaluation at least every 60s
xSemaphoreTake(cm->smphr_calc_steps, 60*1000/portTICK_PERIOD_MS); // i think the problem is related to that line
cm->CalculateSteps();
}
}
这里是派生的 class:
class Mode1:public CommandMode{
public:
Mode1(xSemaphoreHandle* smphr_calc_steps);
~Mode1(){};
int GetNextState() override;
protected:
void CalculateSteps() override;
};
Mode1::Mode1(xSemaphoreHandle* smphr_calc_steps) : CommandMode(smphr_calc_steps){}
void Mode1::CalculateSteps(){
Serial.println("Mode1::CalculateSteps");
}
int Mode1::GetNextState(){
Serial.println("Mode1::GetNextState");
return 5;
}
然后我尝试像这样调用它们:
CommandMode* current = nullptr;
xSemaphoreHandle smphr = xSemaphoreCreateBinary();
//xSemaphoreHandle smphr2 = xSemaphoreCreateBinary();
Serial.println("init with mode1");
delay(200);
Mode1* a = new Mode1(&smphr);
a->GetNextState(); //This will work
current = a;
current->GetNextState(); //This will work as well
xSemaphoreGive(smphr); //This does not work as intended/causes the issue
我也不确定 cm->CalculateStepes() 行。由于我将 'cm' 作为 void* 传递,它是否仍会评估正确的 subclass 模块?我是 运行 在带有 Plattform IO 的 ESP32 上,以防这很重要。
到目前为止我有时会遇到看门狗错误,但大多数情况下我会遇到以下两个错误:
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1443 (xQueueGenericReceive)- assert failed!
abort() was called at PC 0x40087f1d on core 0
assertion "res == coreID || res == portMUX_FREE_VAL" failed: file "/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/portmux_impl.inc.h", line 105, function: vPortCPUAcquireMutexIntsDisabledInternal
abort() was called at PC 0x400d8cf3 on core 0
我尝试使用任务本身的整个代码并尝试使用多个 delays(),但我从来没有让它工作过。
如果有人能告诉我问题出在哪里,或者建议如何以更好的方式实现此行为,我将很高兴?
我也想在基础 class 中包含其他函数和值。这没有问题,但是基于信号量的派生 class 函数的调用根本不起作用。
xSemaphoreTake
希望句柄传值,你传指针,那肯定是错误的。
代码编译是因为 SemaphoreHandle_t
本身是一个隐藏的指针(因此这不是一个好的做法,但由于其他充分的原因经常出现在低级的东西中)。这也意味着您可以而且应该将 smphr_calc_steps
作为一个值传递并存储在您的 class 中,作为一个指针,它的复制成本很低。不需要额外的间接寻址,只会使事情复杂化。
FreeRTOS 在堆上分配信号量和 returns 一个指针(=句柄)给你,你唯一的责任是在将来的某个时候调用 vSemaphoreDelete
来释放内存。
我正在尝试创建一个包含信号量的基 class 并等待它可以获取信号量,然后调用派生 class 中的函数。 (我想有许多不同的基础 classes 来实现不同的功能,但它们都应该在获取信号量后才执行此功能。 我对freertos不是很熟悉,所以我想错误可能与此有关。
我做了一些尝试,但到目前为止没有成功。
基本代码如下:
基地class:
class CommandMode{
public:
CommandMode(xSemaphoreHandle* smphr_calc_steps);
virtual ~CommandMode(){};
virtual int GetNextState()=0;
protected:
static void TSK_CalcSteps(void* params);
xSemaphoreHandle* smphr_calc_steps;
virtual void CalculateSteps(){};
};
CommandMode::CommandMode(xSemaphoreHandle* smphr_calc_steps):smphr_calc_steps(smphr_calc_steps){
xTaskCreate(&TSK_CalcSteps, "output data calc", 2048, this, 1, NULL);
}
void CommandMode::TSK_CalcSteps(void* params){
CommandMode* cm = (CommandMode*) params;
while(true){
//force reevaluation at least every 60s
xSemaphoreTake(cm->smphr_calc_steps, 60*1000/portTICK_PERIOD_MS); // i think the problem is related to that line
cm->CalculateSteps();
}
}
这里是派生的 class:
class Mode1:public CommandMode{
public:
Mode1(xSemaphoreHandle* smphr_calc_steps);
~Mode1(){};
int GetNextState() override;
protected:
void CalculateSteps() override;
};
Mode1::Mode1(xSemaphoreHandle* smphr_calc_steps) : CommandMode(smphr_calc_steps){}
void Mode1::CalculateSteps(){
Serial.println("Mode1::CalculateSteps");
}
int Mode1::GetNextState(){
Serial.println("Mode1::GetNextState");
return 5;
}
然后我尝试像这样调用它们:
CommandMode* current = nullptr;
xSemaphoreHandle smphr = xSemaphoreCreateBinary();
//xSemaphoreHandle smphr2 = xSemaphoreCreateBinary();
Serial.println("init with mode1");
delay(200);
Mode1* a = new Mode1(&smphr);
a->GetNextState(); //This will work
current = a;
current->GetNextState(); //This will work as well
xSemaphoreGive(smphr); //This does not work as intended/causes the issue
我也不确定 cm->CalculateStepes() 行。由于我将 'cm' 作为 void* 传递,它是否仍会评估正确的 subclass 模块?我是 运行 在带有 Plattform IO 的 ESP32 上,以防这很重要。
到目前为止我有时会遇到看门狗错误,但大多数情况下我会遇到以下两个错误:
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1443 (xQueueGenericReceive)- assert failed!
abort() was called at PC 0x40087f1d on core 0
assertion "res == coreID || res == portMUX_FREE_VAL" failed: file "/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/portmux_impl.inc.h", line 105, function: vPortCPUAcquireMutexIntsDisabledInternal
abort() was called at PC 0x400d8cf3 on core 0
我尝试使用任务本身的整个代码并尝试使用多个 delays(),但我从来没有让它工作过。
如果有人能告诉我问题出在哪里,或者建议如何以更好的方式实现此行为,我将很高兴? 我也想在基础 class 中包含其他函数和值。这没有问题,但是基于信号量的派生 class 函数的调用根本不起作用。
xSemaphoreTake
希望句柄传值,你传指针,那肯定是错误的。
代码编译是因为 SemaphoreHandle_t
本身是一个隐藏的指针(因此这不是一个好的做法,但由于其他充分的原因经常出现在低级的东西中)。这也意味着您可以而且应该将 smphr_calc_steps
作为一个值传递并存储在您的 class 中,作为一个指针,它的复制成本很低。不需要额外的间接寻址,只会使事情复杂化。
FreeRTOS 在堆上分配信号量和 returns 一个指针(=句柄)给你,你唯一的责任是在将来的某个时候调用 vSemaphoreDelete
来释放内存。