前回ADCをサンプリングするのにタイマ4を使ってしまいましたが「誰もタイマ4を使っていないの?」という疑問を調べもせずの見切り発車でした。今回は、STM32マイコン専用のstmモジュールを使って、タイマが動いているか否かを判定できるようにしたいと思います。それにしてもSTM32、タイマ充実してます。
※「MicroPython的午睡」投稿順 Indexはこちら
STM32F401RE搭載のタイマ
まず、STM32F401REというマイコンに何本のタイマやタイマ類似のハードウエアが搭載されているのか以下の表にまとめてみました。分類すると4種類で合計12本です。
-
- TIMxという名の汎用タイマ群。TIM1だけはAdvanced Control Timerと呼ばれているが基本は他のTIMと同様。合計8本。
- watchdog(番犬)タイマ2本。
- SysTickタイマ1本。
- RTC(実時間時計)1本。
Name | Type | counter | clk |
---|---|---|---|
TIM1 | Adv. cont. | 16bit | APB2 |
TIM2 | Gen. purpose | 32bit | APB1 |
TIM3 | Gen. purpose | 16bit | APB1 |
TIM4 | Gen. purpose | 16bit | APB1 |
TIM5 | Gen. purpose | 32bit | APB1 |
TIM9 | Gen. purpose | 16bit | APB2 |
TIM10 | Gen. purpose | 16bit | APB2 |
TIM11 | Gen. purpose | 16bit | APB2 |
Independent watchdog | watchdog | 12bit | 32kHz Int.RC |
Windows watchdog | watchdog | 7bit | APB1 |
SysTick | SysTick | 24bit | HCLK/8 or HCLK |
RTC | RTC | RTC | Int/Ext OSC. |
TIMxのxに入る番号が飛んでますが、これはSTM32シリーズ内で番号と機能に一貫性を持たせているためだと思われます。他機種へ行ってもTIM4はTIM4のつもりで使えるのは良いです。他機種でTIM6使っていてもSTM32F401REではTIM6とまったく同じものは無い、ということも分かります。
Watchdogは2本もあります。Independent watchdogと呼ばれている方は、クロックをみるとわかりますが、内蔵の32kHz RC オシレータで動作している番犬のようです。他の信号源とはまったく無関係かつ内蔵発信器なので「最後の砦」として異常事態に備える目的用だと思います。一方、Windows watchdogの方は7ビット(ただし長周期のプリスケーラが付属)で、APBバスのペリフェラルクロック1で動作しているので、通常の異常などはこちらで検出させるものと思われます。
SysTickは、Armコアに付属のタイマです。RTOSが使用したりする高速クロックのタイマです。MicroPythonの内部でもシステムの動作のために使われているかもしれません。
最後のRTCは実時間時計です。ハードウエア・カレンダも搭載しているみたい。32kHzのオシレータでも駆動できますが、1MHzの高速クロックも使えるようです。なかなか高級。
MicroPythonのTimerモジュールで使用可能なのはTIMxの汎用タイマ群のどれかだと思われます。
タイマの使用状況の確認ソース
使用されているタイマにはクロックが供給されている筈なので、RCC(ResetとClockをControlするユニット)内の以下のレジスタを観察すれば、タイマの使用状況がわかると思われます。
-
- RCC_CFGR、CLOCKソースの設定や分周比などを制御するレジスタ
- RCC_APB1ENR、 APB1クロックの供給を制御
- RCC_APB2ENR、 APB2クロックの供給を制御
前掲の表のclk欄をご参照いただけると、TIM2からTIM5の4本はAPB1クロック、TIM1とTIM9からTIM11の4本がAPB2クロックで動作しているとわかります。
ソースが以下に。ようやく stmモジュールが活躍。
#STM32: read GP Timer setting import stm def readRCC_CFGR(): return stm.mem32[stm.RCC + stm.RCC_CFGR] def readRCC_APB1ENR(): return stm.mem32[stm.RCC + stm.RCC_APB1ENR] def readRCC_APB2ENR(): return stm.mem32[stm.RCC + stm.RCC_APB1ENR] def decodePPRE(fieldval): ppre = "DIR" if fieldval == 4: ppre = "1/2" elif fieldval == 5: ppre = "1/4" elif fieldval == 6: ppre = "1/8" elif fieldval == 7: ppre = "1/16" return ppre def decodeRCC_CFGR(regval): ppre2 = (regval & 0xE000) >> 13 ppre1 = (regval & 0x1C00) >> 10 sws = (regval & 0xC) >> 2 swsCLK="n/a" if sws == 0: swsCLK = "HSI" elif sws == 1: swsCLK = "HSE" elif sws == 2: swsCLK = "PLL" print("CFGR : {0:08x}".format(regval)) print(" SWS : {0}".format(swsCLK)) print(" APB1 : {0}".format(decodePPRE(ppre1))) print(" ABP2 : {0}".format(decodePPRE(ppre1))) def decodeAPB1ENR(regval): print("APB1ENR: {0:08x}".format(regval)) if (regval & 0x1) != 0: print(" TIM2 En") if (regval & 0x2) != 0: print(" TIM3 En") if (regval & 0x4) != 0: print(" TIM4 En") if (regval & 0x8) != 0: print(" TIM5 En") if (regval & 0x800) != 0: print(" WWDG En") def decodeAPB2ENR(regval): print("APB2ENR: {0:08x}".format(regval)) if (regval & 0x1) != 0: print(" TIM1 En") if (regval & 0x10000) != 0: print(" TIM9 En") if (regval & 0x20000) != 0: print(" TIM10 En") if (regval & 0x40000) != 0: print(" TIM11 En") def main(): print("STM32F401RE GP CLOCK setting.") decodeRCC_CFGR(readRCC_CFGR()) decodeAPB1ENR(readRCC_APB1ENR()) decodeAPB2ENR(readRCC_APB2ENR()) print("End of test.") if __name__ == "__main__": main()
実機実行結果
STM32F401RE用にビルドしたMicroPythonの起動後デフォルト状態では、
-
- メインのクロックソースは内蔵PLLからのクロック
- APBバスに接続されているペリフェラルを制御する2つのAPBクロックはAHBバスクロックに対して4分周
- 汎用タイマ8本のすべてにクロックは供給されていない
という観察結果を得ました。ホントか?
まあ、これをみるとADのサンプリングに使うだけならどのタイマでも使えそうであります。勿論、MicroPythonのモジュールによってはタイマを使うものがあるハズなので、そのときはぶつからないタイマを選択しないとなりませんが。