Bare metal C Ch16 IWDG - Hongjayeong-02/Basic_SoC_implementation GitHub Wiki

Ch16. Independent Watchdog (IWDG)

ํ•œ ์ค„ ์š”์•ฝ: ์ •์ƒ ๋™์ž‘ ์ค‘ IWDG๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ reloadํ•˜๊ณ , B1์„ ๋ˆ„๋ฅด๋ฉด reload๋ฅผ ์ค‘๋‹จํ•ด ์•ฝ 4์ดˆ ๋’ค hardware reset์„ ์œ ๋„ํ•œ๋‹ค.

1. ํ•ต์‹ฌ ์ด๋ก 

Watchdog Timer๋Š” software๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๊ณ  ์žˆ์Œ์„ ์ฃผ๊ธฐ์ ์ธ reload๋กœ ํ™•์ธํ•˜๊ณ , ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ reload๋˜์ง€ ์•Š์œผ๋ฉด system reset์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ์•ˆ์ „์žฅ์น˜๋‹ค.

IWDG๋Š” LSI๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ main clock๊ณผ ๋…๋ฆฝ์ ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

Key Register

Key | ์˜๋ฏธ -- | -- 0xCCCC | IWDG ์‹œ์ž‘ 0xAAAA | Counter reload 0x5555 | PR/RLR write access enable

Timeout ๊ณ„์‚ฐ

Notion ๊ธฐ๋ก์˜ ์ตœ์ข… ์„ค์ •:

Prescaler = /32
RLR       = 0xFFF
LSI       โ‰ˆ 32 kHz

Timeout โ‰ˆ (32 ร— 4096) / 32000 โ‰ˆ 4.1 s

Reset source ํ™•์ธ

IWDG reset ์ดํ›„:

RCC->CSR & RCC_CSR_IWDGRSTF

๋กœ ์ง์ „ reset ์›์ธ์„ ํ™•์ธํ•˜๊ณ  RMVF๋กœ flag๋ฅผ clearํ•œ๋‹ค.

2. ๋™์ž‘ ํ๋ฆ„

iwdg_init()
โ”‚
โ”œโ”€ 0xCCCC โ†’ start
โ”œโ”€ 0x5555 โ†’ unlock
โ”œโ”€ PR=/32
โ”œโ”€ RLR=0xFFF
โ”œโ”€ PVU/RVU wait
โ””โ”€ 0xAAAA โ†’ reload
โ”‚
โ–ผ
main loop
โ”‚
B1 not pressed?
โ”‚        โ”‚
Yes      No
โ”‚        โ”‚
โ–ผ        โ–ผ
reload     reload ์ค‘๋‹จ
LED toggle    โ”‚
โ–ผ
timeout โ‰ˆ4 s
โ”‚
โ–ผ
Hardware Reset
โ”‚
โ–ผ
IWDGRSTF ํ™•์ธ

3. ์‹ค์ œ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ


Ch16_iwdg/

โ”œโ”€โ”€ Inc/gpio.h

โ”œโ”€โ”€ Src/gpio.c

โ”œโ”€โ”€ Inc/gpio_exti.h

โ”œโ”€โ”€ Src/gpio_exti.c

โ”œโ”€โ”€ Inc/iwdg.h

โ”œโ”€โ”€ Src/iwdg.c

โ”œโ”€โ”€ Inc/uart.h

โ”œโ”€โ”€ Src/uart.c

โ”œโ”€โ”€ Src/main.c

syscalls.c, sysmem.c, startup file, linker script, CubeIDE metadata/build output์€ Ch04์—์„œ ๋‹ค๋ฃฌ ๊ณตํ†ต ๊ธฐ๋ฐ˜์ด๋ฏ€๋กœ ์ด ํŽ˜์ด์ง€์—์„œ๋Š” ๋ฐ˜๋ณตํ•˜์ง€ ์•Š๋Š”๋‹ค. ์•„๋ž˜์—๋Š” ์ด chapter ๊ธฐ๋Šฅ ๊ตฌํ˜„์— ์ง์ ‘ ์‚ฌ์šฉํ•œ source/header๋ฅผ ์ „๋ถ€ ๊ธฐ๋กํ•œ๋‹ค.

