Chapter 07 - Hongjayeong-02/Basic_SoC_implementation GitHub Wiki
NUCLEO-F439ZIμ LD1(PB0) κ³Ό B1(PC13) μ μ§μ μ μ΄νλ€.
μ΄λ² μ₯μμ νμΈν ν΅μ¬:
PB0 β Output β LED
PC13 β Input β Push Button
μ¬μ© register:
RCC->AHB1ENR
GPIOB->MODER
GPIOB->ODR
GPIOB->BSRR
GPIOC->MODER
GPIOC->PUPDR
GPIOC->IDR
GPIO pinμ MODERμμ λμ λͺ¨λλ₯Ό κ²°μ νλ€.
00 = Input
01 = Output
10 = Alternate Function
11 = Analog
Pin νλλΉ 2bitλ₯Ό μ¬μ©νλ€.
Pin n
β MODER[(2n+1):(2n)]
λ°λΌμ:
PB0 β MODER[1:0]
PC13 β MODER[27:26]
NUCLEO-F439ZI:
LD1 Green LED
β PB0
B1 User Button
β PC13
μ΄λ² boardμμ B1μ:
Released β 0
Pressed β 1
μ¦ active-HIGHλ‘ μ¬μ©νλ€.
GPIOC->IDRInput pinμ μ€μ logic levelμ μ½λλ€.
PC13:
GPIOC->IDR & (1U << 13)GPIOB->ODROutput stateλ₯Ό μ μ₯νλ€.
PB0 toggle:
GPIOB->ODR ^= (1U << 0);νΉμ output pinμ ν λ²μ writeλ‘ set/resetν μ μλ€.
BSRR[15:0]
β SET
BSRR[31:16]
β RESET
PB0:
GPIOB->BSRR = (1U << 0); /* SET */
GPIOB->BSRR = (1U << 16); /* RESET */ODR |= ...μ²λΌ Read-Modify-Writeλ₯Ό νμ§ μμλ λλ―λ‘ λ¨μ set/resetμλ BSRRμ΄ μ 리νλ€.
μ΄λ² μ₯λΆν° GPIO μ½λλ₯Ό driver ννλ‘ λΆλ¦¬νλ€.
Inc/
βββ gpio.h
Src/
βββ gpio.c
βββ main.c
#ifndef GPIO_H__
#define GPIO_H__
#include <stdbool.h>
#include "stm32f4xx.h"
/*
* LED control functions
*
* LD1 on NUCLEO-F439ZI is connected to PB0.
*/
void led_init(void);
void led_on(void);
void led_off(void);
void led_toggle(void);
/*
* Push button functions
*
* B1 on NUCLEO-F439ZI is connected to PC13.
* In this project:
*
* Released = LOW
* Pressed = HIGH
*/
void button_init(void);
bool get_btn_state(void);
#endif#include "gpio.h"
/*
* ============================================================
* Pin Definitions
* ============================================================
*/
/*
* LD1 is connected to PB0.
*
* BSRR lower 16 bits are used to SET GPIO pins.
*
* bit0 = PB0 set
*/
#define LED_SET (1U << 0)
/*
* BSRR upper 16 bits are used to RESET GPIO pins.
*
* PB0 reset:
*
* pin number 0 + 16 = bit16
*/
#define LED_RESET (1U << 16)
/*
* ODR bit0 corresponds to PB0.
*
* Used when toggling the LED.
*/
#define LED_PIN (1U << 0)
/*
* B1 user button is connected to PC13.
*
* IDR bit13 represents PC13 input state.
*/
#define BTN_PIN (1U << 13)
/*
* ============================================================
* LED Initialization
* ============================================================
*/
void led_init(void)
{
/*
* Step 1
* Enable GPIOB peripheral clock.
*
* GPIO peripheral registers cannot be used properly
* before its clock is enabled.
*
* RCC_AHB1ENR_GPIOBEN = GPIOB clock enable bit.
*/
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
/*
* Step 2
* Configure PB0 as General Purpose Output.
*
* GPIO MODER uses 2 bits for each pin.
*
* PB0:
* MODER[1:0]
*
* 00 = Input
* 01 = Output
* 10 = Alternate Function
* 11 = Analog
*/
/*
* Clear PB0 mode field first.
*
* 0x3 = binary 11
*
* ~(0x3 << 0)
* clears MODER[1:0].
*/
GPIOB->MODER &= ~(0x3UL << (0 * 2));
/*
* Set MODER[1:0] = 01.
*
* PB0 becomes General Purpose Output.
*/
GPIOB->MODER |= (0x1UL << (0 * 2));
}
/*
* ============================================================
* LED ON
* ============================================================
*/
void led_on(void)
{
/*
* Set PB0 using BSRR.
*
* BSRR lower 16 bits:
* writing 1 sets the corresponding GPIO output.
*
* PB0 β bit0
*
* GPIOB->BSRR = 0x00000001
*
* Result:
* PB0 = HIGH
* LD1 = ON
*/
GPIOB->BSRR = LED_SET;
}
/*
* ============================================================
* LED OFF
* ============================================================
*/
void led_off(void)
{
/*
* Reset PB0 using BSRR.
*
* BSRR upper 16 bits:
* writing 1 resets the corresponding GPIO output.
*
* PB0 reset β bit16
*
* GPIOB->BSRR = 0x00010000
*
* Result:
* PB0 = LOW
* LD1 = OFF
*/
GPIOB->BSRR = LED_RESET;
}
/*
* ============================================================
* LED Toggle
* ============================================================
*/
void led_toggle(void)
{
/*
* XOR the current ODR bit0.
*
* 0 XOR 1 = 1
* 1 XOR 1 = 0
*
* Therefore:
*
* LOW β HIGH
* HIGH β LOW
*
* Note:
* ODR toggle requires Read-Modify-Write.
* BSRR is preferred when only explicit SET/RESET is needed.
*/
GPIOB->ODR ^= LED_PIN;
}
/*
* ============================================================
* Button Initialization
* ============================================================
*/
void button_init(void)
{
/*
* Step 1
* Enable GPIOC peripheral clock.
*
* B1 is connected to PC13.
*/
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
/*
* Step 2
* Configure PC13 as input.
*
* Pin 13 uses:
*
* MODER[27:26]
*
* Input mode = 00
*
* Clear both bits.
*/
GPIOC->MODER &= ~(0x3UL << (13 * 2));
/*
* Step 3
* Disable internal pull-up / pull-down.
*
* PUPDR also uses 2 bits per pin.
*
* PC13:
* PUPDR[27:26]
*
* 00 = No Pull
*/
GPIOC->PUPDR &= ~(0x3UL << (13 * 2));
}
/*
* ============================================================
* Read Button State
* ============================================================
*/
bool get_btn_state(void)
{
/*
* Read PC13 from GPIOC Input Data Register.
*
* BTN_PIN = (1U << 13)
*
* If bit13 is HIGH:
* GPIOC->IDR & BTN_PIN != 0
*
* return true
*
* If bit13 is LOW:
* GPIOC->IDR & BTN_PIN == 0
*
* return false
*
* NUCLEO-F439ZI B1:
*
* Released β LOW
* Pressed β HIGH
*/
return ((GPIOC->IDR & BTN_PIN) != 0U);
}#include <stdbool.h>
#include "gpio.h"
int main(void)
{
/*
* Variable used to store the current
* PC13 button input state.
*/
bool btn_state;
/*
* Initialize PB0 as output.
*
* PB0 β LD1
*/
led_init();
/*
* Initialize PC13 as input.
*
* PC13 β B1 user button
*/
button_init();
while (1)
{
/*
* Read current PC13 input level.
*
* false β button released
* true β button pressed
*/
btn_state = get_btn_state();
/*
* B1 on NUCLEO-F439ZI is active-HIGH.
*
* Pressed:
* PC13 = HIGH
* β turn LED on
*
* Released:
* PC13 = LOW
* β turn LED off
*/
if (btn_state)
{
led_on();
}
else
{
led_off();
}
}
}μ 체 software flow:
main()
β
ββ led_init()
β β
β ββ GPIOB Clock ON
β ββ PB0 Output
β
ββ button_init()
β β
β ββ GPIOC Clock ON
β ββ PC13 Input
β ββ No Pull
β
ββ while(1)
β
ββ Read GPIOC->IDR[13]
β
ββ Pressed?
β
ββ YES β BSRR Set PB0
β
ββ NO β BSRR Reset PB0
Hardware flow:
B1
β
PC13
β
GPIOC IDR[13]
β
CPU
β
if()
β
GPIOB BSRR
β
PB0
β
LD1
λ€μ μ½λλ:
GPIOB->ODR |= (1U << 0);CPU μ μ₯μμλ 보ν΅:
Read ODR
β
Modify bit0
β
Write ODR
κ° λλ€.
μ΄κ²μ:
Read-Modify-Write
λΌκ³ νλ€.
λ°λ©΄:
GPIOB->BSRR = (1U << 0);μ μνλ bitλ₯Ό μ§μ setνλ write commandλ€.
Write BSRR
β
PB0 SET
λ°λΌμ λ€λ₯Έ GPIO output bitμ μν₯μ μ£Όμ§ μκ³ νΉμ pinλ§ λ³κ²½νκΈ°μ μ ν©νλ€.
νμ¬ main loop:
while (1)
{
btn_state = get_btn_state();
}λ CPUκ° κ³μ buttonμ νμΈνλ€.
Read
β
Read
β
Read
β
Read
β
...
μ΄λ₯Ό Pollingμ΄λΌκ³ νλ€.
μ₯μ :
Simple
Easy to debug
λ¨μ :
CPU continuously checks the peripheral
Ch14μμλ κ°μ buttonμ EXTI Interrupt λ°©μμΌλ‘ λ³κ²½νλ€.
Mechanical switchλ μ€μ λ‘ ν λ² λλ μ λ signalμ΄ μλ²½νκ² ν λ²λ§ λ°λμ§ μμ μ μλ€.
Ideal
LOW βββββββββββ
βββββ HIGH
μ€μ switchμμλ:
LOW ββββ βββ βββββ HIGH
βββ βββ
μ²λΌ μ§§κ² μ¬λ¬ λ² λ³ν μ μλ€.
μ΄λ₯Ό:
Switch Bounce
λΌκ³ νλ€.
μ΄λ² μ€μ΅μ λ¨μν:
νμ¬ button level
β LED level
μ μ°κ²°νκΈ° λλ¬Έμ ν° λ¬Έμ κ° μμ§λ§,
Button Counter
LED Toggle Once
Interrupt
κ°μ λμμμλ debounce μ²λ¦¬κ° νμνλ€.
μμμμ μ¬μ©ν boardμ νμ¬ boardμ LED pinμ΄ λ€λ₯΄λ€.
NUCLEO-F411
LD2 β PA5
NUCLEO-F439ZI
LD1 β PB0
λ°λΌμ λ³κ²½:
GPIOA
β GPIOB
bit5
β bit0
Buttonμ PC13μ μ¬μ©νμ§λ§ polarityλ₯Ό board νλ‘μ λ§κ² νμΈν΄μΌ νλ€.
μ΄λ² projectμμλ:
B1 Press
β PC13 HIGH
μ΄λ€.
make clean
makeνμΈ:
Build PASS
Expected:
B1 Released
β LD1 OFF
B1 Pressed
β LD1 ON
λ€μ registerλ₯Ό νμΈνλ€.
RCC->AHB1ENR
GPIOB->MODER
GPIOB->ODR
GPIOC->MODER
GPIOC->IDR
Button released:
GPIOC->IDR bit13 = 0
Button pressed:
GPIOC->IDR bit13 = 1
Breakpointλ₯Ό:
btn_state = get_btn_state();λ€μ μ€μ κ±Έκ³ B1μ λλ¬λ³Έλ€.
Watch:
btn_state
GPIOC->IDR
GPIOB->ODR
νμΈ:
Released
btn_state = false
IDR[13] = 0
ODR[0] = 0
Pressed
btn_state = true
IDR[13] = 1
ODR[0] = 1
μ΄λ κ² λμ€λ©΄:
Physical Button
β Input Register
β Software
β Output Register
β Physical LED
μ 체 νλ¦μ νμΈν κ²μ΄λ€.
images/ch07_build.png
images/ch07_button_released.png
images/ch07_button_pressed.png
images/ch07_idr_debug.png
κ°μ₯ μ’μ ꡬμ±:
Button Released / LED OFF
+
Button Pressed / LED ON
+
Debugger IDR[13]
PC13
β
IDR
β
Software
β
BSRR
β
PB0
β
LED
- GPIOλ₯Ό μ¬μ©νκΈ° μ μ RCC clockμ enableνλ€.
-
MODERλ GPIO pin νλλΉ 2bitλ₯Ό μ¬μ©νλ€. - PB0μ mode fieldλ
MODER[1:0]μ΄λ€. - PC13μ mode fieldλ
MODER[27:26]μ΄λ€. - Input μνλ
IDRμμ μ½λλ€. - Output stateλ
ODRλ‘ νμΈν μ μλ€. - νΉμ outputμ set/resetμλ
BSRRμ μ¬μ©ν μ μλ€. - NUCLEO-F439ZIμ B1μ μ΄λ² μ€μ΅μμ active-HIGHλ‘ μ¬μ©νλ€.
- νμ¬ λ°©μμ pollingμ΄λ©° μ΄ν EXTI interruptλ‘ νμ₯νλ€.