2.2 Base de tiempos

Utilizaremos el temporizador SysTick para establecer una base de tiempos en el microcontrolador. Esto nos permitirá ejecutar acciones en intervalos regulares, y programar la ejecución de tareas.

¿Qué es SysTick?

SysTick (System Timer) es un temporizador de cuenta descendente de 24 bits disponible en los microcontroladores ARM Cortex-M. Se emplea para generar eventos periódicos, medir intervalos de tiempo, y como base temporal para programar tareas.

Diagrama de bloques de Systick:

fig2.1

System Timer (SysTick).

Registros de SysTick

El módulo SysTick se controla mediante los siguientes registros accesibles desde el espacio de memoria del procesador:

  • SYST_CSR (Control and Status Register):

    • bit 0 (ENABLE): habilita/deshabilita el temporizador (1 = activo).

    • bit 1 (TICKINT): habilita la interrupción al llegar a 0 (1 = habilitada).

    • bit 2 (CLKSOURCE): selecciona la fuente de reloj (1 = HCLK del procesador, 0 = reloj externo).

    • Bit 16 (COUNTFLAG): se pone a 1 cuando el contador pasa de 1 a 0; se borra al leer SYST_CSR.

  • SYST_RVR (Reload Value Register):

    • Valor de recarga del contador.

    • Valor Máximo: 0x00FFFFFF (24 bits).

    • El número de ciclos que transcurren entre recargas es SYST_RVR + 1.

  • SYST_CVR (Current Value Register):

    • Valor actual del contador.

    • Se recarga automáticamente desde SYST_RVR al alcanzar 0.

    • Escribir en este registro lo reinicia a 0.

Funcionamiento básico

  1. Al poner a 1 el bit ENABLE en SYST_CSR, SYST_CVR se carga con SYST_RVR y comienza a decrementarse en cada ciclo de reloj.

  2. Cuando SYST_CVR pasa de 1 a 0 se activa COUNTFLAG (bit 16 de SYST_CSR).

  3. En el ciclo siguiente el contador SYST_CVR se recarga automáticamente desde SYST_RVR y continúa contando.

fig2.1

Funcionamiento del System Timer (SysTick).

Nota: el temporizador se detiene cuando el procesador entra en modo de depuración (debug). Además, la lectura de SYST_CSR limpia COUNTFLAG.

Recursos HAL_Systick

Para facilitar el uso de SysTick en nuestras aplicaciones disponemos del módulo HAL_SysTick, que se encuentra en el archivo de recursos (HAL_SysTick.c, HAL_SysTick.h).

Este módulo proporciona funciones para configurar y utilizar SysTick en modo encuesta (polling). De este modo, podemos comprobar periódicamente si SysTick ha desbordado (llegado a 0) y ejecutar acciones en consecuencia.

Incluye las siguientes funciones:

/**
 * @brief   Configura SysTick en modo encuesta
 * @details Inicializa SysTick en modo `free-running` generando eventos
 *          periódicamente, no genera interrupciones.
 * @param [in]  ticks  Número de ticks (ciclos de reloj) entre dos eventos.
 * @return  0  Ejecución exitosa.
 * @return  1  Fallo en la ejecución.
 * @note    Da valor a los registros SYST_RVR y SYST_CSR.
 *          SYST_CSR se configura con los valores:
 *                  CLKSOURCE => 1 (HCLK)
 *                  ENABLE => 1
 *                  others => 0
 */
 uint32_t SysTick_Init(uint32_t ticks);

 /**
 *
 * @brief   Comprueba si ha habido overflow en SysTick
 *
 * @return  0  No ha habido overflow. (COUNTFLAG=0)
 * @return  1  Ha habido overflow. (COUNTFLAG=1)
 *
 * @note    Después de ejecutar la función COUNTFLAF=0
 */
 uint32_t SysTick_ChkOvf(void);
Ejercicio 1: Base de tiempos con SysTick
  1. Preparación del entorno.

    • Abre el proyecto lab2 en Keil.

    • Selecciona el target lab2.0.

  2. Tareas a realizar.

    • Completa el código lab2.0.c, esta aplicación debe utilizar SysTick para cambiar el pin P7D/D8 cada 1 ms.

      nota: Para iniciar SysTick podemos utilizar el macro SystemCoreClock que se expande a la frecuencia de reloj del µP, este caso 200.000.000, por lo tanto para 1ms el argumento de la función ticks será SystemCoreClock/1000.

    fig2.1
    //  includes, recursos externos que se van a utilizar (ficheros.h)
    #include "HAL_FM4_gpio.h"
    ...
    
    //  no utilizamos variables globales
    
    int main(void)
    {
        // Configuración de periféricos:
        //  - Config GPIO para utilizar leds y sw2
        ...
    
        //  -Config pin P7D/D8:
        //    Pin P7D/D8 como salida
        //    Pin P7D/D8 a 0
        ...
        //  -Config SysTick (1ms):
        SysTick_Init(SystemCoreClock / 1000U);
    
        // Ejecutivo cíclico
        while (1)
        {
            if (.......) // Si SysTick ha desbordado
            {
                GPIO_ChannelToggle(P7D); // Actualiza P7D/D8
            }
        }
    }
    
  3. Verificación del funcionamiento.

    • Compila y programa el microcontrolador.

    • Verifica utilizando los timers de Keil que la función GPIO_ChannelToggle(P7D) se ejecuta cada 1ms.

    • Conecta el osciloscopio como se hizo en lab1 para comprobar que P7D/D8 cambia cada 1ms:

      fig2.1

      Pin P7D/D8.