inblog logo
|
isehyeon258
    RTOS

    3장 일단 시작하기

    이세현's avatar
    이세현
    Aug 21, 2024
    3장 일단 시작하기
    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 섹션 끝 */
    • 어셈블러로 컴파일한 후 바이너리 덤프
      • notion image
        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 // 바이너리 출력
    0001 e1a0 → mov r0, r1 / arm은 4바이트 단위로 메모리 관리
    0001 e1a0 → mov r0, r1 / arm은 4바이트 단위로 메모리 관리
    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
    navilos.axf 파일에 있는 코드 데이터가 QEMU의 메모리로 다운로드
    navilos.axf 파일에 있는 코드 데이터가 QEMU의 메모리로 다운로드
    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

    The SYS_ID register at 0x10000000 is a read-only register that identifies the board and FPGA.
    The SYS_ID register at 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 // 레지스터 정보
    list 명령 → navilos.axf 내용이 그대로 출력된다.
    list 명령 → navilos.axf 내용이 그대로 출력된다.
    레지스터의 값이 모두 0
    레지스터의 값이 모두 0
    s (step) → LDR R1, =0x1000000 실행 결과
    s (step) → LDR R1, =0x1000000 실행 결과
    s (step) → LDR R1, R[0] 실행결과 → r1에 0x1780500
    s (step) → LDR R1, R[0] 실행결과 → r1에 0x1780500
    • 0x1780500 → 00000001 01111000 00000101 00000000 (32비트)
    notion image
     
    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

    isehyeon258

    RSS·Powered by Inblog