Cortex-M 은 예외가 나면 8개 워드를 자동으로 스택에 저장한다.
낮은 주소 ┌──────┐
│ R0 │
│ R1 │
│ R2 │
│ R3 │
│ R12 │
│ LR │
│ PC │ ← 폴트가 난 명령의 주소
│ xPSR │
높은 주소 └──────┘
어느 스택인지부터 가른다
void HardFault_Handler(void) {
__asm volatile (
"tst lr, #4
" /* EXC_RETURN 의 비트 2 로 판별 */
"ite eq
"
"mrseq r0, msp
" /* 0이면 메인 스택 */
"mrsne r0, psp
" /* 1이면 프로세스 스택 (RTOS 태스크) */
"b fault_report
");
}
RTOS 를 쓰면 태스크는 PSP 를 쓰므로, MSP 만 보면 엉뚱한 값을 읽는다.
꺼낸 PC 로 무엇을 하나
addr2line -e firmware.elf 0x08001234 소스 파일·줄 번호가 나온다
이 한 줄이 폴트 분석의 결론이다. 그래서 맵 파일과 elf 를 릴리스마다 보관해 두어야 현장에서 올라온 주소를 해석할 수 있다.