Serious Compiler bug with -Os optimisation

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

Serious Compiler bug with -Os optimisation

3,790 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ian Stroud on Tue Mar 15 09:38:25 MST 2011
Using LPCXPRESSO 3.6.
I have a flash based look-up table of UART Register base addresses for the LPC1768.

It is declared as

[B][SIZE=2][COLOR=#7f0055][SIZE=2][COLOR=#7f0055]static[/COLOR][/SIZE][/COLOR][/SIZE][/B][SIZE=2][COLOR=#7f0055]
[LEFT][/COLOR][/SIZE][SIZE=2][COLOR=#005032][SIZE=2][COLOR=#005032]LPC_UART_TypeDef[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] * [/SIZE][B][SIZE=2][COLOR=#7f0055][SIZE=2][COLOR=#7f0055]const[/COLOR][/SIZE][/COLOR][/SIZE][/B][SIZE=2] UART_REG_BASE[] = [/SIZE]

[SIZE=2]{[/SIZE]
[LEFT][SIZE=2]([/SIZE][SIZE=2][COLOR=#005032][SIZE=2][COLOR=#005032]LPC_UART_TypeDef[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] *) LPC_UART0, [/SIZE]
[SIZE=2]([COLOR=#005032][COLOR=#005032]LPC_UART_TypeDef[/COLOR][/COLOR] *) LPC_UART1, [/SIZE][/LEFT]


[SIZE=2]LPC_UART2, [/SIZE]
[SIZE=2]LPC_UART3 [/SIZE]
[SIZE=2]};[/SIZE][/LEFT]

[LEFT][SIZE=2]In debug build this table is set up in flash as expected:[/SIZE]
[ATTACH]349[/ATTACH][/LEFT]

[LEFT]If I do a release build with the -Os option set then the contents of this table is wrong. The entry for UART0 is correct at 0x4000C000, but UART1 is set to 0x00000001 and UART2 and UART3 are set to 0x00000000. Not surprisingly the application then crashes when it tries to de-reference corrupt pointers.[/LEFT]
0 Kudos
Reply
9 Replies

3,782 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by CodeRedSupport on Thu Mar 17 08:52:20 MST 2011

Quote: Ian Stroud

Basically if you were unlucky enough to have a code sector, (rodata in my case) that didn't end on a 4-byte boundary all subsequent sectors in flash were then misaligned.


Just to clarify - this is an issue when the last of your rodata (typically variables specified as const in your code) ends on a non-word boundary - as with LPCXpresso 3.6.0 no padding will get inserted after the rodata.

Code will be placed in your image before your rodata and will not be affected anyway as code input sections will always be always get placed on word boundaries.

The issue is mentioned in the release notes for LPCXPresso 3.6.2.

Regards,
CodeRedSupport.
0 Kudos
Reply

3,782 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ian Stroud on Thu Mar 17 06:56:28 MST 2011
Problem is now resolved.

It was due to a known issue with LPCXPRESSO 3.6 that has already been fixed in 3.6.2, and concerned managed linker scripts and sector alignment.

Basically if you were unlucky enough to have a code sector, (rodata in my case) that didn't end on a 4-byte boundary all subsequent sectors in flash were then misaligned. This in turn confused the flash downloader causing it to corrupt flash (i.e. Write to the same flash location twice with different data).

It's a shame there isn't a verify phase/option after the download.
0 Kudos
Reply

3,782 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by CodeRedSupport on Wed Mar 16 05:10:06 MST 2011
We are going to need source files that reproduce your problem if we are to investigate this any further. If you want to contact our support group directly to send the source, please see the details here:
http://www.code-red-tech.com/support.php
0 Kudos
Reply

3,782 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ian Stroud on Wed Mar 16 05:04:47 MST 2011
You appear to have mis-read my last post.
The UART table in the .axf file is correct. I have proved this by converting the .axf file to Intel Hex and looking directly.

It is when your debugger loads this file into Flash that the problem occurs.
For commercial reasons I cannot upload source files / executables to a public forum. I could attempt to modify your example file to reproduce the fault but this could take days.

To expedite this problem I need a direct contact external to this forum.
0 Kudos
Reply

3,782 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by CodeRedSupport on Wed Mar 16 04:40:26 MST 2011
As before, can you please provide an example that demonstrates this. If you don't want to paste your source, modify the example we posted so that it demonstrates your perceived problem.

However, when using Space optimization, the compiler does all sorts of things to reduce the size of your code, and so your table may not even have been allocated any space at all. For example, in the example we provided, the table is not created, and the values are inlined by the compiler.

Optimizing compilers can appear to do some very weird things to your code, but they will all be safe, and your code will still work. Sometimes, you have to give the compiler additional information to help it make the correct decisions - such as using 'volatile' when things really are volatile. Also if you are using aliases (e.g. using a pointer to a table that the compiler then removes) you have to tell the compiler you are doing that too.

Anyway, if you can provide an example, we can tell you what you need to do.
0 Kudos
Reply

3,781 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ian Stroud on Wed Mar 16 03:46:26 MST 2011
I now think that this problem may not be a compiler issue but may be due to the debugger / download tools. Using the -Os switch may just happen to place the UART look-up table in a "problem" area.

Looking in the .map file I find the UART table is located at 2FFC in flash.

[FONT=Courier New][SIZE=1].rodata.UART_REG_BASE
                0x00002ffc       0x10 ./src/LPCUart.o[/SIZE][/FONT]

I used the [I]fromelf.exe[/I] from Keil to convert the .axf file to Intel Hex, exmining the hex file I found that the initialisation of this area of memory is actually correct.

[FONT=Courier New][SIZE=1]
:102FF0006F6E0D004C696E653A200000[U]00C00040[/U]05
:10300000[U]000001400080094000C00940[/U]200000008D[/SIZE][/FONT]

However when the debugger downloads the code onto the target and I examine this area in flash I find the contents is corrupted.

[ATTACH]353[/ATTACH]

I can supply the fully .map and .axf files for analysis but these will have to outside of this public forum.
0 Kudos
Reply

3,781 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by CodeRedSupport on Tue Mar 15 10:29:22 MST 2011
Please provide a buildable piece of code that actually shows up the problem. The below code seems to compile OK here:

#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include <cr_section_macros.h>
#include <NXP/crp.h>

// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

#include <stdio.h>

int main(void) {

    static
    LPC_UART_TypeDef * const UART_REG_BASE[] =
    {
    (LPC_UART_TypeDef *) LPC_UART0,
    (LPC_UART_TypeDef *) LPC_UART1,
    LPC_UART2,
    LPC_UART3
    };
    
   int loop;
    for (loop = 0; loop < 4; loop++) {
        printf ("%x\n", UART_REG_BASE[loop]);
    }

    // Enter an infinite loop, just incrementing a counter
    volatile static int i = 0 ;
    while(1) {
        i++ ;
    }
    return 0 ;
}


which built for release (-Os) prints out...

4000c000
40010000
40098000
4009c000


Regards,
CodeRedSupport
0 Kudos
Reply

3,781 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ian Stroud on Tue Mar 15 10:27:46 MST 2011
The definitions of LPC_UART0 and LPC_UART1 have a different type to LPC_UART2 and 3. However the registers maps for basic operation of the UARTs are the same.

I need to put in an explicit cast in order to suppress Lint warnings. Lint rightly gets nervous when pointers to different types are interchanged.
0 Kudos
Reply

3,781 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by igorsk on Tue Mar 15 10:16:39 MST 2011
Why do you have a cast for LPC_UART0 and LPC_UART1? It shouldn't be necessary.
0 Kudos
Reply