This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/CC2640R2F: Insufficient Memory in Simple Central Example

Part Number: CC2640R2F

Tool/software: TI-RTOS

Hello,

I built an observer to read non connectable undirected advertisements from a continuously updating broadcaster. This is built with simplelink_cc2640r2_sdk_2_20_00_49 on the BLE5 stack.

It keeps triggering SC_EVT_INSUFFICIEN_MEM after a few seconds of receiving data (broadcaster pushing ~7 packets every 500ms).

To simplify things, I took the simple_central example and only changed the following:

  • Parameters to look for non connectable advertisements
  • HCI Whitelist so it only sees my board
  • Added a function to print payload from the simplelinkacademy example
  • Made it scan continuously by adding SimpleCentral_doDiscoverDevices to the main loop

 I cannot find out where the memory leak is occurring, but others have reported this issue too, so there seems to be some missing memory clearing in the example itself

(https://e2e.ti.com/support/wireless_connectivity/bluetooth_low_energy/f/538/t/638217?tisearch=e2e-sitesearch&keymatch=sc_evt_insufficient_mem)

I ran ICall_getHeapStats(&stats); within the SC_EVT_ADV_REPORT and found that I run out of heap in about 75-85 occurrences

Any help with where I should try clearing memory would help.

Thanks,

Mishca

  • Hi Mishca,

    Thanks for posting.
    The GAP_EVT_INSUFFICIENT_MEMORY can come from the stack in two cases : advertising or scanning.

    Given your description above it sounds like it is originating from the scan process.

    A bit of feedback:

    SimpleCentral_doDiscoverDevices() isn't exactly intended to be called in the SimpleCentral_taskFxn loop as it will always try to trigger a context switch to the stack (via ICall, which will block the app and wait for a message to be sent back). All these messages will definitely strain the system more than needed. Calling GapScan_enable() when you already scanning will just end up returning an error code of bleAlreadyInRequestedMode, which means the overhead is incurred for not much benefit.

    Instead, if you want to continuously scan, I recommend kicking off scanning again in SC_EVT_SCAN_DISABLED.
    Another way to do this is to kick off a single scan that will continue forever by setting DEFAULT_SCAN_DURATION to 0.

    This will help your system's overall robustness.

    Regarding the potential memory leak, have you tried using HeapMem + HeapTrack? They will keep track of all blocks allocated in the heap via ROV and even have pretty good detection of heap issues.

    Assuming the bug is in the application layer and not the stack I would poke around for the mallocs/frees in SC_EVT_SCAN_DISABLED and SC_EVT_ADV_REPORT and be sure that they are balanced in terms of malloc and free.
  • // Allocate buffer to display addresses
          pAddrs = ICall_malloc(numReport * SC_ADDR_STR_SIZE);
          if (pAddrs == NULL)
          {
            numReport = 0;
          }
    
          TBM_SET_NUM_ITEM(&scMenuConnect, numReport);
    
          if (pAddrs != NULL)
          {
            pAddrTemp = pAddrs;
            for (i = 0; i < numReport; i++, pAddrTemp += SC_ADDR_STR_SIZE)
            {
      #if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)
              // Get the address from the list, convert it to string, and
              // copy the string to the address buffer
              memcpy(pAddrTemp, Util_convertBdAddr2Str(scanList[i].addr),
                     SC_ADDR_STR_SIZE);
      #else // !DEFAULT_DEV_DISC_BY_SVC_UUID
              // Get the address from the report, convert it to string, and
              // copy the string to the address buffer
              GapScan_getAdvReport(i, &advRpt);
              memcpy(pAddrTemp, Util_convertBdAddr2Str(advRpt.addr),
                     SC_ADDR_STR_SIZE);
      #endif // DEFAULT_DEV_DISC_BY_SVC_UUID
    
              // Assign the string to the corresponding action description of the menu
              TBM_SET_ACTION_DESC(&scMenuConnect, i, pAddrTemp);
            }
    
            // Disable any non-active scan results
            for (; i < DEFAULT_MAX_SCAN_RES; i++)
            {
              tbm_setItemStatus(&scMenuConnect, TBM_ITEM_NONE, (1 << i));
            }
    
            ICall_free(pAddrs);

    I also also try running your test again with the above code removed just for testing. There is a known issue with the above code that will result in a ptr potentially being accessed after it is free'd. Namely where  TBM_SET_ACTION_DESC(&scMenuConnect, i, pAddrTemp); is used to copy a temp address into the menu system that is free'd later ICall_free(pAddrs). This is a know issue with simplelink_cc2640r2_sdk_2_20_00_49_s and should be fixed lin the next quarterly release.