といってもちょっとだけ改造。青と赤のLEDを外す。光り方が安っぽい上に、PORT で制御するようになっていないので役に立たない。 dingoo なんかも LED が付いていないし。-- ハンダこての二丁使いで外すのは楽勝にできた。
次に外したバッテリーやらスピーカーの線をハンダ付けして、組み付け。ボタンが引っ掛かり気味だったので 靴磨き用のシリコンを塗っておいた。
さて、動作確認。このときは問題なく立ち上がった。-- バッテリーを外していたので時間が設定されていない。時間を設定して一旦電源を落とす。
次に USB につなげてみたのだが、画面がまくらなまま何も起きない。
ちょっとあせったのだが、→ボタンを押しての USB 接続で USBBOOT になることが確認できた。
一旦 USBBOOT にして電源スイッチを ON 。これで USB を抜き差ししても普通に USBBOOT になる。--- どうも電源周りは異常ないようだ。
よくわからないのだが、ファームウェアアップデートの最中に電源を切るようなことをしたとしか思えない。確か ファームウェアを U-Disk に置いていたから アップデートが動く可能性はあった。
まぁファームウェアが壊れただけなら問題ない。ちょうど USBBOOT を改造して、元のファームウェアバックアップして戻せるようにしようとしていた所だし、生きている二号機もある。改造に精を出すことにしよう。
... というわけで usbboot の調査。
まず USBBOOT は データ用に IN,OUT 2つの bulk エンドポイントを持っている。コントロール エンドポイントに コマンドを送り それにしたがって データ用エンドポイントを使って送受信する。
送受信できるデータの量は 最大 1MB 。制限があるが、これだけのバッファを確保している。チェックは特にしていないからこれ以上のデータを送るとどこか壊れる。ホスト側でチェックしないといけない。
NAND FLASH に書くコマンドは、NAND_PROGRAM。 これにはオプションがあって OOB_ECC を指定すると データ以外に OOB も書いてくれる。転送フォーマットは データ(1page) oob ... の繰り返し。
これに対応する 読み込みコマンドは NAND_READ_RAW 。これにも OOB_ECC オプションがある。
HOST 側は
Usage: nprog (1) (2) (3) (4) (5)
(1) start page number
(2) image file name
(3) device index number
(4) flash index number
(5) image type must be:
-n: no oob
-o: with oob no ecc
-e: with oob and ecc
という風に nprog を使って書き込みができる。-e オプションで oob の書き込みもできる。
ただし ファイルへ 読み込むコマンドはない。NAND_READ_RAWをするコマンド nreadraw はあるのだが 16 進ダンプするのみだし OOB_ECC も指定できない。なにより遅い。1 page に 1秒ぐらいかかる。あくまで目でみるためのもの。
... というわけで nreadraw を参考に 新しいコマンドを作る予定。
仕組みは分かったし どう改造すれば良いかも分かった。
... さて、実はもう一つ作りたい機能がある。
それは、シリアルがわりに使える機能。仕組みは上で書いたとおりなので Neo slim 3000 のプログラムから データをたれながす訳にはいかない。ホストからポーリングする必要がある。
... でどうするか。
コマンドを追加して、メッセージのサイズと場所をホストに教えられるようにする。メッセージがなければ サイズ 0 。
HOST はメッセージがあれば メモリーを読み込む。
... とまぁこんな風に考えてみたのだが ... 調べてみるとメモリーを読み込むコマンドがない。
どうも 全部作らないといけないようだ。ならば、メモリーを読み込むコマンドを作り、オプションとしてメッセージを指定できるようにしたほうが楽かも知れない。
仕様が変だと思われるかも知れないが メモリ空間、メッセージ用空間という考え方ならそれほど変でもない。ついでなので GPIO 空間というのを作っても良いかも知れない。GPIO も出力は設定できるが 読み込むコマンドがないのだ。
追記:
FLASH の内容をファイルにセーブする機能は出来た。だが、書き込む nprog が何故かちゃんと動いてくれない。イレースは 出来るから壊れていないと思うのだが ... 正しく書き込めないところが出ている。... ううむ 困った。
... やはりデバッグできないと困るので、シリアルで出力した内容を表示できるようにした。
usbboot :> msg
CPU data: Boot4750
msg_read: 298 (1000)
address is : 0x81C00000
Address offset is: 0x01C00000
GOT correct to : 0x81C06C40
Init UDC
GET_CPU_INFO: 0xFBBBFF7F
GET_CPU_INFO: 0xFBBBFF7F
Configuration: DS_hand_t!
Borad_init! 0x00004750
GET_CPU_INFO: 0x00004750
SET ADDRESS: 0x00000000
DATA_LENGTH: 0x00001000
--- end
usbboot :> msg
CPU data: Boot4750
msg_read: 79 (1000)
0x00004750
SET ADDRESS: 0x00000000
DATA_LENGTH: 0x00001000orrect to : 0x81
--- end
こんな感じ。4KB までバッファに溜められて、msg コマンドでそれを表示。
ポーリングして自動で 出そうかと思ったが、面倒なので とりあえずパス。
ついでに GPIO の 値も調べられるようにして、ボタンの割り当てが分かった。
なにも押さない状態:
PAPIN: 0000bcdb
PBPIN: 823f0401
PCPIN: ffdf7cff
PDPIN: ffffffff
この状態で ボタンを押すと該当ビットが 0 になる。
L: B31
R: D4
up: D0
down: D1
left: D2
right: D3
▲(up) : D11
×(down) : D10
■(left): D12
◯(right): D9
power: NONE
Lボタンだけ LCD と共用になっていない。-- WKUP というピンで サスペンドからの復帰に使える。
ちなみに、LCD の データが有効でないとき、ボタンの値を読むことができるが、正しい値を読むには、最後に LCD のデータを出力してから 少々時間が必要。end of frame interrupt というのがあるようなので、これを イネーブルして、割り込みでボタンの状態を見るようにするのだろう。イネーブルするには LCDCTRL レジスタ を操作する。
あと、SDRAM の内容をダンプする機能を作れば、だいたいデバッグできそう。(これで Jz4740 が Jz4750 として見えてしまう問題も解決できるはず )
ところで、GPIO のまとめで書いた ピンのマッピングは Jz4725 のデータシートを見て書いたのだが、Jz4725B と ポートのアサインが全然違うことが分かった。面倒なことだが、見直さないと。
追記: 原因は分かった
書き込めない原因はわかった。
GET_CPU_INFO: 0x00004750
SET ADDRESS: 0x00000280
DATA_LENGTH: 0x00000080
Request : NAND_PROGRAM!Skip a write fail block
... finished.
stage2 のプログラムがエラーを検出している。-- コードを見るとNAND の チップがエラーを返していたのだった。
NAND 側のデータシートを見ると ...
READ_STATUS コマンドを発行して、データバスに出てきたデータ
busy flag (か FRB) をチェックせよみたいなことが書いてある。
チェックはしているようなのだが、GPIO の Port を決め打ちで書いてある。... よくよく見てみると FRB の Port は、JZ4740/JZ4725 では PC30 , JZ4750/JZ4755/JZ4725B では PC27 だった。気まぐれに Port 番号の割り当てを変更したのではなく、アーキテクチャによって Port 番号が決まっているようだ。
なんども書いているわけではないから、製造時から bad block だったのかも知れない。安物だから bad block の率が高いのを安く仕入れているかも知れないし、有り得そうな話だ。
そうなると ... bad block を使わないようにする仕組みが必要になる。
U-Disk は、FAT でフォーマットしてあって何度も書き換えるから UBI なのだろう。
それは良い。立ち上がってからの話だし。フォーマットする 機能もあるし。
まず問題は、root これは ファームウェアのほとんどを占めるはずだから 60MB ぐらい。jffs2 を使ったり yaffs2 を使ったり するのに違いない とあたりは付けたものの offset と size がわからないとどうにもできない。
しかし、それ以前の問題もあった。bad block を回避するために カーネルや ブートローダまで 固定の位置に置いてないのかも知れないということ。
低レベルのプログラムで bad block を回避するために、例えば使っている データがあるブロックのリストを作って書いておくとか .. そういうことをしているはず。
確かに 2 台のマシンの nand を バックアップしたデータは 、結構違う。だが、2 台の差分ぐらいで データ構造がちゃんと分かるかというと疑問。
いったん復活させたかったのだが、労力ばかり多くなりそうなので 復活は打ち切り、サラのマシンとして扱おうと思う。
さて、次にやりたいことは?
ひとつは、Jz4740/Jz4725 で usbboot を使ったときに 正しく 認識できるようにすること ( なぜか Jz4750 と表示され 動作が不安定 ) -- 済
もうひとつは、neo slim 3000 の ブートローダを なんとかすること。LCDにメッセージも出したいし、USBBOOT で動かしたときは、USB から メッセージを取り出せるようにしたい。
.. その前にプログラムを ロードして実行する機能を確認しないと。
とりあえず ... ここまでの成果
- usbboot-qi.tar.gz -- QI から取ってきたオリジナル(ベース)
- usbboot-wk2.patch.gz -- ここまでの修正パッチ
- usbboot-wk2.tar.gz -- tarball (configure 済みで サイズがでかい )
- JZ4725B 対応
ingenic のオリジナルをベースに 変更。( ちなみに ingenic オリジナルには JZ4760 対応が入っている ) - コマンドの追加
ndump (NAND FLASH をファイルに書き出す)
gpior (GPIO の ピンの値を表示 )
msg (シリアルに出した内容の取得)
mread (SDRAM のダンプ ) - fw_args.cpu_id の値(0x4750/0x4740) は、USB の プロダクトID から取ることにした。もう誤認しないはず。
ちょっと、どんな風に NAND FLASH を使おうか検討してみる。
- まず、最初にブートする領域は 2 つある。最初の 8KB と次の 8KB 。最初のブロックが ECC エラーなら次のブロックからブートする。どちらにも同じ内容の stage1 ブートローダを書き込むことにしよう。
- で、 8KB のどこかに パラメータブロックを置く。できれば fw_args と互換性がある形にしたい。これを見ればクロックやメモリの初期化が正しくできる。ロードする FLASH の アドレス変換をするテーブル(8KB) を作ることにして、1 エントリ 16bit とすれば 8KB で 4096個 入る。ブロックを 8KB にしてしまえば、全体で 32MB まで管理できる。
ここの領域には、zImage と initrd を置く。32MB あれば複数の組みを置ける。普段使うものと、インストーラは置ける必要が出てきそうなので、ブートセレクタ機能がいりそう。 - 残りの部分は rootfs と U-DISK 。両方とも UBI にして、上位に普通のファイルシステム。rootfs は ext3 で U-DISK は FAT32 とか。1 つの UBI にできると 全体を使って ウェアレベリングできるから swap とか書き換えの多い データも置きやすくなる。
... UBI の上に パーティション作れると良いのだが... あ、device-mapper とか使えば良いのか。md でも良さそうだし。 - UBI 前提にしてしまうと、rootfs にブートローダがアクセスできないし、USBBOOT を使って UBI にアクセスするのも難しそう。
-- そうなると インストーラカーネルを使って 初期化できないといけなくなる。
実際に作ってみると違うものになりそうだが、こんな感じでどうだろう。 - メモ1: 電源を入れたときに USB が刺さっていたら ... インストーラカーネルを動かして、そうでなければ通常のカーネルにしたらどうか。
- メモ2:FATファイルシステムではダメなのか?
まず先頭がいきなり書けなかった場合に対処できていない。ルートディレクトリや ファイルアロケーションテーブルも 基本的に固定の場所(全体をずらすことは可能だが、一般的でない)。
仕様をわずかに変えたものは 既にFAT ではないし、かえって混乱しそうなのでやめたほうが無難。
書き換えるには、消去ブロックサイズ ( 128 ページ )を一旦消して書き換える。ただし、未書き込みの部分に書く場合は ページ単位で書ける。--- この特徴なら 先頭の 128 ページ(4K ページだと 512KB) はあまり書き換えないように ファイルアロケーションテーブル相当は 512KB 以降に割り当てたほうが良さそうだ。
もちろんこの領域はあまり書き換えないのが前提なわけだが、先頭ブロックが壊れるのはとても困るので、考慮は必要だろう。