EmbeddedRelated.com
Forums
Memfault Beyond the Launch

can't setup gnu linker script to output .data into flash

Started by Christopher Harvey October 20, 2011
I've having trouble getting gnu ld to output my .data section into
flash. Here is the snippet in my ld script:

MEMORY
{
flash : ORIGIN = 0x00000000, LENGTH = 512K
ram : ORIGIN = 0x40000000, LENGTH = 32K
usbram : ORIGIN = 0x7FD00000, LENGTH = 8K
ethram : ORIGIN = 0x7FE00000, LENGTH = 16K
}

[snip]

.data :
{
__data_beg__ = .;
__data_beg_src__ = __end_of_text__;
*(.data)
__data_end__ = .;
} >ram AT>flash

and the output of a global array that gets linked with that script.

int foo[] = {1,2,3,4,5,6};

40000000 <__data_beg__>:
40000000: 00000001 andeq r0, r0, r1
40000004: 00000002 andeq r0, r0, r2
40000008: 00000003 andeq r0, r0, r3
4000000c: 00000004 andeq r0, r0, r4
40000010: 00000005 andeq r0, r0, r5
40000014: 00000006 andeq r0, r0, r6

Notice that it's in RAM. I thought that saying "AT>flash" would place
it after the .text section.

I also posted this question on stack overflow if anybody prefers to
read it there.

http://stackoverflow.com/questions/7831308/linker-script-load-vs-virtual-address

thanks.

An Engineer's Guide to the LPC2100 Series

Initialized variables should be placed in .rodata section, not .data

DaveS

On Thu, Oct 20, 2011 at 8:26 AM, Christopher Harvey
wrote:

> **
> I've having trouble getting gnu ld to output my .data section into
> flash. Here is the snippet in my ld script:
>
> MEMORY
> {
> flash : ORIGIN = 0x00000000, LENGTH = 512K
> ram : ORIGIN = 0x40000000, LENGTH = 32K
> usbram : ORIGIN = 0x7FD00000, LENGTH = 8K
> ethram : ORIGIN = 0x7FE00000, LENGTH = 16K
> }
>
> [snip]
>
> .data :
> {
> __data_beg__ = .;
> __data_beg_src__ = __end_of_text__;
> *(.data)
> __data_end__ = .;
> } >ram AT>flash
>
> and the output of a global array that gets linked with that script.
>
> int foo[] = {1,2,3,4,5,6};
>
> 40000000 <__data_beg__>:
> 40000000: 00000001 andeq r0, r0, r1
> 40000004: 00000002 andeq r0, r0, r2
> 40000008: 00000003 andeq r0, r0, r3
> 4000000c: 00000004 andeq r0, r0, r4
> 40000010: 00000005 andeq r0, r0, r5
> 40000014: 00000006 andeq r0, r0, r6
>
> Notice that it's in RAM. I thought that saying "AT>flash" would place
> it after the .text section.
>
> I also posted this question on stack overflow if anybody prefers to
> read it there.
> http://stackoverflow.com/questions/7831308/linker-script-load-vs-virtual-address
>
> thanks.
>
>


Try declaring it as:
const int foo[] = {1,2,3,4,5,6};
as this should put it in the flash constant data area. But, you can't
modify the values then (obviously).

Mike
-----Original Message-----
From: l... [mailto:l...]On Behalf
Of Christopher Harvey
Sent: Thursday, October 20, 2011 9:27 AM
To: l...
Subject: [lpc2000] can't setup gnu linker script to output .data into
flash
I've having trouble getting gnu ld to output my .data section into
flash. Here is the snippet in my ld script:

MEMORY
{
flash : ORIGIN = 0x00000000, LENGTH = 512K
ram : ORIGIN = 0x40000000, LENGTH = 32K
usbram : ORIGIN = 0x7FD00000, LENGTH = 8K
ethram : ORIGIN = 0x7FE00000, LENGTH = 16K
}

[snip]

.data :
{
__data_beg__ = .;
__data_beg_src__ = __end_of_text__;
*(.data)
__data_end__ = .;
} >ram AT>flash

and the output of a global array that gets linked with that script.

int foo[] = {1,2,3,4,5,6};

40000000 <__data_beg__>:
40000000: 00000001 andeq r0, r0, r1
40000004: 00000002 andeq r0, r0, r2
40000008: 00000003 andeq r0, r0, r3
4000000c: 00000004 andeq r0, r0, r4
40000010: 00000005 andeq r0, r0, r5
40000014: 00000006 andeq r0, r0, r6

Notice that it's in RAM. I thought that saying "AT>flash" would place
it after the .text section.

I also posted this question on stack overflow if anybody prefers to
read it there.

http://stackoverflow.com/questions/7831308/linker-script-load-vs-virtual-address

thanks.
The following is not going to answer your question, but does explain what you have....

what you are asking of the linker is to reserve space in RAM. The code is linked to the location in 'flash' as described in your memory map. You would need to copy the bytes from flash into RAM in your startup script as an additional step. Look at the .data section in the startup script and compare it with your linker script, for example.

