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_getCount() How does it work? F28027

Other Parts Discussed in Thread: CONTROLSUITE

Hi! 

I'd like to calculate the elapsed time from point A to point B. I found a few function defined for this purpose but i dont know how to use them. 
These functions are:

- TIMER_getCount()
- TIMER_getStatus()

I found them in timer.h.

I'd like to have a code like this:

|------------------------------------------------------------------------------------------

uint32_t start, stop, result;

TIMER_stop(myTimer);
TIMER_reload(myTimer);

TIMER_start(myTimer);
start = TIMER_getCount(myTimer); // Get elapsed time since start
DELAY_US(1000000);
stop = TIMER_getCount(myTimer);

result = (stop - start);

msg = "--> 1\n\r";
scia_msg(msg);
DELAY_US(result);
msg = "--> 2\n\n\r";
scia_msg(msg);

|------------------------------------------------------------------------------------------ 

  • You didn't cite what software release you were using, but after a quick search of my own for "Timer_getCount", I am surmising that you are using controlSUITE and either the C2000 Launchpad software, or generic device_support software for F2802x.  In future, it would be beneficial to cite the source of the software you reference to eliminate guessing.

    Assuming I'm correct regarding what software baseline you are using, there is an example called .\cpu_timer that illustrates how to use the TIMER_* function calls.

    In your pseudo-code above, are you seeing a problem when you try to run it?

    One thing I notice is that you have not configured the Timer "myTimer" in terms of setting its period, etc.  The aforementioned example has calls to TIMER_setPeriod(), etc.

  • Dear BrandonAzbell

    I'm sorry for my  unthoughtfulness about the cite and thank you for the fast answer. I got the files for my projects from C:\ti\controlSUITE\device_support\f2802x\v210. I examined the cpu_timer example but i didnt saw the functions mentioned. Just to be correct i copy the code i used so its easier to see the problems i have.

    ----------------------------------------------------------------------------------------------|

    #include <stdio.h>
    #include <file.h>

    #include "DSP28x_Project.h" // DSP28x Headerfile

    #include "f2802x_common/include/pll.h"
    #include "f2802x_common/include/clk.h"
    #include "f2802x_common/include/wdog.h"
    #include "f2802x_common/include/flash.h"
    #include "f2802x_common/include/gpio.h"
    #include "f2802x_common/include/pie.h"
    #include "f2802x_common/include/adc.h"
    #include "f2802x_common/include/sci.h"
    #include "f2802x_common/include/sci_io.h"
    #include "f2802x_common/include/timer.h"
    #include "f2802x_common/include/pwr.h"

    void scia_echoback_init(void);
    void scia_fifo_init(void);
    void scia_xmit(int a);
    void scia_msg(char *msg);

    extern void DSP28x_usDelay(Uint32 Count);

    //interrupt void xint1_isr(void);
    //interrupt void xint2_isr(void);
    //interrupt void cpu_timer0_isr(void);

    //Interrupt végére
    //---------------------------------------
    //PIE_clearInt(myPie, PIE_GroupNumber_1);
    //---------------------------------------


    volatile uint32_t Xint1Count;
    volatile uint32_t Xint2Count;
    uint32_t LoopCount;

    // you probably need these
    CPU_Handle myCpu;
    PLL_Handle myPll;
    WDOG_Handle myWDog;
    CLK_Handle myClk;
    TIMER_Handle myTimer;
    PWR_Handle myPwr;

    // these are optional
    ADC_Handle myAdc;
    FLASH_Handle myFlash;
    GPIO_Handle myGpio;
    PIE_Handle myPie;
    SCI_Handle mySci;

    uint16_t ReceivedChar;
    char *msg;

    void setup_handles()
    {
    myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
    myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
    myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
    myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
    myTimer = TIMER_init((void *)TIMER0_BASE_ADDR, sizeof(TIMER_Obj));
    myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
    myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
    myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
    mySci = SCI_init((void *)SCIA_BASE_ADDR, sizeof(SCI_Obj));
    myAdc = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj));
    myPwr = PWR_init((void *)PWR_BASE_ADDR, sizeof(PWR_Obj));
    }

    void scia_echoback_init()
    {

    CLK_enableSciaClock(myClk);

    // 1 stop bit, No loopback
    // No parity,8 char bits,
    // async mode, idle-line protocol
    SCI_disableParity(mySci);
    SCI_setNumStopBits(mySci, SCI_NumStopBits_One);
    SCI_setCharLength(mySci, SCI_CharLength_8_Bits);

    SCI_enableTx(mySci);
    SCI_enableRx(mySci);
    SCI_enableTxInt(mySci);
    SCI_enableRxInt(mySci);

    // SCI BRR = LSPCLK/(SCI BAUDx8) - 1
    #if (CPU_FRQ_60MHZ)
    SCI_setBaudRate(mySci, SCI_BaudRate_9_6_kBaud);
    #elif (CPU_FRQ_50MHZ)
    SCI_setBaudRate(mySci, (SCI_BaudRate_e)162);
    #elif (CPU_FRQ_40MHZ)
    SCI_setBaudRate(mySci, (SCI_BaudRate_e)129);
    #endif

    SCI_enable(mySci);

    return;
    }

    void scia_xmit(int a)
    {
    // while (SciaRegs.SCIFFTX.bit.TXFFST != 0) {}
    while(SCI_getTxFifoStatus(mySci) != SCI_FifoStatus_Empty){
    }
    // SciaRegs.SCITXBUF=a;
    SCI_putDataBlocking(mySci, a);

    }

    void scia_msg(char * msg)
    {
    int i;
    i = 0;
    while(msg[i] != '\0')
    {
    scia_xmit(msg[i]);
    i++;
    }
    }

    void scia_fifo_init()
    {

    SCI_enableFifoEnh(mySci);
    SCI_resetTxFifo(mySci);
    SCI_clearTxFifoInt(mySci);
    SCI_resetChannels(mySci);
    SCI_setTxFifoIntLevel(mySci, SCI_FifoLevel_Empty);

    SCI_resetRxFifo(mySci);
    SCI_clearRxFifoInt(mySci);
    SCI_setRxFifoIntLevel(mySci, SCI_FifoLevel_4_Words);

    return;
    }

    void init_system()
    {
    WDOG_disable(myWDog);
    (*Device_cal)();
    CLK_setOscSrc(myClk, CLK_OscSrc_Internal);
    PLL_setup(myPll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2);

    PIE_disable(myPie);
    PIE_disableAllInts(myPie);
    CPU_disableGlobalInts(myCpu);
    CPU_clearIntFlags(myCpu);

    #ifdef _FLASH
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
    #endif

    PIE_setDebugIntVectorTable(myPie);
    PIE_enable(myPie);
    //PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_7, (intVec_t)&cpu_timer0_isr);

    //PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_4, (intVec_t)&xint1_isr);
    //PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_5, (intVec_t)&xint2_isr);

    //PIE_enableInt(myPie, PIE_GroupNumber_1, PIE_InterruptSource_XINT_1);
    //PIE_enableInt(myPie, PIE_GroupNumber_1, PIE_InterruptSource_XINT_2);

    /*TIMER_stop(myTimer);
    TIMER_setPeriod(myTimer, 50 * 600000);
    TIMER_setPreScaler(myTimer, 0);
    TIMER_reload(myTimer);
    TIMER_setEmulationMode(myTimer, TIMER_EmulationMode_StopAfterNextDecrement);
    TIMER_enableInt(myTimer);
    TIMER_start(myTimer);*/

    GPIO_setPullUp(myGpio, GPIO_Number_28, GPIO_PullUp_Enable);
    GPIO_setPullUp(myGpio, GPIO_Number_29, GPIO_PullUp_Disable);
    GPIO_setQualification(myGpio, GPIO_Number_28, GPIO_Qual_ASync);
    GPIO_setMode(myGpio, GPIO_Number_28, GPIO_28_Mode_SCIRXDA);
    GPIO_setMode(myGpio, GPIO_Number_29, GPIO_29_Mode_SCITXDA);

    GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_GeneralPurpose);
    GPIO_setMode(myGpio, GPIO_Number_1, GPIO_1_Mode_GeneralPurpose);
    GPIO_setMode(myGpio, GPIO_Number_2, GPIO_2_Mode_GeneralPurpose);
    GPIO_setMode(myGpio, GPIO_Number_3, GPIO_3_Mode_GeneralPurpose);
    GPIO_setMode(myGpio, GPIO_Number_4, GPIO_4_Mode_GeneralPurpose);

    GPIO_setDirection(myGpio, GPIO_Number_0, GPIO_Direction_Output);
    GPIO_setDirection(myGpio, GPIO_Number_1, GPIO_Direction_Output);
    GPIO_setDirection(myGpio, GPIO_Number_2, GPIO_Direction_Output);
    GPIO_setDirection(myGpio, GPIO_Number_3, GPIO_Direction_Output);
    GPIO_setDirection(myGpio, GPIO_Number_4, GPIO_Direction_Input);

    GPIO_setMode(myGpio, GPIO_Number_12, GPIO_12_Mode_GeneralPurpose);
    GPIO_setDirection(myGpio, GPIO_Number_12, GPIO_Direction_Input);
    GPIO_setPullUp(myGpio, GPIO_Number_12, GPIO_PullUp_Disable);

    CPU_enableInt(myCpu, CPU_IntNumber_1);
    PIE_enableTimer0Int(myPie);
    CPU_enableGlobalInts(myCpu);
    CPU_enableDebugInt(myCpu);

    GPIO_setHigh(myGpio, GPIO_Number_0);
    GPIO_setHigh(myGpio, GPIO_Number_1);
    GPIO_setHigh(myGpio, GPIO_Number_2);
    GPIO_setHigh(myGpio, GPIO_Number_3);

    // GPIO12 is XINT1
    //GPIO_setExtInt(myGpio, GPIO_Number_12, CPU_ExtIntNumber_1);
    //GPIO_setExtInt(myGpio, GPIO_Number_4, CPU_ExtIntNumber_2);

    // Configure XINT1
    //PIE_setExtIntPolarity(myPie, CPU_ExtIntNumber_1, PIE_ExtIntPolarity_RisingEdge);
    //PIE_setExtIntPolarity(myPie, CPU_ExtIntNumber_2, PIE_ExtIntPolarity_FallingEdge);

    //PIE_enableExtInt(myPie, CPU_ExtIntNumber_1);
    //PIE_enableExtInt(myPie, CPU_ExtIntNumber_2);
    }

     

    int main(void)
    {
    setup_handles();
    init_system();
    scia_echoback_init();
    scia_fifo_init();

    uint32_t start, stop, result;

    TIMER_stop(myTimer);
    TIMER_reload(myTimer);

    TIMER_start(myTimer);
    start = TIMER_getCount(myTimer); // Get elapsed time since start
    DELAY_US(1000000);
    stop = TIMER_getCount(myTimer);

    result = (stop - start);

    msg = "--> 1\n\r";
    scia_msg(msg);
    DELAY_US(result);
    msg = "--> 2\n\n\r";
    scia_msg(msg);

     ----------------------------------------------------------------------------------------------------------------------------------|

  • jacksonhead said:

    I'm sorry for my  unthoughtfulness about the cite and thank you for the fast answer.

    My intention for this was not to have you beat yourself up.  I have found it beneficial to understand the reference point that individuals are using.  It cuts out any assumptions that might be made on both ends.  Thanks for providing the background below.

    jacksonhead said:

    I got the files for my projects from C:\ti\controlSUITE\device_support\f2802x\v210. I examined the cpu_timer example but i didnt saw the functions mentioned. Just to be correct i copy the code i used so its easier to see the problems i have.

    So, if I may ask now, what is the observed behavior of the problem you mention?  Is the timer not counting, resulting in the variables start and stop both equaling 0?

    Looking at the source code of TIMER_getCount(), which is found in <CONTROLSUITE_INSTALL_DIR>\controlSUITE\device_support\f2802x\v210\f2802x_common\include\timer.h as an inline function, it is simply returning the value in the TIMERxTIM register (the lower 16-bits of the 32-bit timer register).

    Do you have the ability to halt the code via the IDE (aka. CCS), open up the register window view, and step through the code to see if any of the configuration writes are happening with the TIMER?  Or any other aspect of your code as well?

    This would be the next thing to look at.  Please share what you observe so that we can try to hone in on what is going on.

  • Thank you again for your answer. So the terminal should write "--> 1" and "--> 2" with a delay of stop - start, but instead it writes these without any delay. I commented out these parts originally:

    TIMER_stop(myTimer);
    TIMER_setPeriod(myTimer, 50 * 5000);
    TIMER_setPreScaler(myTimer, 0);
    TIMER_reload(myTimer);
    TIMER_setEmulationMode(myTimer, TIMER_EmulationMode_StopAfterNextDecrement);
    //TIMER_enableInt(myTimer);
    TIMER_start(myTimer);

     but after i read your answer i unommented it and tried to change the TIMER_setPeriod(myTimer, 50 * 5000); functions value but nothing changed. I left commented the TIMER_enableInt() function because it enables the interrupt but i dont need it.

    To answer your second question i'm just learning microcontroller programming and i've been using TI-s product for 2 months. I dont know how to open the register window unfortunetly (maybe if you can link a site where these things explained i could do it i'm sorry for my incompetence).

    By the way i'm really appreciate your help, i'm glad you share some time to help to solve my problems :)

     

  • There are a couple of things that you need to realize with the CPU Timers on the device.  I would encourage you to review the TMS320x2802x/TMS320F2802xx Piccolo System Control and Interrupts Reference Guide to understand the operation of the CPU Timers.

    Firstly, they are down-counters.  Meaning, the start from a value that is found in the timer period register and decrement to zero.  Therefore, you measurements using TIMER_getCount() need to factor in that the value in your variable "stop" will be smaller than the value in your variable "start".  Therefore, you need to modify the result = (start - stop).

    Secondly, the DELAY_US() macro treats the argument passed to it as units of microseconds (ie. usec), but your result variable is in terms of cycles, not time.  You need to convert the result to time with units of microseconds in order to appropriate pass that to DELAY_US().

    As I was experimenting with an example to get a handle on the issues you were facing, I actually did find a couple of issues I believe with the TIMER_setPreScalar() and TIMER_reload() functions.  You should use the definitions I have below instead of what is built into the library.  You can add the timer.c file into your project, modify it and when you build, the code generation tools will pick up your version before looking into a pre-built library.

    void TIMER_reload(TIMER_Handle timerHandle)
    {
        TIMER_Obj *timer = (TIMER_Obj *)timerHandle;


        // set the bit
        timer->TCR |= ((uint32_t)TIMER_TCR_TRB_BITS);

        return;
    } // end of TIMER_reload() function

    void TIMER_setPreScaler(TIMER_Handle timerHandle,
                            const uint16_t preScaler)
    {
        TIMER_Obj *timer = (TIMER_Obj *)timerHandle;


        // set the bits
        timer->TPR |=
        ((uint32_t)(preScaler & 0xFF00) << 8) | ((uint32_t)(preScaler & 0x00FF) << 0);

        return;
    } // end of TIMER_setPreScaler() function

  • I modified the TIMER_setPeriod() to 0,5s like this:

    TIMER_setPeriod(myTimer, 50 * 500000);

    and

    start = TIMER_getCount(myTimer); // Get elapsed time since start
    DELAY_US(500000);  // 0,5s
    stop = TIMER_getCount(myTimer);


    So, i changed the calculation to (start - stop) as you said and converted the result into time. I did it like this:

     it ticks every 0,5s so (ticks * 0,5s) or (ticks / 2Hz)  --->  result = (start - stop) / 2;

    This way the DELAY_US(result) waited around 3s. That means without the devide it returns around 6 seconds, so if i want to have 0,5 seconds delay i needed to devide by 12. It worked and i tried it out with different numbers in the delay between the start and stop variables. But i dont know why it worked with 12?

    Other question is that the TIMER_setPeriod(myTimer, 50 * 500000); -> what is that 50? Why is that there? I dont understand the logic behind it.


    I changed the timer.h but with the modification i got 2 errors that the parts i modifed are undefinied.

    Thank you for your help :).

  • jacksonhead said:

    I modified the TIMER_setPeriod() to 0,5s like this:

    TIMER_setPeriod(myTimer, 50 * 500000);

    and

    start = TIMER_getCount(myTimer); // Get elapsed time since start
    DELAY_US(500000);  // 0,5s
    stop = TIMER_getCount(myTimer);

    Other question is that the TIMER_setPeriod(myTimer, 50 * 500000); -> what is that 50? Why is that there? I dont understand the logic behind it.

    As you stated above, you have modified the code.  Now your asking me why something is there?  What was the original code and does it make sense to you give the comments or context of the original code?

    In the original cpu_timer example, there were comments around the TIMER_setPeriod(myTimer0, 50 * 1000000); statement that indicated the CPU was operating at 50MHz clock and the example wanted to create an interrupt from the timer every 1 second.  Taking those clues into account, (50 * 1000000) = (50,000,000) which assuming the TIMER0 is operating at a divide by 1 prescalar, the timer would be clocked by a 50MHz clock.  So if you want a 1 sec interrupt (interval), divide 50000000 by 50000000.

    jacksonhead said:

    So, i changed the calculation to (start - stop) as you said and converted the result into time. I did it like this:

     it ticks every 0,5s so (ticks * 0,5s) or (ticks / 2Hz)  --->  result = (start - stop) / 2;

    This way the DELAY_US(result) waited around 3s. That means without the devide it returns around 6 seconds, so if i want to have 0,5 seconds delay i needed to devide by 12. It worked and i tried it out with different numbers in the delay between the start and stop variables. But i dont know why it worked with 12?

    I would suggest you take a look at the underlining code for DELAY_US() and the other API functions.  There is some math involved in the DELAY_US() macro because there is overhead for executing a series of instructions to generate a delay loop.  That overhead needs to be taken into account if abstracting that complication into a useful parameter to the user such as a value in units of microseconds.

    jacksonhead said:

    I changed the timer.h but with the modification i got 2 errors that the parts i modified are undefined.

    What was the reason for changing the timer.h file?  The functions I mentioned before are defined in the timer.c file, not the header file.  In the C programming language, you must declare a function before using it.  This allows the compiler to reconcile the prototype of a function as it is parsing a given C source file even though the function may be defined elsewhere (in a separate C source file or library).