0

I have a STM32L476RC nucleo board that I am using to learn STM32. I am using STM32Cube HAL and AC6 System Workbench to develop on. I am trying to stay away from CubeMX as my goal is more towards learning than just getting something to work.

The problem that I am having is when I try to set up the systick timer using the code below, it seems to be counting twice as fast as it should.

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

However if I just leave it default form the power-up then it is counting at the correct speed.

I have used CubeMX to generate the following clock setup, and paste it directly into a fresh project created in System Workbench, however the systick counter still seems to be counting twice as fast as it should be. The project that was generated by CubeMX seems to be running just fine however

    /** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInit;

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 1;
  RCC_OscInitStruct.PLL.PLLN = 10;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    //Error_Handler();
  }

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    //Error_Handler();
  }

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    //Error_Handler();
  }

    /**Configure the main internal regulator output voltage
    */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
  {
    //Error_Handler();
  }

    /**Configure the Systick interrupt time
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

}

There must be something I am missing. Maybe somehow the tick counter is configured elsewhere, and calling HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); is just setting another tick counter? I have no idea! Please help I am completely lost as to what is going on!

I am measuring the tick speed by simply flashing a LED and and measuring the frequency on a logic analyser:

if (HAL_GetTick() - LEDstopwatch > 1000)
{
    // Toggle the LED
    //BSP_LED_Toggle(LED2);
    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);
    // Reset the stopwatch
    LEDstopwatch = HAL_GetTick();
}

The full code for my test project is here: https://github.com/c-herring/STM32L476_Nucleo_FirstTest

Thanks!

Chris
  • 115
  • 2
  • 12

1 Answers1

1

In the SystemClock_Config function you copied, STM32CubeMX initializes the system clock at 80MHz. To do this, it uses HSI (16MHz) as input of the PLL, then divide it by 1 (PLLM), then multiplies it by 10 (PLLN) and finally divides its by 2 (PLLR).

When you don't use STM32CubeMX and creates a project from scratch, the clock is initialized in SystemInit in the system_stm32l4xx.c. SystemInit is called before main in the startup file (startup_stm32l476xx.S). According to the comments SystemInit initializes the clock at 40MHz using the MSI (4MHz) as input of the PLL.

The system clock is twice faster therefore you see the difference in the Systick.

Guillaume Michel
  • 1,189
  • 8
  • 14
  • Hi Guillaume. Thanks for your reply. I am still a little confused. I thought that SysTick is derived from HCLK. I think the code that I copied did change the clock source. I have stepped through the debugger and SystemCoreClock is correctly updated to 80MHz. I have also set up a PWM and I do measure the correct carrier freq for that 80MHz. So HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); should properly update the SysTick Interrupt time with the 80MHz HCLK? The problem is is when I change HCLK to 80MHz but DON'T update systick, it runs at correct speed. When I DO update systick, it runs fast – Chris Feb 27 '17 at 22:23
  • Also, it seems the auto-generated code from CubeMX also calls the same SystemInit function and sets up the clock exactly the same as the code generated by creating a new project in SW. It then goes on to call HAL_Init() and then SystemClock_Config(). I am not seeing a difference in the code between the project created from scratch and the CubeMX code.. CubeMX code: https://github.com/c-herring/testmx – Chris Feb 27 '17 at 23:51