K64F timing issue

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

K64F timing issue

1,212 Views
cesarhoyos
Contributor I

Hello everybody,

I am working with FRDM K64F developer platform.

I am using K64F in order to interface some sensors with my PC.

These sensors work in one of the following frequencies: 400Hz and 10kHz. Also I want a higher frequency in order to have a "clock" for my system (1MHz) counting one by one microsecond, being the time mark for data register.

I programmed three PITs in order to read sensors and get this timing:

    #define PIT_SOURCE_CLOCK CLOCK_GetBusClkFreq()
    #define FEQ_SENS 400U
    #define FEQ_SENS_2 10000U
    #define FEQ_CLOCK 1000000U
    pit_config_t pit_config;
    PIT_GetDefaultConfig(&pit_config);
    pit_config.enableRunInDebug = true;

    //PIT_Deinit(PIT);
    PIT_Init(PIT, &pit_config);

    PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, PIT_SOURCE_CLOCK/(FEQ_SENS)-1);
    PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, PIT_SOURCE_CLOCK/(FEQ_SENS_2)-1);
    PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, PIT_SOURCE_CLOCK/(FEQ_CLOCK)-1);
    PIT_EnableInterrupts(PIT, kPIT_Chnl_0, kPIT_TimerInterruptEnable);
    PIT_EnableInterrupts(PIT, kPIT_Chnl_1, kPIT_TimerInterruptEnable);
    PIT_EnableInterrupts(PIT, kPIT_Chnl_2, kPIT_TimerInterruptEnable);

    EnableIRQ(PIT0_IRQn);
    EnableIRQ(PIT1_IRQn);
    EnableIRQ(PIT2_IRQn);

    PIT_StartTimer(PIT, kPIT_Chnl_0);
    PIT_StartTimer(PIT, kPIT_Chnl_1);
    PIT_StartTimer(PIT, kPIT_Chnl_2);

With all this, then in execution time, I have been looking the number of data that have been registered in 10sec (measured with 1MHz PIT) and there are more data than there should be. If there should be 100k data, there are 101052 (constantly each 10sec).

Also, I have done some proofs toggling digital pins out, and watching square signals in oscilloscope:

- For 400Hz there are not deviation.

- For 10kHz there are little deviation, but there are not problematic (most of measures indicates 10kHz, and a few indicates 9'99804kHz).

- For 1MHz the deviation is bigger. Oscilloscope indicates 983'63kHz and some times is rise to 983'632kHz.

The point is, is there any limitation of use of this PIT module? How much is this error? Could it be fixed by some method?

If there is a frequency limitation, I would be fine by using this limitation as clock of my system. Else, could you recommend another method to solve my timing issue?

Thanks for your attention.

0 Kudos
7 Replies

803 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Cesar,

I think two fators leads to the PIT cycle deviation:

1)The PIT clock source is inaccurate

2)The truncation error

If you use Internal Reference Clock(IRC), the IRC clock should be trimmed, otherwise, it is inaccurate.

Regarding the truncation error, assume that you use the default clock(FEI mode) as the PIT clock, which is 20.6MHz, if you hope PIT output 1MHz interrupt, the PIT load value register is 21, the actual PIT frequency is 20.6MHz/21=0.981Mhz, if you toggle a GPIO in ISR of PIT, there are 981K toggle edges. If you want to get accurate PIT cycle time, pls use120MHz core clcok for K64, and use 60MHz clock as bus clock and PIT driving clock source, in the case, the truncation error will be 1/60=1.7%

Hope it can help you

BR

Xiangjun Rong

0 Kudos

803 Views
cesarhoyos
Contributor I

Thanks for your answer.

I did not reply you back cause of I was re-reading K64 reference manual and KSDK API Reference looking for a better solution.

The point is, ok, I cannot do my microsecond clock by PIT, but can I?

I have been reading deeper the clock driver in both references but I am still not sure how to proceed.

At this point, If the PIT actual frequency is 0.981MHz for sure and constantly, I can use this knowing that each interruption won't be each microsecond but each 1'01941 us.

