MCF52259 GPIO pins deasserting themselves, help tracking down

cancel
Showing results for 
Search instead for 
Did you mean: 

MCF52259 GPIO pins deasserting themselves, help tracking down

672 Views
FridgeFreezer
Senior Contributor I

Yes it's me again! :smileytongue:

 

Micro is MCF52259 LQFP144, code is C in CW7.2.

 

We have a weird problem - we are running a timer (DTIMx) and toggling GPIO pins to control a motor (step & direction & power level) but every so often after setting the GPIO pins (PORTTI) they flip back to their previous state about ~2uS after the ISR exits (our clock is 48MHz). The weird thing is it doesn't appear to be an electrical noise problem, the micro can actually see the register is wrong by reading it back (we can set a breakpoint and it will break when the bit flips)

 

I have checked everything I can think of - we're not nesting interrupts (eg interrupting another read-modify-write of the PORTTI register), we're not re-triggering the interrupt erroneously, we're not modifying the register anywhere else in the code (as far as I can see), the pin assignment is not being changed, etc.

 

We can catch the situation with this code (variables are just there to make debugging easier):

 

void __interrupt__ motor_isr(void){  MCF_GPIO_PORTTI |= MCF_GPIO_PORTTI_PORTTI0; // Set bit}// Now catch it in another rutineif(!(MCF_GPIO_PORTTI & MCF_GPIO_PORTTI_PORTTI0)){    halt(); // Breakpoint}

 

This is happening with more than one pin on PORTTI, it seems to make no difference if we use it as MCF_GPIO_PORTTI or use SETTI/CLRTI to change the output, or always read values from it as SETTI. It also makes no difference if we read-modify-write the register as a byte (eg (MCF_GPIO_SETTI |= MCF_GPIO_PORTTI_PORTTI6)) or if we define a union and modify individual bits (which I think should compile out to bit set/bit clear commands instead).

 

As ever, I'm sure it will turn out to be something stupid I've done incorrectly... but any advice on how to track it down / what to look for would be greatly appreciated!

Labels (1)
0 Kudos
4 Replies

283 Views
foo86
Contributor I

Hello FridgeFreezer

I've got the same problem as you. Did you solve the problem?

best regards

Martin

0 Kudos

283 Views
TomE
Specialist I

Here's a similar case from a bit over a year ago:

Re: MCF51JM Random ,extra output transition after input capture ISR,

My debugging suggestions in that one and in this thread still apply.

It could still be a hardware problem inside the CPU. The Coldfire chips (courtesy of the 68000 heritage) generate "strange" bus cycles during interrupts.

3.3.3 Exception Processing OverviewFor interrupts, the
processor performs an interrupt-acknowledge (IACK) bus cycle
to obtain the vector number from the interrupt controller.
The IACK cycle is mapped to special locations within the interrupt
controller’s address space with the interrupt level encoded
in the address.

With the 68000, the "address space encoding" was exposed, so it was well documented. In these chips, all the magic happens inside them, so the documentation is sketchy. In the case of the MCF52259 you can get a hint of what is going on by looking at the definitions of the RAMBAR and FLASHBAR registers. Read up on the C/I, SC, SD, UC and UD bits are for. The last four allow you to prevent all combinations of Supervisor/User and Program/Data accesses from working on that memory. So you could prevent code from executing out of the FLASH, or prevent user code or data from working. Apparently this can save power in some cases. The real mystery is the "C/I" bit. When the CPU generates an IACK, the only hardware you could ever want to be able to respond to that cycle is the interrupt controller. But the "C/I" bit seems to allow you to have the RAM of FLASH interfere with that. The MOVEC, WDEBUG and WDDATA instructions probably use the other C/I Address Space encoding too.

Having FLASH or RAM respond to C/I cycles doesn't seem like a good idea, and could be causing problems like the other posters are seeing. The following is in the manual:

These bits are useful for power management as detailed
in Section 12.3.2, “Power Management.”
In most applications, the C/I bit is set .

The take-home message is to make sure you have the "C/I" bit set in RAMBAR and FLASHBAR. If your CPU has a ROMBAR or MBAR (documented in CFPRM.pdf) you may want to check the settings of the C/I bit in these too.

Freescale have had other chips in the past that respond strangely to some combinations of these "control cycles" (MPC860 I think), so it isn't impossible that some "normal" set of bus cycles is generating a glitch in the GPIO module..

Tom

Message was edited by: Tom Evans. Again and again and AGAIN to try and get the "plain text" looking right. It looked OK in the Editor, and then looked nothing like in the post. Around and around again and again.

0 Kudos

283 Views
FridgeFreezer
Senior Contributor I

Hi Martin,

We never solved the problem properly, in the end we burned a few CPU cycles by manually setting the pin & then reading it back to check (be sure to read the pin state register not the pin GPIO/out register). Somewhat unfortunately, that has been "good enough" for our purposes, and as it would have complicated consequences for our system if it became unreliable we have not revisited it.

Without delving back into all that was done/tried, off the top of my head it may be worth checking for conflicted interrupts or other bits of code which may be doing read/modify/write on the output registers or suchlike. Also worth trying the MCF_GPIO_SET_ / _CLEAR pin registers rather than read-modify-write of the output registers etc., it certainly shaves a load of CPU cycles off if you can do that.

0 Kudos

283 Views
TomE
Specialist I

Can you set a "Data Watchpoint" in the debugger to catch any unexpected port writes?

 

How about running another timer, running at IPL7 (non-maskable) that you crank up to a speed so it is literally single-stepping the mainline code. Or better, have it give a "oneshot" interrupt, then on exit from the ISR set the next interrupt to trigger a few instruction cycles after the RTI. So you're effectively "single-stepping" your code in software from the IPL7 interrupt.

 

Have it read back the port (and any flag variables that help the routine decide when the bit is wrongly low) and have it halt. Then you can look back on the stack frame to see what it interrupted and you should be only a few instructions away from what wrote to the port.

 

Tom

 

0 Kudos