카드뉴스








STM32 HAL은 편하지만 레지스터 흐름을 알아야 덜 막힙니다
STM32를 처음 시작하면 HAL 예제를 따라 LED를 켜고 UART 로그를 출력하는 단계까지는 비교적 빠르게 갈 수 있습니다. 문제는 코드가 안 될 때입니다. `HAL_GPIO_WritePin()` 한 줄만 보고 있으면 왜 GPIO 클럭을 먼저 켜야 하는지, 핀 모드와 pull-up 설정이 어디에 반영되는지, Alternate Function을 잘못 잡으면 PWM이 왜 안 나오는지 추적하기 어렵습니다. HAL은 개발을 쉽게 해주는 추상화 계층이지만, 실제 하드웨어 동작은 결국 레지스터 설정으로 결정됩니다.
레지스터를 본다는 것은 모든 비트를 외운다는 뜻이 아닙니다. 처음에는 RCC에서 주변장치 클럭을 활성화하고, GPIO MODER로 입력과 출력을 정하고, PUPDR이나 OTYPER로 핀 특성을 맞추고, ODR 또는 BSRR로 출력 상태를 바꾸는 흐름만 잡아도 충분합니다. LED 하나를 켜는 동작 안에도 클럭, 핀 모드, 출력 레지스터가 순서대로 연결되어 있다는 점이 보이면 HAL 코드를 읽는 눈도 달라집니다.
레지스터를 먼저 보면 데이터시트가 읽히기 시작합니다
임베디드 펌웨어에서 데이터시트와 레퍼런스 매뉴얼을 피하기는 어렵습니다. 특정 핀이 어떤 기능을 지원하는지, Timer 채널이 어느 AF 번호와 연결되는지, UART 상태 플래그가 언제 세트되는지 확인해야 할 때가 많습니다. 레지스터 기반으로 한 번이라도 GPIO 입력, 출력, 인터럽트를 구성해보면 문서의 표와 비트 설명이 실제 코드와 연결됩니다.
물론 실무 프로젝트에서 항상 레지스터 직접 접근만 쓰는 것은 아닙니다. HAL, LL, 제조사 SDK, 보드 지원 패키지를 쓰는 경우가 많고, 팀 규칙에 따라 추상화 계층을 유지해야 할 때도 있습니다. 다만 내부 동작을 알고 HAL을 쓰면 디버깅이 쉬워집니다. 함수 호출이 실패했을 때 반환값만 보는 데서 그치지 않고, 클럭 enable, NVIC 설정, DMA 연결, 핀 mux 같은 주변 조건을 함께 확인할 수 있습니다.
공부 순서는 작은 동작에서 시작하는 편이 좋습니다
처음부터 UART, ADC, DMA까지 한 번에 레지스터로 구현하려 하면 부담이 큽니다. GPIO 출력으로 LED를 켜고, 입력으로 버튼을 읽고, pull-up과 pull-down 차이를 확인한 뒤 같은 동작을 HAL로 다시 구현해보면 차이가 잘 보입니다. 이후 Timer로 주기 인터럽트를 만들고 PWM을 출력하면 클럭, prescaler, counter, compare register가 어떻게 이어지는지 자연스럽게 연결됩니다.
STM32 공부에서 목표는 HAL과 레지스터 중 하나만 고르는 것이 아닙니다. 빠른 구현이 필요할 때는 HAL이 도움이 되고, 원인 분석이나 이식성 있는 이해가 필요할 때는 레지스터 흐름이 필요합니다. 초보 단계에서는 “HAL 함수가 어떤 레지스터 흐름을 감싸고 있는가”를 같이 확인하는 방식이 가장 현실적입니다.
HAL 코드도 추적하면 레지스터 공부가 됩니다
HAL을 쓰더라도 함수 내부를 한 번 열어보면 학습 포인트가 많습니다. GPIO 초기화 구조체의 mode, pull, speed 값이 어떤 레지스터 비트로 바뀌는지, UART 초기화에서 baudrate가 어떤 클럭을 기준으로 계산되는지 확인할 수 있습니다. 디버깅 중에는 `HAL_OK`만 믿기보다 초기화 순서, handle 상태, callback 호출 조건을 함께 봐야 합니다. 이렇게 보면 HAL은 원리를 가리는 도구가 아니라 레지스터 접근을 읽기 쉽게 묶어둔 코드로 보입니다.