armでもHello world!


KS8695にu-bootが焼けたので、ネットで見つけたコードを使ってHello world!してみた。

startup.s
.global _Reset
_Reset:
 LDR sp, =stack_top
 BL main
 B .
hello.c
#define KS8695_IO_BASE                  0x03FF0000
#define KS8695_UART_LINE_STATUS         0xE014
#define KS8695_UART_TX_HOLDING          0xE004

void pchar(char c)
{
        // Line status register.
        volatile char* lsr = (volatile char*)(KS8695_IO_BASE + KS8695_UART_LINE_STATUS);
        // Transmitter holding register.
        volatile char* thr = (volatile char*)(KS8695_IO_BASE + KS8695_UART_TX_HOLDING);

        while(((*lsr) & 0x20) == 0) ; // Wait until THR is empty.

        *thr = c;
}

void printk(const char* s)
{
        while(*s)
        {
                pchar(*s);
                s++;
        }
}

void main(void)
{
        printk("Hello world!¥n");
}
hello.ld
ENTRY(_Reset)
SECTIONS
{
 . = 0x100000; /*initial address*/
 .startup . : { startup.o(.text) }
 .text : { *(.text) }
 .data : { *(.data) }
 .bss : { *(.bss COMMON) }
 . = ALIGN(8);
 . = . + 0x1000; /* 4kB of stack memory */
 stack_top = .;
}
Makefile
all:
        arm-none-eabi-gcc -c -mcpu=arm922t hello.c -o hello.o
        arm-none-eabi-as startup.s -o startup.o
        arm-none-eabi-ld -T hello.ld -Map=hello.map hello.o startup.o -o hello.elf
        arm-none-eabi-objcopy -O binary hello.elf hello.bin
        mkimage -A arm -C none -O linux -T kernel -d hello.bin -a 0x00100000 -e 0x00100000 hello.uimg

これでできた、hello.uimgを実行。

boot > tftp 0x300000 hello.uimg
TFTP from server 192.168.1.11; our IP address is 192.168.1.200
Filename 'hello.uimg'.
Load address: 0x300000
Loading: #
done
Bytes transferred = 298 (12a hex)
boot > bootm
## Booting image at 00300000 ...
   Image Name:   
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    234 Bytes =  0.2 kB
   Load Address: 00100000
   Entry Point:  00100000
   Verifying Checksum ... OK
OK

Starting kernel ...

Hello world!

このコードをベースにmruby+newlibをつっこんでみました。

boot > tftp 0x200000 main.uimg
TFTP from server 10.10.10.3; our IP address is 10.10.10.200
Filename 'main.uimg'.
Load address: 0x200000
Loading: ########################################################
done
Bytes transferred = 286464 (45f00 hex)
boot > bootm
## Booting image at 00200000 ...
   Image Name:   
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    286400 Bytes = 279.7 kB
   Load Address: 00100000
   Entry Point:  00100000
   Verifying Checksum ... OK
OK

Starting kernel ...

index:0
index:1
index:2
index:3
index:4
index:5
index:6
index:7
index:8
index:9
index:10

他のmruby on YABMと同じようにhttpsで通信できるところまで作ったのですが、はまった点は以下でした。

アセンブラの割り込み処理からCの割り込み処理を呼ぶときに関数名に文字数の制限があった。

MMUを設定しないととっても遅かった

割り込みのレジスタがちょっと分かりにくい。

newlibのコンパイル方法でオプション無しだとソフトウエア割り込み(svc)を使ったバイナリになった。

Etherswitchのレジスタに連続して書き込むとおかしくなる。

KS8695を使ったルーターは以下のような製品があったようです。

メーカー 機種
アイ・オー・データ NP-BBRM
バッファロー BLR-TX4M
コレガ BAR Pro3
リンクシス・ジャパン BEFSR41C-JP

NP-BBRMはシリアル無しなのでnetconsoleなu-bootを焼いてみました。ずっと基板とにらめっこして、どっかに出てないか見てたんですが、全く見つからなかったので、ピンを跳ね上げようかとおもったのですが、netconsoleで十分でした。