5.16 PWR Guide

This chapter describes the file composition and the 11 public functions of the PWR driver in the N32G41x standard peripheral library: the threshold and filter configuration of the programmable voltage detector (PVD), the NRST digital filter and IWDG reset enabling, and entry into the SLEEP and STOP low-power modes together with the main regulator (MR) low-power configuration. The PVD, SLEEP and STOP examples demonstrate a voltage-threshold interrupt, key wake-up from SLEEP, and a STOP wake-up that rebuilds the system clock. Read the power modes, PVD and the PWR register bit definitions together with the “Power control (PWR)” chapter of the user manual, and take the errata sheet as the authority on known chip issues.

5.16.1 Related files

Relative path Purpose
firmware/n32g41x_std_periph_driver/inc/n32g41x_pwr.h Defines the PVD threshold levels, the PWR_CTRL2 write-protection key and the SLEEP, STOP and MR low-power entry macros, and declares 11 public functions in the five sections PVD configuration, reset configuration, low-power mode, write protection and flag management
firmware/n32g41x_std_periph_driver/src/n32g41x_pwr.c Implements those 11 functions: read-modify-write of PWR_CTRL, PWR_CTRL2 and SCB_SCR, entry into the low-power modes through WFI or WFE, and reading of the PVD flag
projects/n32g41x_EVAL/examples/PWR/ PWR example root directory, containing 3 examples: PVD, SLEEP and STOP
projects/n32g41x_EVAL/examples/PWR/PVD/ Directory layout of the PVD example: MDK-ARM/, EWARM/, inc/, src/, readme.txt
projects/n32g41x_EVAL/bsp/ Board support files shared by the three examples: the button and LED definitions in n32g41x_stb.h, and the millisecond delay and log output functions

5.16.2 API reference

Search API11 functions

The following 11 public functions are listed in the declaration order of n32g41x_pwr.h in 5 groups; each entry gives a summary and the original comment above the function in n32g41x_pwr.c.

PVD configuration

PWR_PvdEnable, PWR_PVDFilterWidthSet, PWR_PVDLevelConfig

Reset configuration

PWR_NRSTFilterWidthSet, PWR_EnableIWDGReset

Low-power mode

PWR_EnterSLEEPMode, PWR_EnterSTOPMode, PWR_ConfigMRLPMode, PWR_ConfigMRLPDelay

Write protection

PWR_CTRL2WriteProtectionEnable

Flag management

PWR_GetFlagStatus

void PWR_PvdEnable(FunctionalState Cmd)Enables or disables the Power Voltage Detector(PVD).
Source comment
name    PWR_PvdEnable.
fun     Enables or disables the Power Voltage Detector(PVD).
param   Cmd:
          - ENABLE
          - DISABLE
return  none

Use note: The implementation sets or clears the PVDEN bit of PWR_CTRL according to Cmd.

void PWR_PVDFilterWidthSet(uint8_t filter_value)Adjusting the PVD Filter Control Count value.
Source comment
name    PWR_PVDFilterWidthSet.
fun     Adjusting the PVD Filter Control Count value.
param   filter_value(Filter Width = (1/fLSI) * filter_value):
        -0 ~ 0x1F
return  none

Use note: The implementation writes filter_value to the PVDCNT field in bits 18:14 of PWR_CTRL.

void PWR_PVDLevelConfig(uint32_t level)Configures the voltage threshold detected by the Power Voltage Detector(PVD).
Source comment
name    PWR_PVDLevelConfig.
fun     Configures the voltage threshold detected by the Power Voltage Detector(PVD).
param   PWR_PVDLevel (The input parameters must be the following values):
          - PWR_PVD_LEVEL_2V0
          - PWR_PVD_LEVEL_2V2
          - PWR_PVD_LEVEL_2V4
          - PWR_PVD_LEVEL_2V6
          - PWR_PVD_LEVEL_2V8
          - PWR_PVD_LEVEL_3V0
          - PWR_PVD_LEVEL_3V2
          - PWR_PVD_LEVEL_3V4
          - PWR_PVD_LEVEL_3V6
          - PWR_PVD_LEVEL_3V8
          - PWR_PVD_LEVEL_4V0
          - PWR_PVD_LEVEL_4V2
          - PWR_PVD_LEVEL_4V4
          - PWR_PVD_LEVEL_4V6
          - PWR_PVD_LEVEL_4V8
