views:

209

answers:

1

I have a program that's resident in flash and will run from flash. Early in the program data segments are copied from flash to ram. I'm using a linker script like (simplified):

.text      :
{
  *(.text)
} > FLASH
_etext = .;
PROVIDE (etext = .);

.rodata  :
{
  PROVIDE(__COPY_DATA_START__ = .); 
  *(.rodata) 
} > ram AT>flash

PROVIDE (__SDATA2_START__ = .);
.sdata2   :
{ 
  *(.sdata2)
} > ram AT>flash

PROVIDE (__sbss2_start = . );
.sbss2   : { 
  *(.sbss2) 
  . = ALIGN(4)
} > ram AT>flash
PROVIDE (__sbss2_end = . );
PROVIDE (__SBSS2_END__ = .);

.data    :
{
  *(.data)
  *(.gnu.linkonce.d*)
  CONSTRUCTORS
  *(.eh_frame)
} > ram AT>flash
PROVIDE (__END_COPY__ = .);

I want the sections to be aligned on 4-byte boundaries (architecture is PowerPC 32-bit). Some of the data sections include sub-word items. I'm finding that the ALIGN instruction aligns the VMA address in RAM but doesn't align the LMA. So my copy-to-ram routine fails because the two areas don't correspond byte-for-byte.

My copy routine looks like

r3 = address in flash of _etext
r4 = address in ram of __COPY_DATA_START__
words to copy = (__END_COPY__ - COPY_DATA_START) / 4

while (words to copy)
  * r4++ = *r3++

When the loop gets to an aligned bit, the destination points to some pad bytes, but the source data doesn't include the align-padding so the data gets put too early in memory.

I can tell this from the map file because it looks like (contrived example)

.rodata         0x00000000      0xb15 load address 0xfff13000
                0x00000000                PROVIDE (__COPY_DATA_START__, .)

.sdata          0x00000b18      0x10  load address 0xfff13b15  <<< origin 0xb18 is aligned but load address hasn't moved on by the padding bytes

Does anyone know the solution to this problem?

Thank you

Chris

+1  A: 

I've had some success by using a different form of the "AT" linker script command. If I use

  _etext = .;
  PROVIDE (etext = .);
  .rodata : AT (_etext)
  { 
... contents of section ...
  }

  .sdata2 : AT (_etext + SIZEOF(.rodata) + SIZEOF(.gcc_except_table))
  { 
... contents of section ...
  } > ram

  .sbss2 : AT (_etext + SIZEOF(.rodata) + SIZEOF(.gcc_except_table) + SIZEOF(.sdata2) )
  { 
... contents of section ...
    . = ALIGN(16);
  } > ram

Then it seems to align as I would expect. The SIZEOF( ) + SIZEOF( ) ... string gets pretty long by the end of the file but at least it works.

(Additional info: Normally you wouldn't copy the rodata section into ram because it's read only. On my system the flash can't handle the kind of accesses requured for floating point constants, so I do need to copy it into RAM even though it won't be modified).

sparklewhiskers