動機
Arduino IDEにはArduino UNOなどのボードをAVRライターにする「ArduinoISP.ino」が含まれています。
ArduinoISPの使い方は下記を参照ください
私はArduinoISPを使ってATtiny841の開発を実施しているのですが、なんとこのマイコン、他のAVRと比べて明かに**ISPの書き込みが遅い(2分30秒かかる!)**のが悩みの種でした。
ATtiny841のFlashはページサイズが1ページ16バイトのものが採用されています。1ページ64バイトのATtiny85やATtiny84と比べて読み・書き回数が4倍に増えます。その分ISP実行時のコマンドが多く発行されるので遅くなっていると思われます。
当初ATtiny841の設定変更で改善を試みたのですがうまくいかなかったので、ArduinoISP.inoを高速化することにしました。
注意
今回は超遅いATtiny841のためにArduinoISPの高速化パッチを用意しましたが、他のマイコンでは書き込みがうまくいかなくなるかもしれません。
危険なので、あまり困ってないなら、標準版をそのまま使った方が良いです。
また、下記修正は Arduino 1.6.3で確認しました。
実施したこと
実施したことは下記の2つです。
- ArduinoISPはPCと19200bpsで通信している。これを115200bpsに変更。
- ArduinoISP.ino内の(応答の調整も兼ねてると思われる)ディレイを少なく
変更方法を紹介しますが、くれぐれも標準のArduinoISP.inoを上書きせず、コピーを用意してくださいね。
1. シリアル通信速度を変更
ArduinoISP.inoのシリアル通信速度を変更するには、下記2つのファイルを修正します。
- ArduinoISP.ino(ArduinoISPのスケッチ)
- Arduino.app/Contents/Java/hardware/arduino/avr/programmers.txt
1-1. ArduinoISP.inoの修正箇所
ArduinoISP.inoの69行目くらいに、Serial.begin(19200);
という箇所があります。
void setup() {
Serial.begin(19200); // <--ここを変更する
:
}
これを、Serial.begin(115200);
に変更します。
もう1カ所、シリアル通信速度の高速化に伴い修正が必要な箇所があります。
ArduinoISP @57600 baud instead of 19200で紹介されている内容ですが、要はheartbeat()
というLEDをチカチカさせる関数があって、この中のdelayが大きすぎるようです。
めんどくさいので、heartbeat()
の呼び出し箇所でコメントアウトします。
void loop(void) {
// is pmode active?
if (pmode) digitalWrite(LED_PMODE, HIGH);
else digitalWrite(LED_PMODE, LOW);
// is there an error?
if (error) digitalWrite(LED_ERR, HIGH);
else digitalWrite(LED_ERR, LOW);
// light the heartbeat LED
heartbeat(); // <--これをコメントアウトする。
if (Serial.available()) {
avrisp();
}
}
1-2. programmers.txtの修正箇所
programmers.txtは、Arduino IDEで選択できるAVRライターを定義するファイルです。
この中に、ArduinoISP.inoを書き込んだArduinoの定義もあります。
Arduino as ISP
arduinoasisp.name=Arduino as ISP
arduinoasisp.communication=serial
arduinoasisp.protocol=stk500v1
arduinoasisp.speed=19200
arduinoasisp.program.protocol=stk500v1
arduinoasisp.program.speed=19200
arduinoasisp.program.tool=avrdude
arduinoasisp.program.extra_params=-P{serial.port} -b{program.speed}
上記のarduinoasisp.speed=19200
とarduinoasisp.program.speed=19200
のパラメータを書き換えることで高速化できますが、この定義を書き換えてしまうと、オリジナルのArduinoISP.inoを焼き込んだArduinoが使えなくなってしまいます。
そこで、上記定義をマルっとコピーして、下記のようにすると良いと思います。
# オリジナル
arduinoasisp.name=Arduino as ISP
arduinoasisp.communication=serial
arduinoasisp.protocol=stk500v1
arduinoasisp.speed=19200
arduinoasisp.program.protocol=stk500v1
arduinoasisp.program.speed=19200
arduinoasisp.program.tool=avrdude
arduinoasisp.program.extra_params=-P{serial.port} -b{program.speed}
# 高速化版
arduinoasisp_115200.name=Arduino as ISP(115200)
arduinoasisp_115200.communication=serial
arduinoasisp_115200.protocol=stk500v1
arduinoasisp_115200.speed=115200
arduinoasisp_115200.program.protocol=stk500v1
arduinoasisp_115200.program.speed=115200
arduinoasisp_115200.program.tool=avrdude
arduinoasisp_115200.program.extra_params=-P{serial.port} -b{program.speed}
上記追加が終わったらArduino IDEを再起動してください。
すると、Tools>Programmer
メニューからArduino as ISP(115200)
が選択できるようになります。
これでPCと高速化したArduinoISP.inoを書き込んだArduinoとの間で115200bpsでシリアル通信できるようになりました。
2. ArduinoISP.ino内の(応答の調整も兼ねてると思われる)ディレイを少なく
これまでのシリアル通信速度の変更だけでも、ATtiny841の書き込み速度で30秒近く改善します。(2:30→2:00くらいに改善)
しかし、2:00でもまだ遅いですよね。
そこで、さらなる調整をします。
ATtiny841が遅いのは、Flashのページ書き込みなので、そこを速くしたい。
そこで、ArduinoISP.inoのwrite_flash_pages()
内のdelay()待ち時間を少なくする方針で調整を行いました。
修正箇所は、ArduinoISP.inoの141行目にある
# define PTIME 30
の部分です。PTIME
で定義した時間、write_flash_pages()
から呼び出されるcommit()
の中のdelay()
で待ってしまいます。
最終的には、
# define PTIME 8
まで減らしました。7
だとうまく書き込めなかったので、限界のようですw
まとめ
ArduinoISP経由でATtiny841を45秒程度で書き込めるようになりました。
これでも遅いのですが、なんとか許せるレベルになったかと。
もちろん、ATtiny841以外も速くなったので、今後これを使っていこうと思います。
もっと良い方法等あれば教えていただけると嬉しいです!