MCU Memory Map 이해: Flash·SRAM·주변장치 주소와 포인터

카드뉴스

CPU는 이름 대신 주소로 자원을 구분한다

CPU는 `GPIOA`, `UART1`, `ADC1` 같은 이름을 직접 이해하지 않는다. 명령어에 들어 있는 주소로 데이터를 읽고 쓰고, 주소를 받은 하드웨어가 그 접근을 Flash나 SRAM, 주변장치 레지스터로 연결한다. Memory Map은 MCU의 전체 주소 공간을 용도별로 나눈 지도다.

자료에서 보이는 Flash, SRAM, Peripheral, System 영역의 주소는 대표 예시다. 실제 시작 주소와 크기는 MCU 제품군에 따라 달라질 수 있다. 다른 칩의 GPIO 주소를 그대로 사용하면 문법은 맞아도 엉뚱한 영역에 접근할 수 있으므로 대상 장치의 문서에서 확인해야 한다.

Flash와 SRAM은 저장하는 대상이 다르다

Flash에는 프로그램 코드와 상수가 저장된다. 전원을 꺼도 내용이 남는 비휘발성 메모리이므로 펌웨어 이미지를 보관하는 데 쓰인다. SRAM은 실행 중 바뀌는 변수와 함수 호출에 필요한 stack 같은 데이터를 담는다. 속도는 빠르지만 전원이 끊기면 내용이 사라진다.

두 메모리는 같은 CPU 주소 공간에 있어도 주소 범위와 역할이 다르다. 디버거의 Memory 창에서 주소를 열었을 때 코드가 보이는지, 실행 중 변하는 데이터가 보이는지는 이 배치에 따라 결정된다.

주변장치 레지스터도 주소가 있는 저장 공간이다

GPIO, UART, ADC 안의 제어·상태 레지스터는 Peripheral 영역에 배치된다. 각 주변장치는 베이스 주소를 가지며, 개별 레지스터는 여기에 오프셋을 더한 위치에 놓인다. `GPIOA->ODR`에 값을 쓴다는 표현도 실제로는 ODR 주소에 데이터를 쓰는 동작이다.

C 포인터가 중요해지는 이유도 여기에 있다. 특정 주소를 `volatile` 포인터로 가리키면 그 위치의 레지스터를 읽고 쓸 수 있다. CMSIS의 레지스터 정의와 HAL은 이 주소 접근을 이름과 함수로 감싸 사용하기 쉽게 만든 계층이다.

디버깅 화면을 주소 흐름으로 읽는다

Memory Map을 알고 나면 장치 문서의 주소, 코드의 포인터, HAL 함수, 디버거의 Register·Memory 창이 따로 보이지 않는다. 신호가 나오지 않을 때 장치 헤더의 베이스 주소와 레지스터 오프셋을 문서와 맞춰 보고, 디버거에서 해당 값이 실제로 바뀌는지 확인할 수 있다.

먼저 대상 MCU의 Memory Map에서 영역을 찾고, 주변장치 베이스 주소와 레지스터 오프셋을 대조해 보자. 그다음 같은 주소를 디버거에서 열어 코드가 쓴 값과 하드웨어 상태가 이어지는지 보면 주소 기반 제어가 한 흐름으로 정리된다.

댓글 남기기