Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Managing heap sizes across Memory Manager module, FreeRTOS, and project settings

TL;DR and just want to get to the questions? See highlighted text below.

I am working with nRF52832 in SEGGER Embedded Studio, working with nRF5 SDK 16.0.0.  I use a SEGGER JLink Base unit for debug, and rely on the Debug Terminal in SES for debug messages.

There are multiple heaps being used in a code base I've inherited and I'm attempting to optimize and reduce RAM usage in the code.  I've noted three different heaps:

  • Project Settings > Runtime Memory Area: __HEAP_SIZE__ = 8192
  • FreeRTOS (using heap_4.c): configTOTAL_HEAP_SIZE = 20480
  • nRF mem_manager module (in mem_manager.c): TOTAL_MEMORY_SIZE  = 6400

The application code makes use of "malloc" and "free" in one 3rd party source module, other than than the heap is not explicitly (malloc, alloc, calloc, free) used in our application code as far as I'm aware.  We do make use of nrf_queues, Flash Data Storage module, mbedtls backend for aes_ccm, BLE services, FreeRTOS tasks, timer and queues, etc. (see configuration macros below). 

xPortGetFreeHeapSize returned 4504 immediately after performing some crypto functions using mbedTLS backend (with FreeRTOS debug printf'ing task disabled).

I couldn't get nrf_mem_diagnose() formatting to print nicely in debug terminal with FreeRTOS printf task enabled, but with a little manual editing, it appears the memory manager is using heap space, and it appears to be using all the chunks available:

+------------+------------+------------+------------+------------+------------+
| Block      | Size       | Total      | In Use     | Min Alloc  | Max Alloc  |
+------------+------------+------------+------------+------------+------------+
| Small      | 32         | 8          | 8          | 32         | 0          |
| Medium     | 64         | 8          | 8          | 64         | 0          |
| Large      | 128        | 8          | 8          | 128        | 0          |
| XLarge     | 256        | 2          | 2          | 256        | 0          |
| XXLarge    | 2048       | 2          | 2          | 2048       | 0          |

At first I thought any heap use would go through the memory manager, e.g. use of heap in FreeRTOS tasks would make use of memory manager, but looking at the map file, they are completely separate.  After seeing that, now I'm not sure which operations/code is using which heap and when, therefore I'm not able to easily figure out where I need to look when trying to optimize/reduce RAM usage.  For example, we receive data via our BLE service, memcpy the data from the service characteristic to another buffer in RAM, then notify our FreeRTOS task to operate on that RAM buffer, then the FreeRTOS task makes a call to mbedTLS backend, which calls mbedtls_free, which is the standard C free (I think), and so on. So my questions are:

  1. Can I trust that each of the modules are using the appropriate heap, is there overlap--where heap space is allocated in two different heaps for the same data?  Is there other mbedTLS/FreeRTOS/SoftDevice/nRF5 SDK configuration settings I can set so that I can combine the heaps to be a little bit more manageable/intuitive?  
  2. In the case where the application code uses explicit malloc/free, can the __HEAP_SIZE__ be adjusted to make sure there is just enough space available for only data?  Do I need to add a certain amount of bytes as overhead for other startup functions?
  3. Should nrf_crypto_aes API methods be used when performing encryption/decryption instead of accessing mbedtls_aes_ccm methods directly?
  4. If printf is used inside FreeRTOS tasks, which heap is used?
  5. If NRF_LOG_ENABLED is 1 (enabled) and calls such as NRF_LOG_DEBUG are used, which heap would it use--does it matter if its called within FreeRTOS task?
  6. printf seems to print to Debug Terminal window, should NRF_LOG_X calls also be printing to Debug Terminal or is there additional steps required to make that happen?

nRF configurations:

  • #define NRF_CRYPTO_ALLOCATOR 0
  • #define NRF_QUEUE_ENABLED 1
  • #define NRF_CRYPTO_BACKEND_MBEDTLS_ENABLED 1
  • #define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM_ENABLED 1
  • #define NRF_CRYPTO_ALLOC(size) (nrf_malloc((uint32_t)(size)))
  • #define NRF_CRYPTO_FREE(p_buffer) (nrf_free((void *)(p_buffer)))
  • #define NRF_CRYPTO_ALLOC_ON_STACK 0
  • #define BLE_APP_ENABLED 1
  • #define NRF_SDH_ENABLED 1
  • #define NRF_LOG_ENABLED 0
  • #define NRF_SDH_BLE_LOG_ENABLED 1
  • #define NRF_SDH_LOG_ENABLED 1
  • #define NRF_SDH_SOC_LOG_ENABLED 1

FreeRTOS configuration:

  • #define configUSE_TIMERS 1
  • #define configSUPPORT_DYNAMIC_ALLOCATION 1
  • #define portUSING_MPU_WRAPPERS 0

mbedTLS configuration:

  • #define MBEDTLS_PLATFORM_MEMORY
  • #define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
  • #define MBEDTLS_PLATFORM_C
  • #define MBEDTLS_PLATFORM_STD_MEM_HDR <stdlib.h>
  • #define MBEDTLS_PLATFORM_STD_CALLOC calloc
  • #define MBEDTLS_PLATFORM_STD_FREE free
Parents
  • Hi,

    The nrf_memory and FreeRTOS Heap are two different things and are not overlapping. FreeRTOS heap is directly controller controlled and managed by the kernel and the amount of heap it reserves is configurable in FreeRTOSConfig.h file. nrf_memory manager is a standalone library that does not depend or communicate with any RTOS. It seems to me that something is using your nrf_memory manager which is not the same as memory managed by FreeRTOS kernel. Not sure what that could be based on the information provided.

    • nrf_mem_init() and nrf_calloc(count, size) is not explicitly called anywhere, nor does the code in the functions get compiled (can't set breakpoints in the function).
    • nrf_malloc(size) and nrf_free(p_mem) is not explicitly called anywhere because I'm not using the nrf_crypto API for the mbedTLS backend, which calls NRF_CRYPTO_ALLOC and NRF_CRYPTO_FREE.  Setting breakpoints within the functions and running the application, the breakpoints are never hit.
    • nrf_mem_reserve(pp_buffer, p_size) is only referenced from within mem_manager.c, so that isn't being called explicitly anywhere.

    That being said, how is nrf_mem_diagnose reporting use of all chunks of data when none of the functions in mem_manager.c are getting executed?  Am I misreading the output of nrf_mem_diagnose?  Is something internal to the SoftDevice using memory manager heap space?

  • kcl74 said:
      Am I misreading the output of nrf_mem_diagnose? 

    Possibly, I think we both are misreading the output. Can you please do a small experiment and actually allocate something in your application using nrf_mem_manager and see if the diagnose output changes a bit giving us hints to interpret it in the proper way.

     

    kcl74 said:
    Is something internal to the SoftDevice using memory manager heap space?

     No, Softdevice never uses ANY of the SDK drivers or libraries.

  • Can you tell me what the heap size, main stack size, and process stack size is used for, that is set in project properties under Project Settings > Code > Runtime Memory Area?

    I imagine SoftDevice reserves all the RAM it needs for heap.  FreeRTOS reserves its own heap space.  So would __HEAP_SIZE__ be for "user" heap; so, any direct calls to malloc?

    If nrf mem_manager is used, does nrf_malloc use space in the memory manager, which would be in the "user" heap area, or is the nrf memory manager heap space reserved in the SoftDevice RAM reserved area?  I assume FreeRTOS pvPortMalloc only uses the FreeRTOS reserved heap space.

    For main stack size, is that used for what CPU is in handler mode, for things like context switching between FreeRTOS tasks, or for code that is executing outside of FreeRTOS tasks?  FreeRTOS tasks have their own stack, so I imagine the main stack size does not affect that?  Does SoftDevice have its own stack space in the SoftDevice reserved RAM area?  How would one go about determining a proper main stack size?

    The process stack size I've seen in the nRF5 SDK FreeRTOS examples have Process Stack Size set to 0, however the PSP holds the RTOS task stack pointer, so I would think the Process Stack Size would be set to the largest FreeRTOS tasks stack size, but this is not the case, it is always 0.  In what cases would that value have to be changed?

  • kcl74 said:
    I imagine SoftDevice reserves all the RAM it needs for heap.  FreeRTOS reserves its own heap space.  So would __HEAP_SIZE__ be for "user" heap; so, any direct calls to malloc?

    I think you need to set these in the FreeRTOSConfig.h file in 

    #define configMINIMAL_STACK_SIZE ( 60 )
    #define configTOTAL_HEAP_SIZE ( 4096 )

    and also set the linker preprocessor defines have atleast the values that are set in FreeRTOSConfig.h. I have to admit that I did not test this myself but I know that FreeRTOS just considers the defines in FreeRTOSConfig.h and the linker has hints only from SES project settings.

Reply
  • kcl74 said:
    I imagine SoftDevice reserves all the RAM it needs for heap.  FreeRTOS reserves its own heap space.  So would __HEAP_SIZE__ be for "user" heap; so, any direct calls to malloc?

    I think you need to set these in the FreeRTOSConfig.h file in 

    #define configMINIMAL_STACK_SIZE ( 60 )
    #define configTOTAL_HEAP_SIZE ( 4096 )

    and also set the linker preprocessor defines have atleast the values that are set in FreeRTOSConfig.h. I have to admit that I did not test this myself but I know that FreeRTOS just considers the defines in FreeRTOSConfig.h and the linker has hints only from SES project settings.

Children
Related