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: ICall_leaveCSImpl using SDI UART.

Part Number: CC2640R2F

Tool/software: TI-RTOS

Hello,

I am using the ProjectZero example with my own BLE characteristics (total of 4) with the SDI from the SPP example.

The UART seems to work for awhile until the app crashes and I get the exception: 

Hard Fault: FORCED: BUSFAULT: PRECISERR.Data Access Error. Address = 0x8

I was getting an IMPRECISERR error but the developer guide said to disable buffered writes.

Below is a screenshot of the exception and disassembly. Also, note the HEAPMGR_SIZE.

To recreate this exception I repeatedly send characters out the UART with SDITask_Printf (Similar to SDITask_sendToUART)

Posted below is the SDITask_Printf function. I tried to mimic SDITask_sendToUART as closely as possible but it seems I have a memory leak somewhere.

Is it possible ICall is not freeing the last pSDIMsg structure? For everything else I've found an ICall_free and it seems to crash when It first calls that structure after its run out of available memory.

The devil must be in the details of this function somewhere and how I'm handling the ICall_malloc, ICall_free, and possibly the ICall Critical Section.

void SDITask_Printf(char *format, ...)
{
    ICall_CSState key;

      char* buffer =  (char *)ICall_malloc(128);
      SDIMSG_msg_t *pSDIMsg = (SDIMSG_msg_t *)ICall_malloc( sizeof(SDIMSG_msg_t));
      SDI_QueueRec *recPtr;

      int i,j;
      va_list args;
      // count number of LF's in format string
      i = 0;
      j = 0;
      while (format[i] != 0)
      {
        if (format[i++] == '\n' ) j++;
      }
      va_start(args, format);
      vsnprintf(&buffer[j],128, format, args);  // format output, skipping j characters

      // shift characters to the left, inserting CR's as needed
      i=0;
      while (buffer[j])
      {
        if (buffer[j]=='\n')
        {
            buffer[i++]='\r';
        }
        buffer[i++] = buffer[j++];
      }

      buffer[i] = 0;  // null-terminate the buffer
      uint16 length =  strlen(buffer);

      key = ICall_enterCriticalSection();
      va_end(args);
      if(pSDIMsg)
      {
        pSDIMsg->msgType = SDIMSG_Type_ASYNC;
        pSDIMsg->pBuf = (uint8 *)ICall_allocMsg(length);
        pSDIMsg->pBufSize = length;

        if(pSDIMsg->pBuf)
        {
            // Payload
            memcpy(pSDIMsg->pBuf, (uint8_t *)buffer, length);
        }

        recPtr = ICall_malloc(sizeof(SDI_QueueRec));

        recPtr->sdiMsg = pSDIMsg;
      }

      switch (pSDIMsg->msgType)
      {
          case SDIMSG_Type_ASYNC:
          {
              Queue_enqueue(sdiTxQueue, &recPtr->_elem);
              Event_post(hUartEvent, SDITASK_TX_READY_EVENT);
              break;
          }
          default:
          {
              //error
              break;
          }
      }
      //ICall_free(pSDIMsg);
      ICall_leaveCriticalSection(key);
      //delay_ms(15);
      ICall_free(buffer);
}

Thanks for your time,,

Brett

  • Also,

    All of my Tasks have a large enough Stack and are not overflowing.
  • Hello,

    Can you enable heap metrics and see if you have failed allocations?
    Based on you description, it seems likely that ICall_malloc() on line 49 above is failing and returning a NULL ptr.
    Later, on line 51 you are referencing recPtr-> without first checking that recPtr is != NULL, if it is NULL this would cause an exception.
  • Hi Sean,

    Thanks for pointing me to the Heap Metrics, i indeed was recieving a null when attempting to malloc.

    I found the issue later on down in sdi_task.c

    I had commented out some ICALL_free lines ! Silly me :)

    static void SDITask_ProcessTXQ(void)
    {
    ICall_CSState key;
    SDI_QueueRec *recPtr = NULL;

    // Processing of any TX Queue should only be done
    // in a critical section since any application
    // task can enqueue items freely
    //key = ICall_enterCriticalSection();

    if (!Queue_empty(sdiTxQueue))
    {
    recPtr = Queue_dequeue(sdiTxQueue);

    if (recPtr != NULL)
    {
    lastQueuedTxMsg = recPtr->sdiMsg->pBuf;

    SDITL_writeTL(recPtr->sdiMsg->pBuf, recPtr->sdiMsg->pBufSize);

    //free the Queue record
    ICall_free(recPtr->sdiMsg); ********
    ICall_free(recPtr); ***********
    }
    }

    ICall_leaveCriticalSection(key);
    }

    Works like a dream now.

    Thanks for your time