스타트업 코드 실행 경로


전원을 인가하면 ARM core는 최초 Reset 신호(PORESETn)가 인가 된다.


참고 링크: http://recipes.egloos.com/5044366
참고 링크: https://developer.arm.com/documentation/ddi0337/e/Clocking-and-Resets/Cortex-M3-reset-modes/Power-on-reset

Reset 신호가 인가 되면 아래와 같은 register가 세팅이 된다.

  • SP (Stack Pointer)는 address 0x00000000 로 부터 MSP(Main Stack Pointer) 값으로 세팅
  • PC(Program Counter)는 address가 0x000000004인 reset vector의 value로 값이 세팅이 된다.

참고 링크: https://developer.arm.com/documentation/dui0552/a/the-cortex-m3-processor/programmers-model/core-registers?lang=en

STM32의 경우 전원을 인가 Boot mode selection pins에 따라서 시 SP, PC 레지스터가 설정이 된다.

boot_configuration

현재 스터디 중인 STM32 Boot mode가 Main Flash Memory로 설정 되어 있어 SP, PC 레지스터는 다음과 같이 설정이 된다.

  1. SP (Stack Pointer)는 address 0x00000000 로 부터 MSP(Main Stack Pointer) 값으로 세팅 STM32의 MSP는 0x020005000
    => DCode bus 를 이용하여 0x00000000로 접근 후 0x00000000 주소에 저장되어 있는 MSP 값인 0x020005000으로 SP를 세팅

  2. PC(Program Counter)는 address가 0x000000004로 부터 reset vector의 value 0x8000384 로 값이 세팅이 된다.
    => ICode bus 를 이용하여 0x00000004로 접근 후 0x00000004 주소에 저장되어 있는 reset vector의 value 값인 0x8000384로 PC를 세팅
    => 0x8000384는 Reset_Handler로 스타트업 코드에 정의 되어 있다.

Dcode-bus 설명 링크: https://developer.arm.com/documentation/ddi0337/e/Bus-Interface/DCode-bus-interface

Icode-bus 설명 링크: https://developer.arm.com/documentation/ddi0337/e/Bus-Interface/ICode-bus-interface

SP와 PC가 세팅되는 참고 영상: https://www.youtube.com/watch?v=3brOzLJmeek


<0x0000000 부터 시작하는 메모리 맵>
memory_address_from_0x0000000
<0x8000000 부터 시작하는 메모리 맵>
memory_address_from_0x8000000

.elf의 파일의 맵은확인시 [0x8000000 ~ 0x800127f]까지 구성이 되어 있고 STM32CubeProgrammer로 보드를 연결하여
메모리 맵을 확인 시 [0x0000000 ~ 0x000127f] 과 [0x8000000 ~ 0x800127f] 의 메모리 맵이 같은 것을 확였다.


<.elf 파일 메모리 맵>
elf_file_map

[0x0000000 ~ 0x000127f] 과 [0x8000000 ~ 0x800127f] 의 메모리 맵이 같은 이유를 찾아보았다.

  1. STM32의 컨셉이 SHADOWING concept이기 때문이다.
    STM32의 SHADOWING concept 설명: https://community.st.com/s/question/0D50X00009XkXNqSAN/how-does-memory-work-in-cortex-m3


2. STM32가 Booting 시 boot configuration을 확인한 후에 flash memory를 remap 하기 때문이다.
STM32의 flash memory remap 설명: https://cwiki.apache.org/confluence/display/NUTTX/STM32+Null+Pointer+Detection


Q1. System memory 사이즈와 Flash memory 사이즈가 다른 이유?
Q2. STM32가 어떻게 메모리를 SHADOWING 또는 remap을 하는가?


디버깅 시 Reset Handler가 호출되는 어드레스 사진

deassembly

STM32 데이터 시트 메뉴얼
4 Memory mapping Figure 11. Memory map 참고
memory_map

데이터 시트 자료 링크 : https://www.st.com/content/ccc/resource/technical/document/datasheet/33/d4/6f/1d/df/0b/4c/6d/CD00161566.pdf/files/CD00161566.pdf/jcr:content/translations/en.CD00161566.pdf

