Micro is MCF52259 @ 48MHz, board is our own PCB.
IDE is CW7.2
Code is controlling 3 stepper motors, each one driven by the toggling of a DTIM (DMA Timer) pin. Here's the config for DTIM0, 1 & 2 are the same:
/* DTIM0 - Motor 1 STEP */ /* Configure DTIM0 as a timeout counter */ MCF_DTIM_DTRR(0) = (0xFFFF); MCF_DTIM_DTMR(0) = 0 | MCF_DTIM_DTMR_PS(SYS_CLK_MHZ/2) // Prescaler | MCF_DTIM_DTMR_ORRI // Enable DMA/IRQ on count reached | MCF_DTIM_DTMR_OM // Toggle pin state on interrupt (omit for a 1-bus-cycle low pulse instead) | MCF_DTIM_DTMR_FRR // Count is restarted after count reached | MCF_DTIM_DTMR_CLK_DIV1 // Internal clock /1 | MCF_DTIM_DTMR_RST; // Enable timer MCF_DTIM_DTXMR(0) = MCF_DTIM_DTXMR_HALTED; // Extended settings - halt on debug
PIT1 is configured to run as a 1ms interrupt where we do various things like calculate acceleration of the motors (because a fixed raster makes it easier to come up with a linear result). The motor speeds are stored in a global variable which is then read by the DMA Timer interrupt for each motor, which keeps a position count based on direction (so every DTIM tick we increment or decrement a position count, load the new speed value into DTRR, and reset DTCN). The output pin is toggled by the DTIM hardware.
Is that we are "missing" DTIM ticks (pin toggles but we don't count it), and the DTIM output frequency is wandering around. We have tracked this down to the fact that when the PIT1 ISR is running, the DTIM interrupt does not happen until after the PIT ISR has completed, despite the fact that the DTIM interrupt is Level 6 / Pri 7 and the PIT1 interrupt is level 5 / pri 1. To my mind, that should mean that DTIM
will should interrupt the PIT ISR.
We can see the DTIM pin toggle, so the hardware is running OK and we have to assume the interrupt is being asserted in a timely manner, but ignored. As soon as we drop out of the PIT ISR, the DTIM ISR is called. This also results in the pulse from the DTIM being skewed.
After previous issues with spurious interrupts (https://community.freescale.com/message/76500#76500 when altering interrupt-related registers we are masking & unmasking interrupts, for example:
ipl = DisableInts(); // Mask IPLMCF_PIT_PCSR_LOWER_BYTE(1) |= MCF_PIT_PCSR_PIF; // Clear interrupt flagEnableInts(ipl); // Restore IPL
We have also applied this fix to the PIT interrupt flag reset (PIF):
Here is a shot of what's going on - we have used GPIO pins which are toggled high for the duration of the ISRs, and the output of the DTIM0 pin which is running at a fixed frequency (~120uS period or 60uS per "tick"/toggle)
You can see that every time the DTIM toggles we get a short pulse showing the DTIM ISR is running, except where the PIT ISR pulse is high, when the DTIM pin toggles but no ISR occurs. When the PIT ISR is over, DTIM ISR happens and the period from there to the next edge is correct.
I'm sure I'm doing something wrong with the way I've arranged interrupts or whatnot, but can't find anything definitive in the reference manual. Can anyone point me in the right direction?