adm5120のu-bootをビルドしてみた
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の回路は以下のようになってました。
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秒でした。
Author And Source
この問題について(adm5120のu-bootをビルドしてみた), 我々は、より多くの情報をここで見つけました https://qiita.com/yamori813/items/4adb399b635dedb4ac72著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .