logo
CODEMBIT
Reliable software engineering partner
Home Blog Tools

How to use co-routines with FreeRTOS

By Toni Akkala, 11th of August, 2022
img

Overview

In the earlier post, I was able to use a static memory allocation with MSP430 and FreeRTOS. Even though that helped me to implement necessary support for a low resource MCU like MSP430FR5739, there is one more option how to optimize memory usage. Co-routines were originally developed to be used with a small embedded devices. Those are conceptually the same as tasks but have some key differences to save memory. The most important one is that all the co-routines share a single stack. Co-routines are not in active development anymore but according to the documentation, there are no plans to remove those either. Co-routines should help me with the small memory size by having a shared single stack with the multiple tasks.

Implementation

Co-routines are implemented by declaring a specific function and created by calling xCoRoutineCreate giving declared function as a parameter. I took the one co-routine from the documentation example which toggles the LED as I don't have anything else the code would do. configUSE_CO_ROUTINES must be defined in FreeRTOSConfig.h to be able to use functions to create and schedule co-routines. I added croutine.c file to my CCS project and placed a call to vCoRoutineSchedule function to my idle task hook to schedule my co-routines. Finally I added xCoRoutineCreate call to main to create my co-routine for the LED flashing.

static void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) { crSTART( xHandle ); for( ;; ) { // Delay for a fixed period. crDELAY( xHandle, 200 ); // Flash an LED. if (uxIndex) { vParTestToggleLED(0); } } crEND(); } void vApplicationIdleHook( void ) { // as we do not do anything else here, it is efficient to schedule co-routines // from within a loop for( ;; ) { vCoRoutineSchedule(); } } int main( void ) { /* Setup the hardware ready for the demo. */ prvSetupHardware(); vParTestInitialise(); /* Start the standard demo application tasks. */ xCoRoutineCreate( vFlashCoRoutine, mainLED_TASK_PRIORITY, 0 ); xCoRoutineCreate( vFlashCoRoutine, mainLED_TASK_PRIORITY, 1 ); /* Start the scheduler. */ vTaskStartScheduler(); /* As the scheduler has been started the demo applications tasks will be executing and we should never get here! */ return 0; }

Testing the modifications

After I tried to build the demo it was obvious that I was still missing something. I had a problem with the linking until I realized that I would need to enable a heap for this project as it creates a co-routine control blocks from the heap. As I was using my static memory allocation project as a basis for this, it was missing heap_1.c file and appropriate configuration from FreeRTOSConfig.h header. After restoring these I was able to try out the code with hardware.

RAM usage

Conclusion

So, having 2 co-routines and 1 task (idle) used 670 bytes. As I had only few co-routines, the benefit of using co-routines was not so obvious. Having tens of co-routines would demonstrate the benefit better. Also, I had to again manually adjust the heap size to avoid losing all the saved memory bytes to the heap. This wasn’t something I wanted to do. Apparently, co-routines cannot be used along static memory allocation or I did not just know how to do that.

References: