LoginSignup
1
1

More than 1 year has passed since last update.

adm5120のu-bootをビルドしてみた

Last updated at Posted at 2019-01-11

10年以上前の有線ルーターで使われていたadm5120というMIPS系のSOCのu-bootをビルドしてみました。

adm5120は元々ADMtek(台湾)という会社が2003年くらいに開発した製品でしたが、ADMtekがInfineon(ドイツ)の会社に買収され、後半はInfineonの製品として販売されていました。MIPS 4KのSOCの先駆けでEthernet Switchも内蔵していました。クロックは175MHzとちょっと遅いです。

チップは下に324本の足が出てるタイプ(BGA)のADM5120と横に208本出ているタイプ(PQFP)のADM5120Pがあります。データーシートはネットで手に入ります。

有線ルーターはadm5120を使う前にはSAMSUNG S3C4510(ARM)やZyDASのZD2001(MIPS)やMICRELのKS8695X(ARM)を使った製品もありましたが、adm5120を使った製品が一番長く作られていたのではないかと思われます。2010年くらいからは蟹に変わったようです。今考えると有線系ルーターSOCの完成形だったようにも思えます。

10年以上前に佐藤益弘さんがコードを作られていました。

これは既存のブートに重ねる形で作られていました。

ほぼ同時期に佐藤さんのコードからスタンドアローン版をRobert Delienさんが作られていたようです。

スタンドアローン版をUrJTAGでFlashの先頭から書きたかったのですが、Robertさんのコードはpatchだけでオリジナルのソースがどれかわからなかったので、佐藤さんのページのアーカイブファイルとガッチャンコする事しました。

Robertさんのコードから利用した部分は二つです。

  • lowlevel_initというメモリの初期化をしているアセンブラ(board/bbr4/lowlevel_init.S)
  • PL010というシリアルのコード(drivers/serial_pl010.c)

佐藤さんのコードではlowlevel_initは空でした。これはオリジナルのブートローダーが処理しているからです。シリアルのコードは佐藤さんも書かれている(cpu/mips/adm5120_serial.c)のですが何故か動かず、既存のコードにパッチをあてたRobertさんのコードを使いました。

何かのtoolchainのmipselのgcc3なLinuxバイナリをLinuxエミュレーションのFreeBSDでビルドしました。このソースが作られた時期を考えるとgcc3が良いような気がしました。

U-Boot 1.1.4 (Jan 11 2019 - 19:53:20)

DRAM:   8 MB
Top of RAM usable for U-Boot at: 80800000
Reserving 183k for U-Boot at: 807d0000
Reserving 2624k for malloc() at: 80540000
Reserving 44 Bytes for Board Info at: 8053ffd4
Reserving 36 Bytes for Global Data at: 8053ffb0
Reserving 128k for boot params() at: 8051ffb0
Stack Pointer at: 8051ff98
Now running in RAM - U-Boot at: 807d0000
flash_protect ON: from 0xBFC00000 to 0xBFC235FF
protect on 0
protect on 1
protect on 2
protect on 3
protect on 4
protect on 5
protect on 6
protect on 7
protect on 8
protect on 9
flash_protect ON: from 0xBFC30000 to 0xBFC3FFFF
protect on 10
Flash:  2 MB
In:    serial
Out:   serial
Err:   serial
Net:   adm0
Hit any key to stop autoboot:  0 
BBR-4MG/HG #

ソース一式はここに置きました。

ビルドはこのスクリプトでやってます。

#!/bin/sh

export PATH="/foo/buildroot-gcc342/bin:${PATH}"

CROSS=mipsel-linux-

gmake distclean
gmake HOSTCC=cc CROSS_COMPILE=${CROSS} bbr4_config
gmake HOSTCC=cc CROSS_COMPILE=${CROSS}

v0.1のタグうってバイナリもアップしてあります。

SHA256(u-boot.bin)= 3bdd92c9ece8f0797b2b665a0dfa7a0ae8d8bb81f79c70bf3e4b8f7cf76bc599

バイナリが128Kをちょっと越えたくらいになっていてenvの保存領域が0x30000から0x3ffffになります。0x40000以降が自由に使える領域になります。ちょっと機能削って、128Kに収まると64K分余計に使えるのですが。

