プログラムの階層

またはシステム(systemIO)とユーティリティ(utility)

main.c, systemIO.c, R8C15.cの関係は、上図のようになっています。main.cは、systemIO.cの関数のみ使っています。そして、R8C15.cはsystemIO.cからのみアクセスされます。

当然、R8C15.cをアクセスする必要もない関数(たとえば、バイナリーHEXコード変換等)もあります。これらは、utility.cにまとめる事にしましょう。utility.cも含めると下図のようになります。

さて、systemIO.cですが、前述のようにR8C15.cとmain.cの橋渡しをしていますから、当然、マイコンの機能に関する関数がほとんどです。また、このマイコンシステム用のワークメモリもここで定義しています。もちろん、このワークメモリは、main.cで定義する方法もあります。それでも、数が少なければ、見通しは、それほど悪くないと思います。

しかし、main.cでは、関数を通してそれらにアクセスする方法にしておけば、メインルーチンのアルゴリズムにのみ集中できます。(system.cの中身にとらわれないで済む)もちろん、使う関数の仕様はしっかりと定義しておく必要はあります。そうすることで前々回も書いたように、階層ごとに人を割り当てるということが容易になります。

「main.cでSYS_TIMEとINT_FLAGを直接使っているじゃないか」と、疑問に思われる方もいらっしゃるでしょう。その通りです。これらも、関数を使ってアクセスした方が良いのです。例えば、

void systime_init(void) { SYS_TIME = 0; } void systime_inc(void) { SYS_TIME++; } unsigned long systime_get(void) { return SYS_TIME; }

という風に、systemIO.cに定義して、main.cのそれに相当する部分を書き換えれば、mainc.cから、内部変数を隠蔽できます。INT_FLAGも、設定関数と取得関数を用意すれば同じです。

では、何故、そうしなかったのか?その理由は2つあります。

一つは、割り込み処理の中で関数を使うのを避けたかったのです。それば、関数を使うことによるオーバーヘッド(遅れ時間とRAMの消費)をなるべく小さいしたいという思惑です。RAMが1Kバイトもあれば、そんなことも気にしなくても良いかもしれません。それでも、たかだか1Kバイトです。

C言語で書いていれば、気を許せば、あっという間に消費してしまいます。

もう一つは、関数を使ってアクセスするのと直接アクセスする方法を同時に紹介したかったからです。「どちらかにしなければならない」のではなく、どちらを使うべきかは、見通しの良さと、オーバーヘッドの兼ね合いでシステムごとに判断する必要があるという事を意識してほしいからです。

では、サンプルプログラムの中身を解説していきましょう。前回も言いましたが、短いプログラムですし、コメントも書いてありますが、一応、解説します。

先ずは、割り込み関数設定から

extern void (*tx_func)(void); void set_t1_func(void p_func(void) ){ tx_func = p_func; }

extern部分は、本来はR8C15.h辺りに置いておくべきでしょう。ここでは、見易さを考えて直前に置きました。main.cからの渡し方と同様に関数ポインタを使ってR8C15.cに渡しています。関数ポインタの使い方は、C言語の解説書やHPがたくさんありますから、そちらを参照して下さい。ポイントは、型の一致を完全に同じにしておかなければならないということです。安易なキャストは、致命的エラーの元です。

その他の各機能設定関数では、一部(UARTのボーレート等)を変数として渡して設定しています。本来であれば、使える機能は、全て変数として渡せるようにしておいた方が、使いやすくなります。しかし、変数が多ければ、それだけ間違いも多くなります。デバックすれば良いと思いがちですが、つまらない間違いほど、見つけにくいものです。ここは、間違いが少なくなる方法を取っておいたほうが無難です。かといって、必要な機能まで絞っては本末転倒です。

main.cからsystemIO.cへのアクセスには、必要なパラメータだけにして、systemIO.cからR8C15.cのアクセスには、全ての機能を実装するというのが良いやり方でしょう。

とは言っても、使わない機能まで設定する必要はありません。

最初にシステムを考えた時、どの程度まで実装すべきかを検討しておくべきでしょう。つまり、何が必要な機能なのかをしっかりとつかんでおく必要があります。

また、後で別なシステムで機能が必要になった時は、今までの関数を書き直すより、それ専用に新たな関数を用意した方が良い場合もあります。

ケース・バイ・ケースでシステムの最適化を考えましょう。

そういう意味で、システムの設計書(最低限、システムの機能、使用マイコン、PIN配置と割り当て等)とマイコンの機能一覧(R8C.xls)を用意しておくと考え易くなります。

次回は、R8C15.cの説明をします。