My first day with PlatformIO and having strange issues with FreeRTOS. Please see at the bottom of the post the code I am using. Situation is this:
FreeRTOS example works just fine if I paste the same code into Arduino IDE
When I try to run the same code on PlatformIO (only difference is the addition of Arduino.h, nothing happens.
If I comment out FreeRTOS related commands, loop works, leds blink.
If I add back the TaskCreate commands, but don’t start the scheduler, loop() runs only once, lights stay lit.
If I start the scheduler as well, nothing happens (doesn’t reach to loop())
I cannot tell what is different or what I might be doing wrong. It almost feels like on FreeRTOS stacks somehow get corrupted, hence I increased stack sizes to 1000 but didn’t make a difference.
I appreciate if you can offer ideas on how this issue can be further troubleshoot (unless of course it is an obvious mistake)
I’m not familiar with STM32, so don’t take my words for it.
As for FreeRTOS, the vTaskStartScheduler() function does not return, as specified in FreeRTOS reference manual, unless memory allocation fails. You can see framework-arduinoststm32/cores/arduino/main.cpp where the main() function is defined.
/*
* \brief Main entry point of Arduino application
*/
int main(void)
{
initVariant();
setup();
for (;;) {
#if defined(CORE_CALLBACK)
CoreCallback();
#endif
loop();
serialEventRun();
}
return 0;
}
Since vTaskStartScheduler() does not return, you can’t use FreeRTOS task mechanism along with Arduino loop().
The commands in the loop() are there purely to test. If I comment out vTaskStartScheduler(); one would expect loop to work. But it gets only executed once, LEDs stays lit and it hangs.
I came across another similar FreeRTOS problem (on ESP32) resolved using lib_archive = no in platformio.ini but it didn’t help in my case.
With STM32 and platformio, STLink V2 is your friend.
It will unlock for you hardware debugging capabilities that the Arduino IDE lacks. For example, you will be able to single step or break or pause the program and understand what’s going on.
@zapta , I do debug but I don’t think platformio/stm32 pair is capable of debugging into the threads and the scheduler. Please let me know if your understanding is different.
@maxgerhardt , thank you, please see platformio below. One of the many tries but this is the latest and most simple one. If Arduino IDE can run RTOS code with no issues using generic variant I am expecting to be able to do the same with platformio.
Wow this was helpful. Debugging actually works into the scheduler (without needing to make the changes mentioned) and obviously I hit the error which says HEAP cannot be allocated.
Now the question is why it manages to allocate heap fine on Arduino IDE but not on Platformio.
Contents of the json file is below, thanks for the help.
Very brave of you to try an RTOS on 8K of RAM. It should be close to its memory limit.
Can you decrease the stack memory created for each thread to e.g., 512 or 256? These should be stack elements (aka 4 bytes / sizeof(int)), so for the executed task code this seems to be very overkill.
Hmm, good point. Still on Arduino I can run 4 tasks (not doing much) with 128 words (256 bytes) stack each. On platformio 2 tasks doesn’t start with 128, or even when I reduce it to 16 words.
I can move to 20k RAM version of the chip, sound like it is a good idea anyways. However I don’t think we are hitting 8k limit here.
Further debugging, in task.c (task creation)
StackType_t *pxStack;
/* Allocate space for the stack used by the task being created. */
pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );
// allocation is for 16 x 4U and looks ok, xTaskCreate is called with 16 bytes stack
if( pxStack != NULL )
{
/* Allocate space for the TCB. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
// this one is odd, sizeof(TCB_t) is 1160U, task surely does not require this much.
So, the compiler versions differ and it could be that their 12.2.1 toolchain was build with e.g. _REENT_SMALL to reduce the size of the reentrancy structure, making the TCB_t structure smaller.
and after saving and waiting for re-init also doing a Ctrl+Shift+P → Reload Window, it does now use a toolchain which has a much small _reent structure size. This should be what STM32Duino is using at 2.5.0. This is also what the Arduino iDE is using at 2.5.0 but PlatformIO differs from that.
Can you test the above platformio.ini and check if now the firmware behaves the same in PlatformIO as in the Arduino IDE?
Oh wow ! It worked ! It for some reason broke debugger hence I cannot report what the TCB dropped to from 1160 bytes, but it is working.
I couldn’t run more than two 128byte tasks, so it is not still as good as Arduino IDE but definitely workable. I’ll try to debug both and see the difference, if any, in stack allocation.
Thanks a lot for your help.
I am getting this error btw, with both compilers, does it ring a bell with you ?
ld/genericSTM32L052K6/lib6dd/STM32duino FreeRTOS/port.c.o
In file included from .pio/libdeps/genericSTM32L052K6/STM32duino FreeRTOS/src/heap.c:25:
.pio/libdeps/genericSTM32L052K6/STM32duino FreeRTOS/src/../portable/MemMang/heap_useNewlib_ST.c:77:4: warning: #warning "This wrapper was verified for newlib versions 2.5 - 3.3; please ensure newlib's external requirements for malloc-family are unchanged!" [-Wcpp]
77 | #warning "This wrapper was verified for newlib versions 2.5 - 3.3; please ensure newlib's external requirements for malloc-family are unchanged!"
| ^~~~~~~
Compiling .pio/build/genericSTM32L052K6/lib6dd/STM32duino FreeRTOS/portasm.c.o
Compiling .pio/build/genericSTM32L052K6/src/main.cpp.o