Skip to content

ARM Cortex M Booting Sequence

Seungpyo Hong edited this page Jul 24, 2019 · 3 revisions

ARM Cortex M Booting Sequence

개요

각 프로세서마다 부팅 시퀀스에는 차이가 있다. 하지만, 큰 틀은 아래의 과정에서 크게 달라지지 않는다.

  1. 레지스터 별로 적절한 초기값을 부여한다. (보통 사전에 약속된 상수값)
  2. 사전에 약속된 주소값에서 "실행"을 시작한다. 그렇다면, 지금부터 ARM Cortex-M 시리즈는 위 두 과정을 어떻게 구현하였는지, 전원 공급 시점부터 순서대로 알아보자.

리셋 (전원 공급)

본 프로젝트는 32비트 프로세서를 사용하므로, 1 워드 == 32 비트 == 4바이트이다.

우리가 보드에서 리셋 버튼을 누르거나, 새 프로그램을 구워서 돌리면 ARM 프로세서는 먼저 0x00000000번 주소에서 1 워드를 읽는다. 0x00000000에 들어있는 워드의 값은 MSP (Main Stack Pointer)로 간주한다. 따라서, 이 값은 sp 레지스터에 저장된다. 그 후, 프로세서는 0x00000004에서 reset handler의 주소값을 읽고, 해당 주소를 pc 레지스터에 저장한다. reset handler에 대해서는 다음 문단인 Interrupt vector table에서 자세히 다루겠다.

Interrupt Vector Table

ARM 프로세서는 고정된 메모리 주소에 인터럽트 핸들러 함수들의 주소를 저장해 둔다. 그리고 인터럽트가 발생하면, 인터럽트 벡터 테이블에서 해당 인터럽트의 핸들러가 저장된 주소값을 읽어온다. 그 후, 읽어온 주소값을 pc 레지스터에 넣음으로써 핸들러 함수를 실행 할 수 있는 것이다. ARM 프로세서는 low vector와 high vector라는 옵션을 통해 어디에 인터럽트 테이블을 저장할지 결정한다. low vector의 경우 0x00000000, high vector의 경우 0xffff0000 에서부터 테이블을 저장한다. 본 프로젝트에선 low vector를 쓴다고 전제하고 설명하겠다.

위 문단에서 말했듯, 0x0번지는 MSP 값이 들어가므로, 0x4번지부터 1 워드씩 핸들러 주소들이 저장된다. 인터럽트 벡터 테이블 보기 어떤 핸들러들이 있으며, 각각 어디에 위치해야 하는지는 위의 링크를 참고하도록 한다.

근데 사실 저 핸들러들 다 안 만들어도 된다. 0x4번지의 Reset handler만 만들어도 지금은 충분할 것 같다.

일반적으로 더 중대한 인터럽트일수록 더 낮은 번지수에 위치하므로, 제일 낮은 인터럽트 3개만 알아보자. 먼저, 0x4번지의 reset handler이다. 말 그대로, 프로세서가 리셋되면 해당 핸들러가 호출된다.

0x8번지의 NMI(Non-maskable Interrupt)는 표준 인터럽트 마스킹으로 마스킹 못하는 것이다. 쉽게 말해, 말 그대로 "무시 못 할 정도"의 심각한 에러인 것이다. 주로 하드웨어 결함을 나타내며, 칩셋 에러, 패리티 오류, 메모리 오염 등이 해당된다. 프로젝트 하는 동안 볼 일 없었으면 하는 인터럽트이다.

0xc 번지의 hard fault 는 말 그대로 "빡센 오류"다. 원인은 여러가지가 있을 수 있지만, 거의 대부분은 "들어가면 안되는 메모리에 들어가서" 생기는 오류다. 쓰기가 금지된 메모리에 무언가를 썼거나, 실행 할 수 없는 메모리로 pc가 이동한 경우 등이 해당된다.

그 외에도 많은 인터럽트들이 있지만, 그때그때 필요하면 핸들러를 구현하도록 하자. 단, 구현을 안 할 거면, 해당 핸들러를 무한루프 형태로만 구현해 놓자. 그러면 디버거에서 pc 값을 읽음으로서 적어도 어떤 인터럽트가 발생한 건지는 파악할 수 있다. 코드 작성 사례는 본 레포지토리의 boot.S를 참고하자.

참고 자료

[1] 유튜브 링크