R8C もようやくタイマー関係の定義が出来ました。
R8C には3つのタイマーモジュールが内臓されています。
それぞれ、RC、RJ、RB です。
AVRに比べると、複雑で、機能を使うには、マニュアルの意図を理解するのに時間がかかりますが、
高機能で、AVRと両方使って思うのは、ルネサス系のタイマーの方が、細かい部分が良くできている点です。
インプットキャプチャー機能などは、ダブルバッファになっていて、正確な値を取得できますし、PWM機能は、
多くの場面を想定していて、十分な使い方が出来ます。
この中で、比較的単純な構造なのはRBです。
単純と言っても、色々な仕組みがあるのですが、とりあえず、16ビットのタイマーとして使い、周期的に割り込みをかけるのに使う事にします。
タイマークラスでは、登録した関数を割り込み内から呼び出す仕組みを設けてありますが、通常「禁止」としています。
これを「有効」にすると、ライブラリー関数の静的変数を全てスタックへ退避するコードが追加される為、注意が必要です。
※そうしないと、メイン側で、あるライブラリー関数を実行していた場合、それを、割り込み側でも呼ぶと、問題が起こります。
周期的な割り込みを使うと、プログラム全体の時間管理が単純に行えるので便利です。
これは、同期式とも言います、ゲームなどに向いた方法で、画像の表示、書き換えを同期させ、常に一定の速度で全体を動作させます。
又、シングルタスクでありながら、マルチタスク的な並列動作を行うのに便利な方式です。
※厳密な意味での「並列」ではありませんが。
組み込みでも、「同期式」は、色々な面で、都合が良い場合が多くあります。
簡易的なマルチタスク的な動作が出来ます。
一つの例として、スイッチのチャタリング除去などが上げられます。
周期的な割り込みを行い、その周期で I/O ポートの値を読み込む事で、デジタルフィルター的な効果が付加され、結果的にチャタリングを除去
します。
この周期はスイッチの機械的特性によりますが、60Hz~100Hzくらいが適当です。
※スクリーンのリフレッシュレートが60Hzなので、その値が使われます。
当然ながら、1秒に60回以上のOn/Offを検出出来なくなりますが、通常は問題ありません。
また、個々の処理を時分割で動作するように実装して、それを周期的に呼び出す事で、並列動作が実現出来ます。
通常は、カーネルがタイムスライスを行い各スレッドを管理しますが、小さなシステムでは、マルチスレッドは複雑になりすぎる場合があり、
「同期式」でも十分な場合があります。
ゲームを作っている人には、常識的な実装ですが、初めて触れる人には新鮮で、判り難いかもしれませんが、馴れておくと良いと思います。
今まで、複雑で、難解な実装が、シンプルに出来る場合があり、モジュール的に他の処理と分離する事ができます。
ここで、今までに実装したR8C関係クラスなどをまとめておきます。
M120AN/ m120an.ld ---> リンカースクリプト system.hpp ---> システム制御 clock.hpp ---> クロック発生回路 port.hpp ---> I/O ポート intr.hpp ---> 割り込み uart.hpp ---> シリアルインターフェース timer_rb.hpp ---> タイマRB timer_rc.hpp ---> タイマRC timer_rj.hpp ---> タイマRJ
I/O制御関係では、以下のファイルがあります。
common/ start.s ---> R8C起動アセンブラソース vect.[hc] ---> 割り込み、割り込みベクター関連 init.c ---> 初期化関連 io_utils.hpp ---> レジスター定義ユーティリティーテンプレート uart_io.hpp ---> シリアルインターフェース制御クラス trb_io.[hc]pp ---> タイマRB制御クラス
各デバイス毎にテストしたプロジェクトがあります。
R8C/ L_chika ---> 基本の基本LED点滅(最小限の実装) UART_test ---> シリアルインターフェースのテスト(ポーリング、割り込み) TIMER_test ---> タイマーRBのテスト(ポーリング、割り込み)
これからも、随時追加していく予定です。