Hello,
My question is about a ColdFire (MCF52235 MCU) behavior when implementing critical region to access safely data handled by the PIT1 peripheral interrupt service routine (PIT1 ISR).
Here is the situation:
I setup an interrupt service routine that simply increment a 32-bit counter ( named "ticks" ) every 10mS using the MCF52235 PIT1 peripheral.
I wrote an interface (function) that enable a function that run on main loop (at fast speed) to get the "ticks" value and do some processing.
To make the things safe, I implemented a critical region (disabling/enabling interrupts) inside that function to prevent that function to be interrupted by the PIT1 ISR, thus preventing data corruption.
The problem is that the only mean to create the critical zone is to disable/enable all MCU interrupts. All other method, like disabling/enabling PIT1 interrupts using the PIE bit in the PIT1 PCSR register (using 'C' instruction or assembly instruction), or disabling/enabling PIT1 interrupts using the associated bit in the IMR register, or disabling/enabling PIT1 interrupts using the ICR56 register, are not working correctly.
When using those methods, there are Spurious Interrupts generated and all interrupt service routines running on the MCU are disrupted a LOT
Am I missing something, or is it possible that creating critical region by disabling/enabling all interrupts are the only mean to create a critical region that work well ???
Below, the significant part of the interface function (using critical region), that show you all the things I tryed to get rid of that problem:
Code:BOOL ticks_cu_goal(ticks_t *ticks_goal, ticks_t interval){ BOOL result = NO; /* Enter critical region... * ************************ *//* - This operation is not atomic and produce spurious interrupts * and erronous operation of the PIT1 interrupts. * - DON'T USE. * -------------------------------------------------------------- */#if FALSE MCF_PIT1_PCSR &= ~MCF_PIT_PCSR_PIE; /* Disable PIT1 interrupts. */#endif/* - This operation produce spurious interrupts * and erronous operation of the PIT1 interrupts. * - DON'T USE. * ------------------------------------------------ */#if FALSE /* Disable PIT1 interrupts. * ------------------------ */ asm { lea __IPSBAR[0x00160000+1],a0 bclr.b #3,(a0) };#endif/* - This operation produce spurious interrupts * and erronous operation of the PIT1 interrupts. * - DON'T USE. * ------------------------------------------------ */#if FALSE /* Mask interrupt source 56 (PIT1). */ MCF_INTC0_IMRH |= MCF_INTC_IMRH_MASK56;#endif/* - This operation produce spurious interrupts * and erronous operation of the PIT1 interrupts. * - DON'T USE. * ------------------------------------------------ */#if FALSE /* Disable PIT1 interrupts by programming its Level and Priority. */ MCF_INTC0_ICR56 = 0;#endif/* Not really the better way to go, but it seems to be the only that work!— * ------------------------------------------------------------------------ */#if TRUE /* TODO: Use a bit instruction in assembly to put PIT1 interrupt off. */ mcf5xxx_lo_disable_all_irq();#endif /* Process safely your data here. * ****************************** */ /* Exit critical region... * *********************** *//* - This operation is not atomic and produce spurious interrupts * and erronous operation of the PIT1 interrupts. * - DON'T USE. * -------------------------------------------------------------- */#if FALSE MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIE; /* Enable PIT1 interrupts. */#endif/* - This operation produce spurious interrupts * and erronous operation of the PIT1 interrupts. * - DON'T USE. * ------------------------------------------------ */#if FALSE /* Enable PIT1 interrupts. * ----------------------- */ asm { lea __IPSBAR[0x00160000+1],a0 bset.b #3,(a0) };#endif/* - This operation produce spurious interrupts * and erronous operation of the PIT1 interrupts. * - DON'T USE. * ------------------------------------------------ */#if FALSE /* Unmask interrupt source 56 (PIT1). */ MCF_INTC0_IMRH &= ~MCF_INTC_IMRH_MASK56;#endif/* - This operation produce spurious interrupts * and erronous operation of the PIT1 interrupts. * - DON'T USE. * ------------------------------------------------ */#if FALSE /* Enable PIT1 interrupts by programming its Level and Priority. */ MCF_INTC0_ICR56 = MCF_INTC_ICR_IL(TIMER_NETWORK_LEVEL) | MCF_INTC_ICR_IP(0);#endif/* Not really the better way to go, but it seems to be the only that work!– * ------------------------------------------------------------------------ */#if TRUE /* TODO: Use a bit instruction in assembly to put PIT1 interrupt on. */ mcf5xxx_lo_enable_all_irq();#endif return (result);}
Regards,
Claude Sylvain
Electro-Technica inc.