[SOLVED] Automatic initialization by the linker of the initialized variables in a specific RAM

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • [SOLVED] Automatic initialization by the linker of the initialized variables in a specific RAM

    Hello,I'm testing the Segger linker, and I have some troubles about initializing variables.

    The processor I use is an STM32H743, the linker is the Segger linker, the icf file is STM32H7xxFlash.icf provided by Segger (which defines the sections AXI_RAM1, RAM1, RAM2, etc.),
    Embedded Studio Release 4.30c Build 2019120200.40763

    I have an array (of structure) which I initialize with constants.
    If I do not give any instruction, the table is implemented in the AXI_RAM and initialized... ok :

    burst32_t burstsDef[NBR_BURST] = {
    {10-1, 0, 1, 1, 1, 1}, {10-1, 0, 2, 2, 2, 2}, {10-1, 0, 5, 5, 5, 5}, {64-1, 0, 32, 32, 32, 32},
    };

    If I set the ram I want to use for this array, for example .RAM1 (__attribute __ ((section (". RAM1")))) the array is in the correct ram, but is NOT initialized (unless I specify ".AXI_RAM1" as the section):

    burst32_t __attribute__((section(".RAM1"))) burstsDef[NBR_BURST] = {
    {10-1, 0, 1, 1, 1, 1}, {10-1, 0, 2, 2, 2, 2}, {10-1, 0, 5, 5, 5, 5}, {64-1, 0, 32, 32, 32, 32},
    };

    If I fix its address (__attribute __ ((section (". ARM .__ at_0x30000000")))) the table is in the correct ram AND initialized.

    burst32_t __attribute__((section(".ARM.__at_0x30000000"))) burstsDef[NBR_BURST] = {
    {10-1, 0, 1, 1, 1, 1}, {10-1, 0, 2, 2, 2, 2}, {10-1, 0, 5, 5, 5, 5}, {64-1, 0, 32, 32, 32, 32},
    };

    Is this behavior normal? Is there something missing in the icf file?
    Is it possible to have the variables automatically initialized in the RAM of my choice, without having to fix their address, and without having to create a specific section in the icf file (which would be a source of error in case of confusion between the section specifically initialized and the section which is not - but which should be?-)?

    Best regards
    Jean-Louis

    The post was edited 1 time, last by jlvern ().

  • Hello Jean-Louis,

    Thank you for your inquiry.
    Placing the array in .RAM1 or .AXI_RAM1 should not behave differently.
    To place variables that are initialized there are multiple approaches.
    We recommend using the one shown in the example .icf file by "initialize by copy".
    Also symbols can be placed withing the linker file, so no need to use the (__attribute __ ((section approach anymore.
    More information about the SEGGER Linker can be found in the SEGGER Linker manual.
    You can find it in Embedded Studio if you open Help->Contents->Using Segger Linker->SEGGER Linker User Guide

    This will open a pdf document with the complete Linker documentation.

    Best regards,
    Nino
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.
  • Hello,I guess I would have to do something simple for it to work, but I can't (despite the fact that I read the doc of the Segger linker)...The xml and icf files I use are those of Segger.

    Source Code: STM32H7xx_Flash.icf

    1. //......
    2. define memory with size = 4G;
    3. //
    4. // Combined regions per memory type
    5. //
    6. define region FLASH = FLASH1;
    7. define region RAM = AXI_RAM1;
    8. //
    9. // Block definitions
    10. //
    11. define block vectors { section .vectors };
    12. define block vectors_ram { section .vectors_ram };
    13. define block ctors { section .ctors, section .ctors.*, block with alphabetical order { init_array } };
    14. define block dtors { section .dtors, section .dtors.*, block with reverse alphabetical order { fini_array } };
    15. define block exidx { section .ARM.exidx, section .ARM.exidx.* };
    16. define block tbss { section .tbss, section .tbss.* };
    17. define block tdata { section .tdata, section .tdata.* };
    18. define block tls { block tbss, block tdata };
    19. define block tdata_load { copy of block tdata };
    20. define block heap with size = __HEAPSIZE__, alignment = 8, /* fill =0x00, */ readwrite access { };
    21. define block stack with size = __STACKSIZE__, alignment = 8, /* fill =0xCD, */ readwrite access { };
    22. //
    23. // Explicit initialization settings for sections
    24. //
    25. do not initialize { section .non_init, section .non_init.*, section .*.non_init, section .*.non_init.* };
    26. initialize by copy /* with packing=auto */ { section .data, section .data.*, section .*.data, section .*.data.* };
    27. initialize by copy /* with packing=auto */ { section .fast, section .fast.* };
    28. //
    29. // Explicit placement in FLASHn
    30. //
    31. place in FLASH1 { section .FLASH1, section .FLASH1.* };
    32. //
    33. // FLASH Placement
    34. //
    35. place at start of FLASH { block vectors }; // Vector table section
    36. place in FLASH with minimum size order { section .init, section .init.*, // Init code section
    37. section .init_rodata, section .init_rodata.*, // Init read-only section
    38. section .text, section .text.*, // Code section
    39. section .rodata, section .rodata.*, // Read-only data section
    40. section .segger.*, // Auto-generated initialization
    41. block exidx, // ARM exception unwinding block
    42. block ctors, // Constructors block
    43. block dtors }; // Destructors block
    44. place in FLASH { block tdata_load }; // Thread-local-storage load image
    45. //
    46. // Explicit placement in RAMn
    47. //
    48. place in ITCM_RAM1 { section .ITCM_RAM1, section .ITCM_RAM1.* };
    49. place in DTCM_RAM1 { section .DTCM_RAM1, section .DTCM_RAM1.* };
    50. place in AXI_RAM1 { section .AXI_RAM1, section .AXI_RAM1.* };
    51. place in RAM1 { section .RAM1, section .RAM1.* };
    52. place in RAM2 { section .RAM2, section .RAM2.* };
    53. place in RAM3 { section .RAM3, section .RAM3.* };
    54. place in RAM4 { section .RAM4, section .RAM4.* };
    55. place in Backup_RAM1 { section .Backup_RAM1, section .Backup_RAM1.* };
    56. //
    57. // RAM Placement
    58. //
    59. place at start of RAM { block vectors_ram };
    60. place in RAM { section .non_init, section .non_init.*, // No initialization section
    61. block tls }; // Thread-local-storage block
    62. place in RAM with auto order { section .fast, section .fast.*, // "ramfunc" section
    63. section .data, section .data.*, // Initialized data section
    64. section .bss, section .bss.*
    65. }; // Static data section
    66. place in RAM { block heap }; // Heap reserved block
    67. place at end of RAM { block stack }; // Stack reserved block at the end
    Display All
    and the file:

    XML Source Code: STM32H743ZITx_MemoryMap.xml

    1. <!DOCTYPE Board_Memory_Definition_File>
    2. <root name="STM32H743ZITx">
    3. <MemorySegment name="ITCM_RAM1" start="0x00000000" size="0x00010000" access="Read/Write" />
    4. <MemorySegment name="FLASH1" start="0x08000000" size="0x00200000" access="ReadOnly" />
    5. <MemorySegment name="DTCM_RAM1" start="0x20000000" size="0x00020000" access="Read/Write" />
    6. <MemorySegment name="AXI_RAM1" start="0x24000000" size="0x00080000" access="Read/Write" />
    7. <MemorySegment name="RAM1" start="0x30000000" size="0x00020000" access="Read/Write" />
    8. <MemorySegment name="RAM2" start="0x30020000" size="0x00020000" access="Read/Write" />
    9. <MemorySegment name="RAM3" start="0x30040000" size="0x00008000" access="Read/Write" />
    10. <MemorySegment name="RAM4" start="0x38000000" size="0x00010000" access="Read/Write" />
    11. <MemorySegment name="Backup_RAM1" start="0x38800000" size="0x00001000" access="Read/Write" />
    12. </root>
    Display All
    At the start of the program, I put some initialized variables:

    C Source Code

    1. /* USER CODE BEGIN 0 */
    2. #define DEBUG_VAR
    3. #if defined( DEBUG_VAR )
    4. uint32_t def = 10;
    5. uint32_t __attribute__((section(".RAM1"))) ram1 = 20;
    6. uint32_t __attribute__((section(".RAM2"))) ram2 = 30;
    7. uint32_t __attribute__((section(".RAM3"))) ram3 = 40;
    8. uint32_t __attribute__((section(".RAM4"))) ram4 = 50;
    9. uint32_t __attribute__((section(".AXI_RAM1"))) axi = 60;
    10. uint32_t __attribute__((section(".DTCM_RAM1"))) dtcm = 70;
    11. uint32_t __attribute__((section(".ARM.__at_0x30000000"))) ram1_ = 80;
    12. uint32_t __attribute__((section(".ARM.__at_0x30020000"))) ram2_ = 90;
    13. uint32_t __attribute__((section(".ARM.__at_0x30040000"))) ram3_ = 100;
    14. uint32_t __attribute__((section(".ARM.__at_0x38000000"))) ram4_ = 110;
    15. #endif
    16. /* USER CODE END 0 */
    Display All
    and at the beginning of main () a printf for debug:

    C Source Code

    1. /* USER CODE BEGIN 2 */
    2. #if defined( DEBUG_VAR )
    3. printf("\n\rDef =%d\n\rAxi =%d\n\rDtcm =%d", def, axi, dtcm );
    4. printf("\n\rRam1 =%d\n\rRam2 =%d\n\rRam3 =%d\n\rRam4 =%d", ram1, ram2, ram3, ram4 );
    5. printf("\n\rRam1_=%d\n\rRam2_=%d\n\rRam3_=%d\n\rRam4_=%d", ram1_, ram2_, ram3_, ram4_ );
    6. #endif
    and the result is this:

    Source Code

    1. /* printf resullt
    2. Def =10
    3. Axi =60
    4. Dtcm =70
    5. Ram1 =1913732878
    6. Ram2 =-1714927937
    7. Ram3 =-431577966
    8. Ram4 =50
    9. Ram1_=-1470746299
    10. Ram2_=-1198926942
    11. Ram3_=-1700774047
    12. Ram4_=110
    13. */
    Display All
    I do not understand why RAM1..3 is not initialized while RAM4 is. I am also sure that the RAM1..3 domain is powered (at the main level) because if I initialize the variables by hand, they are correct.
    Do you have any idea why the variables are not initialized for RAM1..3?
    The ram4 is in the D3 domain while the ram1..3 are in the D2 domain, but I don't understand what this changes for the linker, unless the domain is not powered up during the startup during the copying initialized variables. Do you think this is the case, and if so, do you know how to modify the startup file to make everything work?

    Best regards,
    Jean-Louis
  • I understood the problem!: indeed the domain D2 was not power up when the linker copied the data.
    This is due to the STM32H7xx_Startup.s file which calls the SystemInit () function in system_stm32h7xx.c in which a define allows you to indicate whether or not you want to power up the D2 domain (which by default is not).


    C Source Code: system_stm32h7xx.c

    1. /************************* Miscellaneous Configuration ************************/
    2. /*!< Uncomment the following line if you need to use initialized data in D2 domain SRAM (AHB SRAM) */
    3. /* #define DATA_IN_D2_SRAM */
    4. /*!< Uncomment the following line if you need to relocate your vector Table in
    5. Internal SRAM. */
    6. /* #define VECT_TAB_SRAM */
    7. #define VECT_TAB_OFFSET 0x00000000UL /*!< Vector Table base offset field.
    8. This value must be a multiple of 0x200. */
    9. /******************************************************************************/
    Just uncomment the define DATA_IN_D2_RAM for everything to be ok.

    Best regards
    Jean-Louis
  • Hello Jean-Louis,

    Great to hear that you are up and running again.
    We will consider this thread as solved now.

    Best regards,
    Nino
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.