4. ์ „์ฒด ์ฝ”๋“œ

Inc/gpio.h

#ifndef GPIO_H
#define GPIO_H

#include <stdbool.h>

/* ---- LED (PB0, LD1 ๋…น์ƒ‰) ---- */ void led_init(void); void led_on(void); void led_off(void);

/* ---- Push Button (PC13, B1) ---- */ void button_init(void); bool get_btn_state(void);

void led_toggle(void); /* Ch08์—์„œ ์ถ”๊ฐ€ */

#endif /* GPIO_H */

Src/gpio.c

#include "stm32f4xx.h"
#include "gpio.h"

#define LED_PIN 0U /* PB0 = LD1 (๋…น์ƒ‰) / #define BTN_PIN 13U / PC13 = B1 */

void led_init(void) { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;

GPIOB-&gt;MODER &amp;= ~(0x3UL &lt;&lt; (LED_PIN * 2));
GPIOB-&gt;MODER |=  (0x1UL &lt;&lt; (LED_PIN * 2));

}

void led_on(void) { GPIOB->BSRR = (1UL << LED_PIN); /* Set */ }

void led_off(void) { GPIOB->BSRR = (1UL << (LED_PIN + 16)); /* Reset */ }

void button_init(void) { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;

GPIOC-&gt;MODER &amp;= ~(0x3UL &lt;&lt; (BTN_PIN * 2));  /* Input */
GPIOC-&gt;PUPDR &amp;= ~(0x3UL &lt;&lt; (BTN_PIN * 2));  /* No pull (๋ณด๋“œ๊ฐ€ ์ž์ฒด ์ฒ˜๋ฆฌ) */

}

bool get_btn_state(void) { return (GPIOC->IDR & (1UL << BTN_PIN)) != 0U; /* active-HIGH */ }

void led_toggle(void) { GPIOB->ODR ^= (1UL << 0); /* PB0 = LD1 */ }

Inc/gpio_exti.h

#ifndef GPIO_EXTI_H__
#define GPIO_EXTI_H__

#include <stdint.h> #include "stm32f4xx.h"

#define LINE13 (1U << 13)

void pc13_exti_init(void);

#endif

Src/gpio_exti.c

#include "gpio_exti.h"

#define GPIOCEN (1U << 2) #define SYSCFGEN (1U << 14)

void pc13_exti_init(void) { __disable_irq();

RCC-&gt;AHB1ENR |= GPIOCEN;

GPIOC-&gt;MODER &amp;= ~(1U &lt;&lt; 26);
GPIOC-&gt;MODER &amp;= ~(1U &lt;&lt; 27);

RCC-&gt;APB2ENR |= SYSCFGEN;

/* EXTI13 -&gt; PORTC */
SYSCFG-&gt;EXTICR[3] |= (1U &lt;&lt; 5);

EXTI-&gt;IMR |= (1U &lt;&lt; 13);

/* ์ด ๋ณด๋“œ๋Š” B1์ด active-HIGH๋ผ Rising-edge (์›์„œ๋Š” FTSR/active-LOW) */
EXTI-&gt;RTSR |= (1U &lt;&lt; 13);

NVIC_EnableIRQ(EXTI15_10_IRQn);

__enable_irq();

}

Inc/iwdg.h

#ifndef IWDG_H__
#define IWDG_H__

#include <stdint.h> #include "stm32f4xx.h"

#define IWDG_KEY_RELOAD 0x0000AAAAU

void iwdg_init(void);

#endif

Src/iwdg.c

#include "iwdg.h"

#define IWDG_KEY_ENABLE 0x0000CCCCU #define IWDG_KEY_WR_ACCESS_ENABLE 0x00005555U #define IWDG_PRESCALER_32 0x00000003U /* /256(0x6) -> /32๋กœ ๋ณ€๊ฒฝ */ #define IWDG_RELOAD_VAL 0xFFFU

static uint8_t isIwdg_ready(void);

