6

I'm using GCC. I create a SECTION in Flash by .ld linker file, I placed there some data (704 bytes) with directive __attribute__((section... Data appears to be in flash, but the same space is allocated in RAM if I don't use the const keyword while declaring the data.

If I use const RAM is not used - but I notice increased use of flash, as it was allocated there twice!

Linker file:

FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 14K
USER_DATA_FLASH (rx)      : ORIGIN = 0x8003800, LENGTH = 2K
}

SECTIONS
{ /* placing my named section at given address: */
  .my_block 0x8003800 :
 {
  KEEP(*(.UserDataSector)) 
 } > USER_DATA_FLASH
}

The array declaration has initializers:

mytab_type  __attribute__((section (".UserDataSector "))) progr16[16]=
{ 
    { {LIST1,LIST2....

In this case I did not use const. Assuming that progr16 was forced to be in the flash, and actually it looks there if I check with memory browser during debug. But it appears occupying RAM too

FLASH    RAM
text     data    bss   dec     
9268     772     1948  11988    

If I add the const keyword:

FLASH    RAM
text     data    bss    dec 
9972     68      1948   11988

Ok, 704 bytes of data in RAM are saved, but why the same amount of bytes increases the use of Flash, if this values already where in Flash (because of the initializers)?

vgru
  • 49,838
  • 16
  • 120
  • 201
  • Could you please show the complete declaration of progr? Where are the LIST1, LIST2 items from and how are they declared? – user6556709 Apr 26 '19 at 08:27
  • It probably never was in flash when you didn't use `const` and that's that? – Lundin Apr 26 '19 at 09:23
  • @Lundin The initial values for the .data section are copied from .text in pre-main. So they have to be in the flash otherwise the variables in .data wouldn't have initial values. – user6556709 Apr 26 '19 at 09:28
  • @user6556709 Ah yeah of course. That's probably the answer the OP is looking for, come to think of it. – Lundin Apr 26 '19 at 09:30
  • As in, the initializers were perhaps not in `.text` but in `.rodata` or some such. Which isn't part of the linker output shown. Btw why would custom segments count towards `.text` size. This isn't making much sense, I would guess a complete map file is needed to see what's happening. – Lundin Apr 26 '19 at 09:32
  • @Lundin It is quite common on embedded systems to put .rodata* in .text . So there doesn't have to be a rodata section after linking and if their would be one it would be shown in the usage overview the OP posted. – user6556709 Apr 26 '19 at 10:05
  • @user6556709 it is very common .text and .rodata to occupy the same memory, but it is very unlikely to have only one section in the embedded systems – 0___________ Apr 26 '19 at 12:16
  • @P__J__ I haven't wrote that you have only one section. For what I said you will find many code including example code from the chip designers and manufacturers where the .text section looks like this .text{ [....] (*(.rodata*)) [...] } > FLASH – user6556709 Apr 26 '19 at 12:31
  • Not necessary whole the array will be put as it is into the flash, because if it contains a lot of zeroes, of repeatable values, the initialization code could be optimized to save flash. – AterLux Apr 26 '19 at 13:35
  • Thanks for the answers.This is the complete declaration of variables as asked by user6556709. ' typedef struct { const uint16_t table[22]; }mytab_type;' – Diego Colombo Apr 26 '19 at 14:31
  • Thanks for the answers.This is the complete declaration of variables ,as asked by user6556709. ` typedef struct { const uint16_t table[22]; }mytab_type; mytab_type __attribute__((section (".UserDataSector "))) progr16[16]= { ={ {{LIST1}},{{LIST2}},...{{LIST16}} }; #define LIST1 0,155,340,420,480.......//22 values #define LIST2 .. ` i'm new so i'm not able to format correctly the comments,please forgive me if the code is not correctly indented and formatted – Diego Colombo Apr 26 '19 at 14:38
  • @DiegoColombo, please paste that into the bottom of your question, and simply make a comment to say you've pasted it up there. We can help format it in the question then when you see it formatted you can edit the question to see how we did it. – Gabriel Staples Apr 26 '19 at 23:39

1 Answers1

-1

I haven't had a chance to actually set up and build a stand-alone project, like I plan to do, to thoroughly test this, but does adding NOLOAD, as follows, work?

SECTIONS
{ 
    .my_block (NOLOAD) :
    {
        KEEP(*(.UserDataSector));
    } >USER_DATA_FLASH
}

Here's some notes I took in the v2.32 ld PDF user manual for "NOLOAD": enter image description here

This seems to be what you might need.

Also, I usually place the attribute specifier after the variable, as is shown in many official gcc examples (such as the ones under "section" here), although I'm not sure that's strictly required (see official syntax documentation here).

ie:

static my_type my_array_name[] __attribute__((section(".UserDataSector"))) =
{
    // member 1,
    // member 2,
    // member 3,
    // etc
};

Also, your formatting (spaces, alignment, indentation, etc) in your question isn't very good, I must say, and along these lines of not paying close attention to detail, I see in your section attribute you have an extra space at the end: ".UserDataSector " instead of ".UserDataSector", like it should be, so that might be the issue too.

Also, a few more notes:

  1. Note you should clean up your formatting, indentation, etc, a bit to make code in your question easier to read.
  2. I don't think KEEP is necessary here, but it doesn't hurt anything either I don't think.
  3. You should study and read the official GNU Linker Script (LD) manual. It is available online in html format, here: https://sourceware.org/binutils/docs/ld/. the latest version is v2.32.

    1. However, I think it's much easier to study in a PDF so you can type into it, highlight it, mark it up, search it all at once, etc. Build the LD pdf user manual, then use Foxit Reader (cross-platform, and no-cost) to study and mark up the manual.
    2. How to build the Linker Script (LD) PDF user manual:
    3. Download the source code: https://www.gnu.org/software/binutils/
      1. Ex: get the latest binutils version (currently binutils-2.32.tar.xz) here: https://ftp.gnu.org/gnu/binutils/
    4. Extract it (right-click and go to "Extract Here" in Linux Ubuntu, for instance).
    5. cd into the folder: cd binutils-2.32
    6. Then configure and make:

      ./configure
      make
      make pdf
      
    7. Done! Here are the PDFs now (found with find | grep '\.pdf'):

      binutils-2.32/libiberty/libiberty.pdf
      binutils-2.32/bfd/doc/bfd.pdf
      binutils-2.32/ld/ld.pdf    <----- THE MAIN ONE I WANT!
      binutils-2.32/gprof/gprof.pdf
      binutils-2.32/gas/doc/as.pdf
      binutils-2.32/binutils/doc/binutils.pdf
      
    8. Save and use ld.pdf, which is now the PDF version of the HTML 2.32 binutils manual I linked to above.

  4. You may need to read your startup file to see if it's doing anything weird.

Like I said, I'd like to fully test this answer before posting this, but don't have the chance right now. I've spent many many hours in linker scripts over the last few weeks though, so with some of it fresh in my mind I thought this would help.

Other Linker Script questions of note

  1. Is accessing the "value" of a linker script variable undefined behavior in C?
  2. How to get value of variable defined in ld linker script from C
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265