Free RTOS and idle loop()

Please do not post requests
Post Reply
nrie
Posts: 6
Joined: Fri Sep 08, 2017 11:59 pm

Free RTOS and idle loop()

Post by nrie » Sat Sep 23, 2017 3:09 am

Apologies if this is covered somewhere, I could not find it.
I have looked at the basic rtos_blink example and modified it to do some other stuff. No problem, I have implemented FreeRTOS in platforms outside of Arduino.
My problem is in understanding the FreeRTOS idle task within Arduino. Searching reveals that FreeRtos uses the standard Arduino loop() as its idle task. This does not seem to happen by default. I think the compiler (I am using PlatformIO) wants the file freeRTOSConfig.h changed to set
#define configUSE_IDLE_HOOK 1, which one wpuld normally do if the idle hook was to be used.
However the compiler is still bleating that there is "undefined reference to `vApplicationIdleHook'"
Can someone point me to what Arduino STM32 requires.
Thanks heaps
Robyn

victor_pv
Posts: 1750
Joined: Mon Apr 27, 2015 12:12 pm

Re: Free RTOS and idle loop()

Post by victor_pv » Sat Sep 23, 2017 3:49 am

nrie wrote:
Sat Sep 23, 2017 3:09 am
My problem is in understanding the FreeRTOS idle task within Arduino. Searching reveals that FreeRtos uses the standard Arduino loop() as its idle task.
It should not.

Someone ported FreeRTOS 6 or 7 to libmaple long time ago. I brought that up to date to 8.2.1 and later to 9.0.0, and has been a while since I looked at the code, but I do not remember the idle task using the arduino loop() at all.
The idle task if I remember right is the default one included in FreeRTOS. You can use your own idle task, but then as platformio correctly points out you will have to declare you own idle task code, with the task name in that error message.