return  none

Use note: The implementation writes level to the PLS field in bits 8:5 of PWR_CTRL; the PWR_PVD_LEVEL_* macros are already valued for that field.

void PWR_NRSTFilterWidthSet(uint16_t filter_value)Adjusting the NRST Filter Control Count value.
Source comment
name    PWR_NRSTFilterWidthSet.
fun     Adjusting the NRST Filter Control Count value.
param   filter_value(Filter Width = (1/fSYSCLK) * filter_value):
        -0 ~ 0x7F
return  none

Use note: The implementation writes filter_value to the NRSTCNT field in bits 25:19 of PWR_CTRL.

void PWR_EnableIWDGReset(FunctionalState Cmd)Configure whether to generate a reset request when the IWDG counter reaches 0.
Source comment
name    PWR_EnableIWDGReset.
fun     Configure whether to generate a reset request when the IWDG counter reaches 0.
param   Cmd:
          - ENABLE
          - DISABLE
return  none.

Use note: The implementation sets or clears the IWDGRSTEN bit of PWR_CTRL according to Cmd.

void PWR_EnterSLEEPMode(uint8_t SLEEPONEXIT, uint8_t PWR_SLEEPEntry)Enters SLEEP mode.
Source comment
name    PWR_EnterSLEEPMode.
fun     Enters SLEEP mode.
param   SLEEPONEXIT (The input parameters must be the following values):
          - PWR_SLEEP_ON_EXIT
          - PWR_SLEEP_NOW
param   PWR_SLEEPEntry (The input parameters must be the following values):
          - PWR_SLEEPENTRY_WFI enter SLEEP mode with WFI instruction
          - PWR_SLEEPENTRY_WFE enter SLEEP mode with WFE instruction
return  none

Use note: The implementation first clears SLEEPDEEP in SCB_SCR, then sets or clears SLEEPONEXIT according to SLEEPONEXIT; with PWR_SLEEPENTRY_WFE it executes __SEV and two __WFE instructions.

void PWR_EnterSTOPMode(uint8_t enter_mode)Enters STOP mode.
Source comment
name    PWR_EnterSTOPMode.
fun     Enters STOP mode.
param   PWR_STOPEntry (The input parameters must be the following values):
          - PWR_STOPENTRY_WFI (enter STOP mode with WFI instruction)
          - PWR_STOPENTRY_WFE (enter STOP mode with WFE instruction)
return  none

Use note: The implementation first sets SLEEPDEEP in SCB_SCR and clears it after exit; with PWR_STOPENTRY_WFE it executes __SEV and two __WFE instructions. The comment names the parameter PWR_STOPEntry, while the header prototype names it enter_mode.

void PWR_ConfigMRLPMode(uint32_t Mode)Configure MR lowpower mode.
Source comment
name    PWR_ConfigMRLPMode.
fun     Configure MR lowpower mode.
param   Mode (The input parameters must be the following values):
          - PWR_MRLPMODE_FIXED
          - PWR_MRLPMODE_AUTO
return  none
note    This register has write protection. Before writing PWR_CTRL2, PWR_CTRL2WriteProtectionEnable()
        function must be called, and then write real value to PWR_CTRL2

Use note: The implementation reads and modifies the MRLPEN bit of PWR_CTRL2; this register is write-protected, so PWR_CTRL2WriteProtectionEnable must be called before writing it.

void PWR_ConfigMRLPDelay(uint16_t delay_value)Adjusting the MR lowpower mode enable delay time.
Source comment
name    PWR_ConfigMRLPDelay.
fun     Adjusting the MR lowpower mode enable delay time.
param   delay_value ((delay time = delay_value*(Tsysclk*2)));
        -0 ~ 0xFFF
return  none

Use note: The implementation writes the low 12 bits of delay_value to the MRLPDLY field in bits 12:1 of PWR_CTRL2.

void PWR_CTRL2WriteProtectionEnable(void)Enable the PWR_CTRL2 registers write protection.
Source comment
name    PWR_CTRL2WriteProtectionEnable.
fun     Enable the PWR_CTRL2 registers write protection.
param   none
return  none
note    This register has write protection. Before writing PWR_CTRL2, PWR_CTRL2WriteProtectionEnable()
        function must be called, and then write real value to PWR_CTRL2

