2012年08月07日

ブートローダの検討

PIC32MX-PINGUINO-MX220 のブートローダを壊してしまった。要するにライタの方をなんとかしないと先に進めなくなった。それはさておき、自分でブートローダをビルドしたい。

とにかくいまのやつは気に入らないのだ。なにが気に入らないのか?というと

・ サイズがでかい。(プログラム・フラッシュを 12KB 専有する)
・ スタートアドレス のカスタマイズが出来ない。
・ ブートボタン、LED のカスタマイズが出来ない。

    サイズについては、ブートフラッシュ領域を有効に使うようにすると、8KB かうまくすれば 4KB に抑えられる。 で、jzlib の場合 ロードしたアドレスに JUMP してくれれば、ベクタ領域の 4KB をさらに節約できる。32KB しかない PIC32MX220 で この差は大きい。16KB しか使えなかったものが、24KB (うまくすれば 28KB) 使えるようになるのだ。

    あと 、カスタマイズ機能も欲しい。LED のポートを変更するだけで、再ビルドはしたくないのだ。さらに言うと フラッシュ領域の保護機能も欲しい。コンフィグで設定できるとは言え、チェックしておいた方がより安全だ。

それに、自製のブートローダも作ってみたい。自製の USB デバイスライブラリを使うもので一番シンプルなのが ブートローダだったりするのだ。( 要するにデバッグが目的なので、実用的に使えるのかどうかは気にしない。)

オリジナルのコードについて

    RetroBSD のコードをベースにして、PIC32MX220/PIC32MX250 に対応する。調べて見たが、ビルドするために必要なコードは揃っている。これを jzlib にできるだけ 合わせるように改造した上で、コンフィグ機能を付ける。

    retrobsd-src-r561-20110729.tar.gz

    参考用に取った、このスナップショットをベースにする。

ブートフラッシュ領域を有効に使う案

    jzlib で、割り込みベクタを割り当てない リンク・スクリプトと スタートアップを先に作っている。これを元にブートローダ専用の リンク・スクリプトを仕上げるのだ。

    さて、これのメモリマップの(一部)を説明すると

     program flash + 0x4000 exception_mem size 0x180
    .app_reset (_start)
     program flash + 0x4180 kseg0_program_mem
    .text

    こんな感じにしている。jzlib では exception_mem は、もともとスタートアップと割り込みベクタ領域で、1KB これを 384B に切り詰めた。その後に kseg0_program_mem が続く。これには .text すなわちプログラムコードが含まれる。 ブートローダでは、

     boot flash + 0x0000 exception_mem size 0xBE0
    .app_reset (_start)
    .boot
     program flash + 0x0000 kseg0_program_mem size 8K
    .text

    こんな風に変える。普通にビルドすると、コードは全部 .text になるから、プログラム・フラッシュに行ってしまう。コードを選んで .boot セクションに持って行くと ブートローダが専有する プログラム・フラッシュが減るようになる。

    .boot セクションに持って行くには、

     #define BOOT_SECTION __attribute__((section(".boot")))

     int BOOT_SECTION main(void)
     {
         :

    こんな風に関数を宣言する。ひとつひとつ 宣言することになるが、まぁたいした手間ではない。

    ついでに書いておくと、全部をブートフラッシュ領域に持っていくには、別の方法を使う。普通に戻して、kseg0_program_mem 自体を 移動するのだ。440 なんかでは、12KB もあるから それが可能になる。220 のように 3KB しかなければ頑張っても無理だと分かった。boot flash 3KB + program flash 4KB が精々。

カスタマイズの方法

    リンク・スクリプトには、もともと コンフィグ領域の 指定をする仕組みが仕込まれている。コンフィグ領域は、ブート・フラッシュの 最後 16バイト。これに倣って、その下 に 16Bの ブートローダ・コンフィグ領域を作る。
     
    MEMORY(追加)
    bl_config3 : ORIGIN = 0xBFC00BE0, LENGTH = 0x4
    bl_config2 : ORIGIN = 0xBFC00BE4, LENGTH = 0x4
    bl_config1 : ORIGIN = 0xBFC00BE8, LENGTH = 0x4
    bl_config0 : ORIGIN = 0xBFC00BEC, LENGTH = 0x4

    SECTIONS
    .bl_config3 : {
    KEEP(*(.bl_config3))
    } > bl_config3
    .bl_config2 : {
    KEEP(*(.bl_config2))
    } > bl_config2
    .bl_config1 : {
    KEEP(*(.bl_config1))
    } > bl_config1
    .bl_config0 : {
    KEEP(*(.bl_config0))
    } > bl_config0
    }

    こんな記述を リンク・スクリプトに追加するのだ。

    使う方は、

    #define BLCFG3 (*(unsigned *)0xBFC00BE0)
    #define BLCFG2 (*(unsigned *)0xBFC00BE4)
    #define BLCFG1 (*(unsigned *)0xBFC00BE8)
    #define BLCFG0 (*(unsigned *)0xBFC00BEC)

    こんな風に定義して

    * BLCFG0 アプリケーション領域の先頭(kseg1 address)
    * BLCFG1 アプリケーション領域の最後(kseg1 address) + 1
    * BLCFG2 スタートアドレス (kseg1 address, 省略可)
    * BLCFG3 ボタンとLED のコンフィグ

    struct blcfg3 {
    unsigned REDLED_BIT:4;
    unsigned REDLED_PORT:3; /* 0 A/1 B/... */
    unsigned reserved1:1; /* 0 */

    unsigned GRNLED_BIT:4;
    unsigned GRNLED_PORT:3;
    unsigned reserved2:1; /* 0 */

    unsigned BUT_BIT:4;
    unsigned BUT_PORT:3;
    unsigned reserved3:1; /* 0 */

    unsigned REDLED_TYPE:2; /* 0: LAT_SET 1: LAT_CLR
    2: TRIS_SET 3: TRIS_CLR */
    unsigned GRNLED_TYPE:2;
    unsigned BUT_TYPE:1; /* 0: NOT-PULLUP 1 : PULLUP */
    unsigned reserved:3; /* 000 */
    };

    こう使おうかと思う。

