Changing MSI clock in idle task hooks

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

Moderator: RoccoMarco

Post Reply
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Changing MSI clock in idle task hooks

Post by vrollei »

Hello,

is it possible to change MSI clock in CH_CFG_IDLE_ENTER_HOOK/CH_CFG_IDLE_LEAVE_HOOK to achieve lowest power consumption mode?

I have implemented scenario shown below but system crashes before calling IDLE_LEAVE_HOOK:

IDLE_ENTER_HOOK_BEGIN
disable AHB / APB1 / APB2 peripherals
stop STM32_ST_TIM
change MSI range to lowest and wait until MSI is stable
calculate and set new STM32_ST_TIM prescal
start STM32_ST_TIM
put STM32 to low power sleep
IDLE_ENTER_HOOK_END

IDLE_LEAVE_HOOK_BEGIN
stop STM32_ST_TIM
change MSI range to STM32_MSIRANGE and wait until MSI is stable
calculate and set new STM32_ST_TIM prescal
start STM32_ST_TIM
enable AHB / APB1 / APB2 peripherals
IDLE_LEAVE_HOOK_END

--
Vitaly
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: Changing MSI clock in idle task hooks

Post by Giovanni »

Hi,

Those hooks have exactly that purpose.

There could be several causes for the crash, maybe a stack overflow if you call functions from the hook. Consider also that the hooks are called from within a critical zone, do not call HAL or RT functions from inside hooks, keep the code very simple.

Giovanni
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Changing MSI clock in idle task hooks

Post by vrollei »

Giovanni,

thanks for reply!

This is enter idle hook:

[font=Courier New]palSetGroupMode(GPIOH, 0xFFFF, 0, PAL_MODE_INPUT_ANALOG | PAL_STM32_OSPEED_LOWEST | PAL_STM32_PUPDR_FLOATING);
palSetGroupMode(GPIOE, 0xFFFF, 0, PAL_MODE_INPUT_ANALOG | PAL_STM32_OSPEED_LOWEST | PAL_STM32_PUPDR_FLOATING);
palSetGroupMode(GPIOD, 0xFFFF, 0, PAL_MODE_INPUT_ANALOG | PAL_STM32_OSPEED_LOWEST | PAL_STM32_PUPDR_FLOATING);
palSetGroupMode(GPIOC, 0xFFFF, 0, PAL_MODE_INPUT_ANALOG | PAL_STM32_OSPEED_LOWEST | PAL_STM32_PUPDR_FLOATING);
palSetGroupMode(GPIOB, 0xFFFF, 0, PAL_MODE_INPUT_ANALOG | PAL_STM32_OSPEED_LOWEST | PAL_STM32_PUPDR_FLOATING);
palSetGroupMode(GPIOA, 0x9FFF, 0, PAL_MODE_INPUT_ANALOG | PAL_STM32_OSPEED_LOWEST | PAL_STM32_PUPDR_FLOATING);

rccDisableAHB(RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN |
RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIODEN |
RCC_AHBENR_GPIOEEN | RCC_AHBENR_GPIOHEN |
RCC_AHBENR_DMA1EN | RCC_AHBENR_DMA2EN | RCC_AHBLPENR_FLITFLPEN, true);
rccDisableAPB2(RCC_APB2LPENR_SYSCFGLPEN | RCC_APB2ENR_TIM9EN | RCC_APB2ENR_TIM10EN |
RCC_APB2ENR_TIM11EN |RCC_APB2ENR_ADC1EN |
RCC_APB2ENR_SPI1EN | RCC_APB2ENR_USART1EN, true);
rccDisableAPB1(RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM4EN |
RCC_APB1ENR_TIM6EN | RCC_APB1ENR_TIM7EN | RCC_APB1ENR_WWDGEN |
RCC_APB1ENR_SPI2EN | RCC_APB1ENR_SPI3EN | RCC_APB1ENR_USART2EN |
RCC_APB1ENR_USART3EN | RCC_APB1ENR_I2C1EN | RCC_APB1ENR_I2C2EN |
RCC_APB1ENR_USBEN | RCC_APB1ENR_DACEN | RCC_APB1ENR_COMPEN, true);

// Stop TIM5
STM32_ST_TIM->CR1 &= 0xFFFE;

// Set MSI source to 131k
RCC->ICSCR &= ~(STM32_MSIRANGE_128K);

while ((RCC->CR & RCC_CR_MSIRDY) == 0)
; /* Waits until MSI is stable. */


// New TIM5 prescale
STM32_ST_TIM->PSC = (131000 / OSAL_ST_FREQUENCY) - 1;

// Start TIM5
STM32_ST_TIM->CR1 |= 0x0001;

FLASH->ACR |= FLASH_ACR_SLEEP_PD;

PWR->CR |= (PWR_CR_ULP | PWR_CR_LPSDSR);

SCB->SCR &= (uint32_t) ~((uint32_t) SCB_SCR_SLEEPDEEP);[/font]
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: Changing MSI clock in idle task hooks

Post by Giovanni »

You need to understand where it crashes and why, the code in itself looks good, probably the cause is not in that code.

Giovanni
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Changing MSI clock in idle task hooks

Post by vrollei »

That is the problem to trace root cause.
There is some call after exit from WFI on TIM5 isr and debugger shows only call stack attached as image.

--
Vitaly
Attachments
Screen Shot 2016-11-16 at 21.27.55.png
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: Changing MSI clock in idle task hooks

Post by Giovanni »

I don't know, it could be an overflow, try to disable portions of your code until you find what causes it.

Just a note:

Code: Select all

// Set MSI source to 131k
RCC->ICSCR &= ~(STM32_MSIRANGE_128K);

while ((RCC->CR & RCC_CR_MSIRDY) == 0)
; /* Waits until MSI is stable. */


This is really bad, you don't want to wait in that code, it will just kill the context switch performance. Setup the MSI frequency statically in mcuconf.h.

Giovanni
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Changing MSI clock in idle task hooks

Post by vrollei »

But this is exactly what I need to do: slow down CPU clock to turn on low power sleep mode with active Chibios virtual timers.
It can not be done with static MSI frequency and changing just AHB and APB1 prescalers.
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: Changing MSI clock in idle task hooks

Post by Giovanni »

Then just don't wait, let it run while it changes.

Giovanni
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Changing MSI clock in idle task hooks

Post by vrollei »

Ok, thanks a lot!

I will try it and it seems I am wrong about static MSI and prescalers.
Post Reply