This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Timer Code Example

Other Parts Discussed in Thread: OMAPL138

 Hi All!

 I try to understand how to use the timer for LED blinking application. I investigated L138 StarterWare package and found sample application for timer.

 In the code I understood that Timer configured for internal clock used

 TimerConfigure(SOC_TMR_2_REGS, TMR_CFG_64BIT_CLK_INT);

and period time is

#define TMR_PERIOD_LSB32               (0x07FFFFFF)

TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER34, TMR_PERIOD_MSB32);

But I don't understood where is setted frequency of internal clock, in other words, what means 0x07FFFFFF in seconds?

 Full code of timer application bellow:

/**
 * \file  timerCounter.c
 *
 * \brief Sample application for timer.
 */

/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ 
*
*  Redistribution and use in source and binary forms, with or without 
*  modification, are permitted provided that the following conditions 
*  are met:
*
*    Redistributions of source code must retain the above copyright 
*    notice, this list of conditions and the following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the 
*    documentation and/or other materials provided with the   
*    distribution.
*
*    Neither the name of Texas Instruments Incorporated nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "uart.h"
#include "hw_uart.h"
#include "interrupt.h"
#include "soc_OMAPL138.h"
#include "hw_syscfg0_OMAPL138.h"
#include "timer.h"
#include "evmOMAPL138.h"
#include "uartStdio.h"

#ifndef _TMS320C6X
#include "cpu.h"
#endif

/******************************************************************************
**                      INTERNAL MACRO DEFINITIONS
*******************************************************************************/
#define STR_LEN                        (13)
#define TMR_PERIOD_LSB32               (0x07FFFFFF)
#define TMR_PERIOD_MSB32               (0x0)

/******************************************************************************
**                      INTERNAL FUNCTION PROTOTYPES
*******************************************************************************/
static void TimerIsr(void);
static void TimerSetUp64Bit(void);
static void TimerIntrSetUp(void);

/******************************************************************************
**                      INTERNAL VARIABLE DEFINITIONS
*******************************************************************************/
static unsigned char cntArr[9] = {'8', '7', '6', '5', '4', '3', '2', '1', '0'};
static volatile unsigned int secCnt = 0;
static volatile unsigned int flagIsrCnt = 0;

/******************************************************************************
**                          FUNCTION DEFINITIONS
*******************************************************************************/
int main(void)
{
    /* Set up the UART2 peripheral */
    UARTStdioInit();

    /* Set up the Timer2 peripheral */
    TimerSetUp64Bit();

    /* Set up the AINTC to generate Timer2 interrupts */
    TimerIntrSetUp();

    /* Enable the timer interrupt */
    TimerIntEnable(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);

#ifndef _TMS320C6X
    /* Switch to non privileged mode; This is done for demonstration purpose */
    CPUSwitchToUserMode();
#endif

    /* Send the first String */
    UARTPuts("Tencounter: 9", -1);

    /* Start the timer. Characters from cntArr will be sent from the ISR */
    TimerEnable(SOC_TMR_2_REGS, TMR_TIMER12, TMR_ENABLE_CONT);

    /* make sure all the characters from cntArray from ISR */
    while(secCnt < 9)
    {
        /* Replace previous number each time the timer interrupt occurs */
        if(flagIsrCnt)
        {
            UARTPutc('\b');
            UARTPutc(cntArr[secCnt]);
            secCnt++;
            flagIsrCnt = 0;
        }
    }

    /* Disable the timer. No more timer interrupts */
    TimerDisable(SOC_TMR_2_REGS, TMR_TIMER12);

    /* Halt the program */
    while(1);
}

/*
** Timer Interrupt Service Routine
*/
static void TimerIsr(void)
{
    /* Disable the timer interrupt */
    TimerIntDisable(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);

#ifdef _TMS320C6X
    /* Clear interrupt status in DSPINTC */
    IntEventClear(SYS_INT_T64P2_TINTALL);
#else
    /* Clear the interrupt status in AINTC */
    IntSystemStatusClear(SYS_INT_TIMR2_ALL);
#endif
    TimerIntStatusClear(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);

    /* Signal application to print a new character */
    flagIsrCnt = 1;
  
    /* Enable the timer interrupt */
    TimerIntEnable(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
}


/*
** Setup the timer for 64 bit mode
*/
static void TimerSetUp64Bit(void)
{
    /* Configuration of Timer */
    TimerConfigure(SOC_TMR_2_REGS, TMR_CFG_64BIT_CLK_INT);

    /* Set the 64 bit timer period */
    TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER12, TMR_PERIOD_LSB32);
    TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER34, TMR_PERIOD_MSB32);
}

