
3.1 리셋 벡터
- ARM 코어에 전원이 들어가면 → 리셋 벡터(0x00000000) 32비트를 read
- 메모리 주소 0x00000000에 명령어 넣어주기
- Entry.S
.text /*.end가 나올 때까지 모든 코드가 text 섹션 */
.code 32 /* 명령어 크기 32비트 */
.global vector_start /* .global == extern "vector_start" 레이블 선언 */
.global vector_end /* "vector_end" 레이블 선언 */
vector_start:
mov r0,r1 /* R1 register copy to R0 register */
vector_end:
.space 1024,0 /* 해당 위치부터 1024바이트를 0으로 채우기 */
.end /* text 섹션 끝 */
- 어셈블러로 컴파일한 후 바이너리 덤프

arm-none-eabi-as -march=armv7-a -mcpu=cortex-a8 -o Entry.o ./Entry.S // 어셈블리어 컴파일 arm-none-eabi-objcopy -O binary Entry.o Entry.bin // 바이너리 추출 hexdump Entry.bin // 바이너리 출력

3.2 실행 파일 만들기
- QEMU가 펌웨어 파일을 읽고 부팅 하려면 입력으로 지정한 펌웨어 바이너리 파일이 ELF 파일 형식이어야 한다. (Entry.o 파일도 ELF 파일)
- ELF 파일을 만들려면 링커(Linker)의 도움이 필요하다.
- 링커가 동작하려면 링커에 정보를 던져주는 링커 스크립트가 필요하다.
- 링커 스크립트 navilos.ld
ENTRY(vector_start) SECTIONS { . = 0x0; .text : { *(vector_start) *(.text .rodata) } .data : { *(.data) } .bss : { *(.bss) } }
- 링커로 실행 파일 만들기
ubuntu@ubuntu:~/navilos$ arm-none-eabi-ld -n -T ./navilos.ld -nostdlib -o navilos.axf boot/Entry.o /* -n 링커에 섹션 자동 정렬 금지 지시 -nostdlib 링커가 자동으로 표준 라이브러리 링킹 금지 지시 링커 동작 완료하면 navilos.axf 생성 */ ubuntu@ubuntu:~/navilos$ arm-none-eabi-objdump -D navilos.axf /* 디어셈블 */

3.3 QEMU에서 실행해 보기

- gdb와 QEMU 연결하기
sudo apt install -y gdb-multiarch qemu-system-arm -M realview-pb-a8 -kernel navilos.axf -S -gdb tcp::1234,ipv4 /* 타겟 보드에 실행파일 업로드, 포트 1234 원격 GDB 허용*/ gdb-multiarch navilos.axf // gdb와 QEMU 연결 (gdb) target remote:1234 // 1234번 포트로 원격 디버깅 연결 (gdb) x/4xb 0 . . . 0x0 <vector_start>: 0x01 0x00 0xa0 0xe1

3.4 빌드 자동화 하기
ARCH = armv7-a // RealViewPB의 아키텍쳐
MCPU = cortex-a8 // RealViewPB의 CPU
/* 툴체인 */
CC = arm-none-eabi-gcc
AS = arm-none-eabi-as
LD = arm-none-eabi-ld
OC = arm-none-eabi-objcopy
LINKER_SCRIPT = ./navilos.ld
/* make built-in */
ASM_SRCS = $(wildcard boot/*.S) // boot/Entry.S -> ASM_SRCS
ASM_OBJS = $(patsubst boot/%.S, build/%.o, $(ASM_SRCS)) // build/Entry.o -> ASM_OBJS
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:
gdb-multiarch $(navilos)
$(navilos): $(ASM_OBJS) $(LINKER_SCRIPT)
$(LD) -n -T $(LINKER_SCRIPT) -o $(navilos) $(ASM_OBJS)
$(OC) -O binary $(navilos) $(navilos_bin)
build/%.o: boot/%.S
mkdir -p $(shell dirname $@)
$(AS) -march=$(ARCH) -mcpu=$(MCPU) -g -o $@ $<
// gdb와 QEMU 연결하기 -> 확인
3.5 하드웨어 정보 읽어오기 - 데이터시트를 읽는 방법
- 하드웨어에서 정보를 읽어오고, 쓰는 것은 레지스터를 이용한다.
- 레지스터는 하드웨어가 소프트웨어와 상호작용하는 인터페이스
- 데이터 시트란 해당 하드웨어가 가지고 있는 레지스터 목록과 설명, 레지스터에 어떤 값을 썼을 때 어떻게 동작하는지 기술한 문서 (물론 다른 정보도 많음)
.text .code 32 .global vector_start .global vector_end vector_start: LDR R0, =0x10000000 // R0에 0x10000000 (ID Register) 넣기 LDR R1, [R0] // R0에 저장된 메모리 주소(0x10000000)에서 값을 읽어서 R1에 넣기 vector_end: .space 1024,0 .end
ID Register, SYS_ID

0x10000000
is a read-only register that identifies the board and FPGA.- 하드웨어를 식별할 수 있는 정보를 가진 읽기 전용 레지스터
- 주로 펌웨어가 여러 하드웨어를 대응해야 할 때 사용 (하드웨어 구분)
- 32비트 머신의 모든 레지스터는 32비트를 목적에 맞게 나눠서 사용 (8, 4, 4, 12, 4비트씩 할당)
make make debug gdb-multiarch navilos.axf // gdb와 QEMU 연결 (gdb) target remote:1234 // 1234번 포트로 QEMU 디버깅 소켓 연결 (gdb) file navilos.axf // navilos.axf 읽기 (gdb) list // 디버깅 심벌 확인 (gdb) info register // 레지스터 정보



![s (step) → LDR R1, R[0] 실행결과 → r1에 0x1780500](https://image.inblog.dev?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ffca2d49a-f735-4019-a058-5247e5140890%2Fcc8353ef-0d4d-448b-bfea-548e9eb3e847%2FUntitled.png%3Ftable%3Dblock%26id%3D5b46ad2d-2d11-4dea-abbc-765b3889611d%26cache%3Dv2&w=1920&q=75)
- 0x1780500 → 00000001 01111000 00000101 00000000 (32비트)

Bits | Access | Name | Reset | Description |
[31:28] | Read-only | REV | − | Board revision:
0x0 = Rev A
0x1 = Rev B
0x2 = Rev C |
[27:16] | Read-only | HBI | 0x178 | HBI board number (0178) |
[15:12] | Read-only | BUILD | − | Build variant of board (from BOM) 0xF : all builds |
[11:8] | Read-only | ARCH | 0x5 | Bus architecture
0x4 = AHB
0x5 = AXI |
[7:0] | Read-only | FPGA | − | FPGA build |
- HBI, ARCH 데이터 시트와 일치
- 보드 리비전 Rev A, 버스 아키텍처는 AXI(Advanced eXtensible Inter-face)로 확인
Share article