I have declared my own idle task for measuring CPU usage (the idle task count how much it runs, by increasing a counter, so any time is not running, it's considered as CPU time used in some task other than idle, although I think FreeRTOS had a config option to keep runtime statistics, but those take more cpu time, flash and RAM, mine is just a basic used/not used statistic).

It does use the systick hook, but you don't need to change anything for that, that's already included in our RTOS.

Btw, the FreeRTOS I ported is for the libmaple based core (https://github.com/rogerclarkmelbourne/Arduino_STM32) If you use STM's or Generic cores, there is other FreeRTOS ports.

nrie
Posts: 6
Joined: Fri Sep 08, 2017 11:59 pm

Re: Free RTOS and idle loop()

Post by nrie » Sat Sep 23, 2017 7:15 am

Thanks Victor, I was working from some info I picked up about Arduino and FreeRTOS. This seemed to be the only clue I could find
http://www.instructables.com/id/FreeRTO ... Idle-Hook/
That chap says that the idle loop is tied to the Arduino loop() but I realise that the STM implementation may be different. This is his message.
Step 2: Using Idle Task Hook :
To use the Idle task, configUSE_IDLE_HOOK should be set to 1.In Arduino the loop() function is hooked to freeRtos Idle Task and will be called whenever the scheduler runs its Idle Task.

When I could not get anything to work in loop() I set the configUSE_IDLE_HOOK to 1 and then the compiler gave me the not found error, undefined reference to `vApplicationIdleHook'
I have tried just defining it as a subroutine, same error. I defined it as a task with tskIDLE_PRIORITY same error although I did not expect that would work as when I use it in other platforms I just define the subroutine void vApplicationIdleHook(void) and it links because tasks.c has this as an extern.
I got it to compile by enclosing my subroutine in extern "C{} statements
extern "C" {
void vApplicationIdleHook(void){
digitalWrite(BOARD_LED_PIN, HIGH);
}
}This seemed to work, I suspect that the compiler mangles a name somewhere? I will see if I can put something more meaningful in the loop than turn the LED off and see how it goes.
Thanks a lot

nrie
Posts: 6
Joined: Fri Sep 08, 2017 11:59 pm

Re: Free RTOS and idle loop()

Post by nrie » Sat Sep 23, 2017 7:17 am

BTW, the Arduino method described above seems to be easy to use, I have not tried it to see if it works but would it be worth putting into the STM32 version?
Regards

nrie
Posts: 6
Joined: Fri Sep 08, 2017 11:59 pm

Re: Free RTOS and idle loop()

Post by nrie » Sat Sep 23, 2017 7:36 am

Interesting, you still have to define loop() in the code
void loop() {
Serial.println("Nothing else happening");
delay(1000);
}
even though I don't think it gets called. If you don't the PlatformIO compiler gives you the error
.platformio\packages\framework-arduinoststm32\STM32F1\cores\maple/main.cpp:41: undefined reference to `loop()'

victor_pv
Posts: 1750
Joined: Mon Apr 27, 2015 12:12 pm

Re: Free RTOS and idle loop()

Post by victor_pv » Sat Sep 23, 2017 4:53 pm

In Arduino (and in any core to be used with the arduino IDE) there is still a main() function hidden inside the core.
That main function basically is like this:

Code: Select all

main(){
setup();
while (1) {
    loop();
}
}
So both setup and loop need to exist, but could just as well use a completely empty loop since you start the RTOS during setup(), and that point the RTOS scheduler will start scheduling tasks, and the code will never return from the call to start the scheduler.
But there is nothing preventing you from having an empty setup() and doing all the task set up and start the scheduler from loop() instead.

I disagree about using loop for the idle task. That may be simple, but it may be confusing if people don't know: 1st, why loop is being called after the scheduler is started. 2.- why their loop task seems to be run slow compared to other tasks. 3.- why their huge loop which before had the full stack for local variables, now causes a crash (due to stack overflow since it now has a task stack). Then they may start messing with the stack size for the idle task, and the priority for the idle task, which should not be messed with... Or perhaps arduino declares the idle task with a large stack, and then if you actually try to use FreeRTOS as you would in another platform, and you don't put any code in loop, you are wasting previous RAM in an idle task that does nothing.

I think it's easy to understand from reading FreeRTOS docs that once you start the scheduler, the only things supposed to run are the tasks. If you want to use loop(), you can call it from a task, and set the priority and stack size that you need for your loop code in that task settings. The first time I used it, I did wonder like you why loop was not being called, until I read the FreeRTOS documentation and not just arduino related stuff.

There are minimal changes in the FreeRTOS for stm32duino, mostly related to hooking the scheduler ISR to the libmaple systick ISR. I kind of like that approach so it's the most similar in usage to normal plain FreeRTOS.

That's my opinion, which is not better than anyone's, and I am NOT an experienced programmer. So if a bunch of people in the forum share the same opinion that loop should be called from the idle task, feel free to send a PR to Roger with changes to include loop in the idle task.

ag123
Posts: 811
Joined: Thu Jul 21, 2016 4:24 pm

Re: Free RTOS and idle loop()

Post by ag123 » Sun Sep 24, 2017 4:16 am

I think the integration between Arduino and FreeRTOS is merely to start the FreeRTOS scheduler, thereafter FreeRTOS takes over all the context switches from there.
http://www.freertos.org/a00102.html

Code: Select all

int main( void )
{
   /* Setup the microcontroller hardware for the demo. */
   prvSetupHardware();

   /* Create the common demo application tasks, for example: */
   vCreateFlashTasks();
   vCreatePollQTasks();
   vCreateComTestTasks();
   Etc.

   /* Create any tasks defined within main.c itself, or otherwise specific to the
   demo being built. */
   xTaskCreate( vCheckTask, "check", STACK_SIZE, NULL, TASK_PRIORITY, NULL );
   Etc.

   /* Start the RTOS scheduler, this function should not return as it causes the
   execution context to change from main() to one of the created tasks. */
   vTaskStartScheduler();

   /* Should never get here! */
   return 0;
}
^^^ basically copy all that code in main() into setup() that's it

in FreeRTOS, processing tasks should not run on the main loop, rather those should be implemented as tasks, e.g. using vTaskDelay
http://www.freertos.org/a00127.html

FreeRTOS isn't really arduino, it is its own thing, but arduino works pretty well with it provided you have enough sram

nrie
Posts: 6
Joined: Fri Sep 08, 2017 11:59 pm

Re: Free RTOS and idle loop()

Post by nrie » Sun Sep 24, 2017 10:34 pm

Thanks for all that info. In most of the designs I have worked on I have required an idle loop which FreeRTOS returns to when nothing else is running. It is there that I put sleep functions for power saving.
I am happy now that I can actually hook into the idle loop given the extern "C"{} outlined above.
In implementing some sleep code in that loop though, I have found I seem to have stopped the scheduler on return from sleep so I will have to investigate that farther.
Thanks
Robyn

edogaldo
Posts: 286
Joined: Fri Jun 03, 2016 8:19 am

Re: Free RTOS and idle loop()

Post by edogaldo » Mon Sep 25, 2017 5:16 am

nrie wrote:
Sun Sep 24, 2017 10:34 pm
In implementing some sleep code in that loop though, I have found I seem to have stopped the scheduler on return from sleep so I will have to investigate that farther.
Thanks
Robyn
You should not use the deepsleep modes (stop and standby) as they stop the systick (and standby reboots too) but the sleep mode should work fine.

Post Reply