私が組込みC言語の関数を説明する際に関数を分類して説明しています。この投稿では、その関数分類について説明いたします。
関数の分類は、次のように関数と割込み関数、マクロ関数の大別します。
関数
C言語の関数は、特定の処理をまとめて定義し、必要に応じて呼び出せる構造です。関数は、関数コール時と関数リターン時に次の処理を行います。
関数コール時、汎用レジスタの値およびプログラムカウンタ(PC)の値をスタックに退避させ、関数の引数を汎用レジスタまたはスタックを使って渡します。その後、プログラムカウンタを関数の先頭アドレスに書き換え、関数の実行が開始されます。
関数リターン時、スタックに退避していた汎用レジスタの値を元に戻し、関数の戻り値を汎用レジスタまたはスタックから取得して呼び出し元に返します。その後、プログラムカウンタをスタックから取得した元の値に書き換えて、関数コール前のプログラム位置に戻ります。
退避する汎用レジスタは、デフォルトで決まっていますが、コンパイラの設定で変更できるものもあります。
関数の分類
私は、関数をコンポーネント関数と機能グループ関数、ユニット関数、ライブラリ関数に分類しています。
コンポーネント関数
コンポーネント関数は、レイヤごとに区切られた機能単位の関数です。コンポーネント関数は、機能を機能グループ関数に分け、さらにその機能グループ関数を単一機能に細分化したユニット関数で構成されます。また、コンポーネント関数は、ソフトウェア・アーキテクチャの構成する単位としても用います。尚、コンポーネント関数の分類方法については別に説明します。
コンポーネント関数は、次の品質特性の向上を目的としています。
品質特性 | 効果 |
---|---|
保守性 | 変更や修正の影響を局所化し、管理しやすくする |
再利用性 | 別のシステムやソフトウェアで再利用できる |
モジュール性 | 開発分担を容易にする |
変更容易性 | 影響範囲を限定し、仕様変更に容易にする |
機能グループ関数
機能グループ関数は、コンポーネント関数の機能を細分化し、その細分化したユニット関数群をまとめた関数です。
ユニット関数
ユニット関数は、機能グループ関数の機能を単一機能に絞り込んだ関数です。
ライブラリ関数
ライブラリ関数は、利用頻度の高い処理をライブラリとして共通利用できるようにした関数です。尚、RTOSで用いるライブラリ関数は、原則として静的変数などの共有資源への書込みを用いません。共有資源への書込みを用いる場合は、排他制御(割込み禁止など)の処理を行う必要があります。
割込み関数(コールバック関数)
割込み関数は、割込み要因が発生した際にベクタテーブル等からコールされる関数です。割込み関数は、普通の関数コールや関数リターン時の処理より汎用レジスタ等の退避数が多くなるので、プロトタイプ宣言などを行います。プロトタイプ宣言は、マイコンやコンパイラに依存するので注意してください。
コールバック関数は、割込み関数同様にベクタテーブルからコールされる場合とOS等からコールされる場合があります。
マクロ関数(#defineマクロ)
マクロ関数(#defineマクロ)は、プリプロセッサによってコード内の特定の文字列を別の文字列に置き換え、置き換えられたコードが関数のように動作する仕組みです。
RTOSでの共有資源へのアクセス注意
割込み関数やコールバック関数が共有資源へのアクセスを行う場合、優先順位が低い他の処理が同じ資源にアクセスする可能性があるため、優先順位が低い他の処理に排他制御(ミューテックスやセマフォなど)を行う必要があります。