Use note: The implementation rewrites the KEY bit field of PWR_CTRL2 with the write-protection key 0x57103616.

FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG)Checks whether the specified PWR flag is set or not.
Source comment
name    PWR_GetFlagStatus.
fun     Checks whether the specified PWR flag is set or not.
param   PWR_FLAG (The input parameters must be the following values):
          - PWR_PVDO_FLAG       PVD Output flag
return  SET or RESET.

Use note: The implementation reads the bitwise AND of PWR_CTRLSTS and PWR_FLAG; the parameter only lists PWR_PVDO_FLAG, which is the PVDO bit of PWR_CTRLSTS.

5.16.3 Demo descriptions

This section describes the 3 PWR examples: PVD monitors VDD with the programmable voltage detector and prints through an interrupt when the supply crosses the threshold, SLEEP wakes the CPU from sleep mode with the WKUP key, and STOP enters stop mode and rebuilds the system clock after wake-up.

5.16.3.1 PVD voltage-detector interrupt

Example directory: projects/n32g41x_EVAL/examples/PWR/PVD/

Initialize the log UART→configure EXTI Line16 for rising and falling edges→set the PVD threshold to 2.4 V and enable the PVD→wait for VDD to cross the threshold→print above or below the threshold from the PVD interrupt

Item Source analysis
Function Monitors VDD with the programmable voltage detector (PVD);
when the supply crosses the 2.4 V threshold, EXTI Line16 triggers an interrupt that prints on the serial port whether the supply is above or below the threshold.
Source files src/main.c: main, EXTI_Configuration and NVIC_Configuration;
inc/main.h: includes the PWR, EXTI, RCC and GPIO headers and declares those functions;
src/n32g41x_it.c: interrupt handlers, including PVD_IRQHandler;
inc/n32g41x_it.h: interrupt handler declarations;
readme.txt: function, environment and usage;
MDK-ARM/, EWARM/: Keil and IAR projects.
Key configuration The PVD threshold is set to 2.4 V by PWR_PVD_LEVEL_2V4;
the PVD output is routed to EXTI Line16 with rising and falling edge triggering;
the NVIC priority group is NVIC_PriorityGroup_1 and both the preemption and sub-priority of PVD_IRQn are 0.
USART1 uses PA9 as TX at 115200 bps for log output;
the system clock is HSI+PLL, 80 MHz on N32G412 and 96 MHz on N32G415.
Program and data path main first calls log_init to print the example name, then EXTI_Configuration configures Line16 and NVIC_Configuration enables PVD_IRQn;
PWR_PVDLevelConfig writes the threshold and PWR_PvdEnable enables the PVD, after which the main loop is empty.
When VDD crosses the threshold, PVD_IRQHandler clears the EXTI pending bit and prints above or below according to PWR_GetFlagStatus(PWR_PVDO_FLAG).
Main APIs PWR_PVDLevelConfig, PWR_PvdEnable, PWR_GetFlagStatus
Verification After download and reset the serial port prints This is a PVD demo;
adjust VDD across 2.4 V and the serial port prints VDD below threshold! and VDD above threshold. respectively.
Use note The threshold can be changed through the PWR_PVD_LEVEL_2V4 argument;
N32G412x8L7, N32G412xBL7, N32G415x8L7 and N32G415xBL7 are supported, and the development environment is KEIL MDK-ARM V5.34 or IAR EWARM V8.50.1.
Core-code walkthrough and porting

The example routes the PVD output to the NVIC through EXTI Line16, and the main loop only waits for the interrupt.

Data path: PWR_PVDLevelConfig writes PLS in PWR_CTRL -> PWR_PvdEnable sets PVDEN -> VDD crossing the threshold changes PVDO -> EXTI Line16 triggers PVD_IRQHandler -> PWR_GetFlagStatus reads PWR_PVDO_FLAG -> serial print

1. Configure EXTI Line16 to receive the PVD output. The PVD detection event is internally connected to interrupt line 16; the example first clears the pending bit of that line and then configures it for rising and falling edge triggering.

