とりあえず README から確認。
Building
Linux Mint 12 の arm-linux-gnueabihf な gcc compiler chain で構築されることが知られていて (ry
make と type すれば kernel.img が (ry
RASPBERRY PI で build しない場合 rpi-libgcc ディレクトリの中に RasPI な gcc 4.6 由来の libgcc.a のコピィがあります。make はデフォルトでこれを使います。libgcc.a があなたの compiler で使えることが分かっているのであれば LOCALLIBGCC=1 を Makefile でセットするか make LOCALLIBGCC=1 を実行すればよいでしょう。
RasPI 上で build する時には make は gcc 由来の libgcc.a を使うでしょう。
どちらのケイスでも make LIBGCC=[filename] を実行することで libgcc のファイル名を置き換えることができますが、デフォルトで正常に動作するものと思われます。
補足
Makefile の記述は以下のようになっています。
ifdef LOCALLIBGCC
LIBGCC:=$(shell $(CC) -print-libgcc-file-name)
endif
ifneq ($(shell grep BCM2708 /proc/cpuinfo 2>/dev/null),)
LIBGCC ?= $(shell $(CC) -print-libgcc-file-name)
endif
LIBGCC ?= rpi-libgcc/libgcc.a
?= という演算子は知りませんでした。
Installing
kernel.img は SD card にコピィする。いつもの firmware file (start.elf, bootcode.bin, fixup.dat および config.txt) は必要とされる。必要に応じて cmdline.txt を kernel command line を設定するために使うことができます。現時点ではこれは何かのために使われるというよりは画面に表示され (ry
kernel が起動しなかった場合は以下から最新の firmware を試してみること。 https://github.com/raspberrypi/firmware/tree/master/boot
Code overview
kernel はメモリの 0x8000 番地に load され、start.s の _start から
- stack の設定
- アライメントされてないメモリアクセスを有効に
- initsys() 手続きの呼び出し
などの実行を開始します。
initsys() は MMU を設定し
- kernel を 0xf0000000 に
- kernel のデータを 0xc0000000 に
- 物理メモリと peripherals を 0x80000000 に
remap して新たなアドレスとしての main() 手続きに jmp します。
main() 手続きでは led (GPIO16) や framebuffer などをさらに初期化
# framebuffer あたりはとりあえず略
kernel は割り込みベクタを設定して ARM timer 割り込みを有効にします。この割り込みは OK LED を点灯させるために使われます。
kernel は prefetch abort を起こす 0x02100000 番地に jmp を試みる前に自分自身のコード領域に書き込めないことをチェックします。最後に prefetch abort routine の中で kernek は infinite sleep loop に入ります。
とりあえず
framebuffer 云々のソレを確認すべく、久々にモニタを接続して動作確認してみます。
結果
firmware が微妙なのか、HDMI ケーブルの先のモニタはだんまりでした。LED 点滅してたあたり、以下がアレなのかどうか。
static unsigned int led_status = 0;
void led_invert(void)
{
led_status = !led_status;
if(led_status)
*gpioGPCLR0 = 1<<16; /* on */
else
*gpioGPSET0 = 1<<16; /* off */
}
led.c にて定義されてます。呼び出し元は interrupts.c の以下の手続き。
/* IRQs flash the OK LED */
__attribute__ ((interrupt ("IRQ"))) void interrupt_irq(void)
{
*armTimerIRQClear = 0;
led_invert();
}
割り込みベクタテーブルっぽいソレも interrupts.c にて定義されてました。
/* Interrupt vectors called by the CPU. Needs to be aligned to 32 bits as the
* bottom 5 bits of the vector address as set in the control coprocessor must
* be zero
*
* The RESET vector is set to bad_exception. On CPU reset the interrupt vectors
* are set back to 0x00000000, so it won't be used. Any attempt to call this
* vector is clearly an error. Also, resetting the Pi will reset VideoCore,
* and reboot.
*/
__attribute__ ((naked, aligned(32))) static void interrupt_vectors(void)
{
asm volatile("b bad_exception\n" /* RESET */
"b bad_exception\n" /* UNDEF */
"b interrupt_swi\n"
"b interrupt_prefetch_abort \n"
"b interrupt_data_abort \n"
"b bad_exception;\n" /* Unused vector */
"b interrupt_irq \n"
"b bad_exception\n" /* FIQ */
);
}
手続き定義を見るにコンソールへ色々出力してるのですが何も出力されていない。SD card の boot な区画を見るに中身がどうも微妙なので別な SD 使って検証の方向です。
つうか
RasPI な MMU の使い方をどう V6 方式に adjust するか、が微妙な問題だったりしますね。どうしたものか。