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.

TM4C1294 Periodic Timer with external clock?

Other Parts Discussed in Thread: ADS8688

I am feeding a 16.384Mhz clock to both 16-bit timer A and B of GPTM block 2, hoping to create two independent timers from the same source

B is a simple up counter, no interrupt will be fired from Timer B, it simply wraps around when overflows, and it works fine

A is intended to be configurable with reload and prescale, when it counts to zero, it will reload with preload value and fire an interrupt, and the ISR will generate a pulse

Somehow,  the pulse interval generated from Timer A ISR seems too short.

With reload number of 60000, no prescaler, and clock source of 16384000hz,  I am expecting the pulse interval from TimerA ISR to be 60000 /16384000, or ~3.66ms, but the interval between pulses is around 500us, what did I miss here?

Thanks for your time!

///Configuration codes below

main()

{

....

IntDisable(INT_TIMER2A);

MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
MAP_GPIOPinConfigure(GPIO_PM0_T2CCP0);
MAP_GPIOPinConfigure(GPIO_PM1_T2CCP1);
MAP_GPIOPinTypeTimer(GPIO_PORTM_BASE, GPIO_PIN_0);
MAP_GPIOPinTypeTimer(GPIO_PORTM_BASE, GPIO_PIN_1);

TimerConfigure(TimerBase, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PERIODIC|TIMER_CFG_B_CAP_COUNT_UP); 
TimerControlEvent(TimerBase, TIMER_A, TIMER_EVENT_POS_EDGE);

TimerDisable(TimerBase, TIMER_A);

TimerLoadSet(TimerBase, TIMER_A, 60000); 
TimerMatchSet(TimerBase, TIMER_A, 0);
TimerPrescaleSet(TimerBase, TIMER_A, 0); 
TimerPrescaleMatchSet(TimerBase, TIMER_A, 0); 
TimerEnable(TimerBase, TIMER_A);

// Configuration for Timer B is here, removed so that we don't get distracted.

HWREG(TimerBase+0x50)=0; //Reset counter, only the lower 16 bits!

IntEnable(INT_TIMER2A);

TimerIntEnable (TimerBase, TIMER_CAPA_MATCH|TIMER_CAPA_EVENT|TIMER_TIMA_TIMEOUT);

...

}