--- In l..., Christopher Harvey wrote:
>
> I've having trouble getting gnu ld to output my .data section into
> flash. Here is the snippet in my ld script:
>
> MEMORY
> {
> flash : ORIGIN = 0x00000000, LENGTH = 512K
> ram : ORIGIN = 0x40000000, LENGTH = 32K
> usbram : ORIGIN = 0x7FD00000, LENGTH = 8K
> ethram : ORIGIN = 0x7FE00000, LENGTH = 16K
> }
>
> [snip]
>
> .data :
> {
> __data_beg__ = .;
> __data_beg_src__ = __end_of_text__;
> *(.data)
> __data_end__ = .;
> } >ram AT>flash
>
> and the output of a global array that gets linked with that script.
>
> int foo[] = {1,2,3,4,5,6};
>
> 40000000 <__data_beg__>:
> 40000000: 00000001 andeq r0, r0, r1
> 40000004: 00000002 andeq r0, r0, r2
> 40000008: 00000003 andeq r0, r0, r3
> 4000000c: 00000004 andeq r0, r0, r4
> 40000010: 00000005 andeq r0, r0, r5
> 40000014: 00000006 andeq r0, r0, r6
>
> Notice that it's in RAM. I thought that saying "AT>flash" would place
> it after the .text section.
>
> I also posted this question on stack overflow if anybody prefers to
> read it there.
>
> http://stackoverflow.com/questions/7831308/linker-script-load-vs-virtual-address
>
> thanks.
>

*facepalm*.

I think I figured it out. running objdump -D displays virtual addresses.
So the 0x40000000 values I was worried about are actually in flash.
Running objdump -h showed me a memory map, and indeed the linker script
was doing its job.

On 20/10/11 11:26 AM, Christopher Harvey wrote:
> I've having trouble getting gnu ld to output my .data section into
> flash. Here is the snippet in my ld script:
>
> MEMORY
> {
> flash : ORIGIN = 0x00000000, LENGTH = 512K
> ram : ORIGIN = 0x40000000, LENGTH = 32K
> usbram : ORIGIN = 0x7FD00000, LENGTH = 8K
> ethram : ORIGIN = 0x7FE00000, LENGTH = 16K
> }
>
> [snip]
>
> .data :
> {
> __data_beg__ = .;
> __data_beg_src__ = __end_of_text__;
> *(.data)
> __data_end__ = .;
> } >ram AT>flash
>
> and the output of a global array that gets linked with that script.
>
> int foo[] = {1,2,3,4,5,6};
>
> 40000000 <__data_beg__>:
> 40000000: 00000001 andeq r0, r0, r1
> 40000004: 00000002 andeq r0, r0, r2
> 40000008: 00000003 andeq r0, r0, r3
> 4000000c: 00000004 andeq r0, r0, r4
> 40000010: 00000005 andeq r0, r0, r5
> 40000014: 00000006 andeq r0, r0, r6
>
> Notice that it's in RAM. I thought that saying "AT>flash" would place
> it after the .text section.
>
> I also posted this question on stack overflow if anybody prefers to
> read it there.
>
> http://stackoverflow.com/questions/7831308/linker-script-load-vs-virtual-address
>
> thanks.
On Thu, 20 Oct 2011 11:13:41 -0700, David Smead wrote:
> Initialized variables should be placed in .rodata section, not .data
>
> DaveS

The variables are initialized, but they aren't read-only.

>
> On Thu, Oct 20, 2011 at 8:26 AM, Christopher Harvey
> wrote:
>
>> **
>> I've having trouble getting gnu ld to output my .data section into
>> flash. Here is the snippet in my ld script:
>>
>> MEMORY
>> {
>> flash : ORIGIN = 0x00000000, LENGTH = 512K
>> ram : ORIGIN = 0x40000000, LENGTH = 32K
>> usbram : ORIGIN = 0x7FD00000, LENGTH = 8K
>> ethram : ORIGIN = 0x7FE00000, LENGTH = 16K
>> }
>>
>> [snip]
>>
>> .data :
>> {
>> __data_beg__ = .;
>> __data_beg_src__ = __end_of_text__;
>> *(.data)
>> __data_end__ = .;
>> } >ram AT>flash
>>
>> and the output of a global array that gets linked with that script.
>>
>> int foo[] = {1,2,3,4,5,6};
>>
>> 40000000 <__data_beg__>:
>> 40000000: 00000001 andeq r0, r0, r1
>> 40000004: 00000002 andeq r0, r0, r2
>> 40000008: 00000003 andeq r0, r0, r3
>> 4000000c: 00000004 andeq r0, r0, r4
>> 40000010: 00000005 andeq r0, r0, r5
>> 40000014: 00000006 andeq r0, r0, r6
>>
>> Notice that it's in RAM. I thought that saying "AT>flash" would
>> place
>> it after the .text section.
>>
>> I also posted this question on stack overflow if anybody prefers to
>> read it there.
>>
>> http://stackoverflow.com/questions/7831308/linker-script-load-vs-virtual-address
>>
>> thanks.
>
>
>
If you want “variables” placed in flash then obviously they can’t be variable, so you must declare them as const.



Note that there are sometimes benefits in having “const” data in RAM, but this is dependent on the bus and processor architecture.



