発生した問題

 筆者はマイコン・メーカーで応用技術を担当していることから,ユーザーの方から相談を受けることがあります。実は,同じような質問を複数のユーザーの方から受けることもよくあります。お役に立つかもしれませんので,代表的なものの一つを紹介します。

 ある電子機器の開発が完了し,工場で量産が始まってすぐのことです。量産機が,スイッチを入れた直後にウンともスンとも言わなくなってしまいました。プログラムが暴走したようです。

 開発部署の方が手元にある試作機で同じ条件にしてスイッチを入れると,きちんと動きます。試作機と量産機で何が違うのかを調べましたが,ソフトウエアのバージョンや回路などは同じで,原因が分かりませんでした。このため,当方に相談に来られました。

原因と対策

 試作機と量産機の違いは,マイコン上のRAMの容量だけでした。RAM容量が大きいチップでデバッグして,RAM容量が小さいチップで量産することはよくあります。デバッグ用マイコンのRAM容量が量産に使うマイコンより大きいものしかなかった,予定よりメモリ使用量が小さくなったので容量の小さいマイコンで量産する,といったケースです。

 そこで量産機のソース・コードを調べると,原因が判明しました。初期設定のサブルーチンを呼び出す前に,スタック・ポインタを設定していなかったのです。スタック・ポインタは,サブルーチンや割り込みの戻り先番地を格納するスタック(RAM)の位置を示します。このため,サブルーチン呼び出しや割り込みより前にスタック・ポインタを設定しておかなければなりません。

 これは誰もが承知していることです。しかし,初期設定のプログラムのうち繰り返し出てくる処理をサブルーチンにして,プログラム・サイズ低減と可読性向上を図ったときに,うっかりスタック・ポインタの設定より前にサブルーチンの呼び出しを行ってしまったようです。意外と発生しやすいことですので,気を付けたいものです。

技術者必修の基本

 ところで,なぜ試作機ではきちんと動いてしまったのかを説明しましょう。まず今回のマイコンは,リセット後にスタック・ポインタの値がどうなるか分からない「不定」になるものでした(マイコンによっては,ゼロなど特定の値になるものもあります)。試作機ではマイコンのRAM容量が大きかったため,この値が偶然RAMのアドレスを示していたのです。そうなると,プログラムの手順通りにサブルーチンを実行して,元のルーチンへ戻ることになります(図4-1)。もちろんその番地のRAMのデータは壊れてしまうという問題はありますが,一見正常に動作しているように見えるのです。

 ところが量産時のマイコンではRAM容量が小さかったため,不定の値がRAMを示しませんでした(ロットの違いなどによって,不定の値が変わることもあります)。このため,プログラム・カウンタの正しい戻り先番地はどこにも格納されず,サブルーチン終了時にプログラム・カウンタには訳の分からない値が入ってしまい,暴走したのでした。

 なお,スタック・ポインタの値が周辺のI/O機能を割り当てたレジスタを示していれば,プログラム・カウンタの戻り先番地を書き込むことで,これらレジスタを書き換えてしまいます。この場合,周辺機能の動作に異常が発生しますが,これも原因不明の不具合に見える可能性があります。また,マイコンには予約領域などのアクセス禁止領域があります。スタック・ポインタの値がこれらを示していて,データを書き換えた場合に何が起こるかは分かりません。

 初期設定をしなければならないのは,RAMやカウンタ,ポートなども同様です。ハードウエアの知識がないと,これらのトラブルは解決できませんので気を付けましょう。