Author Topic: Getting current timer counter value (FTM)  (Read 5615 times)

Offline AlexS

  • Newbie
  • *
  • Posts: 46
    • View Profile
Getting current timer counter value (FTM)
« on: June 01, 2018, 03:05:36 PM »
Hi,

Is manually accessing the FTM_CNT register the only option to get the current value of an FTM counter?

Thanks!

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Getting current timer counter value (FTM)
« Reply #1 on: June 01, 2018, 09:12:52 PM »
Hi Alex

There is no API to get the value so direct access is the method to use:
FTM0_CNT
FTM1_CNT
FTM2_CNT

etc.
Or else
FLEX_TIMER_MODULE *ptrFlexTimer = (FLEX_TIMER_MODULE *)FTM_BLOCK_0;
ptrFlexTimer->FTM_CNT;


Generally I think that this is a suitable method due to maximum efficiency.

I believe an API would look something like

volatile unsigned short fnGetCounter(int iTimerRef)
{
    FLEX_TIMER_MODULE *ptrFlexTimer;
    switch (iTimerRef) {
    case 0:
        ptrFlexTimer = (FLEX_TIMER_MODULE *)FTM_BLOCK_0;
        break;
    case 1:
        ptrFlexTimer = (FLEX_TIMER_MODULE *)FTM_BLOCK_1;
        break;
    default:
        return 0;
    }
    return ptrFlexTimer->FTM_CNT;
}


or

volatile unsigned short fnGetCounter(FLEX_TIMER_MODULE *ptrFlexTimer)
{
    return ptrFlexTimer->FTM_CNT;
}


but
FTM0_CNT
is still the fastest....


Regards

Mark



Offline AlexS

  • Newbie
  • *
  • Posts: 46
    • View Profile
Re: Getting current timer counter value (FTM)
« Reply #2 on: July 23, 2018, 02:05:57 PM »
Hi,

So as to not create (yet) another topic, I'll post here. In my PE project that I'm porting, I used one of the FlexTimers to measure the distance between two events. The frequency is configured dynamically on startup, depending on settings, ranging from 2us to 16us / timer tick.  I used the timer period with the 'On Counter Restart' event to detect timeouts.

From my reading of the guide on HW timers (http://www.utasker.com/docs/uTasker/uTaskerHWTimers.PDF), the closest thing available would be the periodic timer using the FlexTimer and then slightly extending its functionality to include the ability to read the counter, change the timer period, reset it and so on.

Also, is it possible to use one of the FTM's channels to essentially have two different periodic interrupts running at the same time on the same module?
« Last Edit: July 23, 2018, 02:39:10 PM by AlexS »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Getting current timer counter value (FTM)
« Reply #3 on: July 24, 2018, 12:21:44 AM »
Alex

I didn't understand fully the first timer requirement - if you try it but have difficulties, explain what is not working as it should (and how it is required) and I'll take a look at it.

It is possible to have a periodic timer interrupt for a FlexTimer (or TPM) plus additional channel interrupts; or channel DMA triggers.

Take a look at the DMX512 code in DMX512.c in the uTasker application, and its function fnConfigDMX_framing() [I have copied it below as it is today]. This is used to generate a DMX512 frame period, plus two two interrupts from channel which fire at defined points in the frame (I have also used DMA to trigger events at the same points when really accurate timing is needed). The diagram on page 5 of the attached DMX512 document (the document is in progress and so is provisional) shows the timing.

Code: [Select]
static void fnConfigureDMX512_framing(void)
{
    // Set up a periodic timer to control the frame rate
    // - this method is suitable for kinetis parts using a PWM channel to control the break and period, plus a second channel to define the MAB
    //

    // TPM1 setup
    //
    PWM_INTERRUPT_SETUP pwm_setup;
    pwm_setup.int_type = PWM_INTERRUPT;
    pwm_setup.int_handler = 0;
    #if defined FRDM_K64F
    pwm_setup.pwm_reference = (_TIMER_0 | 0);                            // timer module 0, channel 0
    pwm_setup.pwm_mode = (/*PWM_SYS_CLK | */PWM_PRESCALER_128 | PWM_EDGE_ALIGNED | PWM_POLARITY/* | PWM_NO_OUTPUT*/); // clock PWM timer from the system clock with /16 pre-scaler (don't configure teh clock until all channels are set up)
    pwm_setup.pwm_frequency = (unsigned short)PWM_TIMER_US_DELAY(DMX512_PERIOD, 128); // generate frame rate frequency on PWM output
    #else
    pwm_setup.pwm_mode = (PWM_SYS_CLK | PWM_PRESCALER_32 | PWM_EDGE_ALIGNED | PWM_POLARITY/* | PWM_NO_OUTPUT*/); // clock PWM timer from the system clock with /32 pre-scaler
    pwm_setup.pwm_reference = (_TPM_TIMER_1 | 0);                        // timer module 1, channel 0
        #if defined _WINDOWS
    pwm_setup.pwm_mode |= PWM_PRESCALER_128;
    pwm_setup.pwm_frequency = (unsigned short)PWM_TPM_CLOCK_US_DELAY(DMX512_PERIOD, 128); // generate frame rate frequency on PWM output
        #else
    pwm_setup.pwm_frequency = (unsigned short)PWM_TPM_CLOCK_US_DELAY(DMX512_PERIOD, 32); // generate frame rate frequency on PWM output
        #endif
    #endif
    pwm_setup.pwm_value = ((pwm_setup.pwm_frequency * DMX512_MASTER_BREAK_DURATION)/DMX512_PERIOD); // output starts low (inverted polarity) and goes high after the break time
    pwm_setup.int_priority = PRIORITY_HW_TIMER;                          // interrupt priority of cycle interrupt
    pwm_setup.pwm_mode |= PWM_CHANNEL_INTERRUPT;                         // use channel interrupt to stop the break
    pwm_setup.channel_int_handler = _mab_start_interrupt;
    START_DMX512_MASTER_BREAK();                                         // generate the first break immediately
    fnConfigureInterrupt((void *)&pwm_setup);                            // configure and start
    #if defined FRDM_K64F
    pwm_setup.pwm_reference = (_TIMER_0 | 1);                            // timer module 0, channel 1
    pwm_setup.pwm_mode |= (PWM_SYS_CLK);                                 // configure the clock so that all channels are ready at start
    #else
    pwm_setup.pwm_reference = (_TPM_TIMER_1 | 1);                        // timer module 1, channel 1
    #endif
    pwm_setup.pwm_value = ((pwm_setup.pwm_frequency * (DMX512_MASTER_BREAK_DURATION + DMX512_MASTER_MAB_DURATION))/DMX512_PERIOD); // second channel goes high after the MAB period to control the timing for the start of the frame transmission
    pwm_setup.int_handler = _frame_interrupt;                            // interrupt call-back on PWM cycle
    pwm_setup.channel_int_handler = _mab_stop_interrupt;
    fnConfigureInterrupt((void *)&pwm_setup);                            // configure and start
}

The use s not described in the HW timer document (yet) but it is simple to use - just add the flag PWM_CHANNEL_INTERRUPT and a a callback to channel_int_handler.

Regards

Mark

Offline AlexS

  • Newbie
  • *
  • Posts: 46
    • View Profile
Re: Getting current timer counter value (FTM)
« Reply #4 on: July 24, 2018, 09:55:23 AM »
Hi Mark,

Thanks, the DMX example covers everything I wanted to know. Much appreciated. Will try it today and let you know how it goes.

Regards,
Alex