I'm using:
yagarto-bu-2.23.1_gcc-4.7.2-c-c++_nl-1.20.0_gdb-7.5.1_eabi_20121222
and it is working well with a project containing dozens of source files.
Then I add the following source files:
FooClass.h
1 | class FooClass {
|
2 | public:
|
3 | FooClass(){};
|
4 | static FooFrame m_fooFrame;
|
5 | };
|
FooClass.cpp
1 | #include "FooClass.h"
|
2 | FooFrame FooClass::m_fooFrame;
|
Here's the file for the static member:
FooFrame.h
1 | class FooFrame {
|
2 | public:
|
3 | FooFrame(){};
|
4 | };
|
No need for FooFrame.cpp
Trivial right? Well, the result is that static vars are erroneously
shifted in memory by 4 bytes.
Here's the map file. These vars reside at __data_start and are copied
there from ROM by the startup code. Adding FooClass doesn't alter these
vars at the beginning. That's all fine and dandy.
1 | 0x40000200 0x1 src\UserIO.o
|
2 | 0x40000200 UserIO::m_dummySystemStatus
|
3 | *fill* 0x40000201 0x3
|
4 | .data._ZN3SAL15m_uart0BaudRateE
|
5 | 0x40000204 0x4 src\SAL.o
|
6 | 0x40000204 SAL::m_uart0BaudRate
|
7 | .data._ZN3SAL15m_uart1BaudRateE
|
8 | 0x40000208 0x4 src\SAL.o
|
9 | 0x40000208 SAL::m_uart1BaudRate
|
This is the happy memory of the ARM7 before adding FooClass:
1 | 40000200 01000000 80250000 80250000 01010100
|
This is correct. You can see m_dummySystemStatus, and the two baud rates
(9600 baud becomes 0x80250000 :-). Great!
Now lets add FooClass to the project and look at memory:
1 | 40000200 FFFFFFFF 01000000 80250000 80250000
|
What the heck? You can see that the static members have been moved by 1
word (4 bytes) and any code that uses them crashes in a pile.
I'm using James P. Lynch's linker script (modified for the LPC2148):
1 | /* Author: James P. Lynch */ /* identify the Entry Point */
|
2 |
|
3 | ENTRY(_startup)
|
4 | /* specify the LPC2148 memory areas */
|
5 |
|
6 | MEMORY
|
7 | {
|
8 | flash : ORIGIN = 0, LENGTH = 512K /* FLASH ROM */
|
9 | ram_isp_low(A) : ORIGIN = 0x40000120, LENGTH = 223 /* variables used by Philips ISP bootloader */
|
10 | ram : ORIGIN = 0x40000200, LENGTH = 32224 /* free RAM area */
|
11 | ram_isp_high(A) : ORIGIN = 0x40007FE0, LENGTH = 32 /* variables used by Philips ISP bootloader */
|
12 | }
|
13 |
|
14 |
|
15 | /* define a global symbol _stack_end */
|
16 |
|
17 | _stack_end = 0x40007EDC;
|
18 |
|
19 | /* now define the output sections */
|
20 |
|
21 | SECTIONS
|
22 | {
|
23 | . = 0; /* set location counter to address zero */
|
24 |
|
25 | startup : {
|
26 | *(.startup)
|
27 | . = ALIGN(0x4);
|
28 | } >flash /* the startup code goes into FLASH */
|
29 |
|
30 |
|
31 |
|
32 | .text : {
|
33 | CREATE_OBJECT_SYMBOLS
|
34 | *(.text .text.* .gnu.linkonce.t.*)
|
35 | *(.plt)
|
36 | *(.gnu.warning)
|
37 | *(.glue_7t) *(.glue_7)
|
38 |
|
39 | . = ALIGN (4);
|
40 | /* These are for static constructors and destructors under ELF */
|
41 | KEEP (*crtbegin.o(.ctors))
|
42 | KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
43 | KEEP (*(SORT(.ctors.*)))
|
44 | KEEP (*crtend.o(.ctors))
|
45 | KEEP (*crtbegin.o(.dtors))
|
46 | KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
47 | KEEP (*(SORT(.dtors.*)))
|
48 | KEEP (*crtend.o(.dtors))
|
49 |
|
50 | *(.rodata .rodata.* .gnu.linkonce.r.*)
|
51 |
|
52 | *(.ARM.extab* .gnu.linkonce.armextab.*)
|
53 | *(.gcc_except_table)
|
54 | *(.eh_frame_hdr)
|
55 | *(.eh_frame)
|
56 |
|
57 | *(.init)
|
58 | *(.fini)
|
59 |
|
60 | PROVIDE_HIDDEN (__preinit_array_start = .);
|
61 | KEEP (*(.preinit_array))
|
62 | PROVIDE_HIDDEN (__preinit_array_end = .);
|
63 | PROVIDE_HIDDEN (__init_array_start = .);
|
64 | KEEP (*(SORT(.init_array.*)))
|
65 | KEEP (*(.init_array))
|
66 | PROVIDE_HIDDEN (__init_array_end = .);
|
67 | PROVIDE_HIDDEN (__fini_array_start = .);
|
68 | KEEP (*(.fini_array))
|
69 | KEEP (*(SORT(.fini_array.*)))
|
70 | PROVIDE_HIDDEN (__fini_array_end = .);
|
71 | } >flash
|
72 |
|
73 | /* .ARM.exidx is sorted, so has to go in its own output section. */
|
74 | .ARM.exidx : {
|
75 | __exidx_start = .;
|
76 | *(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
77 | __exidx_end = .;
|
78 | } >flash
|
79 | _etext = .;
|
80 |
|
81 |
|
82 |
|
83 | .data : {
|
84 | __data_load = LOADADDR (.data);
|
85 | __data_start = .;
|
86 | KEEP(*(.jcr))
|
87 | *(.got.plt) *(.got)
|
88 | *(.shdata)
|
89 | *(.data .data.* .gnu.linkonce.d.*)
|
90 | . = ALIGN (4);
|
91 | _edata = .;
|
92 | } >ram AT >flash
|
93 |
|
94 | .bss : {
|
95 | __bss_start__ = . ;
|
96 | *(.shbss)
|
97 | *(.bss .bss.* .gnu.linkonce.b.*)
|
98 | *(COMMON)
|
99 | . = ALIGN (4);
|
100 | __bss_end__ = .;
|
101 | } >ram
|
102 |
|
103 | }
|
104 | _end = .; /* define a global symbol marking the end of application RAM */
|
So my question is, can you help me identify where I'm going wrong?
Thank you!
David