src/main.csrc/main.c · EXTI_Configuration
    EXTI_InitType EXTI_InitStructure;

    /* Configure EXTI Line16(PVD Output) to generate an interrupt on rising and
       falling edges */
    EXTI_ClrITPendBit(EXTI_LINE16);
    EXTI_InitStruct(&EXTI_InitStructure);
    EXTI_InitStructure.EXTI_Line    = EXTI_LINE16;
    EXTI_InitStructure.EXTI_Mode    = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitPeripheral(&EXTI_InitStructure);

When porting, check the EXTI line that the PVD is wired to, the trigger edges, and the interrupt handler bound to that line.

2. Enable the PVD interrupt channel. Both the preemption and sub-priority of PVD_IRQn are 0, with a priority group of one preemption bit.

src/main.csrc/main.c · NVIC_Configuration
    NVIC_InitType NVIC_InitStructure;

    /* Configure one bit for preemption priority */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    /* Enable the PVD Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                   = PVD_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

When changing the priority, update the preemption and sub-priority here and check the order relative to other interrupts.

3. Set the threshold and turn on the PVD. PWR_PVDLevelConfig first writes the threshold into the PLS field of PWR_CTRL, then PWR_PvdEnable sets PVDEN; after that the main loop is empty.

src/main.csrc/main.c · main
    /* Configure the PVD Level to 2.4V ,from 2V ~ 4.8V,one step mean add 200mv*/
    PWR_PVDLevelConfig(PWR_PVD_LEVEL_2V4);

    /* Enable the PVD Output */
    PWR_PvdEnable(ENABLE);

    while (1)
    {
    }

When porting, change the PWR_PVD_LEVEL_* macro to the required alarm voltage, from 2.0 V to 4.8 V in 200 mV steps.

4. Read the flag and print in the interrupt. The handler first clears the pending bit of EXTI Line16 and then tests PVDO with PWR_GetFlagStatus to print the supply direction.

src/n32g41x_it.csrc/n32g41x_it.c · PVD_IRQHandler
    if (EXTI_GetStatusFlag(EXTI_LINE16) != RESET)
    {
        /* Clear the EXTI line 16 pending bit */
        EXTI_ClrITPendBit(EXTI_LINE16);

        /* Check PVD output */
        if (PWR_GetFlagStatus(PWR_PVDO_FLAG) != RESET)
        {
            /* VDD is below PVD threshold */
            printf("PVD IRQ: VDD below threshold!\r\n");
        }
        else
        {
            /* VDD is above PVD threshold */
            printf("PVD IRQ: VDD above threshold.\r\n");
        }
    }

When changing the decision direction or the output text, keep the order of clearing the pending bit before reading the flag so that a later interrupt is not missed.

Corresponding source files: src/main.c, src/n32g41x_it.c

5.16.3.2 SLEEP mode key wake-up

Example directory: projects/n32g41x_EVAL/examples/PWR/SLEEP/

Initialize the log UART→configure the WKUP key as a rising-edge interrupt input→delay 1 s then enter SLEEP mode→wake the CPU with the WKUP key interrupt→print the SLEEP entry and exit messages

Item Source analysis
Function Uses the WKUP key (PA0) to generate an external interrupt that wakes the CPU from SLEEP mode;
the CPU stops executing and, after wake-up, resumes with no clock reconfiguration.
Source files src/main.c: main and KeyInputExtiInit;
inc/main.h: includes the PWR, EXTI, RCC and GPIO headers and defines the WKUP key port, pin and EXTI line macros;
src/n32g41x_it.c: interrupt handlers, including KEY_EXTI_IRQHandler;
inc/n32g41x_it.h: interrupt handler declarations;
readme.txt: function, environment and usage;
MDK-ARM/, EWARM/: Keil and IAR projects.
Key configuration The WKUP key is PA0, configured as GPIO_MODE_INPUT and mapped to EXTI_LINE0 with rising edge triggering;
the NVIC priority group is NVIC_PriorityGroup_1 and both the preemption and sub-priority of EXTI0_IRQn are 0.
USART1 uses PA9 as TX at 115200 bps;
the system clock is HSI+PLL, 80 MHz on N32G412 and 96 MHz on N32G415.
Program and data path main calls log_init, then KeyInputExtiInit configures PA0 as an input wired to EXTI0 and enables EXTI0_IRQn;
after clearing the pending flag once the loop runs: SysTick_Delay_Ms(1000) delays and prints the entry message, PWR_EnterSLEEPMode(PWR_SLEEP_NOW, PWR_SLEEPENTRY_WFI) enters SLEEP, and after the key interrupt wakes the CPU it prints the exit message.
Main APIs PWR_EnterSLEEPMode
Verification After download and reset the serial port prints --- PWR_SLEEP Demo ---, then prints Entry SLEEP mode every second and enters sleep;
press the WKUP key to wake the CPU and the serial port prints Exit SLEEP mode.
Use note Remove the prints when measuring power consumption;
N32G412x8L7, N32G412xBL7, N32G415x8L7 and N32G415xBL7 are supported, and the development environment is KEIL MDK-ARM V5.34 or IAR EWARM V8.50.1.
Core-code walkthrough and porting