void iwdg_init(void) { IWDG->KR = IWDG_KEY_ENABLE; IWDG->KR = IWDG_KEY_WR_ACCESS_ENABLE; IWDG->PR = IWDG_PRESCALER_32; /* /4 -> /32๋กœ ๋ณ€๊ฒฝ, ํƒ€์ž„์•„์›ƒ โ‰ˆ 4์ดˆ */ IWDG->RLR = IWDG_RELOAD_VAL; while (isIwdg_ready() != 1U) {} IWDG->KR = IWDG_KEY_RELOAD; }

static uint8_t isIwdg_ready(void) { return (uint8_t)((READ_BIT(IWDG->SR, IWDG_SR_PVU | IWDG_SR_RVU) == 0U) ? 1U : 0U); }

Inc/uart.h

#ifndef UART_H
#define UART_H

#include "stm32f4xx.h"

void uart_init(void); void uart_write_string(const char *s); int __io_putchar(int ch);

#endif

Src/uart.c

#include <stdint.h>
#include "uart.h"

#define GPIODEN (1U << 3) #define USART3EN (1U << 18)

#define DBG_UART_BAUDRATE 115200U #define SYS_FREQ 16000000U #define APB1_CLK SYS_FREQ

#define CR1_TE (1U << 3) #define CR1_UE (1U << 13) #define SR_TXE (1U << 7)

static void uart_write(int ch); static uint16_t compute_uart_bd(uint32_t periph_clk, uint32_t baudrate); static void uart_set_baudrate(uint32_t periph_clk, uint32_t baudrate);

int __io_putchar(int ch) { uart_write(ch); return ch; }

void uart_init(void) { RCC->AHB1ENR |= GPIODEN;

GPIOD-&gt;MODER &amp;= ~(0x3UL &lt;&lt; (8 * 2));
GPIOD-&gt;MODER |=  (0x2UL &lt;&lt; (8 * 2));
GPIOD-&gt;MODER &amp;= ~(0x3UL &lt;&lt; (9 * 2));
GPIOD-&gt;MODER |=  (0x2UL &lt;&lt; (9 * 2));

GPIOD-&gt;AFR[1] &amp;= ~(0xFUL &lt;&lt; 0);
GPIOD-&gt;AFR[1] |=  (0x7UL &lt;&lt; 0);   /* PD8 -&gt; AF7 (USART3_TX) */
GPIOD-&gt;AFR[1] &amp;= ~(0xFUL &lt;&lt; 4);
GPIOD-&gt;AFR[1] |=  (0x7UL &lt;&lt; 4);   /* PD9 -&gt; AF7 (USART3_RX) */

RCC-&gt;APB1ENR |= USART3EN;

uart_set_baudrate(APB1_CLK, DBG_UART_BAUDRATE);

USART3-&gt;CR1 = CR1_TE;
USART3-&gt;CR1 |= CR1_UE;

}

static void uart_write(int ch) { while (!(USART3->SR & SR_TXE)) { } USART3->DR = (ch & 0xFF); }

void uart_write_string(const char *s) { while (*s) uart_write((int)*s++); }

static uint16_t compute_uart_bd(uint32_t periph_clk, uint32_t baudrate) { return (uint16_t)((periph_clk + (baudrate / 2U)) / baudrate); }

static void uart_set_baudrate(uint32_t periph_clk, uint32_t baudrate) { USART3->BRR = compute_uart_bd(periph_clk, baudrate); }

Src/main.c

#include <stdio.h>
#include "gpio.h"
#include "gpio_exti.h"
#include "iwdg.h"

extern void uart_init(void);

uint8_t g_btn_press;

static void check_reset_source(void);

int main(void) { uart_init(); led_init(); pc13_exti_init();

check_reset_source();

iwdg_init();

while (1)
{
    if (g_btn_press != 1U)
    {
        IWDG-&gt;KR = IWDG_KEY_RELOAD;
        led_toggle();

        for (volatile int i = 0; i &lt; 90000; i++) {}
    }
}

}

