Sleeping in Tickless mode

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderators: barthess, RoccoMarco

dflogeras
Posts: 195
Joined: Tue Sep 03, 2013 8:16 pm
Has thanked: 3 times
Been thanked: 15 times

Sleeping in Tickless mode

Postby dflogeras » Thu Jul 22, 2021 5:37 pm

Hi,

I'm beginning to play around again with using the low power modes in the STM32L1 series. I did this years ago on a Chibi-3.x based system with a tick, but I think I'm missing something in tickless mode.

I have started with a basic threaded blinker framework copied from demos/STM32/RT-STM32L152-DISCOVERY (I'm using ChibiOS_21.6.0, but same behaviour on 19.1.3)

Then, if the button is pressed, I enter sleep using:

Code: Select all

      chSysLock();
      PWR->CR |= (PWR_CR_LPSDSR | PWR_CR_CSBF | PWR_CR_CWUF);
      PWR->CR &= ~PWR_CR_PDDS;
      SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
      chSysUnlock();
      __WFI();


If I press the button again (generating an interrupt) the mcu wakes back up, but as expected the timings change because the STM32L1 leaves STOP/STANDBY states running from the MSI clock. This was discussed years back in viewtopic.php?f=16&t=2927

So now, if I follow my __WFI() with the following:

Code: Select all

      chSysLock();
      stm32_clock_init();
      chSysUnlock();


The blinker threads never resume blinking. It seems that re-initializing the clocks messes up the virtual timers they have been programmed to wait on perhaps? I manually unblocked my threads using chSchReadyI() and they ran until the next call to chSThdSleepMilliseconds() then never seem to get woken again and the OS just stays in the idle thread.

Any help would be greatly appreciated.
Dave

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

Re: Sleeping in Tickless mode

Postby Giovanni » Thu Jul 22, 2021 5:54 pm

Hi,

I think you could re-initialize the OS using chSysInit(), that also resynchronizes the virtual timers. If the timer continues to run during sleep then that could be the problem.

Note that chSysInit() expects interrupts to be disabled on entry, use chSysDisable() in order to ensure that.

Giovanni

dflogeras
Posts: 195
Joined: Tue Sep 03, 2013 8:16 pm
Has thanked: 3 times
Been thanked: 15 times

Re: Sleeping in Tickless mode

Postby dflogeras » Wed Jul 28, 2021 2:16 pm

Thanks. I tried that and I think I am still doing something against the rules.

So now when I wake, I call (with the system locked)

Code: Select all

stm32_clock_init(); // to re-set my clock ladder with proper timings
halInit(); // Seems to be required after the above or else ST (TIM2) doesn't resume action
chSysInit(); // As suggested


However, now only my main thread keeps moving, while the two blinker threads never wake from their final sleep calls before halting the CPU. If I manually wake them using chSchReadyI() and chSchRescheduleS(), they begin to run but get into an inconsistent state because the scheduler thinks there are still timers running, but the hal driver crashes when it attempts to re-arm the ST timer since it is not running.

The only way I seem to be able to make it work, is If I stop and destroy the threads prior to halting the CPU, then recreate them after the above reset code. However, then I'll lose all state and pay for the init/destroy time.

I must be missing something.

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

Re: Sleeping in Tickless mode

Postby Giovanni » Wed Jul 28, 2021 8:33 pm

Hi,

chSysInit() resets the OS state, there are no more active threads after you do that, you need to create them again.

Try the following:

1) Make sure to do this from within the main() thread.
2) Disable interrupts.
3) chSysDisable().
4) stm32_clock_init()
5) halInit()
6) chSysInit()
7) Create all your threads again.

You could also just jump to _crt0_init and let the system reinitialize fully, it is basically the same but also the C runtime is reinitialized (variables, constructors etc).

The problem is that when the clock switches to MSI all timers become much slower so the timings are no more accurate, a period of 1 seconds could become one minute. This is why restarting the OS is actually safer. This is an STM32 behaviour, not something we can fix.

Alternatively you may use a sleep state (halt ?) that does not shut down clocks and interrupts are still served. In this case you don't need to reinitialize anything.

Giovanni

dflogeras
Posts: 195
Joined: Tue Sep 03, 2013 8:16 pm
Has thanked: 3 times
Been thanked: 15 times

Re: Sleeping in Tickless mode

Postby dflogeras » Thu Jul 29, 2021 11:37 am

Aha, that's what I was missing. I (stupidly) assumed the threads were left alone, but I guess I wasn't thinking that "restarting" the OS was akin to a reboot. It also explains the undefined behaviour I was seeing when using dangling thread_t pointers from before the restart.

It all makes sense now, and works reliably. Thank you!


Return to “STM32 Support”

Who is online

Users browsing this forum: No registered users and 4 guests