ATSAMD21のタイマ・カウンタ機能、インプット・キャプチャとか周波数計測などに触ってみるために、今回からイベントというものを調べていきたいと思います。いつも泥縄、ソースを書きながらデータシートを眺めているので、今回は先にデータシートを読んでみた編。でも端子からタイマ・カウンタまでのイベントの経路の長さ。。。
※「AT SAMの部屋」 投稿順indexはこちら
割り込みとイベント
通常、周辺回路で「何かが完了」したお知らせは割り込みでCPUに通知するのが普通です。CPUは「割り込まれる」と実行中のプログラムを一端中断し、後で再開できるように準備してから、割り込みハンドラを起動、その中でお知らせに対処する処理を行います。そして処理が終われば元のプログラムを再開します。
上記の割り込みのシーケンスを考えると以下のような欠点があることも直ぐに想像できます。
-
- 割り込みハンドラが起動するまでに結構処理時間がかかるので対処のタイミングが遅れる。
- CPUの処理時間を使ってしまう。頻繁に割り込むと割り込み処理のオーバヘッド時間も馬鹿にならない。
- 割り込みに対処できるCPUが一つの場合、多種の割り込みに同時に対処できない。順番待ちが発生する。
- 割り込み不可のクリティカルな区間では割り込み対処が遅れる。
しかしモダンなATSAMD21マイコン様にはイベント処理機構が備わっているのです。簡単に言ってしまえば
ある周辺回路で何かイベント(処理の完了など)が起こったら、CPUが介在することなく別な周辺回路にイベント発生を通知し対処させる
機能です。古典的なマイコンシステムでもDMAC(ダイレクト・メモリ・アクセス・コントローラ)などはこのような動作ができましたが、ATSAMD21がモダンなのはEVSYSというペリフェラルの存在によって、DMACに限らず多種の周辺回路間で多様なイベントの受け渡しが可能になっていることです。イベントの効用をあげるならば以下のようでしょうか。
-
- CPU時間を使うのはイベントの設定時のみ。
- 実際のイベントの発生時にはCPUを使わず、ハードウエアが勝手に動作する。
- ハードウエアによる伝達なので速い。必要なクロック同期なども設定可能。
- ハードウエアによる処理なので、複数のイベントが同時に発生しても「チャネル」が別なイベントならば同時に処理できる
勿論、割り込みを全て置き換えるわけでなく、多くの場合「コマケー処理」はイベントに任せてしまって、その一連の処理が終わったらばCPUに割り込みをかけて〆をお願いする、という使い方になるのではないかと思います。うまく使えばCPUの負荷が減るだけでなく、素早い対応が可能となると。
EVSYSというもの
ザックリ言ってしまえば、EVSYSはイベント処理の司令塔であります。多種のペリフェラルから上がってくるイベントを、これまた多種のペリフェラルに伝えないとならないです。「電話交換機かルーターか」のお役目をするのがEVSYSです。機能的には一度経路設定するとその経路を継続的に維持するので電話交換機的な動作です。ルータじゃありません。
-
- イベントチャネルは12個。このチャネル数までのイベントを同時並行に処理できる。
- イベントジェネレータは74個。イベントを発生できるソースの個数。
- イベントユーザは29個。イベントの通知を受けるデスティネーションの個数。
つまり12個のチャネルのどこかにジェネレータとユーザを紐づけてイネーブルにしてやればイベントが通るようになる、という仕組みです。
タイマ・カウンタにおけるイベント
タイマ・カウンタ(TCCまたはTC)は、イベントジェネレータにも、イベントユーザにもなることができます。例えばカウンタがオーバフローしたらイベントを発生させる、というのはジェネレータとしての動作です。また、後で使用してみるつもりのイベントが到来したらカウンタの値をキャプチャして保存するというのはイベントユーザとしての動作となります。
第14回でTCC1を使ってPWM出力してみました。ATSAMD21のタイマ・カウンタの「チャネル」にはそれぞれ出力端子のアサインがありました。しかし、入力端子のアサインはありません。これは、多分、EVSYSからイベントの配給を受ければほとんどの外部端子を「入力端子」とみなせるためだと思います。それどころか、外部端子でない他の周辺回路の発生するイベントを入力として使うことも可能です。カッコイイです。
ただカッコイイだけに通過経路の設定が複雑デス。冒頭のアイキャッチ画像に掲げましたが、その経路を「単純に」描いたものが以下です。
やりたいことは、左上のPINと書いてある外部端子の状態が変わったとき(立ち上がりエッジとか立下りエッジ)で、右下で「フリーラン」しているCOUNT部分の値をCC0/CC1のカウンタ・キャプチャレジスタに取り込みたい、というだけのことです。
立ち上がりから次の立ち上がり間のカウント数が分かれば入力信号の周期(つまり周波数)が分かるし、立ち上がりから立下り間を測ればパルス幅も分かります(勿論カウンタの周波数は決めておかないとダメですが。)
しかし、PINからそこにいたる経路は上手の黄緑色の各部を通過してくるのでこいつらに適切に設定しなければなりません。メンドクセー。
Xiaoボードの端子とイベント
極小の開発ボードであるXiaoボードの場合、使用できる端子はごく一部に限られます。例によって、以下の表にXiaoボードの端子名と、ATSAMD21G18マイコンチップでのPIN名、そしてそのポートからEIC(割り込み制御用のペリフェラル)へ接続される場合の内部信号を示しました。Func AはそのときポートのPMUXに設定しないといけない値です。
ここでEICが出てくるのは、外部端子からの割り込みとイベントはPortレベルでは同じ経路を通っているためです。次段のEICへいたり、割り込みにするのかイベントにするのか、それともスリープからのお目覚めに使うのかがようやく決定される、と。
Xiao端子名 | ATSAMD21G18 pin名 | Func A |
---|---|---|
D0 | PA02 | — |
D1 | PA04 | EXTINT[2] |
D2 | PA10 | EXTINT[10] |
D3 | PA11 | EXTINT[11] |
D4 | PA08 | NMI |
D5 | PA09 | EXTINT[9] |
D6 | PB08 | EXTINT[8] |
D7 | PB09 | EXTINT[9] |
D8 | PA07 | EXTINT[7] |
D9 | PA05 | EXTINT[5] |
D10 | PA06 | EXTINT[6] |
手元のXiaoボードでは、D1端子を使って波形を入力してみようと思うので、EXTINT[2]をEICに伝達し、そしてEVENTとして扱うように設定するところからですかね。先は長いな。今回はGoのコードまで行き着きませんでした。