【STM32 Cube】APB Timer Clocks の値を取得する


コード

uint32_t apb1_timer_clocks;
uint32_t apb2_timer_clocks;

RCC_ClkInitTypeDef RCC_ClkInitStruct;
uint32_t pFLatency;
HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency);
apb1_timer_clocks = HAL_RCC_GetPCLK1Freq();
apb2_timer_clocks = HAL_RCC_GetPCLK2Freq();
apb1_timer_clocks *= (RCC_ClkInitStruct.APB1CLKDivider == RCC_HCLK_DIV1)? 1 : 2;
apb2_timer_clocks *= (RCC_ClkInitStruct.APB2CLKDivider == RCC_HCLK_DIV1)? 1 : 2;

解説

RCC_ClkInitTypeDef

こんな定義になっています。

typedef struct {
  uint32_t ClockType; // RCC_CLOCKTYPE_xxx
  uint32_t SYSCLKSource; // RCC_SYSCLKSOURCE_xxx
  uint32_t AHBCLKDivider; // RCC_SYSCLK_DIVx
  uint32_t APB1CLKDivider; // RCC_HCLK_DIVx
  uint32_t APB2CLKDivider; // RCC_HCLK_DIVx
} RCC_ClkInitTypeDef;

uint32_t になってはいますが、APB1CLKDivider であれば RCC_HCLK_DIVx の定義された値となっており、 割る数通りの値ではありません。しかし、結局のところ条件式で使うので影響はさほどありません。

HAL_RCC_GetClockConfig

HAL_RCC_ClockConfig で設定された値を取得します。基本的には SystemClock_Config で設定されているはずなので、その後であれば正常な値が返ってくるはずです。

HAL_RCC_GetPCLK1Freq, HAL_RCC_GetPCLK2Freq

この図において、PCLK1PCLK2 を取得することができます。実際はクロックソースから順に計算をしていって算出されていますが、PCLKx を直接取得できるのでこれを使っています。

PCLKxAPBx Timer Clocks に変換する

apb1_timer_clocks *= (RCC_ClkInitStruct.APB1CLKDivider == RCC_HCLK_DIV1)? 1 : 2;

PCLKx の値に掛け算することで APBx Timer Clocks の値を得ています。どんな値を掛ければいいのかよく分からなかったので、検証を繰り返してこの条件式に行きつきました。

ですが、実際のところクロックツリーというところに答えが書いてありました。PCLKx に掛ける値はプリスケーラーが1の時はx1。それ以外の場合はx2になるようです。なのでこの条件式で問題ないですね〜。

環境

  • NUCLEO-F303RE
  • STM32Cube FW_F3 v1.11.1

最後に

APB Timer Clocks の値を取得する」 という内容自体はよく質問されている内容ではありますが、今でも使うことが出来るようなものはあまり見つかりませんでした。HAL関数のみの構成になっているのでマイコン依存ではないとは思いますが、設定次第でおかしな値を取得してしまうかもしれません。上手く取得できなかったことがあれば教えていただけるとありがたいです。