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.

CC2652R: ICall_malloc fails allocating more than 3 bytes

Part Number: CC2652R
Other Parts Discussed in Thread: SYSBIOS

hello, I'm developing an application using SDK 5.20.00.52, derived from project_zero. I need to allocate some memory to send a custom event handled by the processApplicationMessage function. If I call ICall_malloc with more than 3 bytes argument, it fails (returns NULL).

Tha malloc should allocate the pData field for an object of type

typedef struct
{
uint8_t event;
void *pData;
} pzMsg_t;

that is then enqueued using Util_enqueueMsg. If I ask for 3 bytes or less everything works, if my pData object is larger than 3 bytes the ICall_malloc fails.

ICall_malloc is called from an hwi (UART interrupt) but I don't think this is relevant. The heap should be configured as autosize (if I correctly understand the cfg settings) and memory allocation chart says SRAM is 17%, so I don't understand why I cannot allocate more than 3 bytes. When I call the relevant code the application is responding to a UART interrupt (keypress from terminal) while a cyclic routine is called every 1ms by an interrupt issued by sensor controller. Such routine uses some static data structures so no heap is involved, and memory usage is very low (total 17% as said above).

Thanks

Fabio Mannino

  • sorry I made a mistake in my description: I have two ICall_malloc, the first one allocates the space for a string, the second one allocates the pzMsg_t struct and should write to pData the address of the string. All data will be freed when the enqueued data is consumed. Anyway already at the very first run of the code I see that the first malloc (the string) returns a valid pointer, but the second one fails if the first one allocated more than 3 bytes.

    Thanks

    Fabio

  • Hi Fabio,

    Can you share your code snippet and SDK version?

    Best,

    Nate

  • Hello, 

    CC2652 SDK 5.20.00.52

    typedef struct
    {
      uint8_t event;
      void *pData;
    } pzMsg_t;

    void BLE_printf(char *str)
    {
      char *msg = ICall_malloc(strlen(str));
      if(msg != NULL)
      {
        strcpy(msg,str);
        if(BLE_app_enqueueMsg(PZ_APP_PRINTF, msg) != SUCCESS)
        {
           Log_error0("enqueue failed");
        }
      }
      else
      {
         Log_error0("ICall_malloc failed");
      }
    }

    static status_t BLE_app_enqueueMsg(uint8_t event, void *pData)
    {
      uint8_t success;
      pzMsg_t *pMsg = ICall_malloc(sizeof(pzMsg_t));

      if(pMsg)
      {
        pMsg->event = event;
        pMsg->pData = pData;

        success = Util_enqueueMsg(appMsgQueueHandle, syncEvent, (uint8_t *)pMsg);
        return (success) ? SUCCESS : FAILURE;
      }

      return(bleMemAllocError);
    }

    if the argument of BLE_printf is longer than 3 characters ICall_malloc fails. Actually I noticed that if it is much longer (e.g. 20 characters) the malloc does not fail.

    My goal is to enqueue a message with a string stored in the event and dequeue it to use the string (then ICall_free all the data) in a task. I don't even get the consumer task since malloc fails before enqueing.

    Thanks

    Fabio

  • Hi Fabio,

    Could it be possible that the problem is with the call to strlen? What happens if you hard-code a number in there instead?

    Best,

    Nate

  • Hello Nathan, I will let you know.

    In general, is there anything wrong with strlen ? I left my firmware run for long hours under test and it stopped in another piece of code using strlen. The call stack shows:

    ti_sysbios_family_arm_m3_Hwi_excHandler__I() 

    strlen() at 0xFFFFFFF9 (next frame is identical to an existing frame).

    Looking at registers CFSR has IMPRECISERR field at 1.

    Pressing "View disassembly" it shows a long list of lines like this:

    fffffff8:   ???? Memory map prevented reading 0xFFFFFFF8 [code=0x20000] 

    with different values 0xFFFFFFFx (hilighted x=8).

    I have a terminal application on pc that communicates through uart, the test simulates interaction with the user typing some commands at very fast rate. This problem is different than the malloc failure but that code uses strlen as well.

    Thanks

    Fabio

  • Hi Fabio,

    There is not a problem with strlen that I know of, but I don't see it used in our examples, which is why I'm recommending against it. Please confirm or deny that the code original code works/fails when you use sizeof() instead of strlen. As for the other error, I'm not sure if the code you're referencing is having a similar problem, but my recommendation remains the same (use sizeof() instead of strlen()).

    Best,

    Nate

  • Hi Nathan,

    I confirm that replacing strlen with sizeof in my BLE_printf function the ICall_malloc returns a valid pointer.

    Also I noticed that strlen is used in UartLog.c

    About the other error I replaced strlen with a workaround - in that case I just need to know if the string is empty or not (strlen()>0) but I still have the problem, will continue to investigate.

    Best regards

    Fabio

  • Great! Glad we could provide you with a solution for at least the first problem. I'm going to close this thread because we've resolved the issue that you opened it with, and if you want further help debugging the second problem, please open a new thread and link this thread if necessary. This helps us keep our threads concise for future users who may run into the same problem you have.

    Best,

    Nate

  • Hello,

    I have a stable code but actually the behavior of ICall_malloc is still unclear. In the above listed code I had to replace the line

    ICall_malloc(strlen(str));

    with a different call that uses as argument of ICall_malloc the minimum between strlen(str) and the constant 22 (value found after some tests):

    #define MIN_LEN 22

    int len = strlen(str) > MIN_LEN ? strlen(str) : MIN_LEN;
    char *msg = ICall_malloc(len);

    because attempts to allocate a smaller number of bytes ( < 22) results in ICall_malloc returning NULL.

    strlen should not have anything wrong, I'm using it again without problems and the IMPRECISERR was due to another reason and fixed.

    I investigated into ICal_malloc and found that it is actually a call to 

    void *HEAPMGR_MALLOC(hmU32_t size)

    in particular I found this piece of code:

    // Smaller allocations are first attempted in the small-block bucket.
    if (size <= HEAPMGR_SMALL_BLKSZ)
    {
        hdr = HEAPMGR_FF1;
    }
    else
    {
        hdr = HEAPMGR_FF2;
    }

    i.e. allocations are handled differently based on the requested size. HEAPMGR_SMALL_BLKSZ = 16

    Could be the "small-block bucket" memory set already full for some reason ? though a safe value in my case (22) seems to be slightly bigger than the threshold between small block and large block definition (16).

    Thanks

    Fabio

  • Hi Fabio,

    Please follow my above instructions and open a new thread for a new issue. I will be happy to assist you then.

    Best,

    Nate