/*
** Set up the ARM Interrupt Controller for generating timer interrupt
*/
static void TimerIntrSetUp(void)
{
#ifdef _TMS320C6X
    /* Initialize the DSPINTC */
    IntDSPINTCInit();

    /* Register the Timer ISR */
    IntRegister(C674X_MASK_INT4, TimerIsr);

    /* Map Timer interrupts to DSP maskable interrupt */
    IntEventMap(C674X_MASK_INT4, SYS_INT_T64P2_TINTALL);

    /* Enable DSP interrupt in DSPINTC */
    IntEnable(C674X_MASK_INT4);

    /* Enable DSP interrupts */
    IntGlobalEnable();
#else
    /* Initialize AINTC and register timer interrupt */
    IntAINTCInit();
    
    /* Register the Timer ISR */
    IntRegister(SYS_INT_TIMR2_ALL, TimerIsr);
  
    /* Set the channel number for Timer interrupt, it will map to IRQ */
    IntChannelSet(SYS_INT_TIMR2_ALL, 2);
   
    /* Enable IRQ for ARM (in CPSR)*/
    IntMasterIRQEnable();
  
    /* Enable AINTC interrupts in GER */
    IntGlobalEnable();

    /* Enable IRQ in AINTC */
    IntIRQEnable();

    /* Enable timer interrupts in AINTC */
    IntSystemEnable(SYS_INT_TIMR2_ALL);
#endif
}
/***************************** End Of File ***********************************/

  • Hi,

    If you want time delay for LED blinking through timers then you better to "Sysdelay(millsec)"

    Please refer the following function in OMAPL138 starterware code

    OMAPL138_StarterWare_1_10_03_03/platform/evmOMAPL138/sysdelay.c

    OMAPL138_StarterWare_1_10_03_03/utils/delay.c

    OMAPL138_StarterWare_1_10_03_03/drivers/timer.c  (Driver API file)

    Please refer the OMAPL138 TRM chapter 31.2.1.2.1

    http://e2e.ti.com/support/dsp/omap_applications_processors/f/42/p/250316/877053.aspx

    http://e2e.ti.com/support/dsp/omap_applications_processors/f/42/t/337872.aspx

  •  Thanks Titus!

    Is this method is suitable for generating external clock for external ADC ? I think no, because sysdelay can give only millisecond interval. If I need less sysdelay is not helpful.

    I need understand how value in the timer period register can be recalculate to seconds for generating any pulse period (less than ms)

    In sysdelay.c I found follow code of initialization timer period:

    #define TMR_PERIOD_LSB32              0x5DC0
    
    TimerPeriodSet(SOC_TMR_0_REGS, TMR_TIMER12, (milliSec * TMR_PERIOD_LSB32));

    is it means that 0x5DC0 is a period of 1ms. If it so, for 10us period I should set Timer period register to 0xF0

    From L138 technical reference I know that Timer period register store 32-bit value is the number of timer input clock cycles to count.
     So, сonsidering all of the above, input clock for timer in sysdelay.c is (0x5DC0 * 1000) = 24Mhz

     Is it default value? Where it is setted?

  • Hi,

    What i understand,you want to know resolution of Timer Period Register,which depends upon Clock present.

    Say, clock is of 200 Mhz., then resolution is 5 nSec i.e value of 0x01 in timer period register. 

  •  Thanks Vijay!

    I understand how depends timer period of resolution. But I misunderstand how set mentioned clock for timer. In the OMAPL138_StarterWare_1_10_03_03 presents example for the Timer.

     In sysdelay example Timer initialized for internal clock, but value of clock is missing. Indirectly I figure that default internal clock for Timer is 24Mhz. Because follow code from sysdelay.c is for 1ms period:

    #define TMR_PERIOD_LSB32               (0x5DC0)
    
    TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER34, TMR_PERIOD_MSB32);

     

  • Hi,

    For that, you should check out Manual. Internal clock for timer should be mentioned there.

    and you must b knowing,external clock.

    n i think,external clock if you are providing,should be less than internal clock.

    i may b wrong.

    Thanks.

  • Hi Dmitriy1,

    Dmitriy1 says said:
    #define TMR_PERIOD_LSB32               (0x07FFFFFF)

    #define TMR_PERIOD_MSB32               (0x0)

    They are the time period value getting set in the form of a 64-bit timer period register through PRD12 and PRD34.

    When the timer is enabled, the timer counter starts incrementing by 1 at every timer input clock cycle.

    When the timer counter matches the timer period ( the one which is set through the PRD12 and PRD34) , a maskable timer interrupt (TINT12) and a timer EDMA (TEVT12) are generated.

    In the source code timecounter.c, the TImer2 peripheral is configured for 64-Bit Timer Mode and this value ((0x07FFFFFF) is used as timer period.

    As per the starterware code, this timer period value is set in a way that if the time period value is LSB -0x07FFFFFF and MSB - 0x0, the timer interrupt will occur at every 1 sec. If you change the timer period value to LSB - 0x0FFFFFFF and MSB -0x0, then the  timer interrupt will occur at every 2 sec. If you change the timer period value to LSB - 0x03FFFFFF and MSB -0x0, then the  timer interrupt will occur at every 0.5sec.

    Having this claculation in hand,for 1 ms, the time period value might be calculated as 0x20C49 ( I may go wrong. Please experiment and find it out the exact value)

    ( For example, consider the input clock is 130 MHz. then, for 1 clock cycle it takes ~7.69 nanoseconds. For one clock cycle, It will increment one value, so the time period value shall be set as 0x01 and the counter reaches this vlaue, 0x01 in 7.69 nano seconds. For 1 ms/1Micro seconds, you can calculate the time period value according to the input clock.

     

    Regards,

    Shankari

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question.
    --------------------------------------------------------------------------------------------------------

  • Thanks for your answer!

    Shankari, can you show me piece of code where perform initialization of input clock rate for timer? Can I set custom value of input frequency clock or I can use only default value?
    And you told that I should find value for period register by experiment. it is strange, because I think user should be able to calculate precise value of register from pre-known input clock value (for example for Atmel MCU it is so).
    So, my direct question for this topic: Can I set custom value of input clock for timer? If yes, how?

    In the tech ref manual I see: 

    31.2.1.2.1 Using the Internal Clock Source to the Timer
    The internal clock source to the timer is generated by the PLL controller. This clock source determines the
    speed of the timer since the timer counts up in units of source clock cycles. When determining the period
    and prescaler settings for the timer, choose the desired period in units of source clock cycles. For details
    on the generation of the on-chip clocks, see the Phase-Locked Loop Controller (PLLC) chapter.

    But in timer example code PLLC initialization is missing. 

  • Hi,

    yes, ofcourse in the code you pasted above, is configuring the Internal clock source for TImer2.

    PLLC initialization code is not missing!!.

    /* Configuration of Timer */
        TimerConfigure(SOC_TMR_2_REGS, TMR_CFG_64BIT_CLK_INT);

    I would recommend you to go through the PLL Topology in the TRM. As per the PLL topology of TRM, the TImer2 takes the SYSCLK/2 clock. Consider the Core frequency is 300 MHz for me and hence the SYSCLK/2 is 150 MHz. You should look into settings of the core frequency using GEL file. According to the core frequency, the input clock frequency of timer can be set to a desired one.

    Dmitriy1 says said:
    And you told that I should find value for period register by experiment. it is strange, because I think user should be able to calculate precise value of register from pre-known input clock value (for example for Atmel MCU it is so). 

    Yes, theoritically, you can calculate the precise time period value from the known input clock value. The reason I have told you to experiment is I am not aware of your core frequency or timer frequency-(Internal or external) or the user defined Timer ISR and its contents, timer instance and it's mode e.t.c.,

    Points to you:

    1. Check out the Tabular column of System clock domain and the overall clocking diagram in the TRM and find out the appropriate system clock domain for your peripheral ( here, it is TImer2,SYSCLK 2 )

    2. Find the core frequency settings with reference to your GEL file and then derive the (SOC_SYSCLK_1_FREQ/2) for SOC_SYSCLK_2_FREQ

    3. With reference to your peripheral clock, find the time period value.

     

    Regards,

    Shankari

     

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question.
    --------------------------------------------------------------------------------------------------------

  •  Thank you very mach for all answers for my child's question in this topic.

  • Hi Dmitriy 1,

    You are welcome!!.

     

    Regards,

    Shankari