Clocks, Reset & Watchdog Timers

Before any peripheral works, the MCU needs a clock and a clean reset. Learn clock sources (HSI, HSE crystal, LSI, LSE), PLL configuration, bus prescalers and Flash wait states, clock gating, reset sources and brown-out detection, and independent and window watchdogs — including how to size timeouts and design a watchdog strategy that really catches failures.

Every timer frequency, UART baud rate and ADC sample time derives from the clock tree. A wrong PLL setting gives garbled serial output and timers that run at the wrong speed; an unstable crystal can cause intermittent USB failures. Understanding the clock tree is the first step of bring-up on any new board.

Reset and watchdog hardware keep devices recoverable. Brown-out detection prevents corrupted Flash writes when a battery sags; a watchdog resets a hung system so a remote sensor recovers without a site visit.

An analogy

The clock is the heartbeat of the chip and the PLL is a gearbox that multiplies it. The watchdog is a dead-man's switch: if the train driver (firmware) stops pressing it regularly, the train brakes (resets) automatically.

Clock sources

MCUs offer several oscillators with different trade-offs:

PLL and the clock tree

A PLL multiplies a reference to a high frequency (the VCO), then dividers produce the system clock and special clocks (48 MHz USB). The system clock feeds the AHB bus (CPU, DMA, memory) and slower APB buses for peripherals — each with its own maximum. Every peripheral's clock must be enabled (RCC->APBxENR) before use; forgetting this is the #1 bring-up bug ('my register writes do nothing').

Reset sources and brown-out

Resets come from power-on (POR), the reset pin, brown-out (BOR, supply below threshold), watchdogs, software (NVIC_SystemReset), and low-power exits. Read and clear the reset-cause flags at boot and log them — they are invaluable for diagnosing field failures. Brown-out reset holds the MCU in reset when voltage is too low to execute or write Flash reliably.

Watchdog strategy

An independent watchdog (IWDG) runs from its own LSI clock and survives main-clock failure. A window watchdog (WWDG) also resets if kicked too early, catching runaway loops that kick too often. Size the timeout above the longest legitimate gap (Flash erase can block for 100s of ms) but short enough for safe recovery. Safety systems add a clock-security system (CSS) that switches to HSI if the crystal fails, and external watchdog ICs with independent time bases.

Formulas

Worked example: PLL settings

Given: HSE 8 MHz, M = 8, N = 336, P = 2, Q = 7

Find: SYSCLK and USB clock.

Answer: 168 MHz and 48 MHz

Worked example: Watchdog timeout

Given: LSI 32 kHz, prescaler 64, reload 4095

Find: Maximum timeout.

Answer: 8.19 s

Worked example: Crystal load caps

Given: Crystal C_L = 12 pF, stray ≈ 5 pF

Find: C₁ = C₂.

Answer: 14 pF (use nearest standard 15 pF)

168 MHz from an 8 MHz crystal (register-level, STM32F4)

void clock_init_168mhz(void)
{
    RCC->CR |= RCC_CR_HSEON;                         /* start crystal     */
    while (!(RCC->CR & RCC_CR_HSERDY)) { }           /* wait until stable */

    /* VCO = 8 MHz / M(8) * N(336) = 336 MHz; SYSCLK = /P(2) = 168 MHz;
       USB/SDIO = /Q(7) = 48 MHz                                           */
    RCC->PLLCFGR = (8u << RCC_PLLCFGR_PLLM_Pos) | (336u << RCC_PLLCFGR_PLLN_Pos)
                 | (0u << RCC_PLLCFGR_PLLP_Pos)       /* 0 means /2        */
                 | (7u << RCC_PLLCFGR_PLLQ_Pos) | RCC_PLLCFGR_PLLSRC_HSE;
    RCC->CR |= RCC_CR_PLLON;
    while (!(RCC->CR & RCC_CR_PLLRDY)) { }

    FLASH->ACR = FLASH_ACR_LATENCY_5WS | FLASH_ACR_PRFTEN
               | FLASH_ACR_ICEN | FLASH_ACR_DCEN;     /* BEFORE speeding up */
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_PPRE2_DIV2;  /* APB1 42, APB2 84 MHz */
    RCC->CFGR |= RCC_CFGR_SW_PLL;
    while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) { }
}

Order matters: raise Flash wait states before increasing the clock, or the CPU fetches garbage and crashes. APB1 is limited to 42 MHz on this family, hence the /4 prescaler.

Watchdog kicked only when all tasks are healthy

#define ALL_ALIVE  (ALIVE_SENSOR | ALIVE_CONTROL | ALIVE_COMMS)
static volatile uint32_t alive_bits;

void task_report_alive(uint32_t bit) { alive_bits |= bit; }  /* each task */

void watchdog_supervisor(void)                /* runs every 100 ms */
{
    if ((alive_bits & ALL_ALIVE) == ALL_ALIVE) {
        IWDG->KR = 0xAAAA;                    /* refresh ("kick")   */
        alive_bits = 0;
    }
    /* otherwise don't kick: IWDG resets the MCU after its timeout */
}

void iwdg_init_500ms(void)                    /* LSI ~32 kHz         */
{
    IWDG->KR  = 0x5555;                       /* unlock PR/RLR       */
    IWDG->PR  = 3;                            /* prescaler /32       */
    IWDG->RLR = 499;                          /* (499+1)*32/32000 = 0.5 s */
    IWDG->KR  = 0xCCCC;                       /* start (cannot be stopped) */
}

Kicking the dog from a timer ISR alone is useless — the ISR keeps running even if the main logic deadlocks. Kick only when every critical activity has proven it is alive.

Common mistakes

Applications

Key takeaways

Going further