FRDM-K22F PIT TOGGLE Output Frequency

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

FRDM-K22F PIT TOGGLE Output Frequency

Jump to solution
1,250 Views
jackxu
Contributor III

Hi there,

I'm interested about the output frequency of PIT(pit_frdmk22f). I run the project pit_frdmk22f, which is a frdmk22f board driving example. The pit_source_clock is at 40MHz, and the PIT_LDVAL0 is 100000U, and using digital oscilloscope read from port PTA1, shows the frequency is 10Hz.

When i set PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, USEC_TO_COUNT(10000U, PIT_SOURCE_CLOCK)), the digital oscilloscope shows 100Hz.

When i set PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, USEC_TO_COUNT(1000U, PIT_SOURCE_CLOCK)), the digital oscilloscope shows 250Hz.

When i set PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, USEC_TO_COUNT(100U, PIT_SOURCE_CLOCK)), the digital oscilloscope shows 300Hz.

is the frequency  calculated by this PIT_SOURCE_CLOCK / PIT_LDVAL0?

TERATERM.png

#define PIT_SOURCE_CLOCK CLOCK_GetFreq(kCLOCK_BusClk)

#define PIT_CORE_CLOCK CLOCK_GetFreq(kCLOCK_CoreSysClk)

            PRINTF("\r\n PIT_SOURCE_CLOCK is: %d", PIT_SOURCE_CLOCK);

            PRINTF("\r\n PIT_CORE_CLOCK is: %d", PIT_CORE_CLOCK);

Also, what settings are needed to be set to achieve the right frequency?

Thanks in advance!

- Jack

1 Solution
899 Views
ericfoote1
NXP Employee
NXP Employee

Jack,

Additionally, it is worth mentioning that in the pit example there is a printf statement:

        if (true == pitIsrFlag)

        {

            PRINTF("\r\n Channel No.0 interrupt is occured !");

            LED_TOGGLE();

            pitIsrFlag = false;

        }

When the print statement is running, it limits the speed at which the GPIO can toggle. If you want to acheive higher speeds, it will be necessary to comment out or remove the print statement in this if statement. This should clear up your problem.

Best,

Eric

View solution in original post

7 Replies
899 Views
jackxu
Contributor III

Hi Eric,

Thanks, and i'll try some more follow your suggestion.

Regards' Jack

0 Kudos
899 Views
ericfoote1
NXP Employee
NXP Employee

Hi Jack,

After doing a little digging, this is what I found:

USEC_TO_COUNT(10000U, PIT_SOURCE_CLOCK)) is defined in the fsl_common.h file.

I am using a different board, with a core speed of 120 MHz and a bus speed of 60 MHz, but I think the logic will be the same.

In this example the PIT is clocked from the BusCLK, so my Pit source clock is 60 MHz.

Here is what the macro looks like in my fsl_common.h:

/*! Macro to convert a microsecond period to raw count value */

#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)((uint64_t)us * clockFreqInHz / 1000000U)

In essence this macro multiplies the number I enter for us by 60.

For example, if I enter "100000U" for my value,  USEC_TO_COUNT converts it to "6000000" which becomes the LDVAL.

With a PIT clock speed of 60 MHz and a LDVAL counter value of 6,000,000, the resulting frequency is 10 Hz.

I just did a test @ 68 Hz.

1/68 = 1.470588E-2 seconds = 14705.88 uS. Rounding to 14706, and passing that argument to USEC_TO_COUNT, I did indeed acheive a frequency of 68 Hz measured on my scope.

An easy shortcut to get this number is just to take 1000000/(your desired frequency) and pass that number to USEC_TO_COUNT.

I hope this helps!

Warm Regards,

Eric

899 Views
jackxu
Contributor III

Eric,

When i disable the print statement, the toggle frequency is much more higher.

But there is some more question about the macro

/*! @name Timer utilities */

/* @{ */

/*! Macro to convert a microsecond period to raw count value */

#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)((uint64_t)us * clockFreqInHz / 1000000U)

I'm confuse about the us, the us changes @ different frequency?

when i set the core frequency @ 80MHz, bus speed @ 40MHz

     I enter "10U" for my value,  measured @ 100kHz , then the us is 40?

     I enter "100U" for my value,  measured @ 10kHz , then the us is 40?

