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.

TM4C timer and prescaler clarification

Other Parts Discussed in Thread: TM4C1294KCPDT

Hi everybody,
I'm trying to port an LM3S9B96 application to a TM4C1294KCPD and I have some issues with the timers. I'm working with Timer 0 split into two 16 bit timers this way:

  • System clock i 120MHz with oscillator
  • A is configured to timeout each 20ms with interrupt enabled, using a prescaler of 240
  • B is configured to detect input line changes on both edges with a prescaler of 120. I would like to measure pulse width of 256 and 512 µs with a 96µs tolerance

My setup is as follow:

    //
    // Enable peripherals
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);

   static const uint32_t RFID_TIMER_PRESCALER    = 240;
    
    //
    // Calculate switch time each 20ms
    //
    uint16_t SwitchDelayTicks = (g_ui32SysClock / (50 * RFID_TIMER_PRESCALER)) - 1;

    //
    // TIMER0 configured to handle input capture and free running 16 bit counter
    //
    TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC | TIMER_CFG_B_CAP_TIME);
    TimerPrescaleSet(TIMER0_BASE, TIMER_A, RFID_TIMER_PRESCALER - 1);
    TimerLoadSet(TIMER0_BASE, TIMER_A, SwitchDelayTicks);
    TimerPrescaleSet(TIMER0_BASE, TIMER_B, 120 - 1);
    TimerLoadSet(TIMER0_BASE, TIMER_B, 0xFFFF);
    TimerControlEvent(TIMER0_BASE, TIMER_B, TIMER_EVENT_BOTH_EDGES);    
    GPIOPinConfigure(GPIO_PL5_T0CCP1);
    GPIOPinTypeTimer(GPIO_PORTL_BASE, GPIO_PIN_5);

While A timer is correctly working (I had to make it count down instead of up to use prescaler as I was really supposing to use it...), I have strange issues with timer B. My interrupt routine is like this:

static uint16_t CaptureData[512];
static uint16_t CaptureCount = 0;
static uint16_t LastReceivedBitTicks = 0;

void Timer0B_IntHandler()
{
	uint32_t ulStatus = TimerIntStatus(TIMER0_BASE, true);

	if (ulStatus & TIMER_CAPB_EVENT)
	{
		uint16_t Delta, CurrentBitTicks;
                TimerIntClear(TIMER0_BASE, TIMER_CAPB_EVENT);
                CurrentBitTicks = HWREG(TIMER0_BASE + TIMER_O_TBR);
		Delta = LastReceivedBitTicks - CurrentBitTicks;
		CaptureData[CaptureCount] = Delta;
		CaptureCount = (CaptureCount + 1) & 511;
		....
	}
}

I'm supposing to find in CaptureCount vector the time difference between two captures, so numbers like 512 and 256, but I only found numbers around 29500-31200. What am I missing?

Another consideration on TIVA manual. On page 959 there are count ranges when using prescaler. For LM3S9B96 data is correct: when running at X [Hz] core clock, a 16 bit timer would count till (65536 * 1000) / X [ms]. At each prescaler value, this is multiplied by the prescaler factor. This is not valid for TIVA. Is this a manual issue or there is something different to consider?

Thanks in advance and regards,
Stefano

  • Hello Stefano,

    In the edge time mode the 8-bit pre-scalar forms the upper bits [23:16] of the TBR register and [15:0] is the true counter. Are you sure you have taken that into account when doing the edge capture? I would suggest taking raw readings into an array of say 10 entries for a fixed input frequency and publish the same on the forum for analysis.

    Regards
    Amit
  • Hi Amit,
    here is a collection of RAW readings from HWREG(TIMER0_BASE + TIMER_O_TBR), stored into a uint32_t array:

    0016AA47

    00164BC4

    0015EDBD

    00158F37

    00153130

    0014D2AC

    001474A5

    0014161F

    0013B817

    00135993

    0012FB8C

    00129D08

    00123F0B

    0011E08F

    00118287

    00112402

    0010C5FA

    00106775

    0010096F

    000FAAEA

    Input signal is a square wave with 400µs period (200µs high level, 200µs low level). If you consider the whole number as sample time capture, difference between samples falls between 24061 and 24198.

    I would appreciate your consideration.

    Thanks and regards,
    Stefano

  • Hello Stefano

    And it makes sense.

    E.g. Take the last 2 readings of 0x0010096F and 0x000FAAEA

    0x0010096F - 0x000FAAEA = 0x5E85 = 24197 (dec)

    24197/120e6 = 201.64e6 which is close to either the high time or low time of 200us based on which edge to edge it is.

    Regards
    Amit
  • Yep! This sounds good. In fact I was expecting to find data somehow related to fcpu/prescaler, but as I'm also reading prescaler within my counter, I think I have to consider full fcpu value in my calculations.
    And what about the datasheet annotation?
  • Hello Stefano

    Which data sheet annotation? Can you please describe the data sheet section which you are referring to?

    Regards
    Amit
  • Document is DS-TM4C1294KCPDT-15863.2743 (SPMS445B), that is Tiva™ TM4C1294KCPDT Microcontroller datasheet in it's last revision.

    On page 959 there is "Table 13-5. 16-Bit Timer With Prescaler Configurations". It's not so clear how max time is obtained with each prescaler value. For instance when no prescaler is used, with a 16 bit timer fed with 120MHz clock, timer will last till (65536 * 1000) / 120e6 = 0.54613ms and not 0.548258ms as written. Is this a calculation error or there is something more?

    Thanks in advance and regards,
    Stefano
  • Hello Stefano

    Alright I see it now. Yes, that is a mistake in the data sheet. Seems that the original source took 119.xx MHz instead of taking a theoretical 120MHz.

    Regards
    Amit