static void check_reset_source(void) { if ((RCC->CSR & RCC_CSR_IWDGRSTF) == RCC_CSR_IWDGRSTF) { RCC->CSR = RCC_CSR_RMVF;

    led_on();
    printf("RESET was caused by IWDG.....\r\n");

    while (g_btn_press != 1U) {}
    g_btn_press = 0U;
}

}

static void exti_callback(void) { g_btn_press = 1U; }

void EXTI15_10_IRQHandler(void) { if ((EXTI->PR & LINE13) != 0) { EXTI->PR |= LINE13; exti_callback(); } }

5. ์‹ค์Šต ๊ฒฐ๊ณผ ๋ฐ ๋ฌธ์ œ ํ•ด๊ฒฐ

Notion์—๋Š” ์ด chapter์—์„œ ์‹ค์ œ๋กœ ๋งŒ๋‚œ ๋ฌดํ•œ ์žฌ๋ฆฌ์…‹ ๋ฌธ์ œ๊ฐ€ ๊ธฐ๋ก๋˜์–ด ์žˆ๋‹ค.

์ดˆ๊ธฐ ์›์„œ ์„ค์ • /4์—์„œ๋Š” timeout์ด ์•ฝ 0.5์ดˆ๋ผ, IWDG reset ์งํ›„ ๋ฉ”์‹œ์ง€๋ฅผ ํ™•์ธํ•˜๊ณ  button์„ ๋‹ค์‹œ ๋ˆ„๋ฅด๊ธฐ ์ „์— watchdog๊ฐ€ ๋‹ค์‹œ timeout๋˜์–ด reset์ด ๋ฐ˜๋ณต๋˜์—ˆ๋‹ค.

์กฐ์ • ๊ณผ์ •:

/4    โ†’ ์•ฝ 0.5 s : ๋„ˆ๋ฌด ์งง์Œ, ์žฌ๋ฆฌ์…‹ ๋ฐ˜๋ณต
/256  โ†’ ์•ฝ 33 s  : ๋„ˆ๋ฌด ๊น€
/32   โ†’ ์•ฝ 4.1 s : ์ตœ์ข… ์‚ฌ์šฉ

์ตœ์ข… ์‹ค์ œ ๋ณด๋“œ ๊ฒ€์ฆ:

  • ์ •์ƒ ์ƒํƒœ์—์„œ LD1 toggle

  • B1 ๋ˆ„๋ฆ„ โ†’ reload ์ค‘๋‹จ

  • ์•ฝ 4์ดˆ ํ›„ hardware reset

  • UART์— RESET was caused by IWDG..... 1ํšŒ ์ถœ๋ ฅ

  • button ์ž…๋ ฅ ํ›„ ๋‹ค์Œ cycle ์ง„ํ–‰

text = 1536 bytes
data = 0 bytes
bss  = 2568 bytes
warning ์—†์Œ

์ฝ”๋“œ ํ™•์ธ ๋ฉ”๋ชจ

ํ˜„์žฌ ์ฒจ๋ถ€ ZIP์˜ g_btn_press๋Š” ISR๊ณผ main()์ด ๊ณต์œ ํ•˜์ง€๋งŒ volatile ์—†์ด uint8_t๋กœ ์„ ์–ธ๋˜์–ด ์žˆ๋‹ค. ์ด Wiki์—์„œ๋Š” ์‹ค์ œ ์†Œ์Šค๋ฅผ ๊ทธ๋Œ€๋กœ ๊ธฐ๋กํ•œ๋‹ค.

6. ํ•ต์‹ฌ ์ •๋ฆฌ

  • IWDG๋Š” LSI ๊ธฐ๋ฐ˜ ๋…๋ฆฝ watchdog์ด๋‹ค.

  • ์ •์ƒ ์‹คํ–‰ ์‹œ 0xAAAA reload๋ฅผ ๋ฐ˜๋ณตํ•˜๊ณ  ์ค‘๋‹จ๋˜๋ฉด timeout reset์ด ๋ฐœ์ƒํ•œ๋‹ค.

  • ์‹ค๊ธฐ์—์„œ timeout์„ /32 ์•ฝ 4.1์ดˆ๋กœ ์กฐ์ •ํ•ด ์žฌ๋ฆฌ์…‹ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋‹ค.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