when i set the core frequency @ 96MHz, bus speed @ 48MHz

     I enter "10U" for my value,  measured @ 100kHz , then the us is 48?

     I enter "100U" for my value,  measured @ 10kHz , then the us is 48?

when i set the core frequency @ 100MHz, bus speed @ 50MHz

     I enter "10U" for my value,  measured @ 100kHz , then the us is 50?

     I enter "100U" for my value,  measured @ 10kHz , then the us is 50?

Thanks in advance,

Jack

0 Kudos
899 Views
ericfoote1
NXP Employee
NXP Employee

Jack,

The argument you pass to the Marco is constant. It is the number of microseconds you want your period to be. What changes relative to the bus speed is the "count".  Here is how it works. It first takes the argument you pass to it, in your example, "10U" or "100U". This value gets passed to the Macro and becomes us. The other value it uses is the PIT_SOURCE_CLOCK, which becomes clockFreqInHz, which is defined as the bus clock for this example.

This macro converts time in units of micro seconds, into a total count number, or LDVAL. I'll use your example of 40 MHz to illustrate. Let's say we want the period to be half a second, which is 500,000 us. My function call would look something like this:

PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, USEC_TO_COUNT(500000U, PIT_SOURCE_CLOCK));

Now, assuming the bus speed is 40 MHz, the macro would would take the bus speed and divide it by 1000000. This gives a value of 40, which is how many cycles the bus clock goes through in one microsecond. Thus, in order for the PIT to have a period of half a second, or 500000 us, the LDVAL would have to be (40 clock cycles/microsecond)(500000 microseconds) or 20,000,000 clock cycles. Convert to hex and you get 0x1312D00 as your LDVAL. As you adjust your bus speed, the only thing that really changes is the number of cycles per unit time, and thus your count and LDVAL values.

So, for this case:

"when i set the core frequency @ 100MHz, bus speed @ 50MHz

     I enter "10U" for my value,  measured @ 100kHz , then the us is 50?

     I enter "100U" for my value,  measured @ 10kHz , then the us is 50?"

us is "10U" and "100U" respectively. You have the right idea though, 50 is the number of clock cycles per microsecond.

I hope this helps.

Best,

Eric

899 Views
jackxu
Contributor III

Hi Eric,

Recently i'm trying to write some routine with PIT control GPIOs, but it runs in disorder. Part of PIT0_IRQHandler routine as follow:

/****************************PIT0_IRQHandler***********************************************/

cnt1 = (cnt1 + 1) & 0xff;

const1 = 500;

/**********************************************************************************************/

if (const1 >500)

{

     if(cnt1 < 64)

     {

          GPIO_ClearPinsOutput(BOARD_PIN1_GPIO, 1U << BOARD_PIN1_GPIO_PIN);

     }

     else if (cnt1 < 128)

     {

          GPIO_SetPinsOutput(BOARD_PIN1_GPIO, 1U << BOARD_PIN1_GPIO_PIN);

     }

     else

     {

          GPIO_ClearPinsOutput(BOARD_PIN1_GPIO, 1U << BOARD_PIN1_GPIO_PIN);

     }

}

else

     GPIO_ClearPinsOutput(BOARD_PIN1_GPIO, 1U << BOARD_PIN1_GPIO_PIN);

/***************************************************************************************************/

if (cnt1 < 128)

{

     GPIO_ClearPinsOutput(BOARD_PIN2_GPIO, 1U << BOARD_PIN2_GPIO_PIN);

}

else if(cnt1 < 192)

{

     GPIO_SetPinsOutput(BOARD_PIN2_GPIO, 1U << BOARD_PIN2_GPIO_PIN);

}

else

{

     GPIO_ClearPinsOutput(BOARD_PIN2_GPIO, 1U << BOARD_PIN2_GPIO_PIN);

}

/*****************************************************************************************************/

if(cnt1 > 256)

{

     cnt1 = 0;

}

/*****************************************************************************************************/

/********************************Main****************************************************************/

    PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, 2000);

and set my bus clock @ 50MHz, then the PIN1's frequency should @50MHz/2000/256=97.66Hz

But read from my scope is @195Hz

also the PIN2's frequency is the same as the PIN1

also the timing of @64 @128 @192 is wrong.

