Pakurino の ATmega328P 化 (2)

この話題は前回の記事で完結のはずでしたが、予期せぬトラブルがあり、続編を書くはめになりました。
それは、

ブートローダ書き込み直後の、ユーザープログラム領域が消去されて 0xFFFF で埋まっている状態 (初回) ではスケッチ書き込みに成功するが、2回目以降は失敗する。

という症状です。
この現象は、フューズ・ビットの設定がブートローダから実行を始めるモードになっていない場合に起こります。
そして、実際にフューズ・ビットの設定が正しくありませんでした。
この症状について説明すると、まず、ブートローダ書き込み直後はユーザープログラム領域が消去されていて、未定義命令である 0xFFFF で埋まっています。
この状態で通常通りにリセット後 0 番地から実行を始めても、この未定義命令の列を実行し続けて、最終的にはブートローダ領域に達してブートローダの実行を始めることになります。
ユーザ・プログラムが書き込まれた2回目以降の実行では、リセット後は 0 番地からユーザ・プログラムを実行するので、ブートローダに制御が移ることはありません。
この症状から原因が分かっていても、フューズ・ビットの設定は正しいはずだという思い込みから、真の原因にたどりつくのに少し時間がかかりました。
真の原因は、ATmega88 / 168 と ATmega328P とでは、

  • Brown-out Detection の設定ビット (BODLEVEL2..0)
  • ブートローダ・サイズおよびリセット・ベクタ選択の設定ビット (BOOTSIZ1..0, BOOTRST)

が割り当てられているフューズ・バイトが入れ替わっていることにあります。
ATmega88/168 では拡張バイトにブート関係のフューズ・ビットがあるのですが、ATmega328P ではフューズ上位バイトの下 3 ビットがブート関係のフューズ・ビットとなっており、拡張バイトにはブラウンアウト電圧設定のフューズ・ビットが割り当てられています。
328P のフューズ・バイトは 168 と同じと思い込んでいたので、Atmel の Web サイトから ATmega48PA/88PA/168PA/328P の英文データシートをダウンロードして読むまで、全く気が付きませんでした。
Arduino IDE 付属の「boards.txt」には 328P 用の拡張フューズ・バイトの値として 0x05 が指定されているのを不思議に思っていましたが、思い込みのため拡張バイトには 0x02 を書き込んでいました。
「boards.txt」の指定通りに書き込んでいればトラブルはなかったはずです。