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
Changing MSI clock in idle task hooks
Moderator: RoccoMarco
- 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
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
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
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]
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]
- 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
You need to understand where it crashes and why, the code in itself looks good, probably the cause is not in that code.
Giovanni
Giovanni
Re: Changing MSI clock in idle task hooks
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
There is some call after exit from WFI on TIM5 isr and debugger shows only call stack attached as image.
--
Vitaly
- 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
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:
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
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
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.
It can not be done with static MSI frequency and changing just AHB and APB1 prescalers.
- 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
Then just don't wait, let it run while it changes.
Giovanni
Giovanni
Re: Changing MSI clock in idle task hooks
Ok, thanks a lot!
I will try it and it seems I am wrong about static MSI and prescalers.
I will try it and it seems I am wrong about static MSI and prescalers.