GoにいればGoに従え(41) ラズパイPico、ArmのSystick使えるの?

Joseph Halfmoon

前回は周辺装置の割り込みの「元締め」NVICの動作状況を見てみました。しかしNVICを経由しないArmコア固有の例外、システム割り込みの中にSysTickというものも含まれているのです。プロセッサクロックで動作している高速なタイマです。今回はこいつが使えるのか否かを確かめてみます。

※「GoにいればGoに従え」Go関連記事の総Index

※実機動作確認は Arm Cortex-M0+コアのRP2040チップ搭載、Raspberry Pi Pico機にTinyGoのオブジェクトを書き込んで行っています。ビルドはWindows11上です。

※RP2040のデータシート(PDF)はこちら

SysTick

Arm社のCortex-M0plusのデータシートを見ると、SysTickについては optional となっています。しかしほとんどの組み込みArmコアが備えているように思われます(個人の感想デス。)

NVICにぶら下がっているタイマなどはユーザ回路という位置づけでユーザ独自の回路が実装されている筈ですが、SysTickタイマに関してはArm社が仕様を決めているArmコア固有のハードウエアとなります。だいたいのところは以下の如し。

    1. 24ビットのカウンタ
    2. プロセッサクロックでカウントできる(高速)
    3. 用途としてはRTOSなどのシステム「Tick」が想定されている

3の目的としては100Hz(10msインターバル)のタイマTickが得られるように配慮されているみたいです。また2の特徴から極めてレゾリューションの細かい時間間隔を読み取ることも可能。

TinyGo言語でのSysTickタイマの利用

Arm系コアにほぼほぼ共通のハードウエアとはいいつつ、TinyGoが使える全てのコアで動作するわけではないので、その使用は標準のお作法というわけではないみたいです。しかし、tinygoのインストールフォルダ内のexamplesの中にはsystickを使った例題プログラムが存在します。以下はgithub内のファイルへのリンクです。

https://github.com/tinygo-org/tinygo/blob/release/src/examples/systick/systick.go

Systickでどのくらい高速に制御可能か?

上記のひな形はLチカするもので、人間の目で確認可能な遅い周波数です。そこで上記のソースを勝手改変し、どのくらいの速度まで対応できるもんだか実験してみました。実験に使ったTinyGoソースは以下です。systickExample

GPIO10番端子にオシロを接続して波形を確認しています。トグルなので設定した周波数の半分の周期の信号が出てくるハズ。

    • 最初は1kHz(1msインターバル)

Systick1kHz

1kHz事にSystick割り込みをかけるとその半分の500Hzが観測できました。正確。いい感じ。

    • 100kHzでどうよ(10μsインターバル)

Systick100kHz

100kHzでもまだまだ正確、大丈夫そうです。やったね。何が?

    • 1MHzでは??

Systick1MHz

流石に1MHzの頻度で割り込みかけると処理が間に合わなくなるようです。

Systickタイマの使用状況確認

上記の「速度試験」とは両立しないのですが、以下の関数を適宜仕込んで、Systickタイマの使用状況を確認してみました。

func printSYST_CSR() {
    systCSRcountF := rp.PPB.GetSYST_CSR_COUNTFLAG()
    systCSRclksource := rp.PPB.GetSYST_CSR_CLKSOURCE()
    systCSRtickint := rp.PPB.GetSYST_CSR_TICKINT()
    systCSRenable := rp.PPB.GetSYST_CSR_ENABLE()
    fmt.Printf("Does SYSTICK counted?:  %d\n", systCSRcountF)
    fmt.Printf("Dose SYSTICK use processor clock?:  %d\n", systCSRclksource)
    fmt.Printf("TICKINT:   %d\n", systCSRtickint)
    fmt.Printf("ENABLE:    %d\n", systCSRenable)
}

上記関数を走らせるとSystickタイマの状況が判明します。ちょろっと調べたようだと以下のようかと。

    • Goroutineとかtime.Sleepとか使用してもSystickタイマがイネーブルになることはない(そういう共通機能で勝手に使われることは無い?多分。)
    • arm.SetupSystemTimer()で初期化すると動作する

サンプルプログラムに仕込んでSystickタイマが動いているときの上記の出力をモニタしたものが以下に。SystickEnabled

 

結構ユーザプログラムで使えそう?Armの場合だけだけれども。

しかし1点注意点が。野放図に割り込みハンドラ内でいろいろやってしまうとホレこのような。panic

 

 

割り込みハンドラのどこをどう書いても良いものか分かっていないので、とりあえずExampleコードのお作法の範囲で書くのがよろしいようです。TinyGoでの割り込みハンドラの書き方を勉強する?メンドそうだが。。。

GoにいればGoに従え(40) ラズパイPicoの割り込みを探る、その1、イネーブルなのは誰? へ戻る

GoにいればGoに従え(42) ラズパイPico、SSD1315接続、OLEDで表示 へ進む