何度も言うぞ! Arduino(8bitマイコン)の割り込みには気をつけろ!
過去、何度も言ってます。
8bitマイコンの割り込み処理で多バイトデータを扱う時は
「アトミック操作」を!
※1バイトのデータならokということではなく、
マイコンがどんな動きをするのかを想像して
(マイコンになりきって)手順を考えなくてはなり
ません。
割り込み処理なら別の動きを考えるためにもう
一つ頭がいるかも。
今月のトランジスタ技術2022年11月号。
この「倒立振子 立つ」(著者:藤森 嵩人さん) の記事でも
手を抜かれて(cli、seiしていない)ます。
p.188~p.189のリスト。
「volatile」が頭に付いた変数に注目。
割り込みで読み書き。
メインループでも読み書き。
メイン側で「読む」だけでなく、処理したデータを
「書いて」それを割り込み内で使っています。
元はintのエンコーダ入力値。
それを加工してあれこれのfloatデータに。
モータ制御はMstimer2で駆動される1ms周期の
タイマー割り込み内。
面倒でも、メイン側 ←→ 割り込み処理 を受け渡しする
データは「割り込み禁止・割り込み許可」を挟まなくては
なりません。
処理全体を割り込み禁止にするのではなく、受け渡しの
データだけで良いのです。
cli、sei命令の動作は最短の1クロック。
やりとりのための余分なデータ領域が増えますが、
実行時間が遅くなることはありません。
計算には一時的なデータを使って、それを本番データに
コピーするだけ。 その時、割り込み禁止で。
読み出すときも、割り込み禁止で本番データを一時データ
にコピー。
ただ、それだけ。
何度も言います。
起きる可能性があるなら、いつかはアタリます。
それがバグというものです。
最初からちゃんと考えておかないと、
「忘れた頃におかしくなる」が発生します。
※この件、トラ技編集部に伝えています。
※公開されているダウンロードサービスでは
本誌に掲載されたのとは異なったスケッチ
(ちょっと手直し)が出てきます。
しかし、まだ不完全です。
面倒がらずに「cli、sei」の手順をお願い
したいところです。
「とりあえず動いているから」とか
「ちょっとした実験だから」という性質のもの
ではありません。
ネットに上がっているミス含有スケッチ、
「初心者だから許される」は言語道断。
※新たに「割り込み処理」というカテゴリを設けました。
これで、過去記事を追跡してもらえるかと。
ターゲットに「8bitマイコンを選んでしまった・・・」と
いうのが、今回のスカタンの根本原因じゃないでしょか。
32bitマイコンなら、現プログラムのままでOKかと思うのです。
電源やらエンコーダ入力割り込み処理の手軽さから
Arduino nanoを選ばれたんじゃないかと推測します・・・
8bitマイコンを使いこなすにはそれなりの覚悟が必須という
ことで・・・
「どれだけ痛い目にあったか」の経験値がスカタン・バグの
予防になるのかと。
簡単なワクチンはありません。
自分で痛い目にあって「抗体」を作るしか、バグから逃れる術は
ありません。
| 固定リンク
「割り込み処理」カテゴリの記事
- 最適化処理のせいで悩んだぞ 呪文volatile再び(2024.06.06)
- I2C液晶のアクセス、割り込みで処理しないようにすると(2024.04.12)
- I2C液晶のアクセス、割り込み処理で遅れる原因らしきもの(2024.04.07)
- 超低速2相パルス発生回路・ケース入れ(2024.04.03)
- 超低速2相パルス発生回路(2024.03.25)
コメント
大昔、開発中には出会わなかったけど、量産前の試作評価中に出ちゃいました><
大慌てでDI/EI追加して対処^^;
投稿: kaz | 2022年10月11日 (火) 10時07分
DI/EI というと・・・8080、8085、Z80あたり?
投稿: 居酒屋ガレージ店主(JH3DBO) | 2022年10月11日 (火) 10時20分
可能性があるならいつかはスカタン発生。
まさにそれっ ということですな!
8bitマイコンだけの注意点じゃなく、32bitマイコンでも、プログラムの組み立て方によりスカタンの可能性が出てきますんで。
投稿: 居酒屋ガレージ店主(JH3DBO) | 2022年10月11日 (火) 10時24分
はい、Z80系でした。
他にも似たような件で、割り込みで受け取るバッファをメインが都度参照してバグ作りました。
メイン側で一度コピーして保持しなければいけないやつです。
投稿: kaz | 2022年10月12日 (水) 09時45分
トラ技だからいいんじゃないですか?
そこまで細かく上質なコードを安い原稿料じゃ割に合わないと思いますよ。基本原理があっていればいいんじゃないですか? マイクロチップやSTのサンプルコードも酷いものみたいですし、それらがちゃんとしてしまうとちゃんと作って正当なお金取ってる人が困ると思います。
投稿: ochiai | 2022年10月16日 (日) 18時29分
割り込み処理してるデータとのやりとり、
割込禁止・割込有効を入れるのってそんな
面倒じゃないでしょ。
アセンブラでゴソゴソしていた時代から、
あたりまえの記述。
割込禁止・再開を記述すると、
『大事なデータのやりとりをしてるんだぞ』っと
いう意識も生まれるでしょう。
ただ・・・ Arduinoの場合
noInterrrupts();
interrupts();
という関数の名前が長い!。
AVRマイコンに限れば、cli();、sei();っと
アセンブラのニーモニックでokなんだから、
面倒がらずに・・・
思えば、8080やZ80の「DI / EI」は短くって
良かった。
8086になると「CLI / STI」。
「同じにしとけよ」っと。
投稿: 居酒屋ガレージ店主(JH3DBO) | 2022年10月18日 (火) 08時40分