
include ํด๋ ์์ฑ
mkdir include
cd include
vi MemoryMap.h
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 GLOBAL_ADDR_SIZE (DALLOC_ADDR_START-GLOBAL_ADDR_START)
#define DALLOC_ADDR_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 UND_STACK_TOP (UND_STACK_START+UND_STACK_SIZE-4)
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
MemoryMap.h์ ARMv7AR.h๋ C์ธ์ด ํค๋ ํ์ผ์ด๋ค. GCC๋ก ์ปดํ์ผ ํ ๊ฒฝ์ฐ asm ํ์ผ์์๋ ์ฌ์ฉํ ์ ์๋ค. Entry.S์์ ์ฌ์ฉํ๊ธฐ ์ํด ํค๋๋ฅผ ์ถ๊ฐํด ์ค๋ค.
#include "ARMv7AR.h"
#include "MemoryMap.h"
.text
.code 32
.global vector_start
.global vector_end
vector_start:
LDR PC, reset_handler_addr
LDR PC, undef_handler_addr
LDR PC, svc_handler_addr
LDR PC, pftch_abt_handler_addr
LDR PC, data_abt_handler_addr
B .
LDR PC, irq_handler_addr
LDR PC, fiq_handler_addr
reset_handler_addr: .word reset_handler
undef_handler_addr: .word dummy_handler
svc_handler_addr: .word dummy_handler
pftch_abt_handler_addr: .word dummy_handler
data_abt_handler_addr: .word dummy_handler
irq_handler_addr: .word dummy_handler
fiq_handler_addr: .word dummy_handler
vector_end:
reset_handler:
MRS R0, CPSR
BIC R1, R0, #0x1F
ORR R1, R1, #ARM_MODE_BIT_SVC
MSR CPSR, R1
LDR SP, =SVC_STACK_TOP
MRS R0, CPSR
BIC R1, R0, #0x1F
ORR R1, R1, #ARM_MODE_BIT_IRQ
MSR CPSR, R1
LDR SP, =IRQ_STACK_TOP
MRS R0, CPSR
BIC R1, R0, #0x1F
ORR R1, R1, #ARM_MODE_BIT_FIQ
MSR CPSR, R1
LDR SP, =FIQ_STACK_TOP
MRS R0, CPSR
BIC R1, R0, #0x1F
ORR R1, R1, #ARM_MODE_BIT_ABT
MSR CPSR, R1
LDR SP, =ABT_STACK_TOP
MRS R0, CPSR
BIC R1, R0, #0x1F
ORR R1, R1, #ARM_MODE_BIT_UND
MSR CPSR, R1
LDR SP, =UND_STACK_TOP
MRS R0, CPSR
BIC R1, R0, #0x1F
ORR R1, R1, #ARM_MODE_BIT_SYS
MSR CPSR, R1
LDR SP, =USRSYS_STACK_TOP
dummy_handler:
B .
.end
์์ ์ฝ๋๋ .h ํ์ผ ๋๊ฐ๋ฅผ ์ถ๊ฐ ํ SP ์ค์ ๋ฐ ์ด๊ธฐํ๋ฅผ ์ํด reset_handler ๋ถ๋ถ์ ์์ ํ ๊ฒ์ด๋ค. ๋ชจ๋ ๋์ ๋ชจ๋๋ฅผ ํ ๋ฒ์ฉ ์ํํ๋ฉด์ ์คํ ๊ผญ๋๊ธฐ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ SP์ ์ค์ ํ๋ ์ฝ๋์ด๋ค.
SP์ ํด๋น๋ชจ๋์ ์์ ์ฃผ์๋ฅผ ๋ฃ๋ ๊ฒ์ด ์๋ TOP์ ์ฃผ์๋ฅผ ๋ฃ๋ ๊ฒ์ ์คํ์ด ๋์ ์ฃผ์์์ ๋ฎ์ ์ฃผ์๋ก ์๋ผ๋ ํน์ง์ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ด๋ค.( ํ์ง๋ง ์ด๊ฒ์ ์ค๊ณ์ ๋ง์์ด๋ค. ๊ผญ Stack์ด ์์์ ์๋๋ก heap์ ๋ฐ์์ ์๋ก ์๋ผ๋ ๋ฐฉํฅ์ ์๋๋ค.)
Makefile
ARCH = armv7-a
MCPU = cortex-a8
CC = arm-none-eabi-gcc
AS = arm-none-eabi-as
LD = arm-none-eabi-ld
OC = arm-none-eabi-objcopy
LINK_SCRIPT = ./navilos.ld
ASM_SRCS = $(wildcard boot/*.S)
ASM_OBJS = $(patsubst boot/%.S, build/%.o, $(ASM_SRCS))
INC_DIRS = include
navilos = build/navilos.axf
navilos_bin = build/navilos.bin
.PHONY: all clean run debug gdb
all: $(navilos)
clean:
@rm -fr build
run: $(nvailos)
@qemu-system-arm -M realview-pb-a8 -kernel $(navilos)
debug: $(nvailos)
@qemu-system-arm -M realview-pb-a8 -kernel $(navilos) -S -gdb tcp::1234,ipv4
gdb:
arm-none-eabi-gdb
$(navilos): $(ASM_OBJS) $(LINK_SCRIPT)
$(LD) -n -T $(LINK_SCRIPT) -o $(navilos) $(ASM_OBJS)
$(OC) -O binary $(navilos) $(navilos_bin)
build/%.o: boot/%.S
mkdir -p $(shell dirname $@)
$(CC) -march=$(ARCH) -mcpu=$(MCPU) -I $(INC_DIRS) -c -g -o $@ $<
ASM ์ปดํ์ผ๋ฌ๋ฅผ ์ฐ์ฉํด์ ์ปดํ์ผ ํ ๊ฒฝ์ฐ ์ ์ฒ๋ฆฌ๊ธฐ๊ฐ ์๊ธฐ ๋๋ฌธ์ .hํ์ผ์ ์ฝ์ด์ฌ ์ ์๋ค. ๋ฐ๋ผ์, ์ปดํ์ผ๋ฌ๋ฅผ gcc๋ก ๋ณ๊ฒฝํ๋ค. ์ถ๊ฐ์ ์ผ๋ก .h ํ์ผ๋ค์ด ์กด์ฌํ๋ include ๋๋ ํ ๋ฆฌ๋ ์ถ๊ฐํ๋ค. ์์ makefile ๋ด์ฉ์ผ๋ก ์์ ํ๋ค.

make all์ ์ํํ ๊ฒฐ๊ณผ์ด๋ค. ์ดํ QEMU <-> gdb๋ฅผ ์ด์ฉํด sp์ ๋ฉ๋ชจ๋ฆฌ ์์น๋ฅผ ํ์ธํด ๋ณด์.

34๋ฒ์งธ ๋ผ์ธ๊น์ง ์คํ๋๊ณ ์ฒซ๋ฒ์งธ SVC ๋์ ๋ชจ๋ ์คํ์ด ์ค์ ๋๋ค. SVC ๋ชจ๋ ์คํ์ 0x00300000 ~ 0x003FFFFF๊น์ง ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ ์์ญ์ด๋ค. ์คํ๊ณผ ์คํ ๊ฒฝ๊ณ์ 4B๋ฅผ ๋น์๋๋๋ก ํฌ๊ธฐ๋ฅผ ์ค์ ํ์ผ๋ฏ๋ก 0x003FFFFC์ฌ์ผ ํ๋ค. ์ ๊ทธ๋ฆผ์ info register ๊ฒฐ๊ณผ์์ ๋ณผ์ ์๋ฏ์ด sp์ ๊ฐ์ด ํด๋น ๊ฐ์ ๊ฐ๋ฆฌํค๊ณ ์์์ ์์ ์๋ค.
CPSR์ ๋ณด๋ฉด ๋ง์ง๋ง ๋ฐ์ดํธ๊ฐ 0xd3์ด๋ค. ์ด๊ฒ์ 11010011(2)์ด๋ฉฐ, ๋ง์ง๋ง ํ์ 5๋นํธ๋ง ๋ณด๋ฉด 10011์ด๋ค. ์ด๊ฒ์ 16์ง์๋ก 0x13์ ๋ํ๋ธ๋ค. SVC ๋์ ๋ชจ๋๋ฅผ ์ค์ ํ๋ ๊ฐ์ด๋ค.

ARM์ CPSR ๋ ์ง์คํฐ์ bit ํ๋๋ฅผ ๋ํ๋ธ๋ค. ํ์ 5bit๋ ํด๋น ๋ชจ๋์ ๋์ ์ํ๋ฅผ ๋ํ๋ด๋ฉฐ 0b10011์ SVC๋ฅผ ๋ํ๋ธ๋ค. ์ด๋ ๊ฒ ๋ชจ๋ ๋ชจ๋๋ค์ ๋ํด์ sp๋ฅผ ์ ํด ์ค๋ค. ์ค์ ๋ณด๋์์๋ sp๋ฟ๋ง์ด ์๋ ํ๋์จ์ด ์์คํ ํด๋ญ ์ค์ , ๋ฉ๋ชจ๋ฆฌ ์ปจํธ๋กค๋ฌ ์ด๊ธฐํ ๊ฐ์ ์ผ๋ค๋ ํ์ํ๋ค. ์ด๊ฒ์ ์ถํ์ Cortex-M3๋ฅผ ๊ณต๋ถํ๋ฉฐ ์งํํ๋๋ก ํ๊ฒ ๋ค.
Entry.S ๋ถ๋ถ
...
MRS R0, CPSR
BIC R1, R0, #0x1F
ORR R1, R1, #ARM_MODE_BIT_SYS
MSR CPSR, R1
LDR SP, =USRSYS_STACK_TOP
BL main
BL main์ ์ถ๊ฐํด์ค๋ค. ์ด๊ฒ์ ํตํด asm์ ๋์์ด ๋๋ํ C์ธ์ด์ main๋ฌธ์ผ๋ก ํจ์๊ฐ ์ ํํ๊ฒ ๋๋ค.
build/Mainc.C๋ฅผ ์์ฑ ํ ์๋ ๋ด์ฉ ์ ๋ ฅ
#include "stdint.h"
void main(void)
{
uint32_t* dummyAddr = (uint32_t*)(1024*1024*100);
*dummyAddr = sizeof(long);
}
BL ๋ธ๋์น ๋ช ๋ น์ผ๋ก ์ ํ ํ๋ ค๋ฉด ์ ํ ๋์ ๋ ์ด๋ธ์ด ๊ฐ์ ํ์ผ ์์ ์์ด์ผ ํ๋ค. ๋ค๋ฅธ ํ์ผ์ ์๋ค๋ฉด ๋ง์ปค๊ฐ ๋งํนํ ์ ์๋๋ก ๋ ์ด๋ธ์ .global๋ก ์ ์ธํด์ผ ํ๋ค. ์ปดํ์ผ๋ฌ๋ C์ธ์ด ํจ์ ์ด๋ฆ์ ๋ง์ปค๊ฐ ์๋์ผ๋ก ์ ๊ทผํ ์ ์๋ ์ ์ญ ์ฌ๋ฒ๋ก ๋ง๋ ๋ค. ์ ์ญ ์ฌ๋ณผ์ ์ด์ ๋ธ๋ฆฌ๋ก ์ฌ์ฉํ ๋ .global ์ง์์ด๋ก ์ ์ธํ๊ณ C์ธ์ด๋ก ํ ๋๋ extern์ผ๋ก ์ฌ์ฉํ๋ค. ๋ฐ๋๋ก ์ด์ ๋ธ๋ฆฌ์์ .global๋ก ์ ์ธํ ์ด๋ฆ์ c์ธ์ด์์ ํจ์ ํธ์ถ๋ก ์ง์ ํ ์ ์๋ค.
์๋กญ๊ฒ Make ํ์ผ์ ์์ ํด ์ค๋ค.
ARCH = armv7-a
MCPU = cortex-a8
CC = arm-none-eabi-gcc
AS = arm-none-eabi-as
LD = arm-none-eabi-ld
OC = arm-none-eabi-objcopy
LINKER_SCRIPT = ./navilos.ld
MAP_FILE = build/navilos.map
ASM_SRCS = $(wildcard boot/*.S)
ASM_OBJS = $(patsubst boot/%.S, build/%.os, $(ASM_SRCS))
C_SRCS = $(wildcard boot/*.c)
C_OBJS = $(patsubst boot/%.c, build/%.o, $(C_SRCS))
INC_DIRS = -I include
navilos = build/navilos.axf
navilos_bin = build/navilos.bin
.PHONY: all clean run debug gdb
all: $(navilos)
clean:
@rm -fr build
run: $(navilos)
qemu-system-arm -M realview-pb-a8 -kernel $(navilos)
debug: $(navilos)
qemu-system-arm -M realview-pb-a8 -kernel $(navilos) -S -gdb tcp::1234,ipv4
gdb:
arm-none-eabi-gdb
$(navilos): $(ASM_OBJS) $(C_OBJS) $(LINKER_SCRIPT)
$(LD) -n -T $(LINKER_SCRIPT) -o $(navilos) $(ASM_OBJS) $(C_OBJS) -Map=$(MAP_FILE)
$(OC) -O binary $(navilos) $(navilos_bin)
build/%.os: $(ASM_SRCS)
mkdir -p $(shell dirname $@)
$(CC) -march=$(ARCH) -mcpu=$(MCPU) $(INC_DIRS) -c -g -o $@ $<
build/%.o: $(C_SRCS)
mkdir -p $(shell dirname $@)
$(CC) -march=$(ARCH) -mcpu=$(MCPU) $(INC_DIRS) -c -g -o $@ $<

make all ์ํํ gdb๋ฅผ ํตํด ์คํํ์ผ์ runํ ํ ์ ์ง ์ํค์. ๊ทธ๋ผ ํ์จ์ด๊ฐ main() ํจ์๋ฅผ ์คํํ๊ณ ๋๋ฉด ๋ค์ reset handler๋ก ๋์๊ฐ์ ๋ฌดํ๋ฃจํ๋ ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ๊ทธ๋์ '์ปจํธ๋กค+c' ๋ช ๋ น์ ์ ๋ ฅํ๊ธฐ ์ ๊น์ง ์ข ๋ฃ๋์ง ์๋๋ค.
์ดํ x/8wx ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ ๋ช ๋ น์ ์ ๋ ฅํ๋ค. ์ด ๋ช ๋ น์ ์ ๋ ฅ๋ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ถํฐ 8๊ฐ๋ฅผ 4๋ฐ์ดํธ์ฉ 16์ง์๋ก ๊ฐ์ ์ถ๋ ฅํ๋ผ๋ ๋ช ๋ น์ด๋ค. ๊ทธ๋์ 0x6400000 ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ๊ฐ์ 4๋ฐ์ดํธ์ฉ 8๊ฐ ์ถ๋ ฅ์ํ๋ค. ์ถ๋ ฅ ๊ฐ์ 4๊ฐ ๋์จ๋ค.