The example configures the WKUP key EXTI0 interrupt first, then the main loop delays and enters SLEEP, from which the key wakes it to continue.

Data path: KeyInputExtiInit configures PA0 as an input wired to EXTI0 -> PWR_EnterSLEEPMode(PWR_SLEEP_NOW, PWR_SLEEPENTRY_WFI) clears SLEEPDEEP and executes WFI -> a key press triggers EXTI0_IRQHandler to clear the pending bit -> the CPU continues and prints the exit message

1. Define the WKUP key and EXTI line with macros. inc/main.h groups the key port, pin source, EXTI line, interrupt vector and interrupt handler name, and all later configuration goes through these macros.

inc/main.hinc/main.h
/* WKUP EXTI wakeup configuration (PA0 -> EXTI0) */
#define KEY_EXTI_PORT_SOURCE    GPIOA_PORT_SOURCE
#define KEY_EXTI_PIN_SOURCE     GPIO_PIN_SOURCE0

#define KEY_EXTI_LINE           EXTI_LINE0

#define KEY_EXTI_IRQn           EXTI0_IRQn
#define KEY_EXTI_IRQHandler     EXTI0_IRQHandler

When another key is used, change the port, pin source and EXTI line in this group and keep the interrupt handler name consistent with the vector.

2. Configure the key pin as an input wired to EXTI0. KeyInputExtiInit enables the clock of the key port, configures the pin as an input, then selects the port source and pin source with GPIO_ConfigEXTILine, and finally configures the EXTI line for rising edge triggering and enables it.

src/main.csrc/main.c · KeyInputExtiInit
    /* Enable the GPIO Clock */
    BUTTON_WKUP_CLK_ENABLE;

    /*Configure the GPIO pin as input floating*/
    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin        = Pin;
    GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_INPUT;
    GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure);

    /*Configure key EXTI Line to key input  Pin*/
    GPIO_ConfigEXTILine(KEY_EXTI_PORT_SOURCE, KEY_EXTI_PIN_SOURCE);

    /*Configure key EXTI line*/
    EXTI_InitStruct(&EXTI_InitStructure);
    EXTI_InitStructure.EXTI_Line = KEY_EXTI_LINE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitPeripheral(&EXTI_InitStructure);

When porting, change BUTTON_WKUP_PORT, BUTTON_WKUP_PIN and the port source and pin source of GPIO_ConfigEXTILine to match the actual key.

3. Delay, enter SLEEP and print the entry and exit messages. Each loop iteration delays 1 s, prints the entry message and calls PWR_EnterSLEEPMode to enter SLEEP, and prints the exit message after wake-up.

src/main.csrc/main.c · main
    while (1)
    {
       /* Insert a long delay */
       SysTick_Delay_Ms(1000);
       log_info("Entry SLEEP mode\n");
       /* Request to enter SLEEP mode*/
       PWR_EnterSLEEPMode(PWR_SLEEP_NOW, PWR_SLEEPENTRY_WFI);
       log_info("Exit SLEEP mode\n");
    }

The first argument PWR_SLEEP_NOW means sleep-now; changing the delay argument adjusts the interval between two sleeps.

4. Clear the EXTI pending bit in the handler. On the key interrupt the handler tests the status flag of that line and clears the pending bit, so the CPU leaves SLEEP and returns to the main loop.

src/n32g41x_it.csrc/n32g41x_it.c · KEY_EXTI_IRQHandler
void KEY_EXTI_IRQHandler(void)
{
    if (EXTI_GetStatusFlag(KEY_EXTI_LINE) != RESET)
    {
        EXTI_ClrStatusFlag(KEY_EXTI_LINE);
    }
}

