cancel
Showing results for 
Search instead for 
Did you mean: 

Is this the right way to "shut down" a 32F417?

PHolt.1
Senior III

I am implementing a data save procedure when power fail is detected and want to shut down as much stuff as possible to give myself the most time to copy some data into FLASH.

Shutting down the CPU has many modes which are quite complicated. I have been reading the RM and various appnotes. Googling around shows a lot of people are having problems.

Is this a right way to do it? It never needs to come out of it, and it must not come out of it for any interrupt

CLEAR_BIT(PWR->CSR, 0x00000100U);		// disable WKUP pin, just in case
		#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
		portNVIC_SYSTICK_CTRL_REG = 0UL;		// stop systick, just in case (also stops RTOS)
		SET_BIT(PWR->CR, PWR_CR_PDDS);			// select standby mode
		SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));	// Set SLEEPDEEP bit
		__WFI();								// request "wait for interrupt"

Some of the above is out of HAL_PWR_EnterSTANDBYMode().

I don't get what __WFI is supposed to do.

Thank you for any help or suggestions.

26 REPLIES 26

> I don't get what __WFI is supposed to do.

0693W00000KcNy0QAF.pngJW

PHolt.1
Senior III

Thank you. I didn't know that manual existed. Still, the answer is not simple. Quoting, page 48,

"Normally, the processor wakes up only when it detects an exception with sufficient priority to

cause exception entry."

and that could be a whole lot of things.

I wondered if one has to disable ALL interrupts before doing WFI. I am disabling WKUP and Systick.

> I wondered if one has to disable ALL interrupts before doing WFI.

All interrupts cause wakeup, so you have to disable all those you don't want to cause wakeup. It's your program, you surely know what interrupts you have enabled. You would want to "deinitialize" (stop, disable, whatever) most of peripherals causing interrupts, before entering sleep, anyway.

Alternatively, use WFE. Events can be caused by interrupt sources which go through EXTI, see External interrupt/event line mapping subchapter of EXTI chapter in RM, as enabled in EXTI_EMR register.

JW

PHolt.1
Senior III

> All interrupts cause wakeup

I am confused now. I am using Standby, not Sleep. This is my current code

		// stop systick, just in case (also stops RTOS)
 
		#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
		portNVIC_SYSTICK_CTRL_REG = 0UL;
 
		// Issue the (non blocking) FLASH write command (takes about 20us)
		// This is a Buffer 2 -> SSA page 3 write (page 3 = FLASH page 4099)
 
		FLASH_WritePage_NoErase_Buf2(xxxx);
 
		// At this point it would be good to shut down anything that draws a lot of power
 
 
		display_cls();					// Blank LEDs on 655 board
		ARINC_reset();					// Stop any ARINC429 activity
		GPIOD->BSRR = 0x0000fc80;			// Turn off all LEDs and P3EN
 
		// Enter CPU standby mode. Some is out of HAL_PWR_EnterSTANDBYMode().
 
		CLEAR_BIT(PWR->CSR, 0x00000100U);		// disable WKUP pin, just in case
		SET_BIT(PWR->CR, PWR_CR_PDDS);			// select standby mode
		SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));	// Set SLEEPDEEP bit
		__WFI();								// 
 
		// Should never get here
 
		while(true){}

Pavel A.
Evangelist III

If you do not have a backup source or do not expect power to return [soon], low power states and WFI/WFE are not relevant at all. "For in much wisdom is much grief".

Just disable interrupts, write your stuff to flash and loop until power down or reset.

PHolt.1
Senior III

The reason for "shutting down" the CPU is to reduce power draw i.e. reduce the rate at which the 3.3V rail falls. Once it goes below 2.3V, the FLASH chip will go out of spec.

I do have a few ms to play with but no more.

Do interrupts bring the CPU out of Standby?

> Do interrupts bring the CPU out of Standby?

No. Sorry, I overlooked you use Standby.

Meantime, you might want to check DBGMCU_CR.DBG_STANDBY, and/or try without debugger connected.

JW

PHolt.1
Senior III

Interesting. I found this function and it isn't referenced anywhere, so the reg should contain its reset value.

/**
  * @brief  Enable the Debug Module during STANDBY mode
  * @retval None
  */
void HAL_DBGMCU_EnableDBGStandbyMode(void)
{
  SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
}

However, I am not testing this stuff under debug mode (F11 compilation in Cube) which is what is used with breakpoints etc. I simply would not expect this stuff to work with breakpoints... I just compile and load into CPU FLASH. Not sure if that counts as "debug in standby mode".

I tried it with the debugger disconnected and the rate of VCC fall is the same.

And

uint32_t fred;
fred=DBGMCU->CR;

returns 00000000.

I should say that while I am not able to measure the CPU current directly, the indications (from the rate of fall of VCC after the Standby code is issued) are that it IS working. The reason I am taking care over this is because IF some event can bring the CPU out of Standby, that will mess up my scheme and it could happen when the customer gets it ; - )

PHolt.1
Senior III