Thanks in advance!

-Jack

0 Kudos
900 Views
ericfoote1
NXP Employee
NXP Employee

Jack,

Additionally, it is worth mentioning that in the pit example there is a printf statement:

        if (true == pitIsrFlag)

        {

            PRINTF("\r\n Channel No.0 interrupt is occured !");

            LED_TOGGLE();

            pitIsrFlag = false;

        }

When the print statement is running, it limits the speed at which the GPIO can toggle. If you want to acheive higher speeds, it will be necessary to comment out or remove the print statement in this if statement. This should clear up your problem.

Best,

Eric

304 Views
shaq
Contributor I

hi

iam new to this freertos iam facing issue in PIT iam sharing my code once check 

issue:-i am raising interrupt but the semaphore is not relesing and task is not working 

code:

#include <stdio.h>

 

/* Kernel includes. */

#include "FreeRTOS.h"

#include "task.h"

#include "timers.h"

#include "fsl_pit.h"

 

/* Freescale includes. */

#include "fsl_device_registers.h"

#include "fsl_debug_console.h"

#include "board.h"

 

#include "pin_mux.h"

#include "clock_config.h"

#include "semphr.h"

SemaphoreHandle_t xSemaphore = NULL;

TaskHandle_t myTaskHandle = NULL;

 

#define PIT_IRQ_ID PIT_IRQn

/* Get source clock for PIT driver */

#define PIT_SOURCE_CLOCK CLOCK_GetFreq(kCLOCK_OscClk)

 

volatile bool pitIsrFlag = false;

 

void PIT_IRQHandler(void)

{

// Clear the interrupt flag

PIT_ClearStatusFlags(PIT, kPIT_Chnl_0, kPIT_TimerFlag);

pitIsrFlag = true;

 

// Notify the RTOS that an interrupt occurred

BaseType_t xHigherPriorityTaskWoken = pdFALSE;

PRINTF("In IRQ_HANDLER\r\n");

xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );

//vTaskNotifyGiveFromISR(myTaskHandle, &xHigherPriorityTaskWoken);

portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

}

 

void PIT_Task(void *pvParameters)

{

PRINTF(" IN PIT TAsk\r\n");

while (1)

{

// Wait for the PIT interrupt notification

if( xSemaphoreTake( xSemaphore, portMAX_DELAY ) == pdTRUE )

{

// ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

// Handle the PIT interrupt

printf("PIT interrupt occurred\n");

}

}

}

 

int main(void)

{

/* Structure of initialize PIT */

pit_config_t pitConfig;

 

/* Board pin, clock, debug console init */

BOARD_ConfigMPU();

BOARD_InitPins();

BOARD_BootClockRUN();

BOARD_InitDebugConsole();

 

xSemaphore = xSemaphoreCreateBinary();

if(xSemaphore != NULL)

{

PRINTF("semaphore created\r\n");

}

 

/* Enable clock gate for GPIO1 */

CLOCK_EnableClock(kCLOCK_Gpio1);

/* Set PERCLK_CLK source to OSC_CLK*/

CLOCK_SetMux(kCLOCK_PerclkMux, 1U);

/* Set PERCLK_CLK divider to 1 */

CLOCK_SetDiv(kCLOCK_PerclkDiv, 0U);

/*

* pitConfig.enableRunInDebug = false;

*/

PIT_GetDefaultConfig(&pitConfig);

 

/* Init pit module */

PIT_Init(PIT, &pitConfig);

 

/* Set timer period for channel 0 */

// PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, USEC_TO_COUNT(1000000, PIT_SOURCE_CLOCK));

PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, USEC_TO_COUNT(10000U, PIT_SOURCE_CLOCK));

 

 

 

/* Enable timer interrupts for channel 0 */

PIT_EnableInterrupts(PIT, kPIT_Chnl_0, kPIT_TimerInterruptEnable);

 

/* Enable at the NVIC */

EnableIRQ(PIT_IRQ_ID);

 

/* Start channel 0 */

PRINTF("\r\nStarting channel No.0 ...\r\n");

PIT_StartTimer(PIT, kPIT_Chnl_0);

xTaskCreate(PIT_Task, "PIT_Task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &myTaskHandle);

vTaskStartScheduler();

for(;;);

}

 

0 Kudos