もちろんこれを焼くと、ルーターとしての機能はなくなりますので、注意してください。

UrJTAGでのオペレーションはこのようにしてます。

jtag> cable ft2232
Connected to libftd2xx driver.
jtag> detect
IR length: 5
Chain length: 1
Device Id: 00000000000000000000000000000001 (0x0000000000000001)
  Unknown manufacturer!
chain.c(149) Part 0 without active instruction
chain.c(200) Part 0 without active instruction
chain.c(149) Part 0 without active instruction
jtag> include admtek/adm5120/adm5120
ImpCode=01000001010000000100000000000000 41404000
EJTAG version: 2.6
EJTAG Implementation flags: R4k DINTsup ASID_8 NoDMA MIPS32
Processor entered Debug Mode.
jtag> detectflash 0x3fc00000
Query identification string:
        Primary Algorithm Command Set and Control Interface ID Code: 0x0003 (Int
el Standard Command Set)
        Alternate Algorithm Command Set and Control Interface ID Code: 0x0000 (n
ull)
Query system interface information:
        Vcc Logic Supply Minimum Write/Erase or Write voltage: 2700 mV
        Vcc Logic Supply Maximum Write/Erase or Write voltage: 3600 mV
        Vpp [Programming] Supply Minimum Write/Erase voltage: 11400 mV
        Vpp [Programming] Supply Maximum Write/Erase voltage: 12600 mV
        Typical timeout per single byte/word program: 32 us
        Typical timeout for maximum-size multi-byte program: 0 us
        Typical timeout per individual block erase: 1024 ms
        Typical timeout for full chip erase: 0 ms
        Maximum timeout for byte/word program: 512 us
        Maximum timeout for multi-byte program: 0 us
        Maximum timeout per individual block erase: 8192 ms
        Maximum timeout for chip erase: 0 ms
Device geometry definition:
        Device Size: 2097152 B (2048 KiB, 2 MiB)
        Flash Device Interface Code description: 0x0001 (x16)
        Maximum number of bytes in multi-byte program: 1
        Number of Erase Block Regions within device: 2
        Erase Block Region Information:
                Region 0:
                        Erase Block Size: 8192 B (8 KiB)
                        Number of Erase Blocks: 8
                Region 1:
                        Erase Block Size: 65536 B (64 KiB)
                        Number of Erase Blocks: 31
jtag> flashmem 0x3fc00000 u-boot.bin noverify
Manufacturer: Intel
Chip: Unknown (0x88C3)!
program:

block 0 unlocked
erasing block 0: 0
addr: 0x3FC01000

実はかなり以前に佐藤さんのu-bootを使ってFreeBSDを起動しててみたりしていたのですが、Flashの使える領域がオリジナルブートの制約があり窮屈だったので試しにu-bootスタンドアローン版をビルドしてUrJTAGで書き込んだところ、その後Flashが見えなくなってしまって、壊してしまったと思っていたのが、解決策のページがあったのがこれをやってみようと思ったきっかけでした。

ビルドは1分もかからないのですがUrJTAGで128Kちょっとを焼くのに30分くらいかかり安易にトライアンドエラーが出来ず根気のいる作業でした。

Etherが使えるブートが出来ればあとは気軽にトライアンドエラーできます。

FreeBSD 12Rの前にadm5120のコードは消されてしまいました。adm5120は8Mとかのターゲットがほとんどで、しかたがなかったのですが。

追記:このブートは割り込みを使わない実装になっています。そのため、アプリで割り込みを使うためにはCP0のStatusのEXLとERLを0にする必要がありました。

いろいろ調べていたらadm5120を使った製品でCFEをブートに使ったケースがありましたが、ソースは見つかりませんでした。

memory controller

SDRAMの接続はおそらくarmのPL172のIPが使われているのではないかと思われます。lowlevel_init.Sの中に初期化コードがあります。JTAGでレジスタをタンブしたところ、オリジナルと同じ設定になっています。パフォーマンスが出ないのは初期化パラメーターがチューニングされていない可能性があるのではないかと睨んでいます。

LEDデバッグ

uartが使える前に落ちていると、どこまで処理されているのか分からず困ります。そのような時はLEDデバッグが役に立ちます。下記のコードで赤いLEDが消灯します。電源投入時は0となっていて点灯しているので、処理が到達しているかの確認が出来ます。

