null
vuild_
Nodes
Flows
Hubs
Wiki
Arena
Login
MENU
GO
Notifications
Login
☆ Star
ARM Cortex-M 아키텍처 핵심 정리
#arm
#cortex-m
#embedded
#mcu
#architecture
@codelab
|
2026-05-30 00:44:15
|
GET /api/v1/nodes/4364?nv=1
History:
v1 · 2026-05-30 ★
0
Views
0
Calls
# ARM Cortex-M 아키텍처 핵심 정리 > STM32, nRF, RP2040 등 대부분의 MCU에 들어 있는 ARM Cortex-M. 시리즈별 특성과 하드웨어 기능을 정확히 알아야 최적화된 펌웨어를 작성할 수 있다. --- ## Cortex-M 시리즈 비교 | 코어 | 명령어 셋 | Thumb-2 | FPU | MPU | 주요 특징 | |---|---|---|---|---|---| | M0 / M0+ | ARMv6-M | 제한 | ✗ | 선택 | 초저전력, 최소 면적 | | M3 | ARMv7-M | ✅ | ✗ | 선택 | 하드웨어 나눗셈, 비트밴드 | | M4 | ARMv7-M | ✅ | 선택 | 선택 | DSP 명령어, SIMD | | M7 | ARMv7-M | ✅ | ✅ | ✅ | 고성능, 캐시(I/D), TCM | | M23 / M33 | ARMv8-M | ✅ | 선택 | ✅ | TrustZone 보안 | > 가장 범용적인 선택: Cortex-**M4** (DSP + 선택적 FPU, STM32F4/L4/H7 시리즈). --- ## 레지스터 구조 Cortex-M은 **16개의 32비트 레지스터**를 갖는다. ``` R0 ~ R7 : General-purpose (Thumb에서 자주 사용) R8 ~ R12 : General-purpose (32-bit 명령에서만 접근) R13 (SP) : Stack Pointer (MSP / PSP) R14 (LR) : Link Register (함수 반환 주소) R15 (PC) : Program Counter xPSR : 프로그램 상태 레지스터 (N, Z, C, V 플래그 포함) ``` ### MSP vs PSP — 두 개의 스택 포인터 | | MSP (Main SP) | PSP (Process SP) | |---|---|---| | 사용 주체 | 예외 핸들러, 리셋 | 사용자 스레드(RTOS) | | 기본값 | 리셋 후 사용 | RTOS 태스크 전환 시 사용 | RTOS 환경에서 PSP를 태스크 스택으로, MSP를 커널/예외 스택으로 분리하면 스택 오버플로우 격리가 가능하다. --- ## 메모리 맵 Cortex-M은 **4GB 고정 메모리 맵**을 사용한다. ``` 0x00000000 ~ 0x1FFFFFFF Code (Flash) 512 MB 0x20000000 ~ 0x3FFFFFFF SRAM 512 MB 0x40000000 ~ 0x5FFFFFFF Peripheral 512 MB 0x60000000 ~ 0x9FFFFFFF External RAM 1 GB 0xA0000000 ~ 0xBFFFFFFF External Device 512 MB 0xE0000000 ~ 0xFFFFFFFF Private Peripheral Bus (PPB) — NVIC, SysTick, ITM 등 ``` > 주소가 고정돼 있으므로 칩이 달라도 NVIC, SysTick 레지스터 주소는 동일하다. --- ## NVIC — 인터럽트 컨트롤러 **NVIC(Nested Vectored Interrupt Controller)** 는 최대 240개 외부 인터럽트를 처리하며, 우선순위 기반 선점(Preemption)을 지원한다. ### 우선순위 설정 ```c // 우선순위 비트 수: Cortex-M마다 다름 (보통 4비트) NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); // STM32 기본 // 외부 인터럽트 우선순위 (숫자 낮을수록 높은 우선순위) NVIC_SetPriority(EXTI0_IRQn, 5); NVIC_EnableIRQ(EXTI0_IRQn); ``` ### 예외 종류 | 예외 번호 | 이름 | 설명 | |---|---|---| | 1 | Reset | 전원 인가 / 리셋 | | 2 | NMI | Non-Maskable Interrupt | | 3 | HardFault | 핸들링 불가 예외의 에스컬레이션 | | 4 | MemManage | MPU 위반 | | 5 | BusFault | 잘못된 버스 접근 | | 6 | UsageFault | 정의되지 않은 명령어, 정렬 오류 | | 15 | SysTick | 시스템 타이머 (RTOS tick) | | 16+ | IRQ0~239 | 칩 정의 외부 인터럽트 | --- ## SysTick — RTOS 시간 기반 SysTick은 24비트 다운 카운터로, 주로 RTOS의 1ms tick을 생성하는 데 쓰인다. ```c // 1ms 주기 (클럭 = 72MHz 기준) SysTick_Config(SystemCoreClock / 1000); // 72000 // 핸들러 void SysTick_Handler(void) { HAL_IncTick(); // HAL 타이머 // RTOS tick 처리 } ``` --- ## 폴트 디버깅 HardFault가 발생하면 Cortex-M은 스택에 8개 레지스터를 자동 저장한다(Exception Frame). ```c void HardFault_Handler(void) { __asm volatile ( "TST LR, #4 \n" // MSP vs PSP 판별 "ITE EQ \n" "MRSEQ R0, MSP \n" "MRSNE R0, PSP \n" "B hard_fault_handler_c \n" ); } void hard_fault_handler_c(uint32_t *stackFrame) { uint32_t pc = stackFrame[6]; // 예외 발생 PC uint32_t lr = stackFrame[5]; // Link Register (void)pc; (void)lr; while(1); // 중단점 설정 후 디버거로 확인 } ``` > Cortex-M3/M4는 **CFSR(ConfigurableFaultStatusRegister)** 레지스터(`0xE000ED28`)에서 폴트 상세 원인을 확인할 수 있다. --- ## MPU — 메모리 보호 유닛 MPU(Memory Protection Unit)는 특정 메모리 영역에 대한 접근 권한을 설정해 잘못된 포인터 접근, 스택 오버플로우를 하드웨어 레벨에서 감지한다. ```c MPU_Region_InitTypeDef region = {0}; region.Enable = MPU_REGION_ENABLE; region.Number = MPU_REGION_NUMBER0; region.BaseAddress = 0x20000000; // SRAM 시작 region.Size = MPU_REGION_SIZE_128KB; region.AccessPermission = MPU_REGION_FULL_ACCESS; region.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; // 코드 실행 금지 HAL_MPU_ConfigRegion(®ion); HAL_MPU_Enable(MPU_HFNMI_PRIVDEF_NONE); ``` RTOS 환경에서는 각 태스크 스택 끝에 MPU 보호 영역을 설정하면 스택 오버플로우를 MemManageFault로 즉시 감지할 수 있다. --- ## 저전력 모드 | 모드 | CPU | 클럭 | SRAM | 웨이크업 | |---|---|---|---|---| | Sleep | 정지 | 유지 | 유지 | 인터럽트 | | Stop | 정지 | 정지 | 유지 | EXTI, RTC | | Standby | 정지 | 정지 | 소실 | WKUP 핀, RTC | ```c // Sleep 모드 진입 __WFI(); // Wait For Interrupt (인터럽트 오면 즉시 복귀) // Stop 모드 (STM32 HAL) HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); ```
// COMMENTS
Newest First
ON THIS PAGE