AVR 内部の flash さえ AVR から書き込んでしまう

思いつき

bootloader という機能があって、起動時にファームウェアイメージを PC と通信してとってきて、ファームウェアに書いてから、起動。が、普通。起動時のベクタで bootloader mode にはいって、そこから書き込む専用と思いこんでた。

データシートみてたら、そんなモードはなくて好きなときにファームウェアを更新できるみたい。AVR の内部 RAM が 0x400 byte くらいで、ファームウェアが 0x4000 byte くらいなので通信しながら書き込まないと使えない。と、思いこんでた。

UNROM のキャラクタ RAM が 0x2000 byte もあるからいけるな。ってことで下記の流れで USB だけでファームウェアの更新が完結できる!

というわけで実装してみた

なぜか、更新できない... なんでだーと思ってたら、データシートにこう書いてある。

  • ブートローダ領域からでないと書き込めない
    • これはわかってたので関数にセクションを貼って、リンカの設定をかえる
  • ブートローダ領域が 0x1c00 から 0x1fff
  • fuse の設定するブートローダ領域が 0x1c00, 0x1e00 からとなっている

これがまちがいで mega16/164p の領域は 0x3c00 から 0x3fff だっつーの!!! これで1日使った。どのデータシートも間違ってる。

容量の問題

そこを直したら USB と UNROM 経由でファームウェアの更新完了!! それはいいんだが、 0x2000 byte だと思いこんでたので、残りの0x2000 byte を更新する方法を作ってない。現状のファームウェアだとそれで足りるんでいいけど、将来性はない。

セーブデータが消えてもいいなら、 TNROM, SNROM あたりを使って、 CHR-RAM と W-RAM を併用するのもあり。本当は RAM アダプタとか ETROM, EWROM を使えばいいんだけど、現状はアクセスできないし、UNROM という手軽さにかける。

AVR の書き込み手段一覧

AVR ライタなしでファームウェアを更新する手段をもうちょいもみます。販売はもうちょっとまっていただきたい。ihex を読み込むのを C で作ります。こーゆーときに C は弱いからやりたくない。

  • パラレル
    • 利点: AVR の設定を一切利用しないので fuse, flash memory 全てがかける
    • 欠点: 専用のパラレルライタが必要, 事実上やれるのは DIP だけ
  • シリアル/ISP
    • 利点: 6本の端子を出すだけでかける
    • 欠点: AVR の設定を利用するので、間違えたらかけなくなる
  • ブートローダ
    • 利点: 組み込んだ通信手段でかける
    • 欠点: AVR を動かしながらやるので、ブートローダ領域は事実上書き込めないのと、信頼性が通信手段に依存する。fuse はかけない。