Raspberry Pi 3에서 BareMetal 해봤다 ~ 개발 환경 구축과 아무것도하지 않는 무한 루프 프로그램 작성 ~
12838 단어 Raspberrypi3Baremetal
소개
Raspberry Pi 3에서 BareMetal 해 보았으므로 정보를 정리해 둔다.
우선 개발 환경 구축과 최소한의 아무것도 하지 않는 무한 루프 프로그램 작성까지.
자신의 PC 환경은 다음과 같습니다.
준비하는 것
"bootcode.bin"과 "start.elf"는 아래에서 다운로드합니다.
raspberrypi/firmware/boot
다음 두 파일의 페이지로 들어가서
「Download」버튼을 누르면 파일 단독으로 다운로드할 수 있습니다.
이러한 파일을 FAT32 포맷 SD 카드에 넣고 Raspberry Pi 3에 전원을 켜면 프로그램이 실행됩니다.
설정 파일
ARM 코어를 64bit 모드로 기동시키는 설정을 써 둡니다.
config.txt# ARMコアをAArch64で起動させる
arm_control=0x200
프로그램 본체는 디폴트에서는 「kernel8.img」가 실행됩니다만, 이것을 바꾸고 싶은 경우는 이하와 같이 합니다.
config.txt# 動作させたいプログラム本体の名前を指定
kernel=Foo.img
# ARMコアをAArch64で起動させる
arm_control=0x200
컴파일러
다음 명령으로 도구 체인을 설치합니다.
sudo apt install g++-aarch64-linux-gnu
설치되었는지 확인
aarch64-linux-gnu-gcc -v
자신의 환경에서는 다음과 같은 결과가 되었습니다.
gcc version 7.3.0 (Ubuntu/Linaro 7.3.0-27ubuntu1~18.04)
프로그램 작성
다음 파일을 작성합니다.
# ARMコアをAArch64で起動させる
arm_control=0x200
# 動作させたいプログラム本体の名前を指定
kernel=Foo.img
# ARMコアをAArch64で起動させる
arm_control=0x200
다음 명령으로 도구 체인을 설치합니다.
sudo apt install g++-aarch64-linux-gnu
설치되었는지 확인
aarch64-linux-gnu-gcc -v
자신의 환경에서는 다음과 같은 결과가 되었습니다.
gcc version 7.3.0 (Ubuntu/Linaro 7.3.0-27ubuntu1~18.04)
프로그램 작성
다음 파일을 작성합니다.
Makefile
적당히 다음과 같은 느낌으로 Makefile을 작성해 둡니다.
make를 설치하지 않은 경우 다음 명령으로 설치하십시오.
sudo apt install make
Makefile
TARGET = kernel8
TARGET_ELF = kernel8.elf
TARGET_IMG = kernel8.img
PREFIX = aarch64-linux-gnu-
GCC = $(PREFIX)gcc
LD = $(PREFIX)ld
OBJCOPY = $(PREFIX)objcopy
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
CFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles
LDFLAGS = -nostdlib -nostartfiles
%.o: %.S
$(GCC) $(CFLAGS) -c $< -o $@
%.o: %.c
$(GCC) $(CFLAGS) -c $< -o $@
$(TARGET_IMG): boot.o $(OBJS)
$(LD) $(LDFLAGS) boot.o $(OBJS) -T linker.ld -o $(TARGET_ELF)
$(OBJCOPY) -O binary $(TARGET_ELF) $(TARGET_IMG)
clean:
rm $(TARGET_ELF) $(TARGET_IMG) *.o
링커 스크립트
링커 스크립트는 데이터를 실행 파일에 배치하고 생성하는 방법을 정의하는 파일입니다.
자세한 것은 이하등을 참조.
linker.ld
SECTIONS
{
. = 0x80000;
/* .text : プログラムコードが入る領域 */
.text : {
KEEP(*(.text.boot))
*(.text .text.* .gnu.linkonce.t*)
}
/* .rodata : 変更されない文字列とか定数などが入る領域 */
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r*)
}
PROVIDE(_data = .);
/* .data : 初期値を持った変数などを置く領域 */
.data : {
*(.data .data.* .gnu.linkonce.d*)
}
/* .bss : 初期値を持たない変数などを置く領域 */
.bss (NOLOAD) : {
. = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_end = .;
/* 入力セクション破棄 */
/DISCARD/ : {
*(.comment)
*(.gnu*)
*(.note*)
*(.eh_frame*)
}
}
/* .bssのサイズ */
__bss_size = (__bss_end - __bss_start) >> 3;
부팅 처리
C 언어의 메인 함수에 갈 때까지의 처리를 어셈블리 언어로 써 갑니다.
boot.S
.section ".text.boot"
.global _start
_start:
// CPU IDの読み取り、スレーブコアの停止
mrs x1, mpidr_el1
and x1, x1, #3
cbz x1, 2f
1:
// CPU ID > 0, STOP
wfe
b 1b
2:
// CPU ID == 0
// コードの前にスタックを設定する
ldr x1, =_start
mov sp, x1
// Clear bss
ldr x1, =__bss_start
ldr w2, =__bss_size
3:
cbz w2, 4f
str xzr, [x1], #8
sub w2, w2, #1
cbnz w2, 3b
4:
// C言語プログラムのメイン関数にジャンプ
bl main
// フェイルセーフの場合は、このコアも停止
b 1b
프로그램 본체
여기까지 오면 후에는 C언어로 짹짹 쓰는 것뿐입니다.
우선, 아무것도 하지 않는 무한 루프 프로그램을 써 둔다.
main.c
void main(){
while(1){
}
}
마지막으로
어렵지만 매우 재미 있습니다.
Raspberry Pi 3의 BareMetal은 VideoCore와 CPU 간의 통신을 실시하는 「Mailbox」라고 하는 구조를 사용할 수 있게 되고 나서가 프로덕션이므로 현재는 이것을 잘 다룰 수 있도록 공부중입니다.
어느 정도 이해할 수 있으면 기사로 정리하고 싶습니다 ...
이 기사의 소스 코드는 Github에 넣어 있기 때문에, 좋으면 부디 ~
RaspberryPiBareMetal
Reference
이 문제에 관하여(Raspberry Pi 3에서 BareMetal 해봤다 ~ 개발 환경 구축과 아무것도하지 않는 무한 루프 프로그램 작성 ~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/fireflower0/items/47ed5bf9af5bf156a649
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(Raspberry Pi 3에서 BareMetal 해봤다 ~ 개발 환경 구축과 아무것도하지 않는 무한 루프 프로그램 작성 ~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/fireflower0/items/47ed5bf9af5bf156a649텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)