Vector Table
정의
벡터 테이블은 0x08000000에 위치하는 Flash 영역의 제일 앞부분에 위치하며, Stack Pointer 값을 시작으로 각 exception handler들의 주소값을 포함하고 있다.
MSP의 첫번째 주소값은 RAM의 최상단 주소값이 저장되어있다.
SP의 초기값이 RAM 메모리의 최상단인 이유
- RAM의 최 하단값은 FW의 .data, .bss영역(초기화 된/되지 않은 전역,정적 변수영역)이 저장되어 있기 때문이다
추가로, Heap 영역은 .data,.bss 영역 이후 부터 주소가 증가하며 업데이트된다.
SP는 최상단에서부터 주소가 감소하며 업데이트된다.
SP
정의
Stack Pointer는 프로그램의 실행 마지막 주소를 저장하는 메모리공간이다.
SP값 증감 방식
- 프로그램이 실행되면, SP는 Vector Table첫번째에 저장된 MSP 첫번째 주소에 저장된 값(=Ram의 첫번째 주소)으로 설정된다.
- 프로그램 내에서 메서드가 호출되면 SP는 메서드가 호출된 위치 및 메서드 실행에 필요한 주소들을 Ram에 저장하며 아래로 내려간다.
- 이후 메서드가 모두 완료되었을시, 저장한 호출된 위치(return address)로 jump하여 원래 위치로 되돌아간다.
질문: 메서드가 호출될 때, PC가 가리키는 명령어에 되돌아오는 주소 또한 정의 되어있을텐데 왜 SP가 필요한가?
만약 단일 메서드만 호출&복귀한다면 문제가 발생하지 않으나, 다중호출 및 호출 도중 인터럽트 발생시 되돌아올 주소(LR/Link Register)가 덮혀 쓰여지게 된다.
해당 문제 발생시 정상 복귀가 불가능하기에 SP에 해당 LR 주소를 Push & Pop 하여 정상 복귀 가능하도록 하는 것이다.
PC
정의
Program Counter는 다음에 실행될 명령어의 주소를 저장하는 메모리 공간이다.
PC 값 변경 방식
- 일반적인 동작과정에서, Flash 내부의 .text 영역(프로그램 코드 영역)의 명령어가 순차적으로 실행된다.
- PC는 해당 영역의 주소를 명령어 크기 만큼 증가하게 된다. (STM32의 경우 +4)
- 단, 실행하는 명령어가 특정 주소로 jump 하는 명령일 때, PC 값은 특정 주소로 jump 하게 된다.
질문: 프로그램 실행됨에 따라 PC가 지속적으로 증가한다면 오버플로우가 발생하지 않을까?
PC는 단순히 1씩 증가하는 것이 아니라, 실행되는 명령어에 따라 점프한다. 따라서 while(1)문이 존재할때, PC가 무한루프 안에서 특정 주소로 점프하기 때문에 Overflow 되지 않는다.
프로그램 실행 과정
[명령어 실행 프로세스]
- Flash 에서 PC에 저장된 명령어의 주소로부터 명령어를 불러온다. (Fetch)
- Core 내부의 Decoder로 명령어를 해석한다.
- 해석한 명령어를 ALU & Register에서 실행한다.
- PC에 다음 명령어 주소를 인가한다.
[부팅시 동작 프로세스]
- Vector Table의 첫 주소 값을 SP로 설정한다.
- Vector Table의 두번째 주소값에 저장된 reset hadler를 실행한다.
- reset handler 내부에서 .data, .bss 값을 ram의 가장 하위단에 복사한다.
- PC 값을 코드의 main() 주소로 설정한다.
질문: MCU의 Vector Table의 시작 주소는 0x08000000인데, 어떻게 부팅되자마자 해당 주소부터 시작하는가?
STM32는 부팅시 0x00000000부터 주소를 불러와 명령어를 수행한다. 단, 부팅 과정에서 Flash 메모리 주소인 0x00000000을 0x08000000에 aliased 시키기 때문에 부팅시 바로 0x08000000에 접근하여 실행 할 수 있다.
[STM32 부트 모드 및 설정]
STM32의 레퍼런스 메뉴얼을 확인해보면 각 boot mode 설정 별 aliased 되는 메모리공간이 설명되어있다.
'SW 개발 공부 > STM32' 카테고리의 다른 글
[STM32] UART DMA + Ring Buffer (0) | 2025.03.13 |
---|---|
[Stm32 Project]BootLoader 구현 (3) | 2024.11.13 |
[stm32 chip 메모리구조#2] 메모리 디버깅 방법 (0) | 2024.05.27 |
ISR 내부 루틴의 간소화 필요성 (0) | 2024.02.14 |
stm32에서 printf() 함수 사용하기 (0) | 2024.02.07 |