Page 1 of 1
Changing MSI clock in idle task hooks
Posted: Wed Nov 16, 2016 2:32 pm
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
Re: Changing MSI clock in idle task hooks
Posted: Wed Nov 16, 2016 5:08 pm
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
Re: Changing MSI clock in idle task hooks
Posted: Wed Nov 16, 2016 5:18 pm
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]
Re: Changing MSI clock in idle task hooks
Posted: Wed Nov 16, 2016 5:21 pm
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
Re: Changing MSI clock in idle task hooks
Posted: Wed Nov 16, 2016 7:35 pm
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
Re: Changing MSI clock in idle task hooks
Posted: Wed Nov 16, 2016 8:00 pm
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
Re: Changing MSI clock in idle task hooks
Posted: Wed Nov 16, 2016 8:07 pm
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.
Re: Changing MSI clock in idle task hooks
Posted: Wed Nov 16, 2016 8:09 pm
by Giovanni
Then just don't wait, let it run while it changes.
Giovanni
Re: Changing MSI clock in idle task hooks
Posted: Wed Nov 16, 2016 8:17 pm
by vrollei
Ok, thanks a lot!
I will try it and it seems I am wrong about static MSI and prescalers.