Hello FreeRTOS ARM forum…first time poster and new FreeRTOS user.
We are developing on the cortex M7 using IAR Embedded Workbench v9.2. I have successfully implemented a FreeRTOS application in “C” without much difficulty. My team ultimately wants to develop in C++ as we have a large legacy code base in this language.
Not being all that great a C++ programmer, I read some things on this forum to attempt to implement a C++ wrapper for running tasks in a c++ context. In particular, I implemented a subset of Richard-Damon’s wrapper examples.
At first, everything seemed to work. I launched a couple simple tasks that printed out to the UART console once/second.
I then attempted a more “complicated” example that read data from a SPI device and printed this to the console once/second. This example would hard-fault and ultimately the root cause is that the C++ class variables are being dereferenced when the C++ task function is called.
My C++ class looks like…
class clsTTCIMUTask: public clsTTCTaskBase{
public:
void vCreateTask(void);
void vReadEWTS5GValueCmd(uint8_t sensor);
uint8_t CRC_calculation(uint8_t data1, uint8_t data2, uint8_t data3, uint8_t data4);
void imu_task(void);
static void taskfun(void* parm){
static_cast<clsTTCIMUTask *>(parm)->imu_task();
}
protected:
const char * pcMyTaskName = "IMU_TASK";
uint32_t masterRxData;
uint32_t masterTxData;
ecspi_master_config_t masterConfig;
ecspi_transfer_t masterXfer;
ecspi_master_handle_t g_m_handle;
};
I instantiate my class at filescope in my main.cpp file as follows…
clsTTCIMUTask imu_ecspi1_task;
int main()
{
BOARD_InitMemory();
/* Board specific RDC settings */
BOARD_RdcInit();
BOARD_InitBootPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
copyResourceTable();
CLOCK_SetRootMux(kCLOCK_RootEcspi1, kCLOCK_EcspiRootmuxSysPll1); /* Set ECSPI1 source to SYSTEM PLL1 800MHZ */
CLOCK_SetRootDivider(kCLOCK_RootEcspi1, 2U, 5U); /* Set root clock to 800MHZ / 10 = 80MHZ */
/* Set IRQ priority for freertos_ecspi */
NVIC_SetPriority(EXAMPLE_ECSPI_MASTER_IRQN, 2);
imu_ecspi1_task.vCreateTask();
vTaskStartScheduler();
(void)PRINTF("Failed to start FreeRTOS on core0.\r\n");
for (;;)
{
}
return 0;
}
The vCreateTask() function is as follows…
void clsTTCIMUTask::vCreateTask(void){
taskStackSize = 256;
taskPriority = 2;
if (xTaskCreate(&taskfun, pcMyTaskName, taskStackSize, NULL, taskPriority, &taskHandle) != pdPASS)
{
(void)PRINTF("\r\nFailed to create IMU task\r\n");
for (;;)
{
}
}
}
When the scheduler starts my C++ function, I can see with the debugger that the C++ member functions of the class (such as “masterRxData”) have been dereferenced and now point to locations within the Vector table! When data is put into the relocated masterRxData, the machine hard faults because masterRxData now points to the vector table location for a Bus Fault…
I was able to kluge the code to work by doing an extern of the instantiated class in the .cpp for the class itself and explicitly referring to the instantiated class…eg
imu_ecspi1_task.masterRxData…
How have others addressed this issue?
Thanks for your patience.
RichM