スタートアドレスのサーチ

    jzlib でシングルベクターモードにして コードを節約したのに、ブートローダを使うと アプリケーション領域の先頭 + 4K に JUMP してくる。しょうがないので、4KB 後ろにずらして使っている。これが一番気に入らない。

    でも、アプリケーション領域の先頭に JUMP するようにしたら互換性がなくなってしまう。どうしたものかと思ったのだが、a.out を ディスアセンブルすると 必ず先頭が

    9d004000: 3c1a9d00 lui k0,0x9d00

    これで始まっている。k0 に 上位アドレスをロードしているのだが、これは決まりきった手順のようなもの。MichroChip 由来の crt0.S を使っていればこうなるし、特に 変える理由もない。

    あと、スタートアドレスは、4KB にアラインされる。2KB を超えることもある割り込みベクタが先頭にあるから当然なのだ。

    つまり、アプリケーション領域の先頭から 4KB 単位でインクリメントして、0x3c1a9d00 を探せば良い。こうすることで、jzlib では、先頭から使えるようになる。

最初のバージョン

     ・ jzlib-0.2d.tar.gz

    jzlib に依存するように作り替えているので、jzlib に同梱することにした。jzlib をインストールして、hidboot ディレクトリで make すればビルドできる。

    ただし、まだ、全然テストしていない。バイナリを置くのはまだ先になる。

    text data bss dec hex filename
    9056 52 1187 10295 2837 usbboot.elf

    サイズは、9KB 弱。これを 振り分けて 8KB からロードできるようにした。7KB 以下にしないと 4KB からのロードはできないので、これで手をうった。(頑張って小さくするつもりはない。これを参考にして自製の USBASP ブートローダを作るのだ。)

      ------------------------------------------------
      : 02 0000 04 9D00 5D
      : 10 0000 00 8800F07700000000FFFF001000000000 F3
      :
      :
      : 04 1A90 00 000088BF 0B
      ------------------------------------------------
      : 02 0000 04 9FC0 9B
      : 10 0000 00 C09F1A3C10005A270800400300000000 5F
      :
      :
      : 10 08D0 00 05977C6730F044DB00EF0363000200A0 63
      ------------------------------------------------
      : 02 0000 04 BFC0 7B
      : 04 0BE0 00 0A1F170E C3 (Red RA10 (0A), Grn RB15(1F) , BUT RB7(17) )
      : 04 0BE4 00 FFFFFFFF 11 (START_ADDR : auto search)
      : 04 0BE8 00 FFFFFFFF 0D (APP_FLASH_END +1: auto)
      : 04 0BEC 00 002000BD 28 (APP_FLASH_START : 0xbd00_2000 )
      : 04 0BF0 00 FFFFFF0F F5
      : 04 0BF4 00 D979F9FF B3
      : 04 0BF8 00 5BCE60FF 71
      : 04 0BFC 00 EEDFFF7E AB
      ------------------------------------------------
      : 04 0000 05 9FC00000 98
      : 00 0000 01 FF

    さて、HEX ファイルはこうなっている。領域内に収まっていることを確認した。あと最後の部分がコンフィグ。ここを編集すれば ビルドしなくともカスタマイズできる。

    DEVCFG の方は、BWP=0(ブート領域保護) と PWP(8KB 保護)にしてある。JTAGEN は Enable だが、

    /* Disable JTAG port, to use it for i/o. */
    DDPCON = 0;

    こんなコードが入っていて、ブートローダの先頭で Disable にしている。こうすることで、AVR の ISP のように 書き込みするときだけ、JTAG を使えるようにしている。 (注) 1xx/2xx では DDPCON をCFGCON に読み替える。

    ちなみに、Makefile で DIP_MX220 を選択できるようにしているが、LED の設定しか変わらない。また 250 でも同じものが使える(220で動けばの話だが)。PINGUINO_MICRO の設定は、440 用のブートローダで 大きく違う点は、全体が ブート・フラッシュに置かれること。これによって プログラムフラッシュの先頭から使えるようになる。当然ながらこれも未テスト。

