본문 바로가기

Firmware/RTOS

임베디드 OS 개발 프로젝트 4

4장 부팅과정 작성.

 

부팅을 하기 위해서는 우선 메모리 설계를 먼저 해야한다.

 

실행 파일은 메모리를 다섯 가지로 나누어 사용한다.

 

text 영역:  코드가 있는 공간.

 

data 영역:  전역변수가 있는 공간.

 

Stack 영역: 지역변수, 함수 복귀 주소가 들어있는 공간.

 

heap 영역: 코드 실행 중 동적으로 할당하여 사용하는 공간.

 

이때 stack 영역은 동작 모드별 스택, 테스크 스택 별로 나누며 그림으로 나타내면 다음과 같다.

 

위 메모리를 실제 정의하는 코드는 다음과 같다.

 

/*
 *  MemoryMap.h
 */
#define INST_ADDR_START    0
#define USRSYS_STACK_START 0x00100000
#define SVC_STACK_START    0x00300000
#define IRQ_STACK_START    0x00400000
#define FIQ_STACK_START    0x00500000
#define ABT_STACK_START    0x00600000
#define UND_STACK_START    0x00700000
#define TASK_STACK_START   0x00800000
#define GLOBAL_ADDR_START  0x04800000
#define DALLOC_ADDR_START  0x04900000

#define INST_MEM_SIZE	   (USRSYS_STACK_START - INST_ADDR_START)
#define USRSYS_STACK_SIZE  (SVC_STACK_START - USRSYS_STACK_START)
#define SVC_STACK_SIZE     (IRQ_STACK_START - SVC_STACK_START)
#define IRQ_STACK_SIZE     (FIQ_STACK_START - IRQ_STACK_START)
#define FIQ_STACK_SIZE     (ABT_STACK_START - FIQ_STACK_START)
#define ABT_STACK_SIZE     (UND_STACK_START - ABT_STACK_START)
#define UND_STACK_SIZE     (TASK_STACK_START - UND_STACK_START)
#define TASK_STACK_SIZE    (GLOBAL_ADDR_START - TASK_STACK_START)
#define DALLOC_MEM_SIZE    (55 * 1024 * 1024)

#define USRSYS_STACK_TOP   (USRSYS_STACK_START + USRSYS_STACK_SIZE - 4)
#define SVC_STACK_TOP      (SVC_STACK_START + SVC_STACK_SIZE - 4)
#define IRQ_STACK_TOP      (IRQ_STACK_START + IRQ_STACK_SIZE - 4)
#define FIQ_STACK_TOP      (FIQ_STACK_START + FIQ_STACK_SIZE - 4)
#define ABT_STACK_TOP      (ABT_STACK_START + ABT_STACK_SIZE - 4)
#define IRQ_STACK_TOP      (IRQ_STACK_START + IRQ_STACK_SIZE - 4)
#define UND_STACK_TOP      (UND_STACK_START + UND_STACK_SIZE - 4)

 

Stack은 Top에서 Bottom으로 자라는 구조이며 마지막 4Byte를 뺀 이유는 저자가 Stack이 다닥다닥(?) 붙어있는 게 싫다고 하여 분리 하였다. (실제 window 메모리 구조 면 각 메모리 경계에 침범 하였을 시 메모리가 깨지는걸 우려해 Guard page가 있었던거 같다.)

 

Stack은 동작모드에 맞게 입력 해줘야 하므로 동작 모드 전환 하는 header file을 작성한다.

 

/*
 * ARMv7AR.h
 */
#define ARM_MODE_BIT_USR 0x10
#define ARM_MODE_BIT_FIQ 0x11
#define ARM_MODE_BIT_IRQ 0x12
#define ARM_MODE_BIT_SVC 0x13
#define ARM_MODE_BIT_ABT 0x17
#define ARM_MODE_BIT_UND 0x1b
#define ARM_MODE_BIT_SYS 0x1f
#define ARM_MODE_BIT_MON 0x16

 

위 모드를 적용하기 위한 코드는 Assembly로 작성되며 다음과 같다.

 

MRS r0, cpsr
BIC r1, r0, #0x1F
ORR r1, r1, #동작 모드
MSR cpsr, r1
LDR sp, =스택 꼭대기 메모리 주소

CPSR 이란 특수 레지스터를 통해 각각 모드로 전환 할 수 있다.

R1레지스터로 동작 모드를 바꾼다음

Stack 메모리 주소(TOP)를 설정한다. STACK은 TOP에서 Bottom으로 자라기 때문에 Top주소를 넣는다.