Can vTaskDelay() be called outside a task from a different cpp file?

Hi, I’m running FreeRTOS ver 9.0.0 on Cortex-M4 (MK20DX256) and I’ve recently run into an issue with the MCU freezing completely while running FreeRTOS. Although I haven’t managed to replicate the case again, I’m taking precautionary measures so it doesn’t repeat again – hopefully we’ll figure out why it froze in the first place. I’m curious if the cause of crash/freeze could have anything to do with calling vTaskDelay() or any other FreeRTOS function from a function outside the task esp if that function happens to be in a different cpp file e.g. ////////////////////////////////////////////////// Functions.h ////////////////////////////////////////////////// ~~~

ifndef PINDEFS_h

define PINDEFS_h

if defined(ARDUINO) && ARDUINO >= 100

include “Arduino.h”

else

include “WProgram.h”

endif

include “Pins.h” // includes references to pin numbers, delays

void power_down();

endif

~~~ ////////////////////////////////////////////////// Functions.cpp ////////////////////////////////////////////////// ~~~

include “Functions.h”

include “RTOS.h” // FreeRTOS headers e.g. FreeRTOS, task, semphr, timers

void powerdown() { pinMode(PWR, LOW); while (digitalRead(PWRSTAT)) { vTaskDelay(pdMSTOTICKS(DELAY_SHORT)); } } ~~~ ////////////////////////////////////////////////// main.cpp ////////////////////////////////////////////////// ~~~

include “RTOS.h”

include “Functions.h”

void setup() { xTaskCreate(PowerDownTask, NULL, configMINIMALSTACKSIZE, tskIDLE_PRIORITY + 2, NULL); // create other tasks
vTaskStartSchedule();

while (true) {}
} static void PowerDownTask(void *pvParameters) { // do stuff while (true) { // do stuff power_down(); } } ~~~ Can there be any problems leading to system freezing due to calling power_down()?

Can vTaskDelay() be called outside a task from a different cpp file?

Hi AbdulSamad , you should investigate what the “freezing” is. Could there be an exception, that ends in an eternal loop for(;;)? Does your function digitalRead() always succeed? Or does it wait for a condition that sometimes does not occur?
esp if that function happens to be in a different cpp file e.g.
It should not make any difference in which source file a function is located. Are you using C++ ? That should work OK with FreeRTOS, as long as the compiler knows the linkage type of every function ( C versus C++ ). C-only headers will often include these statements: ~~~ #ifdef __cplusplus extern “C” { #endif
/* Put your C declarations here */

#ifdef __cplusplus
}
#endif
~~~ Mind you that constructors of global and static C++ objects, are being called before main() is active. If you use the option nostartfiles, you will have to call the constructors your self. Also make sure that in these constructors, you can not use many resources: for instance the heap has not been set-up yet before main() is running. The code that you’re showing is simple and looks good to me.

Can vTaskDelay() be called outside a task from a different cpp file?

Hi Hein, Thanks for your feedback. Yes, I’m using C++. The code in the example above constitutes a small chunk of the functionalities in the original application and I thought it would be most suitable for elaboration purposes.
you should investigate what the “freezing” is. Could there be an exception, that ends in an eternal loop for(;;)?
Good pointers! I’ve come across such cases before and to avoid them, I’ve added a good amount of precautionary measures as follows:
  • all tasks have while(true) or for( ; ; ) loops
  • all tasks defined as static
  • no while(true) or for( ; ; ) loop exists without vTaskDelay()
  • software doesn’t try to access invalid memory e.g. task handles, and semaphores
  • no unsupported blocking function is called e.g. Arduino’s delay()
  • semaphores are accessed only when available
  • after deleting tasks, assign their task handles to NULL and call vTaskDelay()
I’ll look into the C-only headers and double check the library if the expressions need to be added. Do you mind elaborating on this part please?
Mind you that constructors of global and static C++ objects, are being called before main() is active. If you use the option nostartfiles, you will have to call the constructors your self. Also make sure that in these constructors, you can not use many resources: for instance the heap has not been set-up yet before main() is running.

Can vTaskDelay() be called outside a task from a different cpp file?

Do you mind elaborating on this part please?
Well, here is an example to make it clear: ~~~ class CMyClass { uint8_t *pcBuffer; public: CMyClass(); ~CMyClass(); }; CMyClass::CMyClass() { // main() might not be running yet pcBuffer = pvPortMalloc( BUFFER_SIZE ); } CMyClass::~CMyClass() { // This might never get called vPortFree( pcBuffer ); } // Constructor will be called before main is active. // Destructor will be called after main has exit, // which never happens CMyClass globalObject; int main() { // Initialise hardware. // Initialise heap.
// Here OK : heap has been initialised
// The destructor is never called because
// vTaskStartScheduler() never returns
CMyClass autoObject;

// Start scheduler.
vTaskStartScheduler();
} ~~~

Can vTaskDelay() be called outside a task from a different cpp file?

Ah, right. This has been covered. Thanks a lot, Hein!