RL78/G13、G14の割込み処理設計

RL78/G1xの割込みは、様々なアプリに対応できるように設計されています。しかし、そのハード構成などから、最も適した使い方があります。ここでは、その使い方を解説します。

割込み処理は、マイコン開発にとって重要ポイントです。しかし、機種特定の解説書は、見あたりません。RL78/G1xのアプリケーション・ノートにも、2013年8月時点では無いようです。あまりにも当然の事として、ルネサスは、解説不要と考えているのかもしれません。

そこで、ハード構成やレジスタ・バンク個数などから、素直な、おそらく最もスジが良い割込み処理の設定について考察します。開発当初から、この設定でソフト開発していれば、後々のトラブル回避にも都合が良いと思います。

結論を示します。ハード構成から、多重割込み処理の最適なパラメタ設定は下図です。赤字は、デフォルト以外の設定値を示します。

最適な割込み処理パラメタ設定
最適な割込み処理パラメタ設定

割込み優先レベルとデフォルト・プライオリティ

マスカブル割込みには、各割込み要因に対して0から53までの、「デフォルト・プライオリティの割込み順位がハードで設定済み」で、0が最高位、53が最低位です。これとは別に、「プログラマが設定可能な割込みの順位が、優先レベル0/1/2/3」です。レベル0が最高、レベル3が最低ですが、CubeSuite+のコード生成ツールでは、レベル0を高、レベル3を低、レベル1/2はそのまま表記します。

デフォルト・プライオリティは、複数の割込み要因が、同じ割込み優先レベルで発生した場合に、優先する順番のことで、通信関連の要因は高く、次がAD、タイマ関連が低いなど、マイコン機種に依存せず大体同じ順番です。一方、割込み優先レベルは、CubeSuite+のコード生成ツールで、「低にデフォルト設定」されています。何も考えずに、コード生成すると、「割込み処理は、全てレベル3に設定」されます。割込み優先レベル、次にデフォルト・プライオリティの順番で優先判定しますので、結局、デフォルト・プライオリティ順位がそのまま割込み受付順位となります。

多重割込み

割込み処理中に、より高い優先レベルの割込みを受け付けるか否かを決めます。デフォルトは、「多重割込み禁止」なので、割込み処理内でEI();により明示的に許可が必要です。最高レベルのレベル0でも許可は可能ですが、レジスタ・バンクが4個のため、避けるのが得策です。

レジスタ・バンク

RL78/G1xの汎用レジスタ格納場所がレジスタ・バンクで、RB0/1/2/3の4個あります。スタートアップで「RB0がデフォルト設定」されており、通常プログラムは、RB0を、割込みプログラムが、残り3個のRB1/2/3を使えます。割込みプログラムでの、レジスタ・バンクの使い方は任意です。コード生成出力は、「全ての割込みプログラムのレジスタ・バンクをデフォルトのRB0に設定」します。

このように、割込み処理のパラメタデフォルト設定値は、全処理で割込み優先レベル3、多重割込み禁止、RB0のみ使用となります。この設定では、本来のハード実力を活かした割込み処理はできません。

割込み優先レベル、多重割込み、レジスタ・バンク、それぞれがともに4個の選択肢があることには、関連があり、最大で4レベルの多重割込みを処理できることを示しています。但し、その最高レベルの0だけは特別で、通常の割込み処理には、レベル3~1を使うのがハード構成に適した使い方です。

レベル0は、最低限の処理を実行後、リセットするような特別な割込み処理用で、例えば、電圧低下を検出して、低下直前の動作状態を保持する用途などが考えられます。従って、専用レジスタ・バンクも不要ですし、多重割込みもなしです。処理後は、リセットするからです。万一、EI();で多重許可した場合には、割込み処理中に、受付けた割込みを再受付するようなトラブルに見舞われます。このトラブルは、結構ありがちです。最優先レベル0の多重割込み処理は、避けるべきです。

割込み優先レベル3~1は、多重割込みを許可し、専用レジスタ・バンクを設定しさえすれば、簡単に、しかも高速に3レベルの多重割込み処理が可能です。スタックを使っても同じ事ができますが、レジスタ・バンクの方が高速ですし、その分スタック節約にもなります。3レベルの処理なら、割込みレベルの割当ても容易です。最高優先処理をレベル1、最低優先処理をレベル3に割付け、それ以外は、レベル2に割付けても問題が発生したことは経験上ありません

まとめ