When porting, check the mapping between the handler name and EXTI0_IRQHandler in the startup file, and that the flag cleared matches the EXTI line.

Corresponding source files: src/main.c, src/n32g41x_it.c, inc/main.h

5.16.3.3 STOP mode key wake-up

Example directory: projects/n32g41x_EVAL/examples/PWR/STOP/

Initialize the log UART→configure the WKUP key as a rising-edge interrupt input→delay 1 s then enter STOP mode→wake the MCU with the WKUP key interrupt→rebuild the system clock and print the exit message

Item Source analysis
Function Uses an external interrupt on the WKUP key (PA0) to wake the MCU from STOP mode;
after wake-up it rebuilds the system clock and resumes operation.
Source files src/main.c: main, KeyInputExtiInit and SetSysClockToPLL;
inc/main.h: includes the PWR, EXTI, RCC, GPIO and FLASH headers and defines the WKUP key port, pin and EXTI line macros;
src/n32g41x_it.c: interrupt handlers, including KEY_EXTI_IRQHandler;
inc/n32g41x_it.h: interrupt handler declarations;
readme.txt: function, environment and usage;
MDK-ARM/, EWARM/: Keil and IAR projects.
Key configuration The WKUP key is PA0, configured as GPIO_MODE_INPUT and mapped to EXTI_LINE0 with rising edge triggering;
the NVIC priority group is NVIC_PriorityGroup_1 and both the preemption and sub-priority of EXTI0_IRQn are 0.
After wake-up SetSysClockToPLL(RCC_PLL_SRC_HSI,80000000) rebuilds the 80 MHz system clock with HSI as the PLL source;
USART1 uses PA9 as TX at 115200 bps.
Program and data path main calls log_init, then KeyInputExtiInit wires PA0 to EXTI0 and enables EXTI0_IRQn;
the loop runs: SysTick_Delay_Ms(1000) delays and prints the entry message, then PWR_EnterSTOPMode(PWR_STOPENTRY_WFI) enters STOP;
after the key wakes the MCU, SetSysClockToPLL(RCC_PLL_SRC_HSI,80000000) rebuilds the clock, and after a 10 ms delay and a new log_init call it prints the exit message.
Main APIs PWR_EnterSTOPMode
Verification After download and reset the serial port prints --- Reset for STOP ---, then prints Entry STOP mode every second and enters STOP;
press the WKUP key to wake the MCU and the serial port prints Exit STOP mode.
Use note Remove the prints when measuring power consumption;
the clock and the serial port must be reconfigured after wake-up, and the readme notes that LED1 resumes blinking after wake-up;
N32G412x8L7, N32G412xBL7, N32G415x8L7 and N32G415xBL7 are supported, and the development environment is KEIL MDK-ARM V5.34 or IAR EWARM V8.50.1.
Core-code walkthrough and porting

The example configures the WKUP key interrupt first, the main loop enters STOP, and after wake-up it rebuilds the system clock and continues.

Data path: KeyInputExtiInit wires PA0 to EXTI0 -> PWR_EnterSTOPMode(PWR_STOPENTRY_WFI) sets SLEEPDEEP and executes WFI -> the key wakes the MCU -> SetSysClockToPLL re-enables HSI and the PLL -> print the exit message

1. Wire the WKUP key to EXTI0 on the rising edge. KeyInputExtiInit selects the port source and pin source with GPIO_ConfigEXTILine, then configures EXTI0 as an interrupt on the rising edge and enables it.

src/main.csrc/main.c · KeyInputExtiInit
    /*Configure key EXTI Line to key input  Pin*/
    GPIO_ConfigEXTILine(KEY_EXTI_PORT_SOURCE, KEY_EXTI_PIN_SOURCE);

    /*Configure key EXTI line*/
    EXTI_InitStruct(&EXTI_InitStructure);
    EXTI_InitStructure.EXTI_Line = KEY_EXTI_LINE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitPeripheral(&EXTI_InitStructure);

When porting, change the port source and pin source macros to the actual wake-up pin, and check that this EXTI line has wake-up capability in STOP mode.

