Hello Jorge,
I read the other post about interrupt latency, but I am using the fast GPIO port (IOPORT) at 0xF800_0000, so the peripheral bus latency due to the cross-bar architecture doesn't apply does it?
I know the interrupt latency is not easy to measure, but for my application I need to know the time from an input edge to the interrupt handling routine where I toggle an output pin. If I was off just a couple of clocks from the 15 cycles quoted for M0+ interrupt latency, I wouldn't worry about it. But since I measured an extra 12 clocks, I want to understand where it is coming from in case I can do something about it). For example, is it something in my code, something in my setup, something in the FTM module, or undocumented interrupt latency clock cycles for the Freescale implementation of the M0+?
Background info: I am using PTC0 for the input and PTB5 for the output. I am using a function generator to drive the input pin and I am using an oscilloscope to measure from the rising edge of the input to the toggling edge of the output pin. The core/system clock is running at 48MHz and the Bus/Flash clock is 24MHz.
To try to account for setup/measurement errors, I tried to measure the actual switching threshold of the input by adjusting the output level of the generator until the input was detected as high. Then I added ~ 1.5V to that value for the trigger level on my scope to make sure the rise time of the function generator did not add to the delay I was trying to measure. I also added in one extra clock to the expected interrupt latency as an additional error factor for the input signal rise time.
Here is the end of main() where the FTM gets initialized:
/* Select capture mode for the FTM */
FTM_InputCaptureInit(FTM2, FTM_CHANNEL_CHANNEL0, FTM_INPUTCAPTURE_RISINGEDGE);
/* Select the clock source and PreScale factor for the FTM */
FTM_ClockSet(FTM2, FTM_CLOCK_SYSTEMCLOCK, FTM_CLOCK_PS_DIV1);
NVIC_EnableIRQ(FTM2_IRQn);
/* Load and Clear Ch0 (A) interrupt flag */
u8BME_Temp = BME_BIT_CLEAR_8b(&FTM2->CONTROLS[FTM_CHANNEL_CHANNEL0].CnSC, FTM_CnSC_CHF_SHIFT);
/* Load and Clear Ch1 (B) interrupt flag */
u8BME_Temp = BME_BIT_CLEAR_8b(&FTM2->CONTROLS[FTM_CHANNEL_CHANNEL1].CnSC, FTM_CnSC_CHF_SHIFT);
/* Enable Ch0 (A) interrupt */
u8BME_Temp = BME_BIT_SET_8b(&FTM2->CONTROLS[FTM_CHANNEL_CHANNEL0].CnSC, FTM_CnSC_CHIE_SHIFT);
/* Enable Ch1 (B) interrupt */
//~ u8BME_Temp = BME_BIT_SET_8b(&FTM2->CONTROLS[FTM_CHANNEL_CHANNEL1].CnSC, FTM_CnSC_CHIE_SHIFT);
while(1)
{
}
} /* endmain */
Here is the FTM2 interrupt service routine:
void FTM2_Isr(void)
{
uint8_t u8BME_Temp; /* Temporary variable needed for BME operation */
FGPIO_Toggle(FGPIOA, Z_OUT_MASK);/*~ Debug. Toggle Z when first entering interrupt */
/* Ch0 (A) interrupt? Load and Clear Ch0 interrupt flag in one operation. */
u8BME_Temp = BME_BIT_CLEAR_8b(&FTM2->CONTROLS[FTM_CHANNEL_CHANNEL0].CnSC, FTM_CnSC_CHF_SHIFT);
} /* End of FTM2_Isr() */
And this is the assembly listing where I came up with 6 cycles for the fast GPIO toggle:
1015 FGPIO_Toggle(FGPIOA, Z_OUT_MASK);/*~ Debug. Toggle Z when first entering interrupt */
\ FTM2_Isr: (+1)
\ 00000000 0x2080 MOVS R0,#+128
\ 00000002 0x0180 LSLS R0,R0,#+6 ;; #+8192
\ 00000004 0x.... LDR R1,??DataTable15_7 ;; 0xf800000c
\ 00000006 0x6008 STR R0,[R1, #+0]
For the expected time delay from input edge to output edge, I used 15 + 6 + 1 = 22 clocks, but I was seeing a delay of 24 clocks.
David Hollinrake