This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Specific address location for RAM variable in RX140

Hi everybody,

I would like to force some RAM variables to be saved by compiler in spefic address range (for example from 0x100h to 0x200h).

I know it is possible to use

#pragma address

directive, but this means I have to calculate all the address for the variables.

I'm looking a solution like using

#pragma section

directive but I'm struggling how to setup the "C/C++ Build->Settings->Tool Settings->Linker->Section" linker menu in e2studio.

I tried the following test

#pragma section SafetyRAM
uint16_t a = 0x0000U;
uint16_t b = 0xFFFFU;
#pragma section

And I added a section in linker option with name "SafetyRAM" and address 0x100. Compiler gives me a warning:

W0561100:Cannot find "SafetyRAM" specified in option "start"

How can I solve? Thanks

[locked by: Sai (SWF) at 14:18 (GMT 0) on 8 Feb 2023]
  • here is my solution:

    1. define your section in  "C/C++ Build->Settings->Tool Settings->Linker->Section". in my case 'MYRAM'

    2. add assembler source file to your project. e.g. 'my_asm.src'

    3. define section in assembler code:

        .section    MYRAM, DATA
        .glb        _my_var_1
        .glb        _my_var_2
        .blkl        1
        .blkl        1

    4. you can access your vars in c-files:

    extern    uint16_t    my_var_1;
    extern    uint16_t    my_var_2;

    void main(void)

        my_var_1 = 100;
        my_var_2 = 200,

    .... and so on....

  • There are 2 solutions to put variables and constants on a specific location. The first option is with the pragma address, use as follow:

    #pragma address a=0x0100
    uint16_t a;
    	a = 0;

    The drawback is that you need to initialise the variable yourself. The compiler doesn’t generate code for this. And you need to manually calculate the address if you have multiple variables, but you can solve this by using a struct.

    The second option is with the pragma section. For this you need to add a section entry in the linker section viewer "C/C++ Build->Settings->Tool Settings->Linker->Section" like JanekD shows. Set the address and your section name. Add a ‘*’ after the name If you don’t know the size or have multiple variables withe different width. For example, use “SafetyRAM_D*”. The compiler will then generate the necessary sections SafetyRAM_D_1 (8-bit), SafetyRAM_D_2 (16-bit) and/or SafetyRAM_D (32-bit) to put the variables in properly aligned sections.

    The section that yo need to create depends on how the variable is initialised. If the variable has no value assigned on definition, then you must create a B section in RAM. If the variable has a value assigned on definition (like your case), then you need to create an R section in RAM and a D section in ROM.
    If the D section in ROM doesn't need a specific address, then just leave it blank, the compiler will put it it right after the previous section. And for a constant you need to define a C section in ROM.

    In your case add SafetyRAM_R* in RAM and SafetyRAM_D* in ROM

    If you defined a D section then you also need to add a symbol link to link the D and R section. For this goto "C/C++ Build->Settings->Tool Settings->Linker->Section->Symbol file" and scroll down to the "ROM to RAM mapped section" . In your case you need to add the lines:
    SafetyRAM_D=SafetyRAM_R, SafetyRAM_D_1=SafetyRAM_R_1 and SafetyRAM_D_2=SafetyRAM_R_2.

    A *_8 section is only needed if you use double variables on a RXv3 with DFPU.

    Now we must also change the startup code to properly initialise the variables on startup. Open the "dbsct.c" file in the generate directory and search for "_DTBL[]" table and changed it to:

    #pragma section C C$DSEC
    extern const struct {
        _UBYTE *rom_s;       /* Start address of the initialized data section in ROM */
        _UBYTE *rom_e;       /* End address of the initialized data section in ROM   */
        _UBYTE *ram_s;       /* Start address of the initialized data section in RAM */
    }   _DTBL[] = {
        { __sectop("D_8"), __secend("D_8"), __sectop("R_8") },
        { __sectop("D"), __secend("D"), __sectop("R") },
        { __sectop("D_2"), __secend("D_2"), __sectop("R_2") },
        { __sectop("D_1"), __secend("D_1"), __sectop("R_1") },
        { __sectop("SafetyRAM_D"), __secend("SafetyRAM_D"), __sectop("SafetyRAM_R") },
        { __sectop("SafetyRAM_D_1"), __secend("SafetyRAM_D_1"), __sectop("SafetyRAM_R_1") },
        { __sectop("SafetyRAM_D_2"), __secend("SafetyRAM_D_2"), __sectop("SafetyRAM_R_2") }

    The startup code will copy the SafetyRAM_D sections in ROM to the SafetyRAM_R sections in RAM to initialise the variables.

    If you created a B section then you need to add the sections to the "_BTBL[]" table.

    Now add the variable definition like this in your code, don't forget the 'D'. This tells the compiler that the "D" section is altered to the "SafetyRAM_D" section.

    #pragma section D SafetyRAM_D 	//alter D section to SafetyRAM
    unsigned short a = 0x0000U;
    unsigned short b = 0xFFFFU;
    #pragma section 				//restore all sections to default name

    Just watch out that the order of multiple variables in a section is not guaranteed. Use a single struct if yo want a fixed order.

    It takes some time to properly setup new sections. But once they are correct you can add multiple variables across several source files.

  • Hello JanekD,

    Thanks for reply and suggestion. I will try to follow NGE reply since it seems less painless.

  • Hello NGE,

    Thank you for complete explanation. I will review your description step-by-step. Meanwhile, I'm studying the CCRX manual in order to have a better understand of the various sections.

    For sure I have both unitialized and initialized RAM variable so I need both B and D sections.

  • Hello @NGE,

    Your solution turned out to be very effective and fast to implement. Thank you.

    I have now a related question regarding  section P (code). I would like to isolate some parts of the code to specific location where CRC will be periodically checked.

    I alsready tested the possibility to change section to specific function using #pragma section...  for example

    #pragma section P SafetyROM
    void foo(void)
    void bar(void)
    #pragma section

    So far, so good: the two functions are located at the "SafetyROM" section (which I declared into "C/C++ Build->Settings->Tool Settings->Linker->Section" setting).

    Now I would like to change section only yo part of the "main()" program, something like this:

    void main(void)
        //some code
    #pragma section P SafetyROM
        //some "special" code to be linked to SafetyROM section
    #pragma section
        //some other code

    Compiler/Linker doesn't complain but it seems that the part of the code is not inserted into "SafetyROM" section.

    Is it possible to do that?

    Thanks and regards

  • No, it is not possible, #pragma section P will only alter the section of the function that comes after it. The only way to do it is to create a sub function. A function can always call a function in another section, there are no restrictions on that.