본문 바로가기

Firmware/RTOS

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

이전까지 각 모드마다 스택 설정, 메모리 배치가 끝났으므로 main으로 진입 해보자.

 

C언어에서 main으로 들어가기 위해선 Entry.S 에서 main으로 점프 해야 한다.

 

	MRS r0, cpsr
	BIC r1, r0, #0x1F
	ORR r1, r1, #ARM_MODE_BIT_SYS
	MSR cpsr, r1
	LDR sp, =USRSYS_STACK_TOP

      BL main

 

이전에 작성했던 Reset Handler 에서 마지막 Branch Main으로 점프 한다.

 

점프를 할려면 점프 대상 레이블이 같은 파일에 있어야한다. 다른 파일에 있다면 링커가 링킹할 수 있도록 자동으로 접근할 수 있는 전역 심벌로 만들어야한다. 전역 심벌은 어셈블리어에서는 .global, C언어에서는 extern으로 선언한다.

 

main.c를 만들면서 다음과 같은 tree 구조를 가진다.

.
├── boot
│   ├── Entry.S
│   └── Main.c
├── include
│   ├── ARMv7AR.h
│   └── MemoryMap.h
├── Makefile
└── navilos.ld

 

main.c는 다음과 같이 만들었다.

 

#include "stdint.h"

void main(void)
{
    uint32_t* dummyAddr = (uint32_t*)(1024*1024*100);
    *dummyAddr = sizeof(long);
}

dummyAddr 이라는 포인터 변수를 선언한다음 이 변수위치를  0x6400000 로 설정한다.

이 변수 주소 값에 long의 크기를 저장하게 되므로 (uint32_t*)0x6400000 = 0x00000004 가 된다.

 

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

 

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 로 되어있는데 오타인거 같아 rm -rf로 수정함 #

@rm -rf 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:

gdb-multiarch

 

$(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 $@) #mkdir -p build 실행 됨 #

$(CC) -march=$(ARCH) -mcpu=$(MCPU) $(INC_DIRS) -c -g -o $@ $<

#$(AS) 에서 $(CC)로 수정 include "~~.h" 는 c언어 문법이므로#

 

build/%.o: $(C_SRCS)

mkdir -p $(shell dirname $@)

$(CC) -march=$(ARCH) -mcpu=$(MCPU) $(INC_DIRS) -c -g -o $@ $<


이 Makefile에서 keypoint는 Linker 구문이다. Linker에 심벌에 할당된 메모리주소를 map 파일에 기록하고

Compile 된 object를 LD에 추가 함으로써 main에 점프 할 수 있게 된다.(주황색 강조)

 

terminal에 make all 을 하게 되면 정상적으로 컴파일을 하게 되고  gdb에서 main 함수에 breakpoint를 걸게 되면 

break가 잡히는 거와 앞서 작성했던 코드가 정상적으로 작동하는 걸 볼 수 있다.

 

(gdb) b main
Breakpoint 1 at 0xe0: file boot/Main.c, line 5.
(gdb) c
Continuing.

Breakpoint 1, main () at boot/Main.c:5
5	    uint32_t* dummyAddr = (uint32_t*)(1024*1024*100);
(gdb) si
0x000000e4	5	    uint32_t* dummyAddr = (uint32_t*)(1024*1024*100);
(gdb) p dummyAddr
$1 = (uint32_t *) 0x0 <vector_start>
(gdb) si
6	    *dummyAddr = sizeof(long);
(gdb) p dummyAddr
$2 = (uint32_t *) 0x6400000
(gdb) n
7     p dummyAddr
$3 = (uint32_t *) 0x6400000
(gdb) p *dummyAddr
$4 = 4
(gdb)