[에이콘][요약] 임베디드 시스템 아키텍처 사물인터넷을 위한 임베디드 시스템의 기초 Chapter 4 - Boot-up Process

Embedded June·2021년 8월 8일
0

4.1. IVT (Interrupt Vector Table)

  • IVT는 인터럽트를 처리하기 위한 핸들러 함수인 ISR (Interrupt Service Routain)의 포인터를 모아둔 배열이다.
  • IVT는 보통 바이너리 이미지의 시작 부분에 있고, flash의 가장 낮은 시작 주소에 저장된다.
  • ARM Cortex-M에서 정의한 시스템 인터럽트의 종류는 다음과 같다.
    1. Reset
    2. NMI (non-maskable interrupt)
    3. Hard fault
    4. Memory exception
    5. Bus fault
    6. Usage fault
    7. Supervisor call (Scheduler)
    8. Debug monitor (Breakpoint)
    9. PendSV (Shared resource, Semaphore …)
    10. System tick (Timer)

4.2. 1단계: 메모리 레이아웃

  • 링커 스크립터의 .text에는 가장 먼저 IVT에 대한 부분이 들어가야 한다.

    .text : {
        *(.isr_vector),
        *(.text),
        *(.rodata)
    } > FLASH	// Flash에 할당되는 읽기전용 내용들
  • 시스템이 부트업 하기 위해서는 가장 먼저 IVT가 실행돼 reset handler 함수가 실행돼야 한다. 그래야 .bss, .data section에 정의된 심볼들이 초기화가 되기 때문이다. 따라서 .text의 최상단에는 .isr_vector에 대한 포인터가 들어가야 하고, 이 내용은 flash에 읽기 전용으로 기록된다.

4.3. 2단계: 시작 코드

  • 부트 과정의 첫 단계는 IVT를 정의하고 포인터를 연결하는 것이다.
    GCC의 attribute인 section을 사용해서 IVT를 정의한다.
  __attribute__ ((section(".isr_vector")))
  void (* const IV[])(void) {
      (void (*)(void))(END_STACK),	// Stack pointer 초기값 지정
      isr_reset,
      isr_nmi,
      ...
  }
  // ISR은 parameter도 return도 없다.
  void isr_reset(void) {
      /*...구현...*/
      while(1) {}
  }
  // 사용자 정의 ISR 또는 빈 ISR은 오버라이드 될 수 있도록 __weak 심볼을 사용한다.
  void isr_user(void)__weak {
      /*...구현...*/
      while(1) {}
  }
  • MCU에 전원이 들어오면 IVT의 상단에 정의된 reset handler가 가장 먼저 실행된다.

    • Reset handler는 .data.bss section의 초기화를 수행한다!
    • RAM의 .bss section을 0으로 초기화하고, .data.bss section을 RAM의 실제 section에 복사하는 작업을 수행한다.
    • 초기화 작업 이후 마침내 main()함수를 호출할 수 있다.
  • 링커 스크립터는 VMA (Virtual Memory Address)와 LMA (Load Memory Address) 를 분리하는 메커니즘을 제공한다. 물론 MCU는 MMU가 없어서 모두 physical address로 동작하지만, flash에서 정의된 .data의 주소들이 실제 RAM의 어디로 매핑될지는 컴파일 타임에 결정할 수 없기 때문에 이 메커니즘은 꼭 필요하다. AT 키워드와 _stored_data 라는 링커 스크립터 변수를 이용한다. (내용이 복잡하고 번역이 이해하기 어려워 이정도만 언급하고 넘어간다.)

4.4. 3단계 : 스택(Stack) 할당

  • CPU가 프로그램을 실행하기 위해서는 메모리에 공간을 할당해야 한다.
  • IVT의 최상단에는 END_STACK이라는 미사용 RAM 영역의 끝 주소가 저장돼있다. IVT는 flash에 저장되므로 런타임에 계산될 수 없기 때문에 사전에 정의된 상수값이어야 한다.
  • 프로그램을 가장 효율적으로 실행하기 위한 적절한 stack size 할당을 위한 작업은 매우 민감하고 복잡하다.
image-20210808175709853

(다중 부트와 다중 시스템 디버깅에 대한 내용 그리고 .utils 공유 라이브러리에 대한 내용 생략함.)

profile
임베디드 시스템 공학자를 지망하는 컴퓨터공학+전자공학 복수전공 학부생입니다. 타인의 피드백을 수용하고 숙고하고 대응하며 자극과 반응 사이의 간격을 늘리며 스스로 반응을 컨트롤 할 수 있는 주도적인 사람이 되는 것이 저의 20대의 목표입니다.

0개의 댓글