On the other hand, I did not change PIT source clock, and I thought that by default it was set to use Bus Clk, so in my first post I wrote "#define PIT_SOURCE_CLOCK CLOCK_GetBusClkFreq()" asuming this and working fine with other channels (10k and 400).

Thanks for your attention, I hope I can find out how to go on in the next days but all information you can offer me will be welcome.

Regards,

César Hoyos

0 Kudos

803 Views
mjbcswitzerland
Specialist V

Hi

If you need a 1MHz output a FlexTimer is the best method.

If you need a 1MHz interrupt the PIT can do this very accurately when running from a 60MHz bus clock.

However beware that 1MHz interrupt is a high overhead even for the K64 and if you generate an output it will have a certain amount of jitter.

I have attached a binary for the FRDM-K64F that generates a 500kHz output on J1-2 (PTC16) using PIT0 interrupt. The PIT0 interrupt is given highest priority and can pre-empt other interrupts and otherwise protected critical regions - it has about 10% jitter but is otherwise very accurate - eg. measured over 10 interrupts it it 10.0us.

Regards

Mark

0 Kudos

803 Views
cesarhoyos
Contributor I

Thanks so much for the example.

I am still not sure how to proceed.

Your example works perfectly. I changed my PIT channels in order of your suggestion but I get the same speed.

How can I configure it?

0 Kudos

803 Views
mjbcswitzerland
Specialist V


Hi

I use the uTasker project which does it according to the document:
http://www.utasker.com/docs/uTasker/uTaskerHWTimers.PDF

The project is available in open source form at http://www.utasker.com/forum/index.php?topic=1721.msg7086#msg7086

The user code is:
    PIT_SETUP pit_setup;                                                 // PIT interrupt configuration parameters
    pit_setup.int_type = PIT_INTERRUPT;
    pit_setup.mode = PIT_PERIODIC;
    pit_setup.int_handler = timer_int_1us;
    pit_setup.int_priority = PIT0_INTERRUPT_PRIORITY;
    pit_setup.count_delay = PIT_US_DELAY(1);               // 1us period
    pit_setup.ucPIT = 0;                                                      // use PIT0
    fnConfigureInterrupt((void *)&pit_setup);                      // configure PIT


In the interrupt I toggle the output:

#define TOGGLE_TEST_OUTPUT()    _TOGGLE_PORT(C, PORTC_BIT16)             // J1-2

static void timer_int_1us(void)
{
    TOGGLE_TEST_OUTPUT();
}


The PIT driver does (essentially - showing values)
POWER_UP(6, SIM_SCGC6_PIT);
PIT_MCR = 0;                            // ensure the PIT module is clocked
fnEnterInterrupt(irq_PIT0_ID, PIT_settings->int_priority, _PIT0_Interrupt); // ensure that the handler for this PIT is entered
PIT0_LDVAL = 0x3b;                 // load interval value
PIT0_TCTRL = 0x03;               // start PIT with interrupt enabled

Regards

Mark

0 Kudos

803 Views
cesarhoyos
Contributor I

Thanks so much.

I've looking the links but I am not sure how to transcript this to Kinetis SDK API.

I'm going to follow FTM solution in order to have an accurate precise clock.

Now on, I have been looking that if in clock_config.h file changing #define BOARD_XTAL0_CLK_HZ 50000000U to #define BOARD_XTAL0_CLK_HZ 49283072U which is 47*2²⁰, then I can get the exact same clock pulse at 500'011MHz. Althought this does not seem right to me.

I think I must study deeper the reference manual to understand better how FTM works and then go back to programming.

Regargs,

0 Kudos

803 Views
mjbcswitzerland
Specialist V

Hi

The links may give you a much better overall solution than SDK for getting complete projects finished. If you can only use SDK you will need to work out the underlying details by studying how the peripherals work and piecing the components together. Possibly there are some rounding errors in the present calculations.

Regards

Mark

0 Kudos