2. Enter STOP and rebuild the clock after wake-up. The loop delays 1 s, prints the entry message and calls PWR_EnterSTOPMode; after the key wakes the MCU it calls SetSysClockToPLL to restore the clock, then delays 10 ms and re-initializes the log.

src/main.csrc/main.c · main
    while (1)
    {
       /* Insert a long delay */
       SysTick_Delay_Ms(1000);
       log_info("Entry STOP mode\n"); 
       /* Request to enter STOP mode*/
       PWR_EnterSTOPMode(PWR_STOPENTRY_WFI);
       /* Configures system clock after wake-up from STOP: enable HSI, PLL and select
          PLL as system clock source */
       SetSysClockToPLL(RCC_PLL_SRC_HSI,80000000);
       SysTick_Delay_Ms(10);
       log_init();
       log_info("\nExit STOP mode\n");
    }

The serial port is unusable between the STOP wake-up and the clock rebuild, so the exit message follows SetSysClockToPLL and the new log_init call.

3. The clock rebuild selects PLL parameters for the target frequency. SetSysClockToPLL picks the multiplier, output divider and FLASH latency for the 80 MHz target, sets the bus dividers and then switches the PLL to the system clock.

src/main.csrc/main.c · SetSysClockToPLL
        case 80000000:
            /* 4MHz * 40 = 160MHz(FVCO) / 2(PLLOD) /1 = 80MHz(Fpll) */
            latency   = FLASH_LATENCY_2;   /* 72MHz < SYSCLK <= 80MHz */
            pllmul    = 40;
            plloutdiv = RCC_PLL_OD_DIV_2;
            pllsysdiv = DISABLE;
            break;
        default:
            return ERROR;
    }

    /* HCLK = SYSCLK */
    RCC_ConfigHclk(RCC_SYSCLK_DIV1);

    /* PCLK2 = HCLK */
    RCC_ConfigPclk2(RCC_HCLK_DIV1);

    /* PCLK1 = HCLK/2 */
    RCC_ConfigPclk1(RCC_HCLK_DIV2);

When porting, change pllmul, plloutdiv and pllsysdiv for the actual crystal and target frequency, and adjust FLASH_LATENCY and the bus dividers accordingly.

Corresponding source files: src/main.c

5.16.4 Notes and troubleshooting

Scenario Check & action Source
System clock after wake-up from STOP When STOP mode is exited through an interrupt or wake-up event, the system clock defaults to HSI and, once the clock source is ready, hardware automatically restores the state from before STOP was entered;
where the PLL was the system clock before entry, hardware enables and switches back to the PLL after HSI or HSE is ready.
User manual
Entry into STOP is delayed In STOP mode, if a FLASH operation is in progress or an APB area access is under way, entry into STOP is delayed until the memory access or the APB access completes. User manual
Wake-up sources usable in STOP mode In STOP mode the IWDG, RTC/BTIM1/PVD/COMP and USART1/4 can be configured as wake-up sources;
the PLL, HSI and HSE clocks are off, LSE/LSI can be configured to run, and the SRAM, registers and GPIO states are retained.
User manual
Enable write protection before writing PWR_CTRL2 PWR_CTRL2 is write-protected;
before modifying it, write the 32-bit key 0x57103616 to the register and then perform the write;
the MR low-power mode and delay are both controlled by this register.
User manual
PVD threshold and interrupt triggering The PVD selects a 2.0 V to 4.8 V alarm threshold through PWR_CTRL.PLS[3:0] in 200 mV steps and is enabled by PWR_CTRL.PVDEN;
PWR_CTRLSTS.PVDO indicates whether VDD/VDDA is above the threshold, and this event is internally connected to EXTI interrupt line 16, configurable for a rising or falling edge interrupt.
User manual
Filter bypass The PVDCNT and NRSTCNT fields of PWR_CTRL bypass the corresponding filter when they are all 0;
the NRST filter is bypassed in STOP mode.
User manual

The N32G412 and N32G415 series errata sheet V1.0.0 (2026.6.30) lists a single row for revision A chips with an empty errata link column, and gives no PWR-related entries.

Nations Technologies DevKit Docs

Datasheets, SDK, driver APIs and demo guides for Nations Technologies MCU development kits, organized by chip series.

© 2026 Nations Technologies Inc. All rights reserved.粤ICP备11069485号This site uses cookie-free anonymous analytics.