STM32 - AHB Prescaler inhabilitando Systick

3

Estoy escribiendo firmware completo para un STM32F070 . Cuando configuro el Prescaler AHB ( AHBCLKDivider ) a un valor mayor que 1 , la interrupción del systick nunca ocurre, es decir, nunca se llama a SysTick_Handler() . Esto a su vez hace que HAL_Delay() bloquee el sistema cuando se le llama.

¿Por qué sucede esto? ¿Es posible tener habilitada la interrupción del systick cuando se usa el prescaler AHB?

El código de inicialización de mi reloj está debajo. Lo modifiqué según el código generado por STM32CubeMX.

Además, ¿cuál es el significado del parámetro que se pasa a HAL_SYSTICK_Config() ? ¿Debe ajustarse en función de la configuración del prescaler?

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_HSE |
      RCC_OSCILLATORTYPE_HSI |
      RCC_OSCILLATORTYPE_LSE |
      RCC_OSCILLATORTYPE_LSI |
      RCC_OSCILLATORTYPE_HSI14;
   RCC_OscInitStruct.HSEState   = RCC_HSE_OFF;
   RCC_OscInitStruct.HSIState   = RCC_HSI_ON;
   RCC_OscInitStruct.HSICalibrationValue = 16;
   RCC_OscInitStruct.HSI14State = RCC_HSI14_OFF;
   RCC_OscInitStruct.LSEState   = RCC_LSE_OFF;
   RCC_OscInitStruct.LSIState   = RCC_LSI_ON;
   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF;

   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_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_HSI;
   RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1; //TODO
   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;   //TODO

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

   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
   PeriphClkInit.RTCClockSelection    = RCC_RTCCLKSOURCE_LSI;

   if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
   {
      Error_Handler();
   }

   GPIO_InitTypeDef gpioInit =
   {
      .Pin  = GPIO_PIN_0,
      .Mode = GPIO_MODE_OUTPUT_PP,
      .Pull = GPIO_NOPULL,
      //.Speed = GPIO_SPEED_FREQ_LOW,
      //.Alternate = 0,
   };

   /**Configure the Systick interrupt time 
   */
   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 8000); //TODO: is this correct when using prescalers?

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

   /* SysTick_IRQn interrupt configuration */
   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
    
pregunta cp.engr

1 respuesta

2

El significado del parámetro que pasa a HAL_SYSTICK_Config es el número de tics antes de que se genere una interrupción de SYSTICK. Entonces, en el código de ejemplo, el SYSCLK es el HSI con 8 MHz. Y el HCLK no tiene preescalador, por lo que HCLK también es de 8 MHz.

Se generará una interrupción SYSTICK cada 8 000 000/8 000 = 1 000 tics, ya que el reloj SYSTICK tiene un preescalador propio de 8 basado en HCLK, la frecuencia real de SYSTICK será de 1 MHz. 1 000 ticks se convierte en una interrupción SYSTICK de 1 ms.

Entonces, si configura su HCLK en 2 MHz, se establecerá en 250 tics, lo que dará como resultado interrupciones de 1 ms. Así que no tiene que cambiar ese valor con el cambio de preescalador.

Actualmente no veo una razón por la que esto no funcione. Tal vez pueda comenzar a depurar y ver cuál es el resultado de HAL_RCC_GetHCLKFreq() cuando tiene un divisor en su lugar. Tal vez divida esa línea en dos para facilitar la depuración:

uint32_t hclk = HAL_RCC_GetHCLKFreq();
HAL_SYSTICK_Config(hclk/8000);

RANT

Ugh esto es un desastre como siempre con STM32. Una de las razones por las que no estoy usando ST HAL o Cube es la calidad de la documentación, ya es mala en el manual de referencia, pero peor cuando se trata de entender la API (por ejemplo, ¿devolverá la frecuencia en Hz, kHz o MHz: no se encuentra en ninguna parte (es Hz)).

    
respondido por el Arsenal

Lea otras preguntas en las etiquetas