*(volatile unsigned *)(0xb20000b8) = 0x08080000;

このSOCはGPIO専用のピンとEtherのLEDと兼用のピンがあります。LEDの回路は以下のようになってました。

ADMLED14.png

A B LED
H L 左点灯
L L 右点灯
* H 消灯

UrJTAGを使ったデバッグ

adm5120の一つ目のuartは0x12600000にあります。これのUART Flag(0x18)を確認するのは以下のようになります。

jtag> peek 0x12600018
bus_read(0x12600018) = 0x97 (151)

1バイトアクセスが0x12600000で2バイトアクセスが0x32600000で4バイトアクセスが0x52600000になります。

uartの初期化が終わっていれば下記の方法でuartから1バイト送信ができます。

jtag> poke 0x12600000 0x55

佐藤さんのコードでは何故かこの方法で送信が出来ない状態でした。おそらくなんらかオリジナルのブートの初期化に依存しているのではないかと思われますが、よく分かりませんでした。

mruby動きました

BBR-4MG/HG # setenv serverip 10.10.10.3
BBR-4MG/HG # setenv ipaddr 10.10.10.102
BBR-4MG/HG # saveenv
BBR-4MG/HG # tftp 0x80300000 main.bin.bz2.uboot
Using adm0 device
TFTP from server 10.10.10.3; our IP address is 10.10.10.102
Filename 'main.bin.bz2.uboot'.
Load address: 0x80300000
Loading: #################
done
Bytes transferred = 84701 (14add hex)
BBR-4MG/HG # bootm
## Booting image at 80300000 ...
   Image Name:   mruby VM image
   Created:      2019-01-12   8:32:30 UTC
   Image Type:   MIPS Linux Kernel Image (bzip2 compressed)
   Data Size:    84637 Bytes = 82.7 kB
   Load Address: 80010000
   Entry Point:  80010000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK

Starting kernel ...

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

Flashに焼いてみました。

BBR-4MG/HG # tftp 0x80300000 main.bin.bz2.uboot
Using adm0 device
TFTP from server 10.10.10.3; our IP address is 10.10.10.102
Filename 'main.bin.bz2.uboot'.
Load address: 0x80300000
Loading: #################
done
Bytes transferred = 84701 (14add hex)
BBR-4MG/HG # protect off 0xbfc40000 0xbfe00000
............................
Un-Protected 28 sectors
BBR-4MG/HG # erase 0xbfc40000 0xbfe00000

............................ done
Erased 28 sectors
BBR-4MG/HG # cp.b 0x80300000 0xbfc40000 ${filesize}
Copy to Flash... flash_write_cfiword, cnt=542465, src=80300000
done
BBR-4MG/HG # 

起動後に実行されるbootcmdが元のままなので正しく設定します。

BBR-4MG/HG # setenv bootcmd bootm 0xbfc40000
BBR-4MG/HG # saveenv

RAM 8MでFlash 2MのターゲットはOSを動かすにはちょっときついのですが、mrubyには最適なので、格好の餌食です。:-)

いろいろな人の英知があってでできたことで、感謝しております。

admbm-mrubyの使い方

プリコンパイルしたVMをリリースタグに付けてあるので、以下の操作で試せます。

まずadmbm-mrubyのリリースタグの最新のmain.bin.bz2.ubootをダウンロードします。

mrubyのmrbcでスクリプトをコンパイルして出来たmrbを追加すれば出来上がりです。

% mrbc hello.rb
% cat main.bin.bz2.uboot hello.mrb > hello.img

hello.imgを上記の手順で焼けばOKです。

恒例のfib(32)を計ってみたのですが、447秒と極端に遅いです。メモリコントローラーの最適化などが必要なのかもしれません。

mrubyをupdateしたらfib(32)が114秒とおおよそ想定内のパフォーマンスが出ました。mruby以外はいじってないのですが、何が影響したのか謎です。

mrubyのコードも変わっているので単純な比較はできませんがgcc 4.2からgcc 4.9に変更してfib(32)を確認したら63秒でした。

mruby 3.2ではfix(32)が61秒でした。

1
1
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
1
1