GPIO User Description
현재 구현에서 학생이 GPIOA/GPIOB 핀을 어떤 레지스터로 조작하고 어디서 확인하는지 연결합니다.
GPIO Datasheet 현재 Trainer 실행 예제 RCC Datasheet EXTI Datasheet ADC User Description TIM User Description Lab Guide
1. 그림에서 먼저 보기
Figure 1의 번호는 아래 표의 같은 번호 행으로 이어집니다. 1은 입력 상태를 읽는 IDR, 2는 출력 논리값을 기억하는 ODR, 3은 ODR을 set/reset하는 BSRR/BRR, 4는 핀별 입출력 방식과 출력 형식을 정하는 CRL/CRH입니다. P-MOS/N-MOS는 레지스터가 아니라 실제 pad를 구동하는 물리 회로입니다.
Figure 1. GPIO input state, output data, atomic set/reset, pin configuration, and physical pad driver
Source reconstruction: RM0008 Rev 21 Figure 13. The numbered IDR, ODR, BSRR/BRR, and GPIOx_CRL/CRH callouts are teaching annotations for this User Description; the unnumbered P-MOS/N-MOS stage is the physical pad driver.
2. 블록 → 레지스터 비트
읽는 순서: 지원되는 항목을 먼저 확인하고, 미지원 항목은 문서 하단의 지원하지 않는 항목에서 확인합니다.
2.1 GPIO 데이터시트 값 읽는 법
Pxy에서 x는 port, y는 pin 번호입니다. 예를 들어 PA0은 GPIOA의 0번 필드, PB3은 GPIOB의 3번 필드를 사용합니다. GPIOx_CRL은 pin 0~7, GPIOx_CRH는 pin 8~15를 설정합니다. 각 핀은 CNF[1:0]:MODE[1:0] 순서의 4-bit 값 하나를 사용합니다. GPIO Datasheet Section 4.1의 pin-number lookup에서 모든 필드 위치를 찾을 수 있습니다.
| 핀 번호 y | MODE/CNF 위치 | IDR / ODR | BSRR set / reset | BRR reset |
|---|---|---|---|---|
| 0..7 | CRL[4y+3:4y] | IDRy[y] / ODRy[y] | BSy[y] / BRy[y+16] | BRy[y] |
| 8..15 | CRH[4(y-8)+3:4(y-8)] | IDRy[y] / ODRy[y] | BSy[y] / BRy[y+16] | BRy[y] |
| PA0 예 | GPIOA_CRL[3:0] CNF0[3:2], MODE0[1:0] | IDR0[0] / ODR0[0] | BS0[0] / BR0[16] | BR0[0] |
| 필드 | 값 의미 | 이 문서에서 쓰는 예 |
|---|---|---|
| MODE[1:0] | 00 = 입력 모드01 = 출력, 최대 10 MHz10 = 출력, 최대 2 MHz11 = 출력, 최대 50 MHz | PA5/PA6 입력은 MODE=00, PA3/PA4 출력은 MODE=10입니다. |
| CNF[1:0] (MODE=00) | 00 = analog input01 = floating digital input10 = pull-up / pull-down input11 = 예약값 | PA1은 0x0(analog), PA5는 0x4(floating)입니다. 공통 PA6 단자는 Feedback=HALL이면 0x4, Feedback=POSITION이면 0x0입니다. |
| CNF[1:0] (MODE≠00) | 00 = general-purpose push-pull01 = general-purpose open-drain10 = alternate-function push-pull11 = alternate-function open-drain | 공통 하네스의 PA3/PA4는 0x2이고, 공식 PA2/PA9 AF 출력 예는 0xB입니다. |
| 4-bit nibble | 0x0 = analog input0x2 = push-pull output, 2 MHz0x4 = floating input0x6 = open-drain output, 2 MHz0xB = alternate-function push-pull, 50 MHz | 전체 0x0~0xF 의미는 GPIO Datasheet 표를 기준으로 합니다. |
자주 헷갈리는 부분: STM32F103은 이후 계열의 GPIOx_MODER/OTYPER/OSPEEDR/PUPDR 대신 CRL/CRH의 CNF:MODE 4-bit 값을 사용합니다. MODE=00이면 CNF가 입력 형식을 정하고, MODE!=00이면 MODE는 출력 최대 속도이며 CNF가 push-pull/open-drain/alternate-function 형식을 정합니다. MODE의 MHz 값은 PWM 주파수가 아닙니다. Pull 입력에서는 ODRy=0이 pull-down, ODRy=1이 pull-up 방향을 선택합니다.
2.2 그림 블록과 실제 레지스터
레지스터와 필드 / bit 열은 RM0008 데이터시트 표기만 사용합니다. PA5/FAULT_IN 같은 화면 신호 이름과 코드에서 쓰는 값은 설명 칸에서 연결합니다.
| 그림 블록 | 레지스터 | 필드 / bit | 그림에서 하는 일 / 값 의미 | 지원 여부 |
|---|---|---|---|---|
| 1Figure 1 입력 버퍼 → IDR | ||||
| PA5 / PA6 입력값 | GPIOA_IDR | IDR5[5] IDR6[6] | 그림에서: 외부 pad 전압을 digital 0/1로 읽습니다.0 = pin LOW1 = pin HIGH현재 구현에서는 PA5/FAULT_IN과 PA6/HALL_IN이 보드 입력으로 이 값을 만듭니다. | 지원됨 |
| 2Figure 1 ODR → 출력 논리값 저장 | ||||
| PA3 / PA4 출력값 | GPIOA_ODR | ODR3[3] ODR4[4] | 그림에서: 핀에 내보낼 논리값을 기억합니다. ODR에 직접 쓰거나 BSRR/BRR을 쓰면 이 bit가 바뀝니다.0 = push-pull 출력은 LOW 구동1 = push-pull 출력은 HIGH 구동CRL에서 pin이 output mode이고 IOPAEN=1일 때 PA3/DRV_EN, PA4/DRV_DIR pad에 반영됩니다. | 지원됨 |
| PB0 / PB1 출력 latch | GPIOB_ODR | ODR0[0] ODR1[1] | 그림 밖에서: 같은 ODR 값이라도 CRL에서 선택한 입출력 형식에 따라 pad 동작이 달라집니다.0 = ODR latch LOW; PB0 analog pad에는 영향 없고 PB1 output은 LOW 구동1 = ODR latch HIGH; PB0 analog pad에는 영향 없고 PB1 output 형식에 따라 HIGH 또는 Hi-ZPB0는 현재 TEMPERATURE_SENSE analog input이므로 GPIOB_ODR 변경이 NTC 분압 전압을 바꾸지 않습니다. PB1은 참고용입니다. open-drain은 출력을 놓는 high-impedance 상태를 만듭니다. | 지원됨 |
| 그 밖의 출력 저장 bit | GPIOA_ODR GPIOB_ODR | ODRy[y] | 그림에서: 각 GPIO pin에 대응하는 출력 논리값을 저장합니다.0 = 저장 bit 01 = 저장 bit 1y=0..15입니다. 현재 구현은 GPIOA/GPIOB ODR 하위 16bit 저장값을 Registers에서 확인할 수 있습니다. 다만 보드에 연결되지 않은 bit는 pad 전압이나 Graph 효과 없이 Registers 저장값만 보입니다. | 미지원 |
| 3Figure 1 BSRR / BRR → ODR 변경 명령 | ||||
| PA3 / PA4 set | GPIOA_BSRR | BS3[3] BS4[4] | 그림에서: BSRR 자체가 출력값을 저장하지 않고, 같은 핀 번호의 ODR bit를 한 번의 write로 1로 바꿉니다.0 write = 변화 없음1 write = 같은 번호의 ODR bit를 1로 set다른 ODR bit를 먼저 읽고 다시 쓰지 않으므로 선택한 bit만 원자적으로 변경합니다. | 지원됨 |
| PA3 / PA4 reset | GPIOA_BSRR | BR3[19] BR4[20] | 그림에서: BSRR의 상위 BR 영역이 같은 핀 번호의 ODR bit를 한 번의 write로 0으로 바꿉니다.0 write = 변화 없음1 write = 같은 번호의 ODR bit를 0으로 resetGPIOA 예제는 BSRR.BR4와 GPIOA_BRR.BR3를 각각 실행해 두 reset 경로를 비교합니다. | 지원됨 |
| 그 밖의 BSRR set/reset bit | GPIOx_BSRR | BSy[y] BRy[y+16] | 그림에서: x 포트의 y번 ODR 저장 bit를 BSRR 하나로 set/reset합니다.BSy 1 write = 해당 ODR bit setBRy 1 write = 해당 ODR bit resetx=A/B, y=0..15입니다. 같은 write에서 같은 y의 BSy와 BRy가 모두 1이면 공식 동작대로 set이 우선합니다. 현재 구현의 보드 연결이 없는 bit는 ODR 저장값만 확인할 수 있습니다. | 지원됨 |
| BRR reset 전용 bit | GPIOx_BRR | BRy[y] | 그림에서: BSRR 상위 BR 영역과 같은 reset 명령을 별도 register에서 제공합니다.0 write = 변화 없음1 write = 같은 번호의 ODR bit를 0으로 resetx=A/B, y=0..15입니다. GPIOA/GPIOB 예제 모두 BRR을 실제로 실행하며, 보드 연결이 없는 bit는 ODR 저장값만 바뀝니다. | 지원됨 |
| 4Figure 1 CRL / CRH → 핀별 입출력 구성 | ||||
| PA3 output mode | GPIOA_CRL | CNF3[15:14] MODE3[13:12] | 그림에서: PA3 pad를 일반 push-pull 출력 드라이버에 연결합니다.CRL[15:12] = 0x2 CNF3=00, MODE3=10, push-pull output 2 MHz이후 ODR3 또는 BS3/BR3가 DRV_EN 값을 결정합니다. | 지원됨 |
| PA4 output mode | GPIOA_CRL | CNF4[19:18] MODE4[17:16] | 그림에서: PA4 pad를 일반 push-pull 출력 드라이버에 연결합니다.CRL[19:16] = 0x2 CNF4=00, MODE4=10, push-pull output 2 MHz이후 ODR4 또는 BS4/BR4가 DRV_DIR 값을 결정합니다. | 지원됨 |
| PA5 / PA6 System modes | GPIOA_CRL | CNF5[23:22] / MODE5[21:20] CNF6[27:26] / MODE6[25:24] | 그림에서: PA5는 항상 digital Fault 입력이고, 같은 PA6 단자는 Board의 Feedback 선택에 따라 초기화 mode만 바뀝니다.HALL PA6 = 0x4 HALL_IN / EXTI6POSITION PA6 = 0x0 POSITION_IN / ADC1_IN6 analog input공통 펌웨어가 TRAINER->FEEDBACK_MODE를 읽어 한 경로만 활성화합니다. 두 센서를 동시에 PA6에 연결하지 않습니다. | 지원됨 |
| PA1 analog mode | GPIOA_CRL | CNF1[7:6] MODE1[5:4] | 그림에서: digital 입력 버퍼와 출력 드라이버를 끄고 analog 경로를 엽니다.CRL[7:4] = 0x0 CNF1=00, MODE1=00, analog inputADC1_IN1/CURRENT_SENSE를 쓰기 위한 GPIO 쪽 전제 조건이며 변환 동작은 ADC User Description에서 확인합니다. | 지원됨 |
| PA2 PWM mode | GPIOA_CRL | CNF2[11:10] MODE2[9:8] | 그림에서: timer의 alternate-function 출력을 PA2 pad로 내보내는 경로입니다.CRL[11:8] = 0xB 공식 AF push-pull 50 MHz, PA2의 공식 PA2 기능은 TIM2_CH3CRL[11:8] = 0x2 현재 구현이 사용하는 output 설정현재 구현의 PA2/PWM_OUT은 TIM2_CCR1에 연결된 고정 경로입니다. 공식 TIM2_CH3 AF mux 동작은 구현하지 않습니다. | 지원됨 |
| PB0 / PB1 modes | GPIOB_CRL | CNF0[3:2] / MODE0[1:0] CNF1[7:6] / MODE1[5:4] | 그림 밖에서: PB0는 현재 NTC ADC 입력이며 PB1은 공식 참고용입니다.PB0 0x0 = TEMPERATURE_SENSE analog inputPB1 0x2 = push-pull output 2 MHz referencePB1 0x6 = open-drain output 2 MHz reference현재 System Trainer는 PB0/ADC1_IN8을 지원하고 PB1은 활성 하네스에 포함하지 않습니다. | 지원됨 |
3. 데이터시트 필드 ↔ 현재 코드
| 현재 코드 / 값 | 데이터시트 필드로 해석 | 화면에서 확인 |
|---|---|---|
| RCC->APB2ENR = AFIOEN | IOPAEN | ADC1EN | USART1EN | 공통 하네스의 GPIOA, ADC1, USART1 PCLK2 gate를 엽니다. | Registers → Clock |
| GPIOA->CRL = 0x44422B00u | PA1 analog, PA2 AF output, PA3·PA4 push-pull output, PA5·PA6 floating input인 HALL 기본값입니다. | Registers → GPIOA_CRL |
| if (TRAINER->FEEDBACK_MODE == TRAINER_FEEDBACK_ANGLE) GPIOA->CRL &= ~(0xFu << 24) | 같은 코드에서 ANGLE 선택 시 PA6 nibble만 0x0 analog input으로 바꿉니다. | Board PA6/FEEDBACK_IN, Registers → GPIOA_CRL |
| GPIOA->ODR &= ~(EN | DIR) | ODR3=0, ODR4=0으로 안전 시작합니다. | PA3/DRV_EN LOW, PA4/DRV_DIR CW |
| GPIOA->ODR |= EN 또는 DIR | ODR3 또는 ODR4를 직접 set합니다. | Registers의 GPIOA_ODR, Board pin route |
| GPIOA->ODR &= ~EN 또는 ~DIR | ODR3 또는 ODR4를 직접 clear합니다. 현재 최소 예제는 BSRR/BRR를 사용하지 않습니다. | Registers의 GPIOA_ODR, Board pin route |
4. 현재 Trainer 실행 예제
FW EDIT에 그대로 붙여넣어 공통 PA1~PA6 mode와 PA3·PA4 ODR 변화를 확인합니다. PA6 초기화만 Board의 Feedback 선택값에 따라 HALL/ANGLE로 분기합니다.
#include "training_api.h"
static uint32_t gpio_stage = 0u;
static void gpio_init(void)
{
GPIOA->CRL = 0x44422B00u; /* GPIO User Description 4번: PA1 analog, PA2 AF, PA3·PA4 output, PA5·PA6 digital input */
if (TRAINER->FEEDBACK_MODE == TRAINER_FEEDBACK_ANGLE)
GPIOA->CRL &= ~(0xFu << 24); /* 같은 PA6를 ANGLE analog input으로 전환 */
GPIOA->ODR &= ~(GPIOA_DRV_EN_BIT | GPIOA_DRV_DIR_BIT); /* GPIO User Description 2번: PA3·PA4 ODR=0 */
}
void user_init(void)
{
trainer_clock_init_72mhz(); /* RCC User Description 1~4번: 72 MHz clock 경로 */
RCC->APB2ENR = RCC_APB2ENR_AFIOEN; /* RCC User Description 5번: AFIO gate */
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; /* RCC User Description 5번: GPIOA gate */
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; /* System Trainer 공통 ADC1 gate */
RCC->APB1ENR = RCC_APB1ENR_TIM2EN; /* System Trainer 공통 TIM2 PWM gate */
gpio_init(); /* GPIO User Description 2번·4번 설정 적용 */
}
void user_loop(void)
{
switch (gpio_stage)
{
case 0u: GPIOA->ODR |= GPIOA_DRV_EN_BIT; break; /* 2번: ODR3 set */
case 1u: GPIOA->ODR |= GPIOA_DRV_DIR_BIT; break; /* 2번: ODR4 set */
case 2u: GPIOA->ODR &= ~GPIOA_DRV_EN_BIT; break; /* 2번: ODR3 clear */
case 3u: GPIOA->ODR &= ~GPIOA_DRV_DIR_BIT; break; /* 2번: ODR4 clear */
default: break;
}
if (gpio_stage < 4u) gpio_stage++;
watch_u32("gpio_stage", gpio_stage);
watch_u32("GPIOA_CRL", GPIOA->CRL); /* 4번 pin mode */
watch_u32("GPIOA_IDR", GPIOA->IDR); /* 1번 input value */
watch_u32("GPIOA_ODR", GPIOA->ODR); /* 2번 output latch */
}
5. 사이트에서 확인
바로 위 실행 예제를 실행하고 PA3·PA4 ODR 단계와 선택된 PA6 Feedback mode를 아래 화면에서 확인합니다.
- Registers: Clock 그룹의 IOPAEN, GPIO mode 그룹의 GPIOA_CRL, latch/input 그룹의 GPIOA_ODR/GPIOA_IDR을 확인합니다.
- Board · Lab pin routes: PA3/DRV_EN, PA4/DRV_DIR, PA5/FAULT_IN, PA6/FEEDBACK_IN의 단자와 전압을 확인합니다.
- Graph: PA3/DRV_EN과 PA4/DRV_DIR을 선택하면 trace 목록에 자동으로 추가되며 ODR 단계별 변화를 확인합니다.
- Code Watch: GPIOA 예제는 gpio_stage와 GPIOA_ODR에서 PA3·PA4 변화만 확인합니다.
- System: Feedback 값과 PA6 HALL/ANGLE 선택이 GPIOA_CRL mode와 일치하는지 확인합니다.
- Docs / Log: GPIOA_BSRR/BRR updated 메시지와 각 System route voltage 변화를 같이 확인합니다.
6. 지원하지 않는 항목
공식 STM32에는 있지만 현재 보드 경로에서 실행되지 않는 항목을 아래에서 구분합니다.
6.1 그림 번호와 연결되는 미지원 항목
| 그림 블록 | 레지스터 | 필드 / bit | 공식 의미와 현재 구현 범위 | 지원 여부 |
|---|---|---|---|---|
| 그 밖의 입력 bit | GPIOA_IDR | IDRy[y] | 그림에서: 같은 방식으로 각 GPIOA pad의 digital level을 읽습니다.0 = pin LOW1 = pin HIGHy=0..4, 7..15입니다. 공식 STM32 register에는 존재하지만 현재 구현의 주 보드 입력 경로는 아닙니다. | 미지원 |
| PA9 USART1_TX | GPIOA_CRH | CNF9[7:6] MODE9[5:4] | 그림에서: USART1_TX alternate-function 출력을 PA9 pad로 보냅니다.CRH[7:4] = 0xB CNF9=10, MODE9=11, AF push-pull 50 MHz현재 구현은 USART1_DR 전송 로그만 제공하고 별도 PA9 보드 wire는 없습니다. | 미지원 |
| PA10 USART1_RX | GPIOA_CRH | CNF10[11:10] MODE10[9:8] | 그림에서: PA10 pad의 digital 입력을 USART1_RX 경로로 읽습니다.CRH[11:8] = 0x4 CNF10=01, MODE10=00, floating input현재 구현의 독립 External UART TX → PA10/UART_RX는 고정 경로이며 이 GPIO CRH 필드가 compact 수신 효과를 제어하지 않습니다. | 미지원 |
6.2 추가 지원 경계
| 항목 | 공식 STM32 의미 | 현재 구현 경계 | 지원 여부 |
|---|---|---|---|
| GPIOA_LCKR / GPIOB_LCKR | GPIO configuration lock sequence | register 값은 저장할 수 있지만 lock key sequence와 configuration freeze side effect는 모델링하지 않으므로 제어 예제에서 제외합니다. | 미지원 |
| GPIOA_CRH / GPIOB_CRH | pin 8~15의 MODEy/CNFy를 설정합니다. | 값은 저장되지만 현재 보드 출력 경로를 제어하지 않습니다. PA9 TX는 log-only이고 PA10 RX는 고정 수신 경로이므로 실행 가능한 GPIO 제어로 세지 않습니다. | 미지원 |
| GPIOB_IDR | GPIOB pad의 digital 입력값을 읽습니다. | PB0는 analog mode의 TEMPERATURE_SENSE이므로 NTC 증명은 GPIOB_IDR이 아니라 ADC1_IN8 변환 결과와 Graph/System 값을 사용합니다. | 미지원 |
| Input pull-up / pull-down + ODR | STM32F1 input pull-up/pull-down mode에서는 ODRy가 pull 방향을 선택합니다. | 현재 구현은 이 내부 pull resistor 전기 모델을 구현하지 않습니다. 이 경우 ODR을 output pad 구동 예제로 해석하지 않습니다. | 미지원 |
| Full alternate-function mux | 핀별 AF 선택과 remap으로 USART/TIM/SPI 등의 출력 경로를 선택합니다. | 현재 구현은 PA2/PWM_OUT, PA9/PA10 USART 등 고정 교육 경로만 설명하고 full AF remap mux는 실행하지 않습니다. | 미지원 |
전체 0x0..0xF GPIO nibble 의미, PA9/PA10 USART, PA2의 공식 TIM2_CH3, PA1·PA6 ADC, PA6 EXTI6 세부 동작은 각각 대응 Datasheet/User Description에서 확인합니다. Board selector는 같은 PA6 단자에 HALL 또는 ANGLE 하나만 연결합니다.