Freertos waking up from Deepsleep in stm32l4

Hi,

I’m working on stm32l4 MCU with freertos. My application task stopped working after waking up from stop2 mode. If I do not enter into stop2 mode its works fine. But if its go to stop2 mode and wakeup it get stuck after a while. What I found is if I do not set the deepsleep bit in stop2 mode it works fine as soon as I set that bit, after a while couple of task stopped and those task have long delay as well about 10sec.

If anyone have gone through this situation please help me or do you have any idea why deepsleep bit making problem.

Thanks

Are you using tickless idle?

Also remember that STOP mode disables some clocks “permanently”, which means after wake-up you have to re-enable them. Similarly, waking from STOP mode selects a specific clock to be SYSCLK, so if that’s not the one you want, you have to re-select the desired SYSCLK.

No, I’m using different task for stop2 which will allow device to go stop2 mode when all task are suspended.

I’m check the SFR register such as. RCC, PWR, CSR etc before going to sleep and after waking up all values are same.

  • The clock configuration that might change due to STOP mode is held in RCC->CR and RCC->CFGR. If you’re using MSI for SYSCLK (or HSI for SYSCLK with STOPWUCK set) then these registers won’t change with stop mode.
  • What is happening when the application “gets stuck”? Can you see in the debugger what the system is doing?
  • Can you post the task code that puts the system to sleep and wakes it up again?

Hi Jeff,

I have looked in STOPWUCK bit its cleared before going to sleep and after waking up.

I’m using USART with dma with 1MB/s baudrate. task stop at some point while waiting for the data and one task are sending data to the Queues and other receive the data in the queue and transmit through the usart. if the problem with task priorities than why its not get stuck when deepsleep bit not set. I run application for couple of days with high traffic but it never crash or stuck but as soon as seepsleep bit set it start getting stuck after a while.

Hi Jeff,

Here is the clock setting before going to sleep or when it reset and first time clock configured.

clock init

This is After sleep,

after sleep

Here is the Task list before going to sleep;

Those screen shots of the initialization structure are showing the wrong thing. If you want to be sure STOP mode did not change your clock config, you should check the registers RCC->CR and RCC->CFGR before and after STOP mode.

I think your issue is probably trying to use DMA and/or the USART in STOP mode. They don’t work in stop mode and would likely cause your exact symptoms if you try to use them in STOP mode.

Hi Jeff,

before doing to sleep I’m doing deinit USART and DMA CLK and after waking up I’m also doing uart Init and dma Init as well.

Here are the Screen shot before and after the stope mode for RCC->CR and RCC_CFGR reg

after_RCC_CFGR after_RCC_CR RCC_CFGR RCC_CR

  • Can you “pause” execution in the debugger to see what these tasks are doing when they are “stuck” but in the READY state? Then you might find an important clue.
  • Can you post the code the enters STOP mode? Then we might be able to suggest a method to divide and conquer. For example, the problem may be in the code to enter/exit stop mode instead of stop mode itself.

Yes sure. I find that my dma and usart not getting work properly after waking up: I can’t debug that ready task because they are stop execution I tried to put breakpoints as well they are not executing.

this the Sleep function
void Sleep(void){
bool can_sleep = true;
vTaskDelay(10);
if (errts_awake_tasks)
can_sleep = false;

if (wakeup_required())
	can_sleep = false;
if(UPDATE_ANALOG) can_sleep = false;   // if analog +24v loop supply ON from diagnostic will keep wake up for 2 minutes.

/* Don't sleep while registered tasks are awake */
if (can_sleep){

	vTaskDelay_Out = Set;
	Leds_ctrl_db = 0x00; Leds_ctrl_IO = 0x00; // turn off all leds
	Daug_Board_PinSet(IO_LED_ALL_OFF, DB_LED_ALL, ALL_OFF);

	USB_DEINIT();
	while (1){


		/*Disabling Modules and powers............*/
		DisablePWR();
		DeInit_Modules();
		disable_clocks();

		/*Enter in STOP2 MODE.....................*/
		HAL_SuspendTick();
		HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
		HAL_ResumeTick();

		/*Enabling and Initializing the modules and powers........*/
		if (Init_Modules()){

			HAL_Delay(10);
			Daug_Board_PinSet(IO_LED_ALL_OFF, DB_LED_ALL, ALL_OFF);

			if (wakeup_required()){
				break;
			}

			/* else just keep the OK LED on for 100msec and then back to sleep. */
			ERRTS_Delay(100);
			Daug_Board_PinSet(IO_LED_ALL_OFF, DB_LED_ALL, ALL_OFF);
		}
	}

	vTaskDelay_Out = clear;
}
vTaskDelay(10);

#ifdef EN_BLE
Init_BLEChip_Uart();
#endif
}

A couple of thoughts.

  1. Are you absolutely sure there’s no possibility of a FreeRTOS context switch occurring when can_sleep is true? If there is a context switch during your preparations for stop mode or during your recovery after stop mode, the other task allowed to run could be very confused – especially if it uses the HAL. One specific case worth extra consideration is the interrupt that wakes you from stop mode. Be sure its ISR does not induce a context switch. To this end, you might consider calling vTaskSuspendAll() and vTaskResumeAll() in the same places where you set vTaskDelay_Out. That will protect you from context switches.

  2. To see if stop mode itself is really the culprit, you might try this experiment:

Replace this:

    HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);

with this proposed test (hack):

    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    __DSB();
    __WFI();
    __ISB();
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

This test code should use sleep mode instead of stop mode, so it should tell you whether stop mode is really at fault here.

Hi Jeff,

I tried vTaskSuspendAll() it still didn’t fixed the problem.

It also tried proposed test as well it gives hars fault on __DSB(). Below is the fault details,

  • Bus, memory management or usage fault (FORCED)

  • Attempt to switch to invalid state.

Actually, hardfault was happening because I was initialising the clocks.

Yes, second solution solve the problem, but I have to use stop2 mode because for current consumption.

void HAL_PWREx_EnterSTOP2Mode(uint8_t STOPEntry)
{
/* Check the parameter */
assert_param(IS_PWR_STOP_ENTRY(STOPEntry));

/* Set Stop mode 2 */
MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP2);

/* Set SLEEPDEEP bit of Cortex System Control Register */
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));

/* Select Stop mode entry --------------------------------------------------/
if(STOPEntry == PWR_STOPENTRY_WFI)
{
/
Request Wait For Interrupt */
__WFI();

}
else
{
/* Request Wait For Event /
__SEV();
__WFE();
__WFE();
}
/
Reset SLEEPDEEP bit of Cortex System Control Register */
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));

}

If I do not set SCB->SCR register it start working but if I set does not work.

Solution:

Don’t use systick timer as a timebase. Use any of the TIMx as a timebase solve the problem.

Thanks

Thanks for taking the time to report your solution. It seems many people have struggled with the problems caused by letting the ST HAL use systick for its timebase.