Raspberry Pi でベアメタルプログラミンしたかったので、 いろいろ調べた作業記録を残す。
参考資料を探す
とりあえず、自分のレベルに合っていて、 かつ、わかりやすそうなサイトを探す。
...で、見つかったのがこのサイト。
基本ここを参考に環境構築とかしていくこととする。
必要なハードウェア類の調達
L チカに必要なものを買い集める。
- Raspberry Pi 3 Model B+
- micro SD カード 32GB(1 GB でも十分)
- ブレッドボード
- ブレッドボード用JPワイヤー 200mm×10本 オス-メス 20PS-MIX Linkman製|マルツオンライン
- 1/4W金属皮膜抵抗 スモールサイズ 330Ω 橙橙黒黒茶 MFS1/4CC3300F KOA製|マルツオンライン
- スモークLED(3mm・白・3.3V・20mA・1000mcd(min)) LSLED-W301 Linkman製|マルツオンライン
必要なソフトウェア類の調達
- Raspberry Pi ファームウェア
- 64-bit boot stub? · Issue #579 · raspberrypi/firmware
https://dl.dropboxusercontent.com/u/3669512/temp/firmware_armstub.zip
をダウンロード
- Linaro toolchain
- Linaro Releases
gcc-linaro-6.2.1-2016.11-i686-mingw32_aarch64-linux-gnu.tar.xz
をダウンロード。
ビルド環境構築
ダウンロードした gcc-linaro-6.2.1-2016.11-i686-mingw32_aarch64-linux-gnu.tar.xz
を適当な場所に展開し、 bin
ディレクトリにパスを通す。
L チカプログラムの作成
プログラムを作ってビルドする。
ファイル作成
こんな配置でファイルを作成する。
led_blink_GPIO16
├── main.c
├── Makefile
└── start.S
start.S
/* 現時点ではおまじないスタート地点を調整しているはず */
mov sp, #0x80000
bl main
main.c
#define GPFSEL1 0x3F200004 /* GPIO のピン設定をするためのレジスタ */
#define GPSET0 0x3F20001C /* GPIO を HIGH にするためのレジスタ */
#define GPCLR0 0x3F200028 /* GPIO を LOW にするためのレジスタ */
typedef unsigned char bool;
#define TRUE 1
#define FALSE 0
#define WAIT_COUNT 3000000
/*
* @fn wait_count だけビジーウェイトする
* @param (wait_count) このカウント数だけビジーウェイトする
*/
void busy_wait(int wait_count);
/*
* @fn L チカする
*/
int main(void) {
// GPIO 出力に設定。
// Peripheral specification の
// 92 ページ、Field Name が FSEL16 の行の
// Bit(s) を見ると、18 から 20 ビット目までに
// 0x001 を設定すればよいことがわかる感じ。
*(volatile unsigned int*)GPFSEL1 = (1 << (18));
// セットして待つ、クリアして待つ、を繰り返す。
while (1) {
*(volatile unsigned int*)GPSET0 = (1 << 16);
busy_wait(WAIT_COUNT);
*(volatile unsigned int*)GPCLR0 = (1 << 16);
busy_wait(WAIT_COUNT);
}
return 0;
}
void busy_wait(int wait_count) {
volatile unsigned int i;
for (i = 0; i < WAIT_COUNT; i++);
}
Makefile
CC=aarch64-linux-gnu-gcc
LD=aarch64-linux-gnu-ld
AS=aarch64-linux-gnu-as
OBJCOPY=aarch64-linux-gnu-objcopy
OBJECTS=start.o main.o
all: build link objcopy
objcopy: kernel8.img
kernel8.img: kernel8.elf
$(OBJCOPY) -O binary kernel8.elf kernel8.img
link: kernel8.elf
kernel8.elf: $(OBJECTS)
$(LD) -Ttext 0x80000 -o kernel8.elf $(OBJECTS)
build: $(OBJECTS)
start.o: start.S
$(AS) -o start.o start.S
main.o: main.c
$(CC) -c -o main.o main.c
clean:
rm *.o *.elf *.img
ビルド
make
して kernel8.img
を作成する。
$ make
aarch64-linux-gnu-as -o start.o start.S
aarch64-linux-gnu-gcc -c -o main.o main.c
aarch64-linux-gnu-ld -Ttext 0x80000 -o kernel8.elf start.o main.o
C:\Users\mikoto\app\gcc-linaro-6.2.1-2016.11-i686-mingw32_aarch64-linux-gnu\bin\aarch64-linux-gnu-ld.exe: warning: cannot find entry symbol _start; defaulting to 0000000000080000
aarch64-linux-gnu-objcopy -O binary kernel8.elf kernel8.img
リンカスクリプトを作っていないため、 警告が出ているけど、今回動かす分には問題ない。
Raspberry Pi の準備
ファイルの配置
- ダウンロードした
firmware_armstub.zip
を展開し、bootcode.bin
,start.elf
を SD カードのルートにコピーする - ビルドした、
kernel8.img
を SD カードのルートにコピーする
最終的に、 SD カードに下記感じでファイルを配置する。
SD カード
├── bootcode.bin
├── start.elf
└── kernel8.img
配線
下記感じで配線する。
PIN 36(GPIO16) ─ 抵抗 ─ LED
PIN 6(GND) ────────┘
実行
- Raspberry Pi に SD カードを入れる
- Raspberry Pi に電源供給
以上。
参考資料
この辺を見て試したはず...。ぬけもれあるかも。
- Raspberry Pi 3で64bitベアメタル(bare metal)プログラミング - へにゃぺんて@日々勉強のまとめ
- ARMのプログラムを作成してデバッグする 第2回
- Raspberry Piのクロスコンパイル環境をWindowsパソコン上のEclipceで構築する Linaro Releases
- 64-bit boot stub? · Issue #579 · raspberrypi/firmware
- Lチカ Raspberry PiでC言語からSoCのレジスタを操作してGPIOを制御する - Qiita
- RPi Low-level peripherals - eLinux.org
- BCM2835 - Raspberry Pi Documentation
0 件のコメント:
コメントを投稿