Timer2AIntHandler(void)
{
GPIOPinWrite(GPIO_PORTP_BASE,GPIO_PIN_3, 0); //LED ON
TimerIntClear(TIMER2_BASE, TIMER_CAPA_MATCH|TIMER_TIMA_MATCH|TIMER_TIMA_TIMEOUT);
GPIOPinWrite(GPIO_PORTP_BASE,GPIO_PIN_3, GPIO_PIN_3); //LED OFF
}

  • I think I may have config Timer A to use micro clock with TIMER_CFG_A_PERIODIC

    So the question becomes, how do I configure Timer A to do the job?

    A uses external clock source like B, with reload and prescale, when it counts to zero, it will reload with preload value and fire an interrupt

  • I still haven't figured out how to config the timer, can anyone give me a pointer?

    I would like Timer A to work like TIMER_CFG_A_PERIODIC, but using external clock as source instead
  • Hello David,

    The timer clock source can be either the system clock or one of the global alternate clocks such as the PIOSC, RTCOSC, or LFIOSC. Which clock are you selecting as your clock source? I don't see any clock configuration code in your example above.
  • Thanks for your reply!

    I don't want to use any internal clock courses. I tried to use an external clock on M1&M2 pins.

  • Hello David,

    This is the point. You are limited to using the system clock or one of the global alternate clocks such as the PIOSC, RTCOSC, or LFIOSC. If your system clock is derived from M1 and M2 pins (external crystal/clock source), this will be your system clock, correct? What is the frequency of the clock you are supplying on M1/M2? Do you have MCLK selected as your system clock? Assuming so, your system clock will be the output of the PLL (guessing roughly 120MHz) which is why you are getting 500us for Timer A. You may want to consider using the prescaler to allow for a longer duration of the timer. Using GPTMTAPR.TAPSR = 0x07 will give an effective Timer clock of 120MHz/0x08 will yield an effective timer clock of 15Mhz while setting to GPTMTAPR.TAPSR = 0x06 will yield a result of ~17.14MHz.
  • I can't use the external clock on M1/2 to derive the system clock, since it is also variable. I need a stable system clock to drive USB/Ethernet.

    Thanks,
  • Hi David,

    The only external clock source available for the TimerA/B is the RTCOSC. M1/M2 are not selectable as the input to the general timer module. As an alternative, perhaps you could use the Captive Count Mode to sample the external clock and setup a pseudo timer instead.
  • Can you give a little more detail on how you propose to achieve it? Thanks
  • Hi David,

    The idea is to use the clock input on a timer pin and count the number of edges (rising or falling). Each edge will cause the timer to increment by one count. You can set a match criteria so an interrupt will fire when a threshold is met but I don't think the register will reset the count as you were previously configuring the timer to do so you may need to handle this in your ISR.

    See this post for some details on edge counting code e2e.ti.com/.../1242339
  • "I don't think the register will reset the count " that's exactly what I worried :)

    I am dealing with 17Mhz clock ...

    Thanks

  • Hi David,

    Reviewing the datasheet/userguide, I wasn't correct in assuming the reload value wouldn't be effective in CCP mode. From the user guide:

    "After the match value is reached in down-count mode, the counter is then reloaded using the value
    in GPTMTnILR and GPTMTnPR registers, and stopped because the GPTM automatically clears
    the TnEN bit in the GPTMCTL register. Once the event count has been reached, all further events
    are ignored until TnEN is re-enabled by software. In up-count mode, the timer is reloaded with 0x0
    and continues counting."

    For further details of Input Edge capture mode of operation I would suggest you have a look at the Datsheet/user guide located here www.ti.com/.../tm4c1294ncpdt. Specifically, have a look at section 13.3.3.3 wich outlines the details of input edge capture operation and features.
  • Thanks

    "Once the event count has been reached, all further events are ignored until TnEN is re-enabled by software", so down-count has the possibility of missing events after the match due to latency of ISR.

    Up-count has its own limitations, too, based on my other tests
  • Hi David,

    Some things to consider. First, the latency may not be as big of an impact as you might think given the input clock is approximately 16MHz and the system clock is 120MHz. This means that there are at least 7 system clock cycles to re-enable the counter before an edge is missed. As long as you set up your interrupt priorities to prioritize this interrupt it might be enough time.

    A second alternative is to use 2 timers in CCP mode with the second/backup timer counting edges while the first is being serviced (load the count delta from the second to the first as the starting point in the ISR).

    Or, set up the counter as a 32-bit continuous/free running counter and update the match value in the ISR (perhaps this might work even with a 16 bit counter depending on the max count value you need).

    To help more, I would really need to understand a bit more about your application such as possible implications of missed edges, why the input clock is variable, what the expected range of frequency is for the clock input, etc.
  • Thanks a lot for going the extra mile to help me!

    The first approach may not work because I already have one interrupt that is highly time-critical at this point

    The second won't work due the fact I have to use the second timer connected to the same clock source for other purpose. It may have a chance if I add extra wiring to the design, but this approach has the danger of racing condition

    The third approach is worth consideration if the matching will not force the counter to stop or reload
  • ps. I use 16Mhz external clock to derive a pacing clock for ADC, if I miss counts, timing error occurs
  • "After the match value is reached in down-count mode, the counter is then reloaded using the value
    in GPTMTnILR and GPTMTnPR registers, and stopped because the GPTM automatically clears
    the TnEN bit in the GPTMCTL register. Once the event count has been reached, all further events
    are ignored until TnEN is re-enabled by software. In up-count mode, the timer is reloaded with 0x0
    and continues counting." ---- this seems to add the same timing restriction (as the first) to the third approach
  • David,

    Is the 16MHz pacing clock signal for the ADC derived from an external device such as another MCU, ASIC or system or is it simply a crystal/OSC type of circuit? I'm curious given you prior condition that the frequency is variable.

    With that said, when a match occurs, and ADC trigger can be generated to initiate the ADC conversion as you want. Also, the counter is reset to 0x0 and will begin the count up again until the match occurs again at which point another ADC conversion will be triggered. You can also setup the ADC to trigger an uDMA transfer to RAM on a conversion complete signal. This will result in a completely autonomous operation with respect to the pacing clock coming in on the CCP timer pin and converting the ADC channel(s). Once the information is transferred to RAM, you can process it at your leisure given a large enough buffer location. Is this not what you are looking for?
  • 16Mhz is from VCXOs and it can be from different frequency VCXOs depending on configuration

    I don't think we can use uDMA because the TI ADS8688 requires some handshaking before SPI

    Thanks,
  • David,

    OK. external ADC is a new requirement not previously mentioned. So, you are looking to use the timer to gate a SPI transaction with the external ADC? This means the timers ADC trigger function is not going to work and, as you mention, uDMA of the ADC results would have to be to move the SPI messages around which could be initiated by the timer match function. Not sure I have any other suggestions at this point. I'll bounce off of some other device experts here.
  • I may have to consider a different ADC along with CPLD in the design
  • Hi Chuck,

    With system clock of 120Mhz, I should not have any trouble counting edges of a 25Mhz clock since it is less than 1/4 of the system frequency, right?

    Thanks,
  • Based on my understanding from the datasheet, you are correct. The input clock must be less than 1/4 of the system clock which 25MHz satisfies given a system clock of 120MHz.

  • Chuck Davenport said:

    Based on my understanding from the datasheet, you are correct. The input clock must be less than 1/4 of the system clock which 25MHz satisfies given a system clock of 120MHz.

    Hello Chuck, I want to achieve something similar to this post. Sampling and internal ADC signal, with a high external clock (30Mhz), but at a lower rate (ie 250KHz).

    Do you think I could use any of your ways?

    Thank you