This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to control order of global variables in RAM?

I'd like to store some global variables in RAM in a contiguous order.  For instance if I define:

Uint16 a=0, b=0, c=0;

I want to have the memory map reflect that the variables are store in RAM contiguously.  My RAM starts at 0xC000 so I want a at 0xC000, b at 0xC001, and c at 0xC002).

However when I compile my code the resulting order in RAM is b, a, c.  It is even stranger when I use six variables (i.e. Uint16 a=0, b=0, c=0, d=0, e=0, f=0, g=0, h=0;).  Then I find in the memory map that the variables have been assigned to memory locations in the order c,d,a,b,g,h,e,f from 0xC000 to 0xC007.  There doesn't seem to be a predictable pattern when I try other amounts of variables either.

The only way I found I could keep the variables in order was to use the DATA_SECTION pragma in my source file as:

       #pragma DATA_SECTION (a, "user1"); #pragma DATA_SECTION (b, "user2"); #pragma DATA_SECTION (c, "user3");

and then modify my linker file as follows

MEMORY {
 PAGE 1 : /*Data memory.*/
 user_RAM1   : origin = 0x00C000, length=1
 user_RAM2   : origin = 0x00C001, length=1
 user_RAM3   : origin = 0x00C002, length=1
}

SECTIONS {
 user1        : > user_RAM1,  PAGE = 1
 user2        : > user_RAM2,  PAGE = 1
 user3        : > user_RAM3,  PAGE = 1
}

Is there a better way?  This way is rather clunky and seems like it would take too much work to do so for a large number of variables. 

By the way I am using the C28x build tools V5.2.11 and programming the F28335.  When I used to program the LF2407A with its C24x build tools I never had to go to this extent to have variables stored in the order desired.  I want these variables in order so that external machines which interface to my processor via various serial interfaces will be able to easily access tables of variables.

Thanks,
Mark

  • The easiest (and only portable) way is to use a struct:

    struct {
        Uint16 a;
        Uint16 b;
        Uint16 c;
    } globals = { 0, 0, 0 };
  • Thank you for your reply Archaeologist. 

    The structure idea is great for keeping the variables contiguous (thanks!). 

    Sorry I didn't make it clear in my original post but I would also like to have the individual variables (the structure members in this case) listed in the .map file.

    Previously I used the DATA_SECTION pragma idea above to accomplish this (though it is very clunky).  I can simplify things a little by using GROUP in the linker file.  For instance in the source file:

            #pragma DATA_SECTION (a, "user1"); #pragma DATA_SECTION (b, "user2"); #pragma DATA_SECTION (c, "user3");
          
    Uint16 a=0, b=0, c=0;

    Then in the linker file:

     MEMORY {
     PAGE 1 : /*Data memory.*/
     RAM   : origin = 0x00C000, length=0x4000
    }

    SECTIONS {
     GROUP : run = RAM PAGE 1
     { 
      user1
      user2
      user3
     }
    }

    This still is a bit of work, are there any better ideas to do this?

    Thanks,
    Mark

  • Another option to consider ... Define all those variables in hand coded assembly.  Refer to them from C as "extern".  The order of the variables is determined in the assembly file. The link command file needs to handle only one section.  

    Thanks and regards,

    -George

  • Thanks for your reply George, I appreciate it. 

    Great idea!

    Mark

  • Dear Mark,

    Did you define the variables in assembly? Did it work?

    Ankit