2022-09-10 07:59 AM
Dears,
Currently I'm working on a BLDC project, and with the MC SDK, we can control the motor.
And we also want to make the MCU(STM32F4) into STOP mode to save some power, the issue is the MCU can not goes into STOP mode, anyone tried this before?
The code:
void McuEnterStopMode(void)
{
__disable_irq();
HAL_CAN_Stop(&hcan1);
HAL_SuspendTick();
HAL_TIM_Base_Stop(&htim1);
HAL_TIM_Base_Stop(&htim3);
HAL_NVIC_DisableIRQ(TIM1_BRK_TIM9_IRQn);
HAL_NVIC_DisableIRQ(TIM1_BRK_TIM9_IRQn);
HAL_NVIC_DisableIRQ(TIM3_IRQn);
HAL_NVIC_DisableIRQ(TIM7_IRQn);
HAL_NVIC_DisableIRQ(FPU_IRQn);
htim1.Instance->CR1 &= ~(TIM_CR1_CEN);
htim3.Instance->CR1 &= ~(TIM_CR1_CEN);
htim1.Instance->SR = 0;
htim3.Instance->SR = 0;
TIM7->CR1 &= ~(TIM_CR1_CEN);
TIM7->SR = 0;
TIM3->CR1 &= ~(TIM_CR1_CEN);
TIM3->SR = 0;
ClearFPU();
HAL_NVIC_ClearPendingIRQ(TIM1_BRK_TIM9_IRQn);
HAL_NVIC_ClearPendingIRQ(TIM1_BRK_TIM9_IRQn);
HAL_NVIC_ClearPendingIRQ(TIM3_IRQn);
HAL_NVIC_ClearPendingIRQ(TIM7_IRQn);
HAL_NVIC_ClearPendingIRQ(FPU_IRQn);
// 3. 进入stop
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
__enable_irq();
HAL_ResumeTick();
HAL_Init();
MX_NVIC_Init();
SystemClock_Config();
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/SYS_TICK_FREQUENCY);
HAL_CAN_Start(&hcan1);
HAL_TIM_Base_Start(&htim1);
HAL_TIM_Base_Start(&htim3);
HAL_NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
HAL_NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
HAL_NVIC_EnableIRQ(TIM7_IRQn);
HAL_NVIC_EnableIRQ(FPU_IRQn);
}
Before calling below code, I checked, no pending interrupt, also for EXTI.
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
And I had tried if I do not call the MX_MotorControl_Init(line30) in main, the sleep and wakeup both work, anyone can provide some suggestions?
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_TIM1_Init();
MX_TIM3_Init();
MX_USART1_UART_Init();
MX_MotorControl_Init();
MX_SPI2_Init();
MX_SPI1_Init();
MX_UART5_Init();
MX_CAN1_Init();
/* Initialize interrupts */
MX_NVIC_Init();
/* USER CODE BEGIN 2 */
Thanks�?
Solved! Go to Solution.
2022-09-10 06:01 PM
The code indeed is an absolute nonsense. Read the reference manual, look at examples and learn what a Stop mode and a Sleep modes are and how to use them.
https://m0agx.eu/2021/04/16/stm32-stop-mode-exti-wakeup-example-without-hal/
2022-09-10 08:27 AM
Your void McuEnterStopMode(void) is little ******** force. In normal situation your code need handle all in loop and if all is clear use only
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
for testing place gpio led off before this line and on after. (no debug)
2022-09-10 06:01 PM
The code indeed is an absolute nonsense. Read the reference manual, look at examples and learn what a Stop mode and a Sleep modes are and how to use them.
https://m0agx.eu/2021/04/16/stm32-stop-mode-exti-wakeup-example-without-hal/
2022-09-10 09:52 PM
Thanks for the comments.
I understood the last half, but I'm not sure wherther this is usful, because I tired without calling the "MX_MotorControl_Init", then with debug, I can see the MCU in stop mode, and wake up from a hardware pin, with the debug connected.
For the first half, I'm not sure whther I get the point, in my McuEnterStopMode, I just disabled some Peripheral and cleared the interrupt pending register.
What do you mean by " handle all in loop and if all is clear use only", can you make this more specific, would be greate you could share a reference code, thanks again for your suggestion.
2022-09-10 09:58 PM
Thanks for your feedback.
But I don't think such kind of comments would help, did you checked my code, and the code example from ST with Hal, actually the example you shared is amost the same, difference is I'm using Hal, your are without HAL.
it is clearly mentioned in the reference manuall, all interrupt pending bit should be cleared, also for EXTI, but if you check your example, and the one I mentioned from ST, none is related to this.
I know there is something wrong with my code, and if I commented "MX_MotorControl_Init", the stop and wakeup is working.
So would be great if you could share some suggestions on how to imprve rather than a very simple example, because such a simple demo for sure is working, when we introduce more in the project, it becames more complicate.
Anyway, thanks again for your comments.
2022-09-10 11:58 PM
Simply as first comment MC Init and leave in func only
void McuEnterStopMode(void)
{
// 3. 进入stop
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
SystemClock_Config(); // if PLL HSE ...
}
and test code . Better is add LED and no debug.
Every interrupt have callback with clear and service and if ocur before EnterSTOP flag is ok serviced and no brute forcing required. Stop mode stops too timers usw.
After this work add MC Init and check registers and setup before stop and after wake.
2022-09-11 08:54 AM
Careless reading is the thing that doesn't help...
> it is clearly mentioned in the reference manuall, all interrupt pending bit should be cleared
Reference manual says that the low-power mode will only be entered if there are no interrupts pending, not that the code, which enters low-power mode, must clear those interrupts. If the code clears those interrupts, then it looses them and that's a flaw. Instead the code should allow the WFI instruction to skip entering the Stop mode, return the CPU to normal processing, process the pending interrupts normally and after that it can try entering the Stop mode again.
> the example you shared is amost the same
It has an important differences. The most important one is that it explains and shows that after wake-up the clocks must be reconfigured before enabling interrupts, otherwise the pending interrupt code will run with the wrong clock configuration.
__disable_irq();
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();
ReconfigureClocks();
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
__enable_irq();
Yes, as simple as that... Of course the PWR_CR register must be configured accordingly. If Standby is not used, it can be done just once at startup. The function ReconfigureClocks() must work correctly regardless if the Stop mode was actually entered or not. Basically it should just skip the reconfiguration, if the Stop mode was not entered.
And also read this closely related article:
2022-09-11 09:08 AM
ST's HAL and examples are broken... For more information read my post and the linked article above.
2022-09-11 09:08 AM
Thanks for the suggestion, I think the issue is from the debug tool.
Once I disconnect the debug, with the two lines, it works with the MC init function.
Thanks again for the support.
2022-09-11 10:46 AM
Thanks for the informaiton.
One last question(maybe stupid as this is the first time to use this STOP mode), let's say we reduce the current for MCU to less than 1ma, but still we need the external power supply to keep the MCU in STOP mode, and currently I'm using a TPS5430 DCDC as the power supply, and I found that only to power this dcdc, without any load, the current is about 5ma(12V), which is too big for my project.
My question would be: do you have any suggestions for this external power supply part?
should we shut it down and add a small battery to power the MCU in stop mode, or other solution could reduce the power consumption of the power supply, thanks.