10
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ラズパイ2+RustでOSはじめの一歩

Last updated at Posted at 2017-04-25

大仰なタイトルにしてしまいましたが、
http://wiki.osdev.org/Raspberry_Pi_Bare_Bones
ここの内容の一部をRustに置き換えてみようというだけの記事です。
qemuを使うので実機がなくても大丈夫です。

開発環境はDebian testing(stretch)です。

準備

qemuインストール

$ sudo aptitude install qemu-system-arm

ツールチェインインストール

Debianにはgcc-arm-none-eabiパッケージが存在しているのでインストールするだけです。

$ sudo aptitude install build-essential gcc-arm-none-eabi

Rustインストール

rustupを使います。

$ curl https://sh.rustup.rs -sSf | sh
$ source $HOME/.cargo/env

ビルドにはnightlyが必要です。

$ rustup default nightly

ターゲットにarm-none-eabiが無いので、替わりにarm-unknown-linux-gnueabiを使用します

$ rustup target add arm-unknown-linux-gnueabi

似たターゲット名にarm-unknown-linux-gnueabihfがありますが、こちらを使うとビルドエラーが出るので注意です。1

まずはRust抜きで

http://wiki.osdev.org/Raspberry_Pi_Bare_Bones
ここの内容通りに進めていくだけです。
いちいちコマンド打たなくて良いようにMakefileを作りましょう。

Makefile
#!/usr/bin/make

CC = arm-none-eabi-gcc
CFLAGS =  -mcpu=arm1176jzf-s -fpic -ffreestanding -std=gnu99 -O2 -Wall -Wextra
ASM_FLAGS = -mcpu=arm1176jzf-s -fpic -ffreestanding
OBJ = boot.o kernel.o

kernel.elf: ${OBJ}
        ${CC} -T linker.ld -o $@ -ffreestanding -O2 -nostdlib ${OBJ}

boot.o: boot.S
        ${CC} ${ASM_FLAGS} -c $< -o $@

kernel.o: kernel.c
        ${CC} ${CFLAGS} -c $< -o $@

clean:
        rm -f *.o *.elf

.PHONY: clean

ビルドしてqemuで実行してみます。

$ make
$ qemu-system-arm -m 256 -M raspi2 -serial mon:stdio -kernel kernel.elf
Hello, kernel World!

kernel_main()をRustにしてみる

いよいよRustを使ってみます。

main.rs
#![feature(lang_items)]
#![crate_type = "staticlib"]
#![no_std]

extern {
    fn uart_init();
    fn uart_puts(data: &'static str);
}

#[no_mangle]
pub extern fn kernel_main() {
    unsafe {uart_init();}
    unsafe {uart_puts("Hello, kernel World!\r\n");}

    loop{}
}

#[lang = "eh_personality"]
extern fn eh_personality() {}

#[lang = "panic_fmt"]
extern fn panic_fmt() -> ! { loop {} }

#[no_mangle]
pub extern fn __aeabi_unwind_cpp_pr0 () {}

stdlibは使わない(使えない)ため#[no_std]で無効にします
使用するCの関数はexternで宣言します
kernel_main()は外部から呼び出せるようにpub#[no_mangle]を付けます

kernel.cとMakefileを修正します。

kernel.c
@@ -112,19 +112,3 @@ unsigned char uart_getc() {
 void uart_puts(const char* str) {
     for (size_t i = 0; str[i] != '\0'; i++) uart_putc((unsigned char)str[i]);
 }
-
-#if defined(__cplusplus)
-extern "C" /* Use C linkage for kernel_main. */
-#endif
-    void
-    kernel_main(uint32_t r0, uint32_t r1, uint32_t atags) {
-    // Declare as unused
-    (void)r0;
-    (void)r1;
-    (void)atags;
-
-    uart_init();
-    uart_puts("Hello, kernel World!\r\n");
-
-    while (1) uart_putc(uart_getc());
-}
Makefile
@@ -3,7 +3,7 @@
 CC = arm-none-eabi-gcc
 CFLAGS =  -mcpu=arm1176jzf-s -fpic -ffreestanding -std=gnu99 -O2 -Wall -Wextra
 ASM_FLAGS = -mcpu=arm1176jzf-s -fpic -ffreestanding
-OBJ = boot.o kernel.o
+OBJ = boot.o kernel.o main.o

 kernel.elf: ${OBJ}
        ${CC} -T linker.ld -o $@ -ffreestanding -O2 -nostdlib ${OBJ}
@@ -14,6 +14,9 @@ boot.o: boot.S
 kernel.o: kernel.c
        ${CC} ${CFLAGS} -c $< -o $@

+main.o : main.rs
+       rustc --target arm-unknown-linux-gnueabi --emit=obj $<
+
 clean:
        rm -f *.o *.elf

ビルドして実行してみます。

$ make clean
$ make
$ $ qemu-system-arm -m 256 -M raspi2 -serial mon:stdio -kernel kernel.elf
Hello, kernel World!

無事実行できました。

参考

Raspberry Pi Bare Bones
RustでベアメタルRaspberry PiのLチカ

  1. arm-unknown-linux-gnueabihfのhfはhard floatの略で、こちらを使う場合はCコードのコンパイルやリンク時に-mfloat-abi=hard等の指定が必要になってくると思われます

10
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?