割込み処理のトラブルは、処理ソフトのバグ以外にも、優先順位に起因するものもあり、難しいデバッグになりがちです。ソフト設計当初に、ここで示したハード構成に適した多重割込みパラメタを設定することがトラブル回避に役立ちます。

テンプレート使用法(2):分析とテンプレート組込み

第2回は、LCDアプリ分析とテンプレートへの追加方法の説明です。

ドライバとアプリ分離:先ず、LCD制御ソフトを、ドライバ処理とアプリケーション処理(以後アプリ処理と略す)に分けて考えます。ドライバ処理とは、制御対象がLCDコントローラのソフトです。アプリ処理は、ドライバ処理を使ってLCDに出力する文字列を設定するソフトのことです。

LCDドライバ処理:LCD表示を行うには、マイコンピン初期設定、LCDコントローラのパワーオン処理、LCDコントローラ初期設定、LCD表示データ書込みの4種の処理が必要です。そこで、各処理をそれぞれ関数化し、条件によりこの4ドライバ関数に分岐します。これらのドライバ処理をテンプレートへ組込むと、下図(左側)のようになります。

LCDアプリ処理:ドライバ処理で準備が完了したLCDコントローラに対して、LCDで表示する文字列を設定する関数です。コンローラ準備完了判断や、通常表示と、エラーを表示する場合などの条件で分離することを考慮すると、下図(右側)のようになります。

ポータル関数の構成
ポータル関数の構成

ドライバ処理もアプリ処理も、テンプレートへ組み込む形は同じです。ポータル関数でインタフェースRAMの値によって条件分離し、各イベント処理を実行します。各イベント処理後にインタフェースRAM値を変更し、次回の条件分岐に備えます。

インタフェースRAM:関数間の変数をRAMに展開したものをインタフェースRAMと呼びます。RL78/G13やG14には、アクセス頻度が高い変数は、ショート・ダイレクト・アドレッシングsreg領域(FFE20~FFEB3 の147バイト)へ配置すると高速化が図れます。引数で記述する場合に比べ、関数単体デバックが簡単になるメリットがあります。

処理が遅い周辺回路の対処:最近のマイコンは高速動作です。しかし、LCDコントローラなどの周辺回路は、マイコン動作に比べ、とても遅いという問題があります。この遅さに対して、マイコンのポーリングや割込みを使う方法で解決できます。しかし、今回のLCD接続は、リード動作ができないので、これらは使えません。第2の方法は、周辺回路動作完了まで、マイコン側の処理に待ち時間を入れる方法です。サンプルプログラムなどでは、この方法を多く用います。マイコン処理は簡単ですが、無駄に時間を消費しますので、高速マイコンに効果的な方法とは言えません。

第3の方法が、タイムシェアリングを使う方法です。周辺回路の動作を設定した後は、マイコンに別処理を行わせ、周辺回路の処理が完了したころを見計らってさらに追加処理をする方法です。第2の方法より、効率的にマイコンを使えますが、処理完了のころあいを見積もることが大切です。見積もりが上手くいけば、多重処理ができるので、高速マイコンの特長を活かせたソフトができます。リアルタイムOSも、簡単に言うとこの方法を使っています。プログラマの処理完了の見極めが不要で、タスク切換えをOSが行ってくれます。が、それなりの大容量RAMが必要で、4MB程度のRAMでは足りませんし、使いこなしの知識や経験も必要です。また、無料OSもありますが、有料版はコストアップになります。

タイムシェア間隔固定:提供テンプレートは、タイムシェアリング間隔が、予め決まっています。ドライバ処理起動用に、250ms/1ms/10ms/100ms/1s、アプリ処理起動用には、1ms/10ms/100ms/1sです。つまり、この間隔で、遅い周辺回路の処理完了を見積もって、割り振れば良い訳です。間隔が決まっていますので、リアルタイムOSよりは効率が下がりますが、オーバーヘッドは少なくなります。

LCDコントローラの場合は、パワーオン処理に5ms、表示クリアに1.64ms、その他の処理に40us(いずれも最大値)が必要です。そこで、ドライバ処理のポータル関数は10ms間隔、アプリ処理のポータル関数は1s間隔に割り振りました。40usの処理待ちは、タイムシェアリングせずに、時間消費で対応しました。テンプレートに組込んだドライバポータル関数を下図に示します。

テンプレートへ組込んだドライバポータル関数
テンプレートへ組込んだドライバポータル関数

リアルタイムOSに比べれば効率が低下しますが、テンプレートは、少ないRAM使用量で、高速マイコンの特徴を活かした多重処理を、簡単に実現できることが判ると思います。