Bare metal C Ch14 EXTI - Hongjayeong-02/Basic_SoC_implementation GitHub Wiki

Ch14. ์™ธ๋ถ€ ์ธํ„ฐ๋ŸฝํŠธ (EXTI)

ํ•œ ์ค„ ์š”์•ฝ: B1(PC13)์„ pollingํ•˜์ง€ ์•Š๊ณ  EXTI13 + NVIC interrupt๋กœ ์ฒ˜๋ฆฌํ•ด LED toggle๊ณผ UART message ์ถœ๋ ฅ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

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

Polling์€ CPU๊ฐ€ ์ƒํƒœ๋ฅผ ๊ณ„์† ๋ฐ˜๋ณตํ•ด์„œ ์ฝ๋Š”๋‹ค. Interrupt ๋ฐฉ์‹์—์„œ๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ๋งŒ CPU๊ฐ€ ISR๋กœ ์ง„์ž…ํ•œ๋‹ค.

ํ•ต์‹ฌ ์šฉ์–ด

  • ISR: Interrupt Service Routine

  • IVT: Interrupt Vector Table

  • NVIC: Cortex-M interrupt controller

  • EXTI: STM32 external interrupt/event controller

EXTI line๊ณผ GPIO port

EXTI๋Š” pin number ๊ธฐ์ค€์œผ๋กœ line์ด ์ •ํ•ด์ง„๋‹ค.

PA13
PB13
PC13
...
   โ””โ”€ ๋ชจ๋‘ EXTI13 ํ›„๋ณด

์–ด๋А port์˜ pin์„ EXTI13์— ์—ฐ๊ฒฐํ• ์ง€๋Š” SYSCFG->EXTICR[]๋กœ ์„ ํƒํ•œ๋‹ค.

F439ZI ๋ฒ„ํŠผ ๊ทน์„ฑ

Notion ๊ธฐ๋ก์—์„œ๋Š” NUCLEO-F439ZI B1์„ active-HIGH๋กœ ์ •๋ฆฌํ–ˆ๋‹ค.

๋ฒ„ํŠผ ์•ˆ ๋ˆ„๋ฆ„ : Low
๋ฒ„ํŠผ ๋ˆ„๋ฆ„    : High

๋”ฐ๋ผ์„œ:

Low โ†’ High
= Rising Edge
= EXTI->RTSR

์„ ์‚ฌ์šฉํ•œ๋‹ค.

ํ•ต์‹ฌ register

Register | ์—ญํ•  -- | -- SYSCFG->EXTICR[3] | EXTI13์„ Port C์— ์—ฐ๊ฒฐ EXTI->IMR | interrupt mask EXTI->RTSR | rising-edge trigger EXTI->PR | pending flag NVIC | EXTI15_10_IRQn enable

EXTI10 ~ EXTI15๋Š” ํ•˜๋‚˜์˜ EXTI15_10_IRQHandler()๋ฅผ ๊ณต์œ ํ•˜๋ฏ€๋กœ ISR ์•ˆ์—์„œ PR์„ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค.

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

B1 / PC13
   โ”‚ Rising Edge
   โ–ผ
EXTI13
   โ”‚
   โ–ผ
NVIC
   โ”‚
   โ–ผ
EXTI15_10_IRQHandler()
   โ”‚
   โ”œโ”€ PR13 clear
   โ–ผ
exti_callback()
   โ”‚
   โ”œโ”€ UART message
   โ””โ”€ LD1 toggle

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


Ch14_exti/

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

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

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

โ”œโ”€โ”€ Src/gpio_exti.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/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"

extern void uart_init(void);

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

while (1)
{
    /* ์ธํ„ฐ๋ŸฝํŠธ๋งŒ์œผ๋กœ ๋™์ž‘ โ€” ํด๋ง ์—†์Œ */
}

}

static void exti_callback(void) { printf("BTN Pressed...\r\n"); led_toggle(); }

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

5. ์‹ค์Šต ๊ฒฐ๊ณผ

Notion ๊ธฐ๋ก ๊ธฐ์ค€ ์‹ค์ œ ๋ณด๋“œ ๊ฒ€์ฆ ์™„๋ฃŒ.

  • B1์„ ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค LD1 toggle

  • Terminal์— BTN Pressed... ์ถœ๋ ฅ

  • polling ์—†์ด interrupt ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘

text = 1272 bytes
data = 0 bytes
bss  = 2560 bytes
warning ์—†์Œ

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

  • EXTI๋Š” pin number ๊ธฐ์ค€ line์„ ์‚ฌ์šฉํ•˜๊ณ  port๋Š” SYSCFG์—์„œ ์„ ํƒํ•œ๋‹ค.

  • F439ZI B1์€ active-HIGH ๊ธฐ๋ก์— ๋”ฐ๋ผ Rising Edge๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

  • ISR์—์„œ๋Š” pending flag๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  callback์œผ๋กœ ๋™์ž‘์„ ๋ถ„๋ฆฌํ–ˆ๋‹ค.

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