I am trying to use the PWM mode as a timer to measure the execution time of a certain code block. Can someone guide me on the steps to get that working. Or point me to some resources that might be handy. I have already reviewed the manuals and data sheet. I am using the Kinetis Design Studio 3.
解決済! 解決策の投稿を見る。
Hi Subhradeep,
Actually it is the same, you just need to refer the configuration code.
1. You should know your TPM source clock.
From this picture, you can get that the TPM have four source clock: MCGIRCLK, OSCERCLK, MCGFLLCLK, MCGPLLCLK.
Because I use the OSCERCLK 8Mhz, then the code is:
SIM_SOPT2 = (uint32_t)((SIM_SOPT2 & (uint32_t)~(uint32_t)(
SIM_SOPT2_TPMSRC(0x01)
)) | (uint32_t)(
SIM_SOPT2_TPMSRC(0x02)
));
2. Configure the TPM module
The TPM input clock is 8Mhz, because you want to get the 10us, then I divide the TPM clock with 8, and get 1Mhz, it is 1us.
Now, if you want to get 10us cycle, you just need to set MOD=9, then you will get (1+9)*1us=10us cycle.
The bare bone TPM code can be initialized like this:
void TPM0_Init(void)
{
/* SIM_SCGC6: TPM0=1 */
SIM_SCGC6 |= SIM_SCGC6_TPM0_MASK; // enable the TPM module
TPM0_C0SC = (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); // choose the channel 0 mode as edge-aligned PWM mode
TPM0_C0V = TPM_CnV_VAL(0x05); // choose channel 0 value = 5, dufy is 5us
/* TPM0_MOD: MOD=9 */
TPM0_MOD = (uint32_t)((TPM0_MOD & (uint32_t)~(uint32_t)(
TPM_MOD_MOD(0xFFF6)
)) | (uint32_t)(
TPM_MOD_MOD(0x09)
)); // TPM MOD =9 ,it means the TPM cycle is 10us
/* TPM0_SC: DMA=0,TOF=1,TOIE=1,CPWMS=0,CMOD=1,PS=3 */
TPM0_SC = (uint32_t)((TPM0_SC & (uint32_t)~(uint32_t)(
TPM_SC_DMA_MASK |
TPM_SC_CPWMS_MASK |
TPM_SC_CMOD(0x02) |
TPM_SC_PS(0x04)
)) | (uint32_t)(
TPM_SC_TOF_MASK |
TPM_SC_TOIE_MASK |
TPM_SC_CMOD(0x01) |
TPM_SC_PS(0x03)
));
}
The test result is the same as PE.
You can try it on your side, but at first, you should make sure your project have 8Mhz OSC at first, you can use the FRDM-KL25 board to test it.
Wish it helps you!
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Subhradeep,
If you want to measure the execution time of a certain code block, I highly suggest you use the systick instead of the PWM.
About the systick method, you can refer to our FRDM-KL25 sample code which can be downloaded from this link:
Folder:kl25_sc_rev10\klxx-sc-baremetal\build\iar\LQRUG_bme_ex1
The following code is measure the GPIOA_PDOR ^= 0x20; execution time:
systick_init();
logic_op_demo_with_normalc();
systick_disable();
void systick_init(void)
{
SYST_CVR = 0x0; //clear current timer value
SYST_RVR = 0x00FFFFFF;
SYST_CSR = SysTick_CSR_CLKSOURCE_MASK | SysTick_CSR_ENABLE_MASK;
}
void systick_disable(void)
{
SYST_CSR &= ~SysTick_CSR_ENABLE_MASK;
}
void logic_op_demo_with_normalc(void)
{
uint32_t cnt_start_value;
uint32_t cnt_end_value;
uint32_t execution_cycle; //actual execution cycle
//configure PTA5 as GPIO
PORTA_PCR5 = PORT_PCR_MUX(1);
//configure PTA5 as output pin
GPIOA_PDDR |= 0x20;
cnt_start_value = SYST_CVR;
GPIOA_PDOR ^= 0x20;
cnt_end_value = SYST_CVR;
execution_cycle = cnt_start_value - cnt_end_value - overhead;
#ifdef DEBUG_PRINT
printf("systick start value: 0x%x\n\r", cnt_start_value);
printf("systick end value: 0x%x\n\r", cnt_end_value);
printf("actual execution cycle for logic operation with normal C code: 0x%x\n\r", execution_cycle);
#endif
}
You should better use the systick to measure the code execution time, it is simple,easy and accurate.
Wish it helps you!
If you still have question, please let me know!
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Kerry
Thank you for your response. I understand that it can be done using the systick but the requirement is to use a 10us period edge aligned PWM to calculate the time duration. I am aware of what the registers need to be loaded with, I am just looking for a step by step guide, i.e. some kind of algorithm to generate the PWM and then use it to measure code execution time.
Hi Subhradeep,
If you just want to get 10us period PWM, you can refer to the KLQRUG.pdf document:
http://cache.nxp.com/files/32bit/doc/quick_ref_guide/KLQRUG.pdf
Chapter 12, you can find the TPM configuration step by step.
Besides, I also help you create a TPM KDS project, and test it on my FRDM-KL25 board, it can output 10us period edge aligned PWM in PTD0.
For the detail configuration, please check my attached KDS project.
This is the test result:
Wish it helps you!
If you still have question, please let me know!
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I forgot to mention that I need to do it without processor expert code.
I have some initial config here but it doesnt seem to work correctly
#include "MKL25Z4.h"
void main()
{
SIM_SOPT2 |= 0x01000000; //Select MCGFLLCLK as source for TPM
SIM_SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK;//Clear PLLFLLSEL to select MCGFLLCLK
SIM_SCGC5 |= 0x00003E00; //Enable Clock to Port A, B, C, D, E
SIM_SCGC6 |= 0x01000000; //Enable Clock Gating for TPM0
PORTC_PCR2 = PORT_PCR_ISF_MASK |PORT_PCR_MUX(0x4)| PORT_PCR_DSE_MASK;//Enable PTC2
PORTC_PCR3 = PORT_PCR_ISF_MASK |PORT_PCR_MUX(0x4)| PORT_PCR_DSE_MASK;//Enable PTC3 as channel outputs of TPM0
PORTB_BASE_PTR->PCR[18]=PORT_PCR_MUX(3);
TPM0_SC &= 0xFFFFFFE7;//Disable clock mode CMOD
TPM0_CNT &= 0xFFFF0000;//Initialize counter
TPM0_SC |= 0x00000080; //Clear overflow flag
TPM0_SC &= 0xFFFFFFDF; //Select up counting mode
TPM0_SC &= 0xFFFFFFF9; //Prescaler selection set to divide by 2
TPM0_MOD |= 0x0000000C;//Assuming 24 MHz clock to TPM to get 1us resolution
TPM0_SC |= 0x00000008;//Enable clock mode CMOD
TPM0_C0SC = TPM_CnSC_MSB_MASK| TPM_CnSC_ELSB_MASK;//Channel 0 is set to edge aligned and high true pulses
//TPM0_C0V = 0x00;//Initialize channel value
PTB_BASE_PTR->PDDR=1 << 18;
for(;;)
{
if(TPM0_SC & 0x00000008 == 0x00000008)
{
TPM0_SC |= 0x00000080; //Clear overflow flag
//TPM0_C0V = 0x00;//Not sure about this part
PTB_BASE_PTR->PDDR=0 << 18;
}
}
}
Hi Subhradeep,
Actually it is the same, you just need to refer the configuration code.
1. You should know your TPM source clock.
From this picture, you can get that the TPM have four source clock: MCGIRCLK, OSCERCLK, MCGFLLCLK, MCGPLLCLK.
Because I use the OSCERCLK 8Mhz, then the code is:
SIM_SOPT2 = (uint32_t)((SIM_SOPT2 & (uint32_t)~(uint32_t)(
SIM_SOPT2_TPMSRC(0x01)
)) | (uint32_t)(
SIM_SOPT2_TPMSRC(0x02)
));
2. Configure the TPM module
The TPM input clock is 8Mhz, because you want to get the 10us, then I divide the TPM clock with 8, and get 1Mhz, it is 1us.
Now, if you want to get 10us cycle, you just need to set MOD=9, then you will get (1+9)*1us=10us cycle.
The bare bone TPM code can be initialized like this:
void TPM0_Init(void)
{
/* SIM_SCGC6: TPM0=1 */
SIM_SCGC6 |= SIM_SCGC6_TPM0_MASK; // enable the TPM module
TPM0_C0SC = (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); // choose the channel 0 mode as edge-aligned PWM mode
TPM0_C0V = TPM_CnV_VAL(0x05); // choose channel 0 value = 5, dufy is 5us
/* TPM0_MOD: MOD=9 */
TPM0_MOD = (uint32_t)((TPM0_MOD & (uint32_t)~(uint32_t)(
TPM_MOD_MOD(0xFFF6)
)) | (uint32_t)(
TPM_MOD_MOD(0x09)
)); // TPM MOD =9 ,it means the TPM cycle is 10us
/* TPM0_SC: DMA=0,TOF=1,TOIE=1,CPWMS=0,CMOD=1,PS=3 */
TPM0_SC = (uint32_t)((TPM0_SC & (uint32_t)~(uint32_t)(
TPM_SC_DMA_MASK |
TPM_SC_CPWMS_MASK |
TPM_SC_CMOD(0x02) |
TPM_SC_PS(0x04)
)) | (uint32_t)(
TPM_SC_TOF_MASK |
TPM_SC_TOIE_MASK |
TPM_SC_CMOD(0x01) |
TPM_SC_PS(0x03)
));
}
The test result is the same as PE.
You can try it on your side, but at first, you should make sure your project have 8Mhz OSC at first, you can use the FRDM-KL25 board to test it.
Wish it helps you!
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thanks Kerry. just need to initialize the correct clock in the beginning.