What's going on here then?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

What's going on here then?

1,831 Views
FridgeFreezer
Senior Contributor I

I am gradually building up a project for MCF52259 in CodeWarrior7.2, I have a couple of interrupts set up, DMA timers running (only as pin-toggling outputs) and was working on the PWM timers when I hit a weird problem:

 

In the main() loop, if I implement a very basic for() loop using a locally declared int, the program crashes:

 

void main()

{

uint32 i = 0;

 

    while(1)

    {

       for(i = 0; i < 100; i++)

      {

            LED_TOGGLE;

      }

    }

}

 

If I do the same loop with an externally declared global variable, the thing works fine. If I cut the thing right down it still crashes:

 

void main()

{

uint32 i;

 

    while(1)

    {

      i++;

    }

}

 

If I replace it with a uint8 or int8 it behaves exactly the same.

 

What on earth is going on here?

Labels (1)
0 Kudos
11 Replies

607 Views
vier_kuifjes
Senior Contributor I

Could also be an optimisation issue. Because you don't use the locally declared variable for anything else, the code might be optimised away. Try disassembling the code (right mouse click -> disassemble) and see what's really inside the loop.

 

Besides, when compiled with CW7.2, the local variable probably will not be on the stack but in one of the data registers of the CPU...

0 Kudos

607 Views
FridgeFreezer
Senior Contributor I

I don't have any optimisations on at the moment, I figure they're best left until the code actually works :smileytongue:

 

Anyone have any ideas why or how the IRQ's are trashing the stack/registers or what can be done about it?

0 Kudos

607 Views
vier_kuifjes
Senior Contributor I

True, but I had a similar issue this weekend, and even with optimisation set to '0', some of the code that initialised some local variables that were never used after that, got trimmed away. That surprised me a bit...

0 Kudos

607 Views
FridgeFreezer
Senior Contributor I

I can understand trimming away unused variables, but these are *used* variables!

 

I have just tried declaring them as static and the code works OK then, if you declare them normally it crashes straight off.

0 Kudos

607 Views
FridgeFreezer
Senior Contributor I

 

Here's what it looks like when I try to debug the program, this doesn't seem right to me at all.

 

This looks wrong to me

0 Kudos

607 Views
J2MEJediMaster
Specialist I

1) Declare your variables as volatile to prevent them from being optimized away.

 

2) The problem cropped up when you started adding more interrupts, right? Try disabling the older interrupts and see if the new ones work. If they do, you have a stack problem. Long ago, I had an interrupt handler that would work for a while, then crash the system. Adding a second interrupt caused the thing to die immediately. It turns out that my first handler failed to clean up the stack properly, and thus created a slow memory leak. The system was OK with this until the stack grew so much it collided with the heap. Addng a second interrupt drove the problem out into the open, because obviously the stack has to be in perfect order for two or more interrupts to execute and return properly.

 

---Tom

0 Kudos

607 Views
FridgeFreezer
Senior Contributor I

Tom,

Declaring the variables as volatile has stopped it from crashing, I can understand why it would stop it but I would still like to know why the compiler feels the need to optimise them away in the first place and how I can tell it not to.

 

Sorry to be a newbie about all this, I've come into embedded from a slightly sideways angle so have a few gaping holes in my knowledge. One thing I'm slightly mystfied about is what I can do in the interrupt handler to prevent stack trashing - currently I'm using Freescale's example code (qspi.c, uart.c, etc.) with their own interrupt routines and handler with very few changes.

 

I've looked in the .lcf files to see if I can increase the stack size (with no success currently) so will explore that too.

 

Fundamentally I think that now the compiler is behaving it's stopped the stack trashing problem, so until it falls over again I will assume the ISR code is reasonably sane. I realise that's quite a big assumption :smileywink:

0 Kudos

607 Views
J2MEJediMaster
Specialist I

The compiler tries to optimize away what it thinks are unused variables to reduce the code and memory footprint. Sometimes it can be tripped up. The best way to prevent this from happening is to use the volatile keyword. Volatile signals to the compiler that the variable is a front for a register and so should not be removed from the code.

 

For information on changing the stack size, check out this https://community.freescale.com/message/23100#23100.

0 Kudos

607 Views
Piotr
Contributor I

There is some problem in peephole optimization in 7.2. I suspect that your issue could be caused by incorrect compilation of one of interrupt service routines. Could you try to compile your project with 'peephole' switched off (look in 'Code Generation - ColdFire processor' panel )?

 

0 Kudos

607 Views
J2MEJediMaster
Specialist I

My first guess would be to ask if you have disabled the watchdog timer, but since the fault lies in the type of varaible you are using, the watchdog may not be the culprit. Since local variables live on the stack, I am thinking that something is trashing your stack. Have you checked to see if your interrupt routines are restoring the stack properly?

 

---Tom

0 Kudos

607 Views
FridgeFreezer
Senior Contributor I

That makes sense, from what I can glean from the debugger (been working for over a year without one so not 100% used to using it yet!) it is throwing an illegal address error.

 

None of the interrupts are doing anything particularly special, mostly incrementing a (global) count and reloading a timer from a (global) variable, then resetting the interrupt flag.

 

Is there something else I should be doing in my interrupts to make sure it returns cleanly? I know in our old code (MMC2114 / CW5) there was an emptyfunction() call at the end of many of the interrupt routines to stop the thing trashing the stack when [] indexing was used (apparrently a known bug) but I'd hope that sort of thing would be sorted by CW7.

0 Kudos