Thread scheduling - unexpected behavior

Discussions and support about ChibiOS/RT, the free embedded RTOS.
Raul
Posts: 43
Joined: Thu Aug 13, 2015 5:15 pm
Has thanked: 3 times
Been thanked: 1 time

Thread scheduling - unexpected behavior

Postby Raul » Mon Jul 02, 2018 1:48 pm

Hi all,

I have a conceptual/super simple test case whose result I'm struggling to fathom.

All the configuration is as set in the STM32F407 Discovery demo, discovery board is the hardware platform. Tested with -O2 and -O0, no difference.

I wanted to verify that among all the threads ready for execution, the one with the highest priority is the one being executed,
no exceptions to this rule.

It seems to be the case, what I find striking is the behavior of the blinker thread, I would expect it to alternate output state at 10 Hz.

Code: Select all

 22 /*
 23  * This is a periodic thread that does absolutely nothing except flashing
 24  * a LED.
 25  */
 26 static THD_WORKING_AREA(waThread1, 128);
 27 static THD_FUNCTION(Thread1, arg) {
 28
 29   (void)arg;
 30   chRegSetThreadName("blinker");
 31   while (true) {
 32     chThdSleepMilliseconds(100);
 33     palTogglePad(GPIOD, GPIOD_LED3);     /* Orange.  */
 34   }
 35 }
 36
 37 /*
 38  * Application entry point.
 39  */
 40 int main(void) {
 41
 42   /*
 43    * System initializations.
 44    * - HAL initialization, this also initializes the configured device drivers
 45    *   and performs the board-specific initializations.
 46    * - Kernel initialization, the main() function becomes a thread and the
 47    *   RTOS is active.
 48    */
 49   halInit();
 50   chSysInit();
 51
 52   /*
 53    * Creates the example thread.
 54    */
 55   chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO+1, Thread1, NULL);
 56
 57   /*
 58    * Normal main() thread activity, in this demo it does toggle
 59    * a yellow led as fast as possible while in running state.
 60    */
 61   while (true)
 62   {
 63         palTogglePad (GPIOD, GPIOD_LED4);       /* Yellow.  */
 64   }
 65 }


Output registered with logic analyzer (colours of the channels map to the leds):

priority.png
priority.png (9.91 KiB) Viewed 4424 times


Any ideas?

Raul

User avatar
wurstnase
Posts: 121
Joined: Tue Oct 17, 2017 2:24 pm
Has thanked: 43 times
Been thanked: 30 times
Contact:

Re: Thread scheduling - unexpected behavior

Postby wurstnase » Mon Jul 02, 2018 1:53 pm

The concept of chibios is a chThdSleep in the main loop.
\o/ Nico

Raul
Posts: 43
Joined: Thu Aug 13, 2015 5:15 pm
Has thanked: 3 times
Been thanked: 1 time

Re: Thread scheduling - unexpected behavior

Postby Raul » Mon Jul 02, 2018 1:58 pm

Hi Wurstnase,

That was quick :) Could you elaborate on that please? Is that specific to the main thread? Would the result be any different if I moved the main thread to a separate one, lower priority than blinker and main to sleep infinitely?
From a theoretic perspective, any reason not to have a low priority thread that doesn't sleep?

Raul

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Thread scheduling - unexpected behavior

Postby Giovanni » Mon Jul 02, 2018 2:34 pm

Hi,

Main() is a thread at priority NORMALPRIO, if it does not release the CPU then all threads at lower priority will never be scheduled, other threads at NORMALPRIO would be scheduled only if main() calls chThdYield() or its time slice elapsed (depending on if RR scheduling is cooperative or preemptive).

Note that in the test suite there are test cases testing exactly the behaviour you tested, you may look at those too.

Giovanni

Raul
Posts: 43
Joined: Thu Aug 13, 2015 5:15 pm
Has thanked: 3 times
Been thanked: 1 time

Re: Thread scheduling - unexpected behavior

Postby Raul » Mon Jul 02, 2018 3:25 pm

Hi Giovanni,

Main() is a thread at priority NORMALPRIO, if it does not release the CPU then all threads at lower priority will never be scheduled, other threads at NORMALPRIO would be scheduled only if main() calls chThdYield() or its time slice elapsed (depending on if RR scheduling is cooperative or preemptive).


That makes sense, that was my understanding (for a cooperative kernel like the one in the example). Note that in the example I posted, the blinker thread has a priority of NORMALPRIO+1.

I expanded the example slightly, added a push button to toggle the yellow led in the main.

I thought I had a decent understanding of the scheduler, I would have thought that the orange led would be toggling regularly every 100 ms. Are the results that I am measuring what you would expect?

