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.

Can the timer be run at 3usec rate

What I want to do is have the timer trigger an ADC converstion every 3 usecs and then use DMA to pick upt conversion results. I have tried to do some preliminary tests and the best I see 6 usecs. If I set the timer to run at 30usecs its seems to work fine but when I set it to 3usecs it looks like the best it can do is 6usecs. I am using the DK-TM4C123G Tiva C launchpad and I run my clock at 80 Mhz.

 

void

hwiInit()

{

uint32_t ui32Period;

uint32_t testNum =55;

   

GPIO_setupCallbacks(&Board_gpioCallbacks0);

   

/* Enable interrupts */

    

GPIO_enableInt(Board_BUTTON0, GPIO_INT_RISING);

 

//Set CPU Clock to 40MHz. 400MHz PLL/2 = 200 DIV 5 = 40MHz

 

//SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

// Timer 2 setup code

SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); // enable Timer 2 periph clks

TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC); // cfg Timer 2 mode - periodic

ui32Period = (

SysCtlClockGet() * 3)/1000000;

// set to 3 microseconds

TimerLoadSet(TIMER2_BASE, TIMER_A, ui32Period); // set Timer 2 period

TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT); // must clear timer flag FROM timer

TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT); // enables Timer 2 to interrupt CPU

TimerDisable(TIMER2_BASE, TIMER_A); // disable Timer 2 until ready to start taking ADC data

/*Enable output */

GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_2);

GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_2, 0x00);

}

 

 

 

void

timerInterrupt()

{

  

TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT); // must clear timer flag FROM timer

if(GPIOPinRead(GPIO_PORTJ_BASE, GPIO_PIN_2))

{

GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_2,0);

}

else

{

GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_2, 4);

}

}

/*

*  ======== main ========

*/

Int

main(Void)

{

   

/* Call board init functions. */

    Board_initGeneral();

    Board_initGPIO();

    hwiInit();

 

   

/* Start BIOS */

    BIOS_start();

   

return (0);

}

Void gpioButtonFxn0(Void)

