STM32F3 SysTickについて


もともとは同僚から「マイコンなら標準のタイマーの一つはもっているはずだ」と言われたことから始まっています。調べて,自分の覚書としてまとめてみた。

動作確認のため,以下の環境を使いました。

  • NUCLEO-F303K8 CPUはSTM32F303K8
  • STM32CubeIDE 1.7.0 ( for mac )
  • HALライブラリー

基本

  • SysTickカウンターが回っている。

ここではSysTick - STCVR - CURRENT が, 周波数 HCLK でカウントダウンされる。

私のテストプロジェクトでは, HSI(8MHz) * 8 = HCLK(64MHz)となっている。

  • カウンターが0になると,SysTick - STRVR - RELOAD 値に戻される。同時に割り込みが発生する。

上記では 0xf9ff(=63999)なので, (0xf9ff + 1) / 64MHz = 1msec ごとに割り込みが発生している。

HALライブラリーを使う今回のプロジェクトでは, SysTick_Handler(void) がコールされる。実態は stm32f3xx_it.c に記載されている。

  • HAL_Delay() はこれを使っている。また HAL_GetTick() は,これを使ってカウントして,起動後からの時間を msec で得ることができる。

  • 現在の SysTick値を読むこともできる。

printf("HAL_GetTick = %d.  ",HAL_GetTick());
printf("SysTick_VAL = %d.\r\n",SysTick->VAL);

割り込み周期を変えるとき

  • SysTick->LOAD に直接代入しても良いし, HAL_SYSTICK_Config() を使っても良い。(後者は割り込みのセット等も行なっている)
HAL_SYSTICK_Config(SystemCoreClock/2); // Systick interrupt to 1/2 sec 

当然 HAL_Delay() も影響を受けるので注意。

割り込んだ時のコードを追加したい時

main.c じゃなくて,まずは stm32f3xx_it.c に追記します。

stm32f3xx_it.c
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */  
  HAL_SYSTICK_Callback();// ここを追加
  /* USER CODE END SysTick_IRQn 1 */
}

んでmain.cに追記します。

main.c
void HAL_SYSTICK_Callback() {
          HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
}

HAL_SYSTICK_Callback() をmain.cで再定義することになります。

参考

stm32f3xx_hal_cortex.c
void HAL_SYSTICK_IRQHandler(void)
{
  HAL_SYSTICK_Callback();
}

/**                                                                                                 
  * @brief  SYSTICK callback.                                                                       
  * @retval None                                                                                    
  */
__weak void HAL_SYSTICK_Callback(void)
{
  /* NOTE : This function Should not be modified, when the callback is needed,                      
            the HAL_SYSTICK_Callback could be implemented in the user file                          
   */
}

参考 PIOのSTM32では, SysTick_Handler() は main.c に記載されているので,ちょっとわかりやすい。

main.c
#include "stm32f3xx_hal.h"

void SysTick_Handler(void)
{
  HAL_IncTick();
  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
}

int main(void)
{
  HAL_Init();

  // init PB3

  __HAL_RCC_GPIOB_CLK_ENABLE();
  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.Pin = GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  HAL_SYSTICK_Config(SystemCoreClock/3 - 1); // call SysTick_Handler(void) every 1/3 seconds

  while (1)
  {
  }
}

参考URL