
void HAL_PWR_EnterSTANDBYMode(void)
{
/* Select Standby mode */
SET_BIT(PWR->CR, PWR_CR_PDDS);
/* Set SLEEPDEEP bit of Cortex System Control Register */
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
/* Request Wait For Interrupt */
__WFI();
}
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
HAL_PWR_EnterSTANDBYMode();

The device exits the Standby mode when an external reset (NRST pin), an IWDG reset, a rising edge on the WKUP pin, or an RTC alarm / wakeup / tamper /time stamp event occurs.
I presume you're not using one of the wake-up, exti, rtc, iwdg peripherals/pins for any other purpose? If so disable them, clear flags, etc. before entering standby. I see one mention in the errata on standby, that if multiple wake-up sources in standby are enabled, it could cause an instant reset.
#define USB_CF *(volatile uint32_t*) (USB_OTG_FS_PERIPH_BASE+GAHBCFG)
USB_CF &= ~1 #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
portNVIC_SYSTICK_CTRL_REG = 0UL;Only hard reset, RTC, IWDG, WKUP event can wake up the CPU.
Standby: HF OSC shuts down, voltage regulators shut down. All SRAM and register state is lost, except for in RTC domain. Only hard reset, RTC, IWDG, WKUP event can wake up the CPU.
SET_BIT(PWR->CR, PWR_CR_PDDS); // select standby mode
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); // Set SLEEPDEEP bit
__WFI();
CLEAR_BIT(PWR->CSR, 0x00000100U); // disable WKUP pin, just in case
SET_BIT(PWR->CR, PWR_CR_PDDS); // select standby mode
TopLED(true); // this pulse comes out
TopLED(false);
TopLED(true); // this pulse comes out
TopLED(false);
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); // Set SLEEPDEEP bit
TopLED(true); // this pulse comes out, and DAC outputs are seen floating at this point
TopLED(false);
TopLED(true); // this pulse doesn't come out
TopLED(false);
__WFI // this is obviously never reached
And you can't possibly get any internal interrupts. Which confirms the quoted text above is probably spot on.
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); // Set SLEEPDEEP bit
__WFI();
TopLED(true); // this pulse doesn't come out
TopLED(false);
__WFI();
TopLED(true);
TopLED(false);
if you hit that __WFI() with a masked interrupt pending of *any* type, the __WFI() effectively becomes a NOP
Another gotcha: IIRC, if you hit that __WFI() with a masked interrupt pending of *any* type, the __WFI() effectively becomes a NOP.
Go to the NVIC and clear all pending IRQ vectors.
Go to the RCC bits and turn off all peripherals.
do you also observe current measurements of your system? A 168MHz CPU going to effectively a shutdown state should show some difference in power state of the system. Perhaps that's a way to know if it's working (plotting current vs sleep trigger on o'scope could also be useful).

// 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();
// CPU clock stops, DAC outputs float, etc
// ** Code after this point is not executed (checked by waggling GPIO) **
hang_around_us(500);
__WFI(); // 2nd one to handle some weird cases
// Should never get here, but if we did, we want to start with a freshly
// initialised unit
reboot();
satisfactory
All relevant caps are ceramics.
But what you can't see on the above trace is how long the VCC remains above 2.3V. It is a long time... because everything else has died. Also the above pic is from pulling out the USB cable, which kills the 5V rail almost instantly and the 3.3V rail starts to drop within ~100us of that. In normal circumstances the "power failure" will be a loss of 24V DC input to a switch mode PSU which generates its outputs down to about 10V DC in. The USB power option is really just for mucking about on the bench, config after the box was opened, etc. Parts of the product are non-functional with just USB power, for complicated reasons. And if I want to do a better power fail detect off the DC IN (which is isolated, btw) I can do that with a $0.10 optoisolator and then I will have ~100ms warning.
Quoteif you hit that __WFI() with a masked interrupt pending of *any* type, the __WFI() effectively becomes a NOP
It doesn't appear to be as simple; I have not disabled e.g. a TIM6 1kHz interrupt, but it does not terminate the Standby mode. Perhaps you mean if one executes __WFI and at that instant there is an interrupt pending, the __WFI is skipped. But how could one avoid that? If I clear all "IP" bits (lots of them around) there is no guarantee that one of them won't get set when I then execute the __WFI. One would have to disable all interrupts individually, clear the IP bits, and wait a bit. Is that really the procedure??
Honestly in that case I'd think about working a NVIC_SystemReset() in there before sleeping to help with cleaning the slate.
static inline void reboot(void)
{
// Ensure all outstanding memory accesses including buffered write are completed before reset
__ASM volatile ("dsb 0xF":::"memory");
// Keep priority group unchanged
SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
SCB_AIRCR_SYSRESETREQ_Msk );
__ASM volatile ("dsb 0xF":::"memory");
// wait until reset
for(;;)
{
__NOP();
}
}

Where in the RM does it say that a __WFI is skipped if there is an int pending? This is a 32F417.

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(); // This actually does the "shutdown"
// CPU clock stops, DAC outputs float, etc
// ** Code after this point is not executed (checked by waggling GPIO) **
// But sometimes __WFI can fail - if e.g. there is an interrupt pending
// e.g. USB serial FLASH read interrupt can be blocked for 200-300us.
hang_around_us(500); // wait for a bit longer than a FLASH read
for (uint32_t i=0; i<100000; i++)
{
__WFI();
}
// Should never get here, but if we did, we want to start with a freshly
// initialised unit
reboot();
Amazing, because in your page above it states
which is the conclusion I came to also. If the 1st __WFI gets skipped, eventually you will hit one which works.
So a lot more margin./**
* @brief Disables the MAC transmission.
* @param heth pointer to a ETH_HandleTypeDef structure that contains
* the configuration information for ETHERNET module
* @retval None
*/
static void ETH_MACTransmissionDisable(ETH_HandleTypeDef *heth)
{
__IO uint32_t tmpreg1 = 0U;
/* Disable the MAC transmission */
(heth->Instance)->MACCR &= ~ETH_MACCR_TE;
/* Wait until the write operation will be taken into account:
at least four TX_CLK/RX_CLK clock cycles */
tmpreg1 = (heth->Instance)->MACCR;
ETH_Delay(ETH_REG_WRITE_DELAY);
(heth->Instance)->MACCR = tmpreg1;
}mysterious delay