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.
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
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
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
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?
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
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,
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