5.13 IWDG Guide
This chapter describes the file composition and the 7 public functions of the IWDG driver in the N32G41x standard peripheral library: write-protection configuration, prescaler and reload-value setup, counter reload and freeze control, and status-flag reading, together with the IWDG_Reset example that triggers a system reset on a watchdog timeout. Read the register definitions, the configuration sequence and the debug-halt behaviour together with the “Independent watchdog (IWDG)” chapter of the user manual, and take the errata sheet as the authority on known chip issues.
5.13.1 Related files
| Relative path | Purpose |
|---|---|
firmware/n32g41x_std_periph_driver/inc/n32g41x_iwdg.h |
Defines the IWDG status-flag and write-configuration enums, the key command values and the prescaler macros, and declares 7 public functions in the configuration, enable and flag sections |
firmware/n32g41x_std_periph_driver/src/n32g41x_iwdg.c |
Implements those 7 functions: key commands written to KEY, a bounded wait for PVU to clear before writing PREDIV and RELV, freeze and unfreeze control, and status-flag reading |
projects/n32g41x_EVAL/examples/IWDG/ |
IWDG example root, holding 1 example: IWDG_Reset |
projects/n32g41x_EVAL/examples/IWDG/IWDG_Reset/ |
Project directory of that example: MDK-ARM/, EWARM/, inc/, src/, readme.txt |
projects/n32g41x_EVAL/bsp/ |
Board support files the example uses: evaluation-board LED pin definitions, the millisecond delay and the logging functions |
5.13.2 API reference
The following 7 public functions are listed in the declaration order of n32g41x_iwdg.h in 3 groups; each entry gives a summary and the original comment above the function in n32g41x_iwdg.c.
Configuration
IWDG_WriteConfig, IWDG_SetPrescalerDiv, IWDG_CntReload, IWDG_ReloadKey
Enable and disable
IWDG_Enable, IWDG_Freeze_Enable
Flag management
IWDG_GetStatus
void IWDG_WriteConfig(IWDG_WRITE_CONFIG IWDG_WriteAccess)Config write protection of IWDG_PREDIV and IWDG_RELV registers.
name IWDG_WriteConfig.
fun Config write protection of IWDG_PREDIV and IWDG_RELV registers.
param IWDG_WriteAccess : key value written to IWDG_KEY.KEYV[15:0]
- IWDG_WRITE_ENABLE (0x5555) : disable the write protection, so
that IWDG_PREDIV and IWDG_RELV become writable
- IWDG_WRITE_DISABLE (0x0000) : re-arm the write protection
return none
void IWDG_SetPrescalerDiv(uint8_t IWDG_Prescaler)Sets the IWDG prescaler divider ratio (IWDG_PREDIV.PD[2:0]).
name IWDG_SetPrescalerDiv.
fun Sets the IWDG prescaler divider ratio (IWDG_PREDIV.PD[2:0]).
param IWDG_Prescaler : prescaler divider, one of :
- IWDG_PRESCALER_DIV4 (PD[2:0] = 0b000, divisor 4)
- IWDG_PRESCALER_DIV8 (PD[2:0] = 0b001, divisor 8)
- IWDG_PRESCALER_DIV16 (PD[2:0] = 0b010, divisor 16)
- IWDG_PRESCALER_DIV32 (PD[2:0] = 0b011, divisor 32)
- IWDG_PRESCALER_DIV64 (PD[2:0] = 0b100, divisor 64)
- IWDG_PRESCALER_DIV128 (PD[2:0] = 0b101, divisor 128)
- IWDG_PRESCALER_DIV256 (PD[2:0] = 0b111, divisor 256)
return none
Use note: The implementation first waits for IWDG_STS.PVU to clear in a loop bounded by IWDG_PVU_POLL_LIMIT (0x0000FFFF) and then writes IWDG->PREDIV; the wait is bounded, so the function can never block forever.
void IWDG_CntReload(uint16_t Reload)Sets IWDG reload value.
name IWDG_CntReload.
fun Sets IWDG reload value.
param Reload :
- 0x000 ~ 0xFFF (REL[11:0]); larger values are truncated by the field mask
return none
Use note: The implementation ANDs the argument with the IWDG_RELV_REL mask before writing IWDG->RELV; values above 0xFFF are truncated.
void IWDG_ReloadKey(void)Reload IWDG counter with value defined in IWDG_RELV register.
name IWDG_ReloadKey.
fun Reload IWDG counter with value defined in IWDG_RELV register.
param none
return none
void IWDG_Enable(void)Start watch dog counter.
name IWDG_Enable.
fun Start watch dog counter.
param none
return none
void IWDG_Freeze_Enable(FunctionalState Cmd)Freeze or unfreeze IWDG while IWDG is running in run mode.
name IWDG_Freeze_Enable.
fun Freeze or unfreeze IWDG while IWDG is running in run mode.
param Cmd : freeze control, written to IWDG_KEY.KEYV[15:0]
- ENABLE : 0x4567, stops the IWDG counter in RUN mode
- DISABLE : 0x89AB, resumes the counter in RUN mode
return none
Use note: The implementation writes IWDG_FREEZE (0x4567) only when Cmd is ENABLE; any other value writes IWDG_UNFREEZE (0x89AB).
FlagStatus IWDG_GetStatus(IWDG_STATUS_FLAG IWDG_FLAG)Checks whether the specified IWDG flag is set or not.
name IWDG_GetStatus.
fun Checks whether the specified IWDG flag is set or not.
param IWDG_FLAG : status flag selected in the IWDG_STS register
- IWDG_PVU_FLAG
- IWDG_CRVU_FLAG
- IWDG_FRZF_FLAG
return FlagStatus :
- RESET
- SET
5.13.3 Demo descriptions
This section describes the single IWDG example: IWDG_Reset triggers a system reset when the watchdog is not fed in time and reports the reset source on the LED and the serial port.
5.13.3.1 IWDG_Reset Independent watchdog reset
Example directory: projects/n32g41x_EVAL/examples/IWDG/IWDG_Reset/
Enable the LSI clock and stop IWDG on a debug halt→set the prescaler and reload value and start the watchdog→toggle LED3 and feed the watchdog in the main loop→a feed interval longer than the timeout triggers a system reset→light LED1 from the reset flag after the reset
| Item | Source analysis |
|---|---|
| Function | Demonstrates the IWDG timeout reset: with feeding kept below the timeout LED3 blinks continuously; when the feed interval is raised above the timeout the system resets repeatedly, LED1 stays on and the serial port prints reset by IWDG. |
| Source files | src/main.c: main, MCO_Configuration, LedInit, LedOn, LedOff, LedBlink and the optional GTIM3_ConfigForLSI;inc/main.h: driver headers, the MCO pin and alternate-function macros and the LSI-measurement macros;src/n32g41x_it.c, inc/n32g41x_it.h: exception handlers and the optional GTIM3_IRQHandler;readme.txt: function, environment and test steps;MDK-ARM/, EWARM/: Keil and IAR projects.The LED pin macros come from bsp/inc/n32g41x_stb.h and SysTick_Delay_Ms from bsp/src/delay.c. |
| Key configuration | The IWDG clock is LSI/32 (IWDG_PRESCALER_DIV32) and the reload value is LsiFreq / 128, giving a timeout of about 250 ms;LsiFreq defaults to 32000 Hz, and main calls DBG_ConfigPeriph(DBG_IWDG_STOP, ENABLE) so the counter stops while the core is halted.LED1 is PA1 and LED3 is PB1, both push-pull outputs; the MCO pin is PA8, mapped to GPIO_AF7 on the N32G412 and GPIO_AF13 on the N32G415.The system clock is HSE+PLL, 80 MHz on the N32G412 and 96 MHz on the N32G415. |
| Program and data path | main configures the debug-halt behaviour, enables the LSI clock and waits for RCC_CTRL_FLAG_LSIRDF, then routes LSI to MCO and initialises the LEDs and logging;after a 1 s delay it reads RCC_CTRLSTS_FLAG_IWDGRSTF to tell whether the reset came from IWDG, lights LED1 and clears the reset flags if so;it then disables the write protection, sets the prescaler and reload value, reloads the counter and starts the watchdog; the while(1) loop toggles LED3, waits 249 ms and reloads the counter. |
| Main APIs | DBG_ConfigPeriph, RCC_EnableLsi, RCC_GetFlagStatus, RCC_ClearResetFlag, IWDG_WriteConfig, IWDG_SetPrescalerDiv, IWDG_CntReload, IWDG_ReloadKey, IWDG_Enable |
| Verification | After download LED3 blinks continuously, showing the watchdog is fed; changing the SysTick_Delay_Ms(249) argument to 251 or more makes the system reset repeatedly, keeps LED1 on and prints reset by IWDG on the serial port.Without LSI measurement, the actual LSI frequency can be observed on MCO (PA8) with an oscilloscope. |
| Use note | Supports N32G412x8L7, N32G412xBL7, N32G415x8L7 and N32G415xBL7; the development environment is KEIL MDK-ARM 5.34 or IAR EWARM 8.50.1. LSI_TIM_MEASURE in inc/main.h is commented out by default;when enabled, GTIM3 input capture measures the LSI frequency automatically for the timeout calculation. |
Core-code walkthrough and porting
The example prepares the LSI clock and the debug-halt behaviour of the watchdog first, then configures the timeout and starts the watchdog, and finally feeds it in the main loop and reads the reset flag.
Data path: DBG_ConfigPeriph and RCC_EnableLsi enable LSI → IWDG_WriteConfig, IWDG_SetPrescalerDiv, IWDG_CntReload write PREDIV and RELV → IWDG_Enable starts the counter → IWDG_ReloadKey reloads the counter in the while(1) loop → a timeout sets RCC_CTRLSTS_FLAG_IWDGRSTF → LedOn lights LED1
1. Prepare the LSI clock and the debug-halt behaviour. The watchdog is driven by the LSI, so main first stops the IWDG counter while the core is halted and then enables the LSI and polls its ready flag, so that the timeout configuration is based on a settled clock.
DBG_ConfigPeriph(DBG_IWDG_STOP, ENABLE);
/* Enable LSI Clock */
RCC_EnableLsi(ENABLE);
while (RCC_GetFlagStatus(RCC_CTRL_FLAG_LSIRDF) != SET)
{
}
To keep the watchdog counting during a debug halt, replace DBG_IWDG_STOP with another peripheral macro or drop this call; the LSI ready wait feeds the timeout calculation and should not be removed.
2. Configure the prescaler and reload value and start the watchdog. This part disables the write protection of PREDIV and RELV, sets the prescaler to LSI/32 and derives a reload value of about 250 ms from LsiFreq / 128, then reloads the counter and starts the watchdog.
/* IWDG timeout equal to 250 ms (the timeout may varies due to LSI frequency
dispersion) */
/* Enable write access to IWDG_PR and IWDG_RLR registers */
IWDG_WriteConfig(IWDG_WRITE_ENABLE);
/* IWDG counter clock: LSI/32 */
IWDG_SetPrescalerDiv(IWDG_PRESCALER_DIV32);
/* Set counter reload value to obtain 250ms IWDG TimeOut.
Counter Reload Value = 250ms/IWDG counter clock period
= 250ms / (LSI/32)
= 0.25s / (LsiFreq/32)
= LsiFreq/(32 * 4)
= LsiFreq/128 */
log_debug("LsiFreq is: %d\n", LsiFreq);
IWDG_CntReload(LsiFreq / 128);
/* Reload IWDG counter */
IWDG_ReloadKey();
/* Enable IWDG (the LSI oscillator will be enabled by hardware) */
IWDG_Enable();
The timeout follows from both the prescaler and the reload value; changing the prescaler means updating the LsiFreq / 128 conversion and making sure LsiFreq matches the actual LSI frequency.
3. Feed the watchdog in the main loop. The loop toggles LED3 to show the program is running and then reloads the counter after a 249 ms delay (below the 250 ms timeout), so the watchdog is never triggered.
while (1)
{
/* Toggle LED3 */
LedBlink(LED3_PORT, LED3_PIN);
/* Insert 249 ms delay (exceeds IWDG timeout -> reset) */
SysTick_Delay_Ms(249);
/* Reload IWDG counter */
IWDG_ReloadKey();
}
The feed interval must stay below the timeout derived from the reload value; setting the SysTick_Delay_Ms argument to 251 or more triggers a reset and can be used to check the timeout.
4. Tell the reset source from the reset flag. After a reset the code reads RCC_CTRLSTS_FLAG_IWDGRSTF; when it is set the reset came from IWDG, so LED1 is lit and the reset flags are cleared, otherwise LED1 stays off.
/* Check if the system has resumed from IWDG reset */
if (RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_IWDGRSTF) != RESET)
{
/* IWDGRST flag set */
LedOn(LED1_PORT, LED1_PIN);
log_info("reset by IWDG\n");
/* Clear reset flags */
RCC_ClearResetFlag();
}
else
{
/* IWDGRST flag is not set */
LedOff(LED1_PORT, LED1_PIN);
}
RCC_ClearResetFlag clears all reset flags, so when several reset sources must be told apart it also wipes the others; LED1 staying on after a reset means an IWDG reset has already occurred.
Corresponding source files: src/main.c, inc/main.h, projects/n32g41x_EVAL/bsp/inc/n32g41x_stb.h
5.13.4 Notes and troubleshooting
| Scenario | Check & action | Source |
|---|---|---|
| The prescaler or reload value is changed without clearing the write protection | IWDG_PREDIV and IWDG_RELV are write-protected;0x5555 must be written to IWDG_KEY.KEYV[15:0] before they can be changed, writing any other value re-arms the write protection, and a reload operation (writing 0xAAAA) also starts the write protection. |
User manual |
| An update to the prescaler or reload value does not take effect | The prescaler value and the reload value can be updated only while IWDG_STS.PVU and IWDG_STS.CRVU are respectively 0;the hardware sets the corresponding bit during an update, and reading back IWDG_PREDIV.PD or IWDG_RELV.REL while it is set is invalid, so the read must wait until the hardware clears it. |
User manual |
| The counter reaches 0 without a reset | A system reset is generated when the IWDG counter reaches 0x000 only while PWR_CTRL.IWDGRSTEN is 1;when the bit is 0 the IWDG keeps counting but does not reset. |
User manual |
| Counter behaviour while the core is halted | In debug mode, once the Cortex-M4 core is halted, whether the IWDG counter keeps running or stops is selected by DBG_CTRL.IWDG_STOP: the counter stops when the bit is 1 and keeps running when it is 0. |
User manual |
| The watchdog cannot be stopped once enabled | Once the IWDG is enabled by software or hardware it never stops counting unless a system reset occurs or 0x4567 is written to freeze it; freezing in SLEEP and STOP mode is configured through the FLASH_OB.IWDGSLEEPFRZ and FLASH_OB.IWDGSTOPFRZ option bytes. |
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 IWDG-related entries.