STM32 레퍼런스 메뉴얼
3.1 System architecture 참고
3.4 Boot configuration 참고
system_architechture

레퍼런스 메뉴얼 자료 링크: https://www.st.com/resource/en/reference_manual/rm0008-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

스타트업 코드에서 Reset_Handler가 실행되는 순서는 아래와 같다.

  1. STM32에 전원 연결 시 Reset이 발생
  2. Boot configuration 확인하여 Boot mode 선택
  3. Boot mode가 Main Flash Memory 인 것을 확인
  4. ICode와 DCode Bus를 이용하여 SP: 0x020005000, PC: 0x8000384 를 세팅
  5. 스타트업 코드의 Reset_Handler 실행

STM32CubeIDE는 디버그 모드 시 GDB Server를 이용하며 디버그 모드 실행 시 Reset_Handler가 호출되는 순서는 다음과 같다.

  1. ST-Link 연결 시 Reset 신호 발생 아래와 같이 Connect under reset 옵션으로 ST-Link 연결 시 Reset이 발생
  2. Boot configuration 확인하여 Boot mode 선택
  3. Boot mode가 Main Flash Memory 인 것을 확인
  4. SP: 0x020005000, PC: 0x8000384 를 세팅
    reset_option
  5. 아래와 같이 Download True로 설정 시 Erasing internal memory sectors [0 4] 가 실행 된다.
    Debug Configuration
    download_enable_config
    Debug 실행 후 로그
    debug_mode_download_enable
  6. Download 진행
  7. 디버그 모드 시 GDB는 링커 스크립트에 정의된 ENTRY(Reset_Handler) 주소를 PC 레지스터에 설정한다.
    entry_point_info
  8. 스타트업 코드의 Reset_Handler 실행

** ENTRY 란 프로그램의 시작 지점을 정의한다.

참고 링크: https://www.st.com/resource/en/user_manual/um2609-stm32cubeide-user-guide-stmicroelectronics.pdf

debug_and_run_lunch_flow

링커 스트립터 파일에서 ENTRY(Reset_Handler)를 아래와 같이 주석 처리 후 STM32CubeIDE는 디버그 모드 실행 시 Hard Fault가 발생
entry_point_block

hardfault

STM32CubeIDE Run 동작 시에도 ENTRY(Reset_Handler)를 주석 처리 시 PC register가 설정이 되지 않아 정상 동작을 하지 않았다.

이유는 GDB Server는 Entry Pointer를 찾았는데 이 값을 찾지 못해 PC 값을 0xfffffff로 세팅한 것으로 예상한다.

링커 스트크립터 파일에서 Entry Point를 주석 처리 한 후 아래와 같이 Debug Configuration에서 Download false로 설정하여 디버그/Run 실행 시 정상 동작한다.
Debug Configuration false
download_false_config


GDB monitor reset command 설명
monitor_reset_command

이유는 Download false 시 GBD Server 스크립트에 monitor reset이 포함되어 있어 reset 후 코드가 바로 시작되어 정상 동작을 하는 것으로 예상한다.

STM32CubeProgrammer로 다운로드 후 STM32의 PC register를 설정하지 않아 스타트업 코드의 Reset_Handler가 실행 되지 않는다.

아래와 같은 Case로 테스트를 진행

Case1) 링커 스트립터 파일에서 ENTRY(Reset_Handler)를 주석 처리 후 빌드 한 .elf 파일을 STM32CubeProgrammer로 다운로드 후 STM32를 동작 시
elf_file_download

Reset_Handler가 실행 되지 않는다.

Case2) 링커 스트립터 파일에서 ENTRY(Reset_Handler)를 주석을 해제한 후 빌드 한 .elf 파일을 STM32CubeProgrammer로 다운로드 후 STM32를 동작 시 Reset_Handler가 실행 되지 않는다.

Case3) STM32CubeProgrammer로 다운로드 후 STM32의 Reset 버튼을 누른 후 동작 확인 Reset_Handler가 실행 됨

Case4) STM32CubeProgrammer로 다운로드 후 STM32 Power Cable을 다시 연결 Reset_Handler가 실행 됨

테스트 결과 ENTRY(Reset_Handler)는 디버깅 시 필요한 지시자라고 생각한다.