โ† Back

[์š”์•ฝ] ๐Ÿ–ฅ๏ธ์ž„๋ฒ ๋””๋“œ OS ํ”„๋กœ์ ํŠธ Ch.4

๋ถ€ํŒ…ํ•˜๊ธฐ
์ธ๋„ค์ผ

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๊ฐ€ ๋‚˜์˜จ๋‹ค.

โ†

[์š”์•ฝ] ๐Ÿ–ฅ๏ธ์ž„๋ฒ ๋””๋“œ OS ํ”„๋กœ์ ํŠธ

[์šฉ์–ด ์ •๋ฆฌ]

โ†’

[์š”์•ฝ] ๐Ÿ–ฅ๏ธ์ž„๋ฒ ๋””๋“œ OS ํ”„๋กœ์ ํŠธ Ch.5

UART