Release vs Debug Builds - One Works, One Doesn't

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

Release vs Debug Builds - One Works, One Doesn't

1,689 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ajacks504 on Thu Apr 12 06:59:19 MST 2012
Hi All,

I have a very simple applications, it works like this:

Power on reset.
Send some TXT out of the SCI port.
Configure a SPI sensor (SSP0).
Send some more TXT out of the SCI port about the success or failure of configuring the the SPI sensor (SSP0).
Enter a infintite loop where I wait for a flag to be set by an interrupt with the "WFI" instruction.
If the flag gets set, I read the value of the SPI sensor (SSP0) and output it over the other SPI port (SSP1).

The flag is set in an interrupt routine on the falling edge of PIO1_0.

My code works great when I build the "debug" version and fails when I try the "release" version.  The way that it fails is this:

The SCI port output works, but it reports that configuring the SPI sensor fails, and I never hit my interrupt routine.  I know that I'm getting the interrupts in hardware, but my routine never gets hit.

So, right now, I'm guessing that somehow the SPI peripheral isn't being configured properly in the "release" version, but I have no clue as to why my interrupt routine isn't being hit.
[B]
Does anyone have any clues for me about the differences between "debug" and "release" builds that might cause such behavior?[/B]

Thanks,
Adam
0 Kudos
Reply
7 Replies

1,607 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by atomicdog on Thu Apr 12 16:14:09 MST 2012
The LPC1114 is a cortex-M0 not a cortex-M3. One of the selling points for M0 is that it has deterministic instruction cycles.
0 Kudos
Reply

1,607 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ajacks504 on Thu Apr 12 13:51:57 MST 2012
Yep, what I find extremely weird is that the for loop NOP C code, when compiled give assembly that doesn't actually contain a NOP instruction.

If the NOP might not even get executed, why is there a NOP instruction?

The other strange thing is that in the LPC1114 user manual 9.3.9, it says:

Remark: The synchronizer between the GPIO and the
NVIC blocks causes a delay of 2 clocks. [B]It is recommended
to add two NOPs[/B] after the clear of the interrupt edge
detection logic before the exit of the interrupt service
routine.


The synchronizer is probably just 2 cascaded D flip flops, so adding 2 clks makes sense, but if the NOPs are going to get “folded out,” why ask that we insert NOPs?  The compiler can't be THAT smart huh?
0 Kudos
Reply

1,607 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Thu Apr 12 09:26:21 MST 2012

Quote: ajacks504
I still don't see just how exactly, but that will come.



BTW, ARM is warning you :eek:


Quote:

4.5 Timing and delays

It is common, when programming for PIC devices, to use NOP instructions as a way of consuming time. The execution time of NOP instructions is easily determined from the system clock speed. When developing for Cortex-M3 devices this cannot be relied on as the pipeline is free to “fold out” NOP instructions from the instruction stream. When this happens, they do not consume time at all.
Deterministic delays in Cortex-M3 systems must therefore make use of a timer peripheral.

See: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0234a/index.html
0 Kudos
Reply

1,607 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ajacks504 on Thu Apr 12 08:36:34 MST 2012
I turned off optimization on the "release" build, now I'm back to working.

I've tried adding the volatile qualifier on interrupts, no fix.  I'll need to look closely at the SSP_IOConfig(), SSP_Init(), GPIOInit(), GPIOSetDir(), GPIOIntEnable() and GPIOSetInterrupt() CMSIS functions and see if some of that maybe is getting optimized away.

Thanks for all the help guys.
0 Kudos
Reply

1,607 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by frame on Thu Apr 12 07:56:06 MST 2012
I don' want to bring coals to Newcastle, but there is one common issue revealed with higher optimization levels.
Beginners usually forget the [B][COLOR=Blue]volatile[/COLOR][/B] qualifier in important cases.
Especially peripheral registers and variables used in interrupts are critical.

As I assume you use CMSIS headers, I guess it is related to variables used in interrupts..
If you are really interrested, try to debug the release version - you might be surprised.
0 Kudos
Reply

1,607 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ajacks504 on Thu Apr 12 07:47:05 MST 2012
That was fast, thanks for the link to that Zero, good read, good to know.

I've got a few software timing loops, I marked the counters in them as volatile, but it didn't fix them, I'll change them to use a timer or systick.

I'll dial back the optimization and see where it gets me.

I just don't really see how this will get further optimized:
void SensorStartupDelay()
{
    volatile uint32_t i;

    for (i = 0; i < 500000; i++) __NOP();
    UARTSend( SENSOR_START_DELAY, sizeof(SENSOR_START_DELAY) );
}
Anyway, I know, I know, I'm a bad programmer
0 Kudos
Reply

1,607 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Thu Apr 12 07:16:22 MST 2012

Quote: ajacks504
[B]Does anyone have any clues for me about the differences between "debug" and "release" builds that might cause such behavior?[/B]



Yes, Code Red does :)

http://support.code-red-tech.com/CodeRedWiki/CompilerOptimization?
0 Kudos
Reply