USBASP ブートローダの検討

    まだまだなのだが、どんなものになるかちょっと触れておこうと思う。

    PIC32 用のライタソフトとして、avrdude を使っているものがある。ちゃんと調べていないのだが、arduino と互換にしているらしい。それがありならば、USBASP でもなんとかできるのかも知れない。自製の USB device ライブラリ向けに移植した USBASP ブートローダのコードがあるし、USB device ライブラリを PIC32MX に移植したいと思っていたので検討してみることにした。

    まず、USBASP ブートローダは割り込みを使わずに実装できている。また、USB シリアル プロトコルの CDC とは違って 基本の機能しか使っていない。... どうもこれでデバッグするのが良さそうなのだ。

    このブートローダは、サイズが小さいのが特徴のひとつで AVR では 2KB で実装できている。PIC32MX では、コードが大きくなってしまって、3KB の領域には収まりそうにない。3KB を超えると 次は 7KB 以内が目標になる。それで、機能を充実させる方向で 検討を進めている。

    text data bss dec hex filename
    5016 64 873 5953 1741 asp162bl.elf

    いまのサイズは 5KB ぐらいで、ブートローダ自体の機能は一応入っている。上で説明したブートローダ・コンフィグ機能なども全部入れた。ただし、USB device ライブラリのほうがまだで、これよりちょっと大きくなる予定。それでも 7KB には収まるだろうし、収める。こうすれば、HID ブートローダより使えるメモリが増えてメリットが出る。

      text data bss dec hex filename
      3924 64 873 4861 12fd asp162bl.elf

      嘘のような話なのだが、ポートをコンフィグ可能にするだけで 1KB 使っている。上は、define で指定したケース。

    さて、機能として最も重要なのが、シグネチャー。ライターソフトは、これを見てどういう動作をするか決める。だが、AVR に合わせないと、avrdude で使うのは厳しい。

    AVR の場合、第一バイトが 0x1E で ベンダーのコードになっている。第二が FLASH サイズで、第三がそのサイズでの識別番号。 で、PIC32MX にも当然デバイスの ID はある。こちらは、1word - 4 バイト。下位 8bit がベンダーコードで 0x53 。その後がどうなるかちょっと調べてみた。

    [1][2][3]
    * 00 A0 04 220 B 32
    * 10 A0 04 210 B 16
    * 20 A0 04 220 C 32
    * 30 A0 04 210 C 16
    * 40 A0 04 220 D 32
    * 50 A0 04 210 D 16

    * 00 D0 04 250 B 128
    * 10 D0 04 230 B 64
    * 20 D0 04 250 C 128
    * 30 D0 04 230 C 64
    * 40 D0 04 250 D 128
    * 50 D0 04 230 D 64

    * 20 94 -- 420 H 32
    * D0 94 -- 440 H 128
    * 20 95 -- 440 H 256
    * 60 95 -- 440 H 512

    * D0 96 -- 440 L 128
    * 80 97 -- 460 L 512
    * 40 97 -- 460 L 256

    一応、第二、第三バイトでデバイスを特定できるようだ。2xx は、規則正しい。5xx/6xx/7xx は、沢山ある上に良くわかっていないのでパス。4xx もリストしただけ。ベンダーコードさえ違えば重ならないから、なんとかなりそう。これをシグネチャの定義にしてしまおうと思う。

    これだけなんとかなれば、後は アドレスを指定してメモリを読み書きする仕組みがあれば、事足りる。USBASP には、上位 16bit を指定する機能と、下位 16 bit でアドレスを指定して ブロックを読み書きする機能がある。

    アドレスの範囲をチェックして、余計なところを読み書きできないようにすることは必要だが、新たなプロトコルの定義はいらない。ちなみに、HID ブートローダには、メモリを読み出す機能がない。製品としては、セキュリティ上必要なんだろうけれども、趣味で使う分には不便でしかたがない。書き込みは、アプリケーション領域のみ。読み込みは、フラッシュ全域のみということにしようかと。こうしておけば、使っているブートローダをバックアップできるし、コンフィグがどうなっているかも分かる。

    ソースコード (USBASP ブートローダの方)

     ・angel_loader-p32mx-wk05.tar.gz

    全然動くことが期待できるものではないが、一応置いておく。周りは固めたのだが、肝心の USB device ライブラリがまだまだ。

関連記事
posted by すz at 19:32| Comment(0) | TrackBack(0) | PIC32MX
この記事へのコメント
コメントを書く
お名前: [必須入力]

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

ホームページアドレス:

コメント: [必須入力]

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


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

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