{

GPIO_clearInt(Board_BUTTON0);

TimerEnable(TIMER2_BASE, TIMER_A); // disable Timer 2 until ready to start taking ADC data

TimerIntEnable(TIMER2_BASE, TIMER_A);

}

  • Hi Teresa,

    The SysCtlClockSet function is commented, so I am not sure what the System Clock is. However looking at the code, it should be OK for the timer as you have used the clock frequency to compute. Instead of toggling a GPIO, you can use the Timer CCP Pins which can be toggled on timeout. This way any CPU overhead is eliminated.

    Regards

    Amit Ashara

  • Hi Amit,

    I have not used the Timer CCP so just to verify since I am using Timer 2 I want to configure PF4 which is T2CCP0

    GPIOinConfigure(GPIO_PF4_T2CCP0)

    GPIOinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_4)

  • Hi Teresa,

    Yes, that is correct. I have updated the code as below.

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    GPIOPinConfigure(GPIO_PF4_T2CCP0)

    GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_4)

    I think I made a mistake as well. The CCP pin is available only in PWM Mode and not Periodic Mode. But having said that it should still be able to tell that the 3us pulse tick is correct or not.

    You can refer to the pwm.c example in the TIVAWare.

    Regards

    Amit Ashara

  • Hi Teresa,

    Also a couple of questions

    1. What is the value of the register SYSCTL.DC1 (@ address 0x400FE010)

    2. The only change when you are running the code for 30us is in the equation for calculating ui32Period

    (SysCtlClockGet()*30)/1000000 Is that right?

    Regards

    Amit

  • 1. ox13332fff

    2. I want my interrupt every 3usec not 30

  • Hello Teresa,

    Thanks for the data. In the first post you mentioned that it works properly for 30us but not for 3us. Hence I asked how you were configuring for 30usec.

    Also can you please send the function call for setting the clock frequency for 80MHz?

    Regards

    Amit Ashara

  • 1. when I got to working 30 usec I used ui32Period = (SysCtlClockGet() * 3)/100000;

    2. I tried configuring using CCP and setting it up for PWM operation but nothing come out on the pin Port F pin4 

         //Set CPU Clock to 80MHz. 400MHz PLL/2 = 200 DIV 2.5 = 80MHz
        SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

        // Timer 2 setup code
        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);            // enable Timer 2 periph clks
        SysCtlPWMClockSet(SYSCTL_SYSDIV_1);

        TimerConfigure(TIMER2_BASE, TIMER_CFG_A_PWM);        // cfg Timer 2 mode - periodic
        testNum = SysCtlClockGet();
        ui32Period = (SysCtlClockGet() * 3)/1000000;
        System_printf("ui32Period after  =  %i, %i", ui32Period,testNum);

        System_flush();
        // set to 3 microseconds
        TimerLoadSet(TIMER2_BASE, TIMER_A, ui32Period);            // set Timer 2 period
        TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT);            // must clear timer flag FROM timer

        TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);        // enables Timer 2 to interrupt CPU
        //TimerControlTrigger(TIMER2_BASE, TIMER_A, 1);            // set Timer 2 period

        TimerDisable(TIMER2_BASE, TIMER_A);                        // disable Timer 2 until ready to start taking ADC data

        /*Enable output */
        SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);            // enable Timer 2 periph clks
        GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_4);
        PWMGenConfigure(PWM0_BASE, PWM_GEN_0,PWM_GEN_MODE_DOWN|PWM_GEN_MODE_NO_SYNC);

        GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_2);
        GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_2, 0x00);
        //Configure PWM mode
        PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0,ui32Period);
        PWMPulseWidthSet(PWM0_BASE, PWM_GEN_0, ui32Period);
        PWMGenEnable(PWM0_BASE, PWM_GEN_0);

  • Hello Teresa,

    I tired the code that you sent yesterday with 32-bit periodic timer and I see 3us interval. Now the DC1 register I asked for has the value 0x13332FFF. The value 2 in this register corresponds to a maximum system clock of 66MHz and not 80MHz. You can see the description.

    In other words it does not allow 80MHz clock to be set. This along with the fact that 30us works are contradictory. I will suggest tow things here

    1. Can you change the System Clock to be 40MHz and then see the 3us works in the old code you had as it is working fine on my device.

    2. I will write a simple test code which will allow you to see regular 1us/3us/30us event based on both 40MHz and 80MHz. This can then be used to find out whether there is a Software problem in reading the system clock or not.

    Regards

    Amit

  • Did you run your test on the same board as me? Why does all the literature say it can run at 80 MHz and yet i it can only run at 66Mhz? Do I have to make a register change to get it to run at 80?

  • Hi Teresa,

    I have attached a simple C Code to lock the PLL at 80MHz and tested it on my side (it is a derivative of your test code). The first thing I noticed was the time period of the square pulse is 6us as you mentioned. However this because you are running the timer in periodic mode with 3us and toggling the GPIO on every interrupt. So I made a small change to the Timer Load computation (divided it by 200000). I was able to get 3 us timer period on the square wave. Now if you run this test code with different clock settings could you let me know what is the period of the square wave.

    Please note that for 80MHz the square wave period of this test code is 3 us.

    //*****************************************************************************
    //
    // hello.c - Simple hello world example.
    //
    // Copyright (c) 2012-2013 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.0.1.11577 of the EK-TM4C123GXL Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/timer.h"
    #include "driverlib/interrupt.h"
    #include "utils/uartstdio.h"
    #include "utils/random.h"
    
    #include <string.h>
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>Hello World (hello)</h1>
    //!
    //! A very simple ``hello world'' example.  It simply displays ``Hello World!''
    //! on the UART and is a starting point for more complicated applications.
    //!
    //! UART0, connected to the Virtual Serial Port and running at
    //! 115,200, 8-N-1, is used to display messages from this application.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    void hwiInit()
    {
      uint32_t ui32Period;
    
      SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    
      // Timer 2 setup code
      SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); // enable Timer 2 periph clks
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ); // enable Timer 2 periph clks
      TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC); // cfg Timer 2 mode - periodic
    
      ui32Period = (SysCtlClockGet() * 3)/2000000;
    
      // set to 3 microseconds
      TimerLoadSet(TIMER2_BASE, TIMER_A, ui32Period); // set Timer 2 period
      TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT); // must clear timer flag FROM timer
      TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT); // enables Timer 2 to interrupt CPU
      TimerEnable(TIMER2_BASE, TIMER_A); // disable Timer 2 until ready to start taking ADC data
      IntMasterEnable();
      IntEnable(INT_TIMER2A);
    
      /*Enable output */
      GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_2);
      GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_2, 0x00);
    
    }
    
    void timerInterrupt(void)
    {
    
      TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT); // must clear timer flag FROM timer
      if(GPIOPinRead(GPIO_PORTJ_BASE, GPIO_PIN_2))
      {
       GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_2, 0);
      } else {
       GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_2, 4);
      }
    
    }
    
    /*
    
    *  ======== main ========
    
    */
    
    int main(void)
    
    {
    
        hwiInit();
    
        while(1);
    
        return (0);
    
    }
    

    Regards

    Amit Ashara

  • Hi Amit,

    When I run the code you attached in a standard code composer project everything runs fine. When I put that same code in a project that uses the TI_RTOS the interrupt goes out to 5.5 u sec. So it must have to do with some overhead associated with how the RTOS handles interrupts.

  • Hello Teresa,

    That is correct. The RTOS has overhead and this gets added to the GPIO toggling. If the same value is used for ADC HW trigger, then it should work fine at 3us resolution

    Regards

    Amit Ashara