For Von-Neumann architectures ( ARM7 ) it makes no difference since everything is fetched over a single bus, but for Harvard Architecture processors with multi-layer AHB or tightly coupled data ram this can improve performance if the RAM / FLASH can be simultaneously accessed for example over independent AHB interconnects.



Regards



Phil.













From: l... [mailto:l...] On Behalf Of Christopher Harvey
Sent: 20 October 2011 19:37
To: l...
Subject: Re: [lpc2000] can't setup gnu linker script to output .data into flash





On Thu, 20 Oct 2011 11:13:41 -0700, David Smead wrote:
> Initialized variables should be placed in .rodata section, not .data
>
> DaveS

The variables are initialized, but they aren't read-only.

>
> On Thu, Oct 20, 2011 at 8:26 AM, Christopher Harvey
> >wrote:
>
>> **
>> I've having trouble getting gnu ld to output my .data section into
>> flash. Here is the snippet in my ld script:
>>
>> MEMORY
>> {
>> flash : ORIGIN = 0x00000000, LENGTH = 512K
>> ram : ORIGIN = 0x40000000, LENGTH = 32K
>> usbram : ORIGIN = 0x7FD00000, LENGTH = 8K
>> ethram : ORIGIN = 0x7FE00000, LENGTH = 16K
>> }
>>
>> [snip]
>>
>> .data :
>> {
>> __data_beg__ = .;
>> __data_beg_src__ = __end_of_text__;
>> *(.data)
>> __data_end__ = .;
>> } >ram AT>flash
>>
>> and the output of a global array that gets linked with that script.
>>
>> int foo[] = {1,2,3,4,5,6};
>>
>> 40000000 <__data_beg__>:
>> 40000000: 00000001 andeq r0, r0, r1
>> 40000004: 00000002 andeq r0, r0, r2
>> 40000008: 00000003 andeq r0, r0, r3
>> 4000000c: 00000004 andeq r0, r0, r4
>> 40000010: 00000005 andeq r0, r0, r5
>> 40000014: 00000006 andeq r0, r0, r6
>>
>> Notice that it's in RAM. I thought that saying "AT>flash" would
>> place
>> it after the .text section.
>>
>> I also posted this question on stack overflow if anybody prefers to
>> read it there.
>>
>> http://stackoverflow.com/questions/7831308/linker-script-load-vs-virtual-address
>>
>> thanks.
>
>
>
> If you want “variables” placed in flash then obviously they can’t be
> variable, so you must declare them as const.

You seem to be missing the point. There are two images of the data required for "int x = 5" -- one in flash, one in RAM. It seems as though the OP has some trouble getting the one in flash set up correctly.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
SolderCore running Defender... http://www.vimeo.com/25709426

Hi Paul,

I’m not missing the point, he states he wanted the variable in flash, i.e. not variable.



With GNU it’s different than the ARM tools, but essentially if it is to be an initialized variable then it needs 2 image addresses, a load address and an execution address.

For GCC the image will generally contain an exact image of the data init state at the load address which has to be copied by the loader, ( in a static app by the startup code ) to the execution address, in ARM tools this is sightly different since by default they compress the image so it has to be de-compressed and copied.



If it was truly const then it would be in .rodata not .data, and the load and execute addresses would be the same. ( section naming conventions also change of course for different toolchains just to make life harder ).



(one reason that sometimes ARM generates smaller code than GCC, if you have a lot of initialized data is the compression of the image ).



One thing that gets confusing for people, and I noticed it in some of the comments to this thread, is the concept of virtual addressing.

Without an MMU the concept of virtual addressing does not apply since all addresses are physical addresses, and it should not be confused with the load address and the execution address.



For a system without an MMU the load address is where the physical copy exists at startup, the execution address is the physical address of where it will be copied to at runtime.

For a system WITH an MMU, the load address does not change ( for an image in flash ), but the execution address becomes the virtual address at runtime, the physical address of the data at runtime is then determined by the systems memory management algorithm.



Regards



Phil.





From: l... [mailto:l...] On Behalf Of Paul Curtis
Sent: 01 November 2011 09:02
To: l...
Subject: RE: [lpc2000] can't setup gnu linker script to output .data into flash





> If you want “variables” placed in flash then obviously they can’t be
> variable, so you must declare them as const.

You seem to be missing the point. There are two images of the data required for "int x = 5" -- one in flash, one in RAM. It seems as though the OP has some trouble getting the one in flash set up correctly.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
SolderCore running Defender... http://www.vimeo.com/25709426



> Hi Paul,
>
> I’m not missing the point, he states he wanted the variable in flash,
> i.e. not variable.

No, the OP stated in a follow-up post:

"The variables are initialized, but they aren't read-only."

http://tech.groups.yahoo.com/group/lpc2000/message/55641

So I think you *are* missing the point. He has stated that he needs them read-write but initialized to a non-zero value on startup.

Your suggestion of making them const and putting .rodata in flash does not address the OP's well-stated high-level problem.

Regards,

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
SolderCore running Defender... http://www.vimeo.com/25709426


Memfault Beyond the Launch