Hi all!
I am trying to sample two channels with ADC0 on Kinetis K66 (MK66FN2).
I have configure the ADC to be triggered by TPM1:
tmp32 = SIM->SOPT7 & ~(SIM_SOPT7_ADC0TRGSEL_MASK | SIM_SOPT7_ADC1TRGSEL_MASK);
tmp32 |= SIM_SOPT7_ADC1ALTTRGEN_MASK | SIM_SOPT7_ADC1TRGSEL(15U) | SIM_SOPT7_ADC0ALTTRGEN_MASK | SIM_SOPT7_ADC0TRGSEL(15U);
SIM->SOPT7 = tmp32;
TPM1 is configured with a period of 8us, triggering the two ADC channels in alternating fashion:
tpm_config_t tpmConfig;
CLOCK_SetTpmClock(1U);
CLOCK_SetPllFllSelClock(1,0,0);
TPM_GetDefaultConfig(&tpmConfig);
TPM_Init(TPM1, &tpmConfig);
TPM_SetTimerPeriod(TPM1, 960); // equals 8us at 120 MHz
TPM_SetupOutputCompare(TPM1, kTPM_Chnl_0, kTPM_HighPulseOutput, 0);
TPM_SetupOutputCompare(TPM1, kTPM_Chnl_1, kTPM_HighPulseOutput, 480);
The ADC results are transfered using DMA. DMA is also triggered by TPM1:
TPM1->CONTROLS[kTPM_Chnl_0].CnSC |= TPM_CnSC_DMA_MASK;
TPM1->CONTROLS[kTPM_Chnl_1].CnSC |= TPM_CnSC_DMA_MASK;
Now the problem is, that the ADC samples after I turn off TPM1 via
TPM_StopTimer(TPM1);
I observed this by turning a GPIO pin on and off in the conversion complete ISR of the ADC. Additionally I also turn a pin on and off in the overflow ISR of TPM1 and I am able to observe the pulses using an oscilloscope.
Does anyone have an idea why the timer runs and fires after I stop it?
Hi @EdwinHz!
Thanks for your answer!
I'm afraid I cannot share the complete code.
Do you have any suggestions on how do debug this? Where to look?
I first suspected, that what I see is a product of delayed ISR execution (due to priorities or similar).
However, I am quite sure, that the conversion actually happens at those delayed times, as I inserted a test ramp and the converted values correspond to the times I meausred on the oscilloscope
Is there a more immediate option to stop a timer?
Is it somehow possible to "chain" timers/counters to start/stop a timer in hardware?
Can you think of any reason a timer would produce a trigger or an ADC would convert after the triggering timer has been stopped?
Thanks!
My guess would be that, for some reason, the CMOD register is not being written correctly by the TPM_StopTimer function. If CMOD was able to change to 00, the TPM would have no clock source to count and wouldn’t keep triggering the ADC. Why this could be the case is beyond me, but I would look into this possibility before anything else.
You could always force stop the timer with TPM_Deinit, although this is obviously NOT recommended as an alternative to stop the TMP clock.
Let me know if you find something about this.
Thanks @EdwinHz for your suggestion!
I'm still looking for the cause of this.
I'll come back and report if I find something or give up.
I tried to make a quick test based on the SDK to see if there was a more “immediate” thing that was being overlooked, but I wasn’t able to reproduce your situation. If you are willing to share your project, perhaps I could get a better insight of the problem. You can also submit a support ticket from our support webpage to send us the code directly, instead of publishing it the public community.