i.MX 8M EVK : how to calculate the frequency values for a 1ms timer ?

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

i.MX 8M EVK : how to calculate the frequency values for a 1ms timer ?

跳至解决方案
622 次查看
martindenion
Contributor II

Hello,
I want to implement a simple "GPT" timer that generates an interrupt every 1ms.
However, I get an interrupt exactly every 3ms (instead of the desired 1ms).

Where is my error? What values should I set to get a 1ms timer?

Here is my calculation for the GPT timer:

/* EXPLANATION OF TIMER VALUES */
/*
* We take for source clock the PLL1 DIV2 400MHz
* We define the root divisor at 4 => 400MHz / 4 = 100MHz
*
* 100MHz = one increment every 10ns
* We want an interrupt to be generated every 1 ms
* So we have :
* Output_compare_value = delay_time x GPT_frequency
* 1
* Output_compare_value = 1 x 10^-3 x ---------- = 100
* 10 x 10^-9
*/

Here is my code (I change the state of a GPIO at each interrupt to check the operation of my timer on the oscilloscope):

 

/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright 2016-2017 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_gpt.h"
#include "fsl_gpio.h"

#include "fsl_common.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define GPT_IRQ_ID  GPT1_IRQn
#define EXAMPLE_GPT GPT1
//#define EXAMPLE_GPT_CLK_FREQ                                                                \
//    (CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / (CLOCK_GetRootPreDivider(kCLOCK_RootGpt1)) / \
//     (CLOCK_GetRootPostDivider(kCLOCK_RootGpt1)) / 2) /* SYSTEM PLL1 DIV2 */
#define EXAMPLE_GPT_CLK_FREQ	100000
#define EXAMPLE_GPT_IRQHandler GPT1_IRQHandler

#define EXAMPLE_LED_GPIO     GPIO3
#define EXAMPLE_LED_GPIO_PIN 23U

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/

volatile bool gptIsrFlag = false;
/* The PIN status */
volatile bool g_pinSet = false;

/*******************************************************************************
 * Code
 ******************************************************************************/
void EXAMPLE_GPT_IRQHandler(void)
{
    /* Clear interrupt flag.*/
    GPT_ClearStatusFlags(EXAMPLE_GPT, kGPT_OutputCompare1Flag);

    gptIsrFlag = true;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F, Cortex-M7, Cortex-M7F Store immediate overlapping
  exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U || __CORTEX_M == 7U)
    __DSB();
#endif
}

/*!
 * @brief Main function
 */
int main(void)
{
    uint32_t gptFreq;
    gpt_config_t gptConfig;

    /* Define the init structure for the output LED pin*/
    gpio_pin_config_t led_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};

    /* Board pin, clock, debug console init */
    /* Board specific RDC settings */
    BOARD_RdcInit();

    BOARD_InitBootPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();
    BOARD_InitMemory();

    CLOCK_SetRootMux(kCLOCK_RootGpt1, kCLOCK_GptRootmuxSysPll1Div2); /* Set GPT1 source to SYSTEM PLL1 DIV2 400MHZ */
    CLOCK_SetRootDivider(kCLOCK_RootGpt1, 1U, 4U);                   /* Set root clock to 400MHZ / 4 = 100MHZ */

    GPT_GetDefaultConfig(&gptConfig);

    /* Initialize GPT module */
    GPT_Init(EXAMPLE_GPT, &gptConfig);

    /* Divide GPT clock source frequency by 3 inside GPT module */
    GPT_SetClockDivider(EXAMPLE_GPT, 1);

    /* Get GPT clock frequency */
    gptFreq = EXAMPLE_GPT_CLK_FREQ;

    /* GPT frequency is divided by 3 inside module */
    gptFreq /= 1;

    /* Set both GPT modules to 1 second duration */
    GPT_SetOutputCompareValue(EXAMPLE_GPT, kGPT_OutputCompare_Channel1, gptFreq);

    /* Enable GPT Output Compare1 interrupt */
    GPT_EnableInterrupts(EXAMPLE_GPT, kGPT_OutputCompare1InterruptEnable);

    /* Enable at the Interrupt */
    EnableIRQ(GPT_IRQ_ID);

    PRINTF("\r\nPress any key to start the example");
    GETCHAR();

    /* Init output LED GPIO. */
    GPIO_PinInit(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, &led_config);

    /* Start Timer */
    PRINTF("\r\nStarting GPT timer ...");
    GPT_StartTimer(EXAMPLE_GPT);

    while (true)
    {
        /* Check whether occur interupt and toggle LED */
        if (true == gptIsrFlag)
        {
            PRINTF("\r\n GPT interrupt is occurred !");
            gptIsrFlag = false;
            if (g_pinSet)
            {
                GPIO_PinWrite(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, 0U);
                g_pinSet = false;
            }
            else
            {
                GPIO_PinWrite(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, 1U);
                g_pinSet = true;
            }
        }
        else
        {
            __WFI();
        }
    }
}

 

0 项奖励
1 解答
606 次查看
martindenion
Contributor II

I found out what my problem was with the timer. The truth is that all my values were fine, but it was the execution of the logging that was taking time (line PRINTF("GPT interrupt is occurred !");) So I could have lowered my reload value even more, but I would still have the logging that was taking time to run.

在原帖中查看解决方案

0 项奖励
1 回复
607 次查看
martindenion
Contributor II

I found out what my problem was with the timer. The truth is that all my values were fine, but it was the execution of the logging that was taking time (line PRINTF("GPT interrupt is occurred !");) So I could have lowered my reload value even more, but I would still have the logging that was taking time to run.

0 项奖励