Code: Select all

 22 /*
 23  * This is a periodic thread that does absolutely nothing except flashing
 24  * a LED.
 25  */
 26 static THD_WORKING_AREA(waThread1, 128);
 27 static THD_FUNCTION(Thread1, arg) {
 28
 29   (void)arg;
 30   chRegSetThreadName("blinker");
 31   while (true) {
 32     chThdSleepMilliseconds(100);
 33     palTogglePad(GPIOD, GPIOD_LED3);     /* Orange.  */
 34   }
 35 }
 36
 37 /*
 38  * Application entry point.
 39  */
 40 int main(void) {
 41
 42   /*
 43    * System initializations.
 44    * - HAL initialization, this also initializes the configured device drivers
 45    *   and performs the board-specific initializations.
 46    * - Kernel initialization, the main() function becomes a thread and the
 47    *   RTOS is active.
 48    */
 49   halInit();
 50   chSysInit();
 51
 52   /*
 53    * Creates the example thread.
 54    */
 55   chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO+1, Thread1, NULL);
 56
 57   /*
 58    * Normal main() thread activity, in this demo it does toggle
 59    * a yellow led as fast as possible while in running state.
 60    */
 61   while (true)
 62   {
 63           if (! palReadPad (GPIOA, GPIOA_BUTTON))
 64                 palTogglePad (GPIOD, GPIOD_LED4);       /* Yellow.  */
 65   }
 66 }


buttonUnpressed.png
Button open
buttonUnpressed.png (9.55 KiB) Viewed 4410 times

buttonPressed.png
Button closed
buttonPressed.png (9.32 KiB) Viewed 4410 times

User avatar
alex31
Posts: 374
Joined: Fri May 25, 2012 10:23 am
Location: toulouse, france
Has thanked: 38 times
Been thanked: 61 times
Contact:

Re: Thread scheduling - unexpected behavior

Postby alex31 » Wed Jul 04, 2018 12:56 pm

Hello,

That makes sense, that was my understanding (for a cooperative kernel like the one in the example). Note that in the example I posted, the blinker thread has a priority of NORMALPRIO+1.

I expanded the example slightly, added a push button to toggle the yellow led in the main.

I thought I had a decent understanding of the scheduler, I would have thought that the orange led would be toggling regularly every 100 ms. Are the results that I am measuring what you would expect?


I have reproduced your behavior.

This has nothing to do with the scheduler which work as expected, the problem is on the GPIO side. When you do a toogle, one have to read / modify / write the register, and theses 3 operations are not atomic. So doing this at high frequency without locking on the same port from two threads is the problem.

The problem is solved if :

a/ one keep toogle API but use two pins on two different ports (no shared resource)

or

b/ one replace tooglePad by a setPad followed by clearPad ( theses operations are atomic)

or

c/ one use bitband alias region on MCU that have this capability



Alexandre

Raul
Posts: 43
Joined: Thu Aug 13, 2015 5:15 pm
Has thanked: 3 times
Been thanked: 1 time

Re: Thread scheduling - unexpected behavior

Postby Raul » Wed Jul 04, 2018 9:20 pm

Hi Alexandre,

Thanks for taking the time of actually run it and shedding some light, that makes perfect sense (so great to know the cause !). Didn't realiaze about the atomicity of the toggle call.

Also never heard of bit-banding before, appreciated.

Raul

User avatar
wurstnase
Posts: 121
Joined: Tue Oct 17, 2017 2:24 pm
Has thanked: 43 times
Been thanked: 30 times
Contact:

Re: Thread scheduling - unexpected behavior

Postby wurstnase » Thu Jul 05, 2018 5:50 am

What could be a reason to use a bit-banding instead of the set/reset registers on STM32 (BSRR/BRR)?
\o/ Nico

User avatar
alex31
Posts: 374
Joined: Fri May 25, 2012 10:23 am
Location: toulouse, france
Has thanked: 38 times
Been thanked: 61 times
Contact:

Re: Thread scheduling - unexpected behavior

Postby alex31 » Thu Jul 05, 2018 12:41 pm

What could be a reason to use a bit-banding instead of the set/reset registers on STM32 (BSRR/BRR)?


I don't advocate bitbanding for all the situations. In a set/reset scenario, BSRR/BRR are the way to go (chibios hal use it), it's simpler and faster than using bitbanding. But in the special case of toggling one bit, the hardware take care of atomicity at register level.

User avatar
alex31
Posts: 374
Joined: Fri May 25, 2012 10:23 am
Location: toulouse, france
Has thanked: 38 times
Been thanked: 61 times
Contact:

Re: Thread scheduling - unexpected behavior

Postby alex31 » Thu Jul 05, 2018 12:57 pm

Also never heard of bit-banding before, appreciated.


here a small header only library helper for bitbanding :
bitband.h on github

Alexandre


Return to “ChibiOS/RT”

Who is online

Users browsing this forum: No registered users and 9 guests