2010年06月07日

Neo Slim 3000 が文鎮に

分解した Neo Slim 3000 を元に戻すことにした。

といってもちょっとだけ改造。青と赤の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 以降に割り当てたほうが良さそうだ。

    もちろんこの領域はあまり書き換えないのが前提なわけだが、先頭ブロックが壊れるのはとても困るので、考慮は必要だろう。













posted by すz at 00:55| Comment(0) | TrackBack(0) | Jz47xx(機種解析)
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス: [必須入力]

ホームページアドレス: [必須入力]

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/38795700
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック