EXTI6 / Hall User Description
공식 EXTI edge·mask·pending 흐름을 현재 구현의 고정 PA6 / HALL_IN → EXTI6 경로와 연결합니다.
EXTI Datasheet RCC Datasheet GPIO User Description TIM2/PWM User Description Lab Guide
1. 그림에서 먼저 보기
Figure 1의 번호는 아래 표의 같은 번호 행으로 이어집니다. 이 EXTI 문서는 GPIO source → edge/SWIER request → IMR → PR → handler interrupt branch와 EMR → pulse generator → Event branch를 설명합니다. 현재 구현은 그중 PA6 rising edge → RTSR.TR6 → IMR.MR6 → PR.PR6 → EXTI6_IRQHandler subset을 실행합니다.
1
2
3
4
Figure 1. RM0008-style EXTI interrupt/event controller architecture
RM0008 Rev 21 Figure 20과 EXTI register 설명을 바탕으로 직접 생성한 래스터 재구성입니다. 이 문서의 interrupt branch는 selected trigger request가 IMR을 통과해 PR pending latch를 세운 뒤 handler로 이어집니다. PRx에 1을 쓰면 latched request가 해제됩니다. EMR event branch는 pulse를 만들지만 PR을 거치지 않습니다.
Figure 2. 공식 EXTI6 source selection과 현재 구현의 고정 PA6 route
RM0008 Rev 21 Figure 21과 AFIO_EXTICR2[11:8] (EXTI6[3:0])을 재구성했습니다. GPIO EXTI mapping은 pin index와 line index가 같고, 각 line에는 한 port source만 선택됩니다. 따라서 EXTI6에 PA6·PB6·PC6를 동시에 연결할 수 없습니다. 현재 구현은 PA6 / HALL_IN만 연결하고 AFIO_EXTICR2를 노출하지 않습니다.
핵심: MR6, TR6, PR6의 숫자 6은 모두 EXTI line 6을 뜻합니다. 이것만으로 PA6라고 판단할 수는 없습니다. PA6 선택의 근거는 AFIO_EXTICR2.EXTI6[3:0] = 0000이며, 현재 Trainer는 이 선택을 PA6로 고정합니다.
| 그림 구간 | 공식 RM0008 흐름 | 현재 구현 해석 |
|---|---|---|
| Input source | PxN → AFIO_EXTICRx → EXTIN. Pin index와 EXTI line index는 같고, line마다 한 port만 선택합니다. | PA6 → EXTI6 → HALL_IN으로 고정됩니다. |
| Edge / software request | RTSR과 FTSR이 transition을 선택하고 SWIER request와 OR됩니다. 선택한 transition마다 한 번 요청하며 HIGH level 유지만으로 반복 요청하지 않습니다. | Hall rising edge만 effect를 만들고, FTSR은 저장·표시만 하며 SWIER는 노출하지 않습니다. |
| Interrupt branch | request → IMR → PR → handler. IMR이 0이면 이 branch를 통과하지 않아 PR도 이 경로로 set되지 않으며, PR은 write-1-to-clear입니다. | PR6를 set한 뒤 EXTI6_IRQHandler compatibility hook을 직접 dispatch합니다. |
| Event branch | request → EMR → pulse generator → Event. Event-only 요청은 PR을 거치지 않으며 IMR branch와 동시에 enable할 수 있습니다. | EMR, pulse generator와 Event output은 모델링하지 않습니다. |
| Register interface / lane width | AMBA APB bus ↔ Peripheral interface를 PCLK2가 구동합니다. /19는 EXTI0..18의 19개 병렬 lane이며 connectivity-line device만 EXTI19를 추가합니다. RCC에는 별도 EXTIEN이 없습니다. | EXTI register는 MMIO로 접근합니다. AFIOEN과 IOPAEN은 upstream source/configuration prerequisite이며 EXTI 자체 enable bit가 아닙니다. |
2. 블록 → 레지스터 비트
| 그림 블록 | 레지스터 | 필드 / bit | 그림에서 하는 일 / 값 의미 | 지원 여부 |
|---|---|---|---|---|
| 1Figure 1 rising trigger selection | ||||
| Rising-edge selector | EXTI_RTSR | TR6[6] | 그림에서: EXTI6 입력의 low-to-high edge를 selected trigger request로 보냅니다.0 = rising trigger 비활성화1 = rising trigger 활성화현재 Hall pulse가 pending으로 이어지려면 TR6가 1이어야 합니다. | 지원됨 |
| 2Figure 1 falling trigger selection | ||||
| Falling-edge selector | EXTI_FTSR | TR6[6] | 그림에서: EXTI6 입력의 high-to-low edge를 selected trigger request로 보냅니다.0 = falling trigger 비활성화1 = falling trigger 활성화현재 구현은 값을 저장하고 Registers에 표시하지만 Hall count와 pending 생성은 rising edge만 사용합니다. | 미지원 |
| 3Figure 1 interrupt mask gate | ||||
| Interrupt request gate | EXTI_IMR | MR6[6] | 그림에서: selected EXTI6 trigger request가 pending latch로 들어갈지 결정합니다.0 = line 6 interrupt request mask1 = line 6 interrupt request unmask현재 구현에서도 MR6가 0이면 Hall rising edge가 PR6를 set하지 않습니다. | 지원됨 |
| 4Figure 1 pending latch and clear command | ||||
| Pending state | EXTI_PR | PR6[6] | 그림에서: unmasked selected trigger request가 발생했음을 pending state로 보관합니다.0 = line 6 pending 없음1 = line 6 pending 있음현재 구현은 active Hall rising edge에서 PR6를 set한 뒤 compatibility handler를 호출합니다. | 지원됨 |
| Write-1-to-clear command | EXTI_PR | PR6[6] | 그림에서: pending state를 지우는 software write command입니다.0 write = pending state 변화 없음1 write = PR6 pending clearEXTI->PR = EXTI_PR_PR6처럼 대입하며 read-modify-write clear를 가르치지 않습니다. | 지원됨 |
3. 표 기준 단순 코드
| 현재 코드 / 값 | 데이터시트 필드로 해석 | 화면에서 확인 |
|---|---|---|
| RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN | RCC_APB2ENR.AFIOEN[0] = 1, IOPAEN[2] = 1: 현재 EXTI/GPIOA route prerequisite | Registers → Clock |
| GPIOA_CRL[27:24] = 0x4 | CNF6[27:26] = 01, MODE6[25:24] = 00: PA6 floating digital input | Registers, Board · Lab pin routes |
| AFIO_EXTICR2[11:8] (EXTI6[3:0]) = 0000 | 공식 STM32F103에서 PA6를 EXTI6 source로 선택 | 현재 구현에는 해당 register가 없고 PA6 route가 고정됨 |
| EXTI->RTSR = EXTI_RTSR_TR6 | EXTI_RTSR.TR6[6] = 1: rising trigger 선택 | Registers, Graph |
| EXTI->IMR = EXTI_IMR_MR6 | EXTI_IMR.MR6[6] = 1: interrupt request unmask | Registers, Code Watch |
| exti_pr_before_clear = EXTI->PR | EXTI_PR.PR6[6] = 1 상태를 W1C command 전에 보존 | Code Watch |
| EXTI->PR = EXTI_PR_PR6 | EXTI_PR.PR6[6] write-1-to-clear command | Registers, Docs / Log |
| EXTI_EMR / EXTI_SWIER | 공식 event gate와 software-trigger register | 현재 header/MMIO에는 없으며 Figure 1과 경계 표에서만 확인 |
4. 실행해 보기
FW EDIT에 붙여넣고 BUILD 후 START합니다. EXTI 설정만으로 Hall edge가 생기지는 않으므로, 이 예제는 Hall source를 만들기 위한 현재 구현 전용 전제 조건으로 TIM2 PWM과 PA3 driver enable도 함께 켭니다. PA2/CCR1 fixed PWM alias는 공식 PA2 timer mapping이 아니며 TIM2/PWM User Description의 경계를 따릅니다. 여러 tick 뒤 HALL_COUNT와 hall_irq_count가 함께 증가하는지 확인합니다.
#include "training_api.h"
volatile uint32_t hall_irq_count = 0u;
volatile uint32_t exti_pr_before_clear = 0u;
void user_init(void)
{
trainer_clock_init_72mhz();
RCC->APB2ENR = RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN;
RCC->APB1ENR = RCC_APB1ENR_TIM2EN;
/* PA2 PWM, PA3 driver enable, PA4 direction, PA6 Hall input. */
GPIOA->CRL = 0x44422200u;
TIM2->PSC = 11999u;
TIM2->ARR = 99u;
TIM2->CCR1 = 70u;
TIM2->CCER = TIM2_CCER_CC1E;
TIM2->CR1 = TIM2_CR1_CEN;
GPIOA->BSRR = GPIOA_DRV_EN_BIT;
EXTI->IMR = EXTI_IMR_MR6;
EXTI->RTSR = EXTI_RTSR_TR6;
EXTI->FTSR = 0u;
EXTI->PR = EXTI_PR_PR6;
}
void EXTI6_IRQHandler(void)
{
if ((EXTI->PR & EXTI_PR_PR6) != 0u)
{
exti_pr_before_clear = EXTI->PR;
hall_irq_count++;
EXTI->PR = EXTI_PR_PR6;
}
}
void user_loop(void)
{
watch_u32("HALL_COUNT", HALL->COUNT);
watch_u32("hall_irq_count", hall_irq_count);
watch_u32("exti_pr_before_clear", exti_pr_before_clear);
}
5. 사이트에서 확인
- Registers: Clock의 AFIOEN·IOPAEN, GPIOA_CRL, EXTI_IMR, EXTI_RTSR, EXTI_FTSR, EXTI_PR, HALL_COUNT와 HALL_STATUS를 확인합니다.
- Board · Lab pin routes: PA6 / HALL_IN을 선택하면 Official device functions와 Current fixed route를 구분할 수 있고 Graph trace 목록에 자동으로 추가됩니다.
- Graph: 자동으로 추가된 PA6/HALL_IN trace의 rising edge와 HALL_COUNT 증가 시점을 비교합니다.
- Code Watch: HALL_COUNT와 hall_irq_count가 같은 Hall event를 따라 증가하는지, exti_pr_before_clear에 PR6가 clear 전 보존되는지 확인합니다.
- Docs / Log: EXTI register update, Hall rising-edge, handler 실행과 pending clear 메시지 계열을 확인합니다.
6. 현재 구현 범위
| 항목 | 공식 STM32 의미 | 현재 구현 범위 | 지원 여부 |
|---|---|---|---|
| AFIO_EXTICR2[11:8] (EXTI6[3:0]) | EXTI6 source port를 PA6, PB6, PC6 등에서 선택 | header/MMIO에 없고 PA6 / HALL_IN route가 고정입니다. | 미지원 |
| EXTI_FTSR.TR6[6] | falling edge trigger 선택 | 값은 저장·표시되지만 Hall pending/count effect는 rising edge만 실행합니다. | 미지원 |
| EXTI_EMR / EXTI_SWIER | event pulse gate와 software trigger command | 공식 offset 자리는 C pointer struct에서 reserved로 유지되지만 실행 register로 노출하지 않습니다. | 미지원 |
| EXTI6_IRQHandler | 현재 구현 전용 compatibility handler name | active MR6/TR6 route에서 PR6가 pending이면 직접 dispatch합니다. | 지원됨 |
| GPIOA_CRL / GPIOA_IDR / RCC_APB2ENR | PA6 input mode, live IDR6와 AFIOEN·IOPAEN clock prerequisites | AFIOEN·IOPAEN은 실제 route gate입니다. GPIO는 정확한 0x4뿐 아니라 output이 아닌 mode를 input으로 인정하고, IDR6 level은 virtual Hall source가 board-driven으로 갱신합니다. | 지원됨 |
| HALL_COUNT / HALL_STATUS | STM32F103 EXTI register map 밖의 구현 전용 telemetry | COUNT는 active route에서 본 rising edge 수입니다. STATUS bit 0은 level, bit 1은 pending 또는 같은 tick의 rising edge, bit 2는 EXTI6 route active를 뜻하며 STATUS는 read-only입니다. | 지원됨 |
| PA2 / TIM2_CCR1 / PA3 | Hall edge source를 만드는 구현 전용 motor prerequisite | PA2/CCR1 fixed PWM alias와 PA3 driver enable로 virtual motor를 움직입니다. EXTI 공식 설정 순서가 아니며 TIM2/PWM companion의 구현 경계입니다. | 지원됨 |
| PA6 input voltage | DS5319의 PA6는 FT pin으로 표시되지 않으며 non-FT input의 허용 전압을 따라야 함 | Board와 Graph의 0/5 V는 virtual proof입니다. 실제 STM32F103C8 PA6에 5 V를 직접 연결하지 말고 level conditioning을 적용합니다. | 미지원 |