This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Some questions about RAM non_init

Hello,

I want to use RAM to keep some data after a soft reset, so that I can find problems after reset.
And I also found some implementation methods, such as using .non_init section. I also achieved it, but I still have some doubts and hope to get answers.

https://devzone.nordicsemi.com/f/nordic-q-a/48919/ram-retention-settings-with-softdevice-enabled/194367#194367

1).  In the flash_placement.xml file, there is clearly a .non_init part, but it is not displayed during debugging. 


When I assign size to .non_init in the flash_placement.xml file or define variable in the code, I can see the non_init section during debugging. Why is this?

static uint8_t data[16] __attribute__((section(".non_init")));
or 
<ProgramSection alignment="4" load="No" name=".non_init" size="16"/>

 

2). What is the RAM that has not been allocated?

For example, the address 0x200046f7-0x20005800 in the figure. Is its value maintained, or is it used by the .stack section when the program is running?

Thanks & Regards

Gray

Parents
  • Hi,

     

    1).  In the flash_placement.xml file, there is clearly a .non_init part, but it is not displayed during debugging. 

    Is the variable, placed in .non_init, actually used? It might be that the linker places it in the UNUSED section, and discards it.

     

    When I assign size to .non_init in the flash_placement.xml file or define variable in the code, I can see the non_init section during debugging. Why is this?

     Now you address the section with an absolute size. Look through the .map file, and see if there's something placed in the .non_init section, or if it is just an empty 16 byte section.

     

    For example, the address 0x200046f7-0x20005800 in the figure. Is its value maintained, or is it used by the .stack section when the program is running?

     .heap grows up in address space, .stack grows down in address space. A region should not go outside its own bounds, but it can happen.

    The section in-between is considered "unused", but in case of a .heap or .stack overflow occurring, those two will grow into the unused space. There are drawbacks of such an implementation, which is essentially that you mask or hide overflows, until you for instance add another module that uses a bit more RAM (both stack and .data/.bss). The positive side is that you don't strictly need to adjust your .stack size, as the linker will dynamically adjust it for you. There's several articles, forumposts, etc on this matter (stackoverflow, Keil, IAR, SES/gcc; most will have include discussions around stack placement)

    What you really should do is to analyze the stack usage of your firmware image to determine the stack size:

    https://stackoverflow.com/questions/6387614/how-to-determine-maximum-stack-usage-in-embedded-system-with-gcc

    https://www.keil.com/appnotes/files/apnt_316.pdf

     

    Note that a callgraph / -fstack-usage gives a theoretical approach and does not take re-entrant functions (functions that call them selves, or get called through different contexts) into consideration.

     

    Kind regards,

    Håkon

  • Hello,Håkon.

    Thank you for your reply.

    The positive side is that you don't strictly need to adjust your .stack size, as the linker will dynamically adjust it for you.

    I was on SES and saw that .stack and .heap are set to 2048 bytes. Are these two sections fixed in size?

    Thanks & Regards

    Gray

  • Hi,

     

    Palmer Huang said:
    I was on SES and saw that .stack and .heap are set to 2048 bytes. Are these two sections fixed in size?

    The sections are sized, but the .heap is placed right after the .bss (zero initialized globals) and .data (non-zero initialized globals), while the stack is placed at the top of RAM (growing downwards.

    Do note that there's no runtime checks (maybe calloc/malloc() has, depending on your implementation) to see if the section goes out-of-bounds runtime.

    If you set the .stack section to 2K, then do this in a function, your compiler and linker will highly likely not complain:

    int stack_smasher(int input)
    {
      int smash_the_stack[4096];
      for (int i = 0; i < (sizeof(smash_the_stack) / sizeof(int)); i++)
        smash_the_stack[i] = i;
    
      return 0;
    }
     

     

    However; you're digging quite deep into your stack, "unused" RAM, and other regions below that address space if that function runs.

     

    Kind regards,

    Håkon

Reply
  • Hi,

     

    Palmer Huang said:
    I was on SES and saw that .stack and .heap are set to 2048 bytes. Are these two sections fixed in size?

    The sections are sized, but the .heap is placed right after the .bss (zero initialized globals) and .data (non-zero initialized globals), while the stack is placed at the top of RAM (growing downwards.

    Do note that there's no runtime checks (maybe calloc/malloc() has, depending on your implementation) to see if the section goes out-of-bounds runtime.

    If you set the .stack section to 2K, then do this in a function, your compiler and linker will highly likely not complain:

    int stack_smasher(int input)
    {
      int smash_the_stack[4096];
      for (int i = 0; i < (sizeof(smash_the_stack) / sizeof(int)); i++)
        smash_the_stack[i] = i;
    
      return 0;
    }
     

     

    However; you're digging quite deep into your stack, "unused" RAM, and other regions below that address space if that function runs.

     

    Kind regards,

    Håkon

Children
Related