Arduinoにライトプロテクト(書き込み禁止)をする方法5選

ライトプロテクトという言い方が適切かどうかわかりませんが、要は「うっかりプログラムを書き換えてしまうのを防止したい」という趣旨の記事です。
どうも普通に上書き防止を設定するような機能はボード側にもIDEにもないようなので、書き込み時にエラーを発生させる方法を集めました。書き込みしようとしたときにこうなるのが目標です。

f:id:slideglide:20171021221739p:plain

想定される利用ケースは……正直あんまり思いつきませんが、強いていえば「大事なプログラムの入ったArduinoを書き換えられたくない」等のケースで使えるかもしれません。また個人的な需要として、AVRのライターとしてArduinoを使うときにボードを選択し忘れて目標のAVRではなくArduinoの方を書き換えてしまうことがよくあり、それを防止したかったというのが発端です。

*初心者OK

1.RESETピンとGNDの間にコンデンサを入れる(Arduino Unoの場合)

Arduino(に載ってるAVRのメモリ)には、スケッチで書いたプログラムのほかにブートローダと呼ばれる小さなプログラムが入っています。起動時には先行してブートローダが立ち上がり、その後、メインのプログラムが実行されます。
実はプログラムの書き換えの際はこのブートローダが窓口となります。なので書き込み時はこれを立ち上げるために、まず最初にIDEArduinoをリセットしようとするんですね。そのリセット処理を妨害するのがこの技です。

f:id:slideglide:20171022010008j:plain
コンデンサの容量は資料によって10uFと0.1uFの2種類ありました。10uFなんて持ってなかったので0.1uFのみ動作確認済みです。「104」と書いてあるやつです。

f:id:slideglide:20171022233505j:plainf:id:slideglide:20171022233526j:plain
刺しておくだけだと不安なので、裏側にスイッチと一緒にはんだづけしてみました。SDカードの書き込み禁止スイッチみたいで便利では。

2.5VピンとRESETの間に120Ωの抵抗を入れる(Arduino Uno以外)

狙いとしては上記と同じです。Uno以前のボードではこの方法がよく使われていたようです。抵抗値は110~124までの間であればいいとのこと。Arduino Unoでは使えないとのことですが、具体的にどのボードに対応しているかは不明です。

3.Arduino Leonardoを使う

Leonardoはちょっと特殊で、書き込み時に自分でリセットボタンを押してあげないと自動リセットせず、プログラムも書き込まれてくれません。書き込みに人の手を要求するということで、これも一種のうっかり防止としては使えるかも?
ただし「Leonardoは書き込み時にリセットボタン必須」が自然に身についている熟練者の前には無力です。

話は逸れますがLeonardoはキーボードやマウスとしてふるまうことができるので、普通のArduinoにはできない面白いことができます。

www.youtube.com
上の動画ではマウスとして動作しており、MSペイントを起動してボタンを押すと絵を描いてくれます。ツマミを回すと絵の大きさが変わります。


*慣れた人向け

ここから先はArduinoというより、Arduinoに載っているAVRマイコンの設定をいじっていきます。

4.ヒューズビットを書き換えてブートローダの起動を抑制

ヒューズビットというのはAVRの中にある設定項目みたいなものです。その中にBOOTRSTという、「起動時にブートローダを起動するか否か」の設定があり、これを1(起動しない)にします。
前項まではブートローダを起動させるためのリセット処理を妨害する方法でしたが、このようにブートローダがそもそも起動しない設定ならば、リセットされようが何されようがプログラムは書き換えられないですよね。

ヒューズビットの書き換えにはArduinoのほかにISPライターが必要です。
Arduino Uno(ATmega328P)の場合、BOOTRSTはHigh byteの0バイト目です。標準のHigh byteは0xD6なので、これを0xD7にしましょう。
手順としては、PC→ISPライター→Arduinoと接続した状態で、コマンドラインから

cd C:\Program Files (x86)\Arduino\hardware\tools\avr\bin
avrdude.exe -C "..\etc\avrdude.conf" -P COM3 -b 19200 -c avrisp -p m328p -u -U hfuse:w:0xD7:m

です(Windows環境)。avrdudeのパスやCOMポートの番号は環境に合わせて変えてください。
同じATmega328Pを使っていてもArduinoの種類によって標準のHigh byteは異なるようです。現在の値は

cd C:\Program Files (x86)\Arduino\hardware\tools\avr\bin
avrdude.exe -C "..\etc\avrdude.conf" -P %COM_PORT% -b 19200 -c avrisp -p m328p -u -U hfuse:r:-:h -U lfuse:r:-:h -U lock:r:-:h

でLow byteとLock bits含めて全部見られます。


f:id:slideglide:20171022010454j:plain
ちなみにISPライターがなくてもArduinoがもう1台あれば代用することが可能です。写真はArduino Unoをライター代わりにしてArduino Nanoのヒューズビットを書き換えているところ。やり方は以前書いたこれと同じで、生AVRに繋ぐかわりにArduinoに接続すればいいです。基板の端っこにあって「ICSP」と書かれた2×3の端子を使います(普通のD10~D13とかを使うこともできます)

Arduinoは2台あるとなにかとできることが広がるので、1台しか持っていない人はもう1台買うの結構おすすめです。

【永久保証付き】Arduino Uno

【永久保証付き】Arduino Uno

5.ブートローダを消す

さらに野蛮な方法として、ブートローダ自体を削除してしまうという手もあります。こちらもISPライターまたはもう1台のArduinoが必要です。

プログラムの入ったAVRからブートローダだけを消す方法は見当たらなかったので、作業としては

です。これをやると書き込みのタイミングで一度フラッシュメモリが初期化されるため、ブートローダはその時に消えます。

まずPC→ISPライター→Arduinoと接続した状態で、IDEの「ツール」メニュー上でボードやポート、書込装置などを選択します。もう1台のArduinoISPライターの代わりに使用する場合は、書込装置は「Arduino as ISP」を選びます。
その後「スケッチ」メニューから「書込装置を使って書き込む」を選択すると、プログラム(だけ)のアップロードが行われ、ブートローダは消えます。

ちなみに勘違いされがちですがブートローダがなくてもプログラムは普通に動きます。ただブートローダを消してしまうとそれはもはやArduinoといえず、言ってみれば「Arduinoのゾンビ」みたいな感じでちょっと不憫です。

未検証:ロックビットについて

ロックビットというのもAVRの設定項目の一つで、名前のとおり、メモリの読み書きをロックします。まさにライトプロテクトと呼ぶのにぴったりの機能に見えますが、いろいろ試してみても思い通りの結果を得られませんでした。どうもAVRライターを使った書き換えを対象としているようで、ブートローダからの書き換えには対応していないのかもしれません。


以上です。どの方法にも言えることですが、プロテクト発動時はブートローダの反応を待つ×10回くらいリトライしてからようやくエラーになるので、レスポンスが遅いです。自分がうっかりしたことに対する罰だと思えばやむなしという気持ちにもなりますが、もっと即時で「書き込みできません」的なレスポンス返してくれるいい方法はないものでしょうか。