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

Putting my app on a (RAM) memory diet

I'm running out of RAM in my 51822 app and I need to take a look at what's using RW and ZI memory. Very little memory is being allocated with malloc. The rest is allocated at build time. How can I generate a memory map at build time that tells me the size of the various static and global objects?

  • With some tips from Pratyush, I found the map file which the Keil dev environment creates. One surprise is that arm_startup_nrf51.o takes 4096 bytes of ZI RAM. Since I only have 8K available after the SoftDevice takes its chunk, this is a big hit. Does anyone know how to get this module to scale back its RAM requirements?

  • I also notice that main.o is using 972 bytes, despite the fact that I'm just calling inits from main and all the real work is done in other modules. But the main entrypoint might have some hidden memory requirements that I don't know about. Can anyone comment?

  • It looks like each member of the event queue takes 16 bytes and I'm using a queue size of 10 in APP_SCHED_INIT. So that accounts for 160 of the 972 mystery bytes. So 812 bytes are still unexplained.

  • You do have a lot of questions here, so I'll try to answer them sequentially:

    1. For completeness, Keil will put a .map file in the _build folder as long as the "Linker listing" options are on on the "Listing" tab of the target options.
    2. arm_startup_nrf51.s contains the definitions of the heap and the stack, each being 2 kB by default, and this is therefore the reason it shows up with 4 kB in your map file. If you know that you don't use 2 kB of heap, feel free to reduce the heap size. The memory usage of S110 itself is given in the Softdevice Specification (1.5 kB of stack, no heap), and no heap is used by the SDK.
    3. Some of the initalization macros used in main.c contains a static buffer for data storage. This applies for for example BLE_STACK_INIT, APP_TIMER_INIT, APP_BUTTON_INIT and friends, and this is most likely the cause of the 972 bytes used in main. You can for example take a look at the timer queue size, as explained here and the maximum number of timers, since this is usually a big part of the main memory.

    Apart from this, your map file should contain a listing of the symbols defined in main, and how much memory each consumes, like this:

    .bss                                     0x200020f0   Section      776  main.o(.bss)
    APP_TIMER_BUF                            0x200020f0   Data         576  main.o(.bss)
    EVT_BUFFER                               0x20002330   Data          80  main.o(.bss)
    app_gpiote_buf                           0x20002380   Data          20  main.o(.bss)
    m_tps                                    0x20002394   Data          10  main.o(.bss)
    m_ias                                    0x200023a0   Data          16  main.o(.bss)
    m_lls                                    0x200023b0   Data          20  main.o(.bss)
    m_bas                                    0x200023c4   Data          24  main.o(.bss)
    m_ias_c                                  0x200023dc   Data          12  main.o(.bss)
    m_battery_sim_cfg                        0x200023e8   Data          16  main.o(.bss)
    

    For this application, the timer buffer is the biggest consumer in main, with the event buffer for the softdevice being second. Also the app_gpiote structure consumes a bit, as well as the different services.

    Another module that might easily consume some RAM is the bond manager. It needs to fit all bond information in RAM before writing to flash, so by reducing the max number of bonds you can store, you can reduce its RAM consumption.

    PS: You make it much more likely to get quick answers if you edit your original question instead of continuously posting new information as answers, since the answers moves the question out of the "Unanswered" category. :-) I'd also be very happy if you could go back and take a look at other questions you have asked and accept an answer to those that you consider solved. That makes it a lot easier for others to find useful information!

  • I found this answer to be very helpful. While trying to slim my multi-link central based application down I found that the major RAM user in device_manager was

    DEVICE_MANAGER_MAX_CONNECTIONS

    I found that each additional connection used between 152-160 bytes (I think it varied due to alignment). Since it's initially configured for 8 connections your looking at potentially (160*8)=1,280 bytes!

Related