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: RTOS Queue issue

Part Number: CC2640R2F
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI-RTOS

Hi all,

I am trying to fill queue with messages. After filling some messages, i will iterate queue and remove some messages on any spesific place(middle, tail or head). When i try removing messages with this code in below, program crashes after some time.

        if (!Queue_empty(outgoingMsgQueue))
        {
            Queue_Elem *pRec;
            pRec = Queue_head(outgoingMsgQueue);
            for (pRec = Queue_head(outgoingMsgQueue); pRec != (Queue_Elem *) outgoingMsgQueue; pRec = Queue_next(pRec))
            {
                queueRec_t * questr = (queueRec_t*) pRec;
                sbpUARTEvt_t *pMsg = (sbpUARTEvt_t *) questr->pData;
                if (pMsg)
                {

                        Queue_remove(pRec);
                        ICall_free(pRec);
                        ICall_freeMsg(pMsg->pData);
                        ICall_free(pMsg);
                }
             }
        }

It goes HWI in Queue_remove(pRec);

HW exception :

Exception call stack
0 ti_sysbios_knl_Queue_remove__E at Queue.c:219 :
PC=0x1001BF66

In Queue.c 219:

    qelem->next->prev = qelem->prev;
This line occurs hardware fault. According to Runtime Object view.

But when i try with this, it works properly

        if (!Queue_empty(outgoingMsgQueue)) //no ack msg but there are msgs sent
        {
            Queue_Elem *pRec;
            pRec = Queue_head(outgoingMsgQueue);
                queueRec_t * questr = (queueRec_t*) pRec;
                sbpUARTEvt_t *pMsg = (sbpUARTEvt_t *) questr->pData;
                if (pMsg)
                {
                        Queue_remove(pRec);
                        ICall_free(pRec);
                        ICall_freeMsg(pMsg->pData);
                        ICall_free(pMsg);
                }
        }

So, when i iterate with for loop, program stucks after some time . What can be the problem ?

Best regards.

  • Hi,

    Let me dig into this a bit and examine it and I'll respond by tomorrow.
  • Hi,

    My concern is that your code is not thread safe. What threads are potentially adding and removing elements? If this is a task, and it's traversing a linked list and a higher priority thread (hwi, swi or task) changes the linked list, trouble could happen.

    Also, when you are adding elements to the queue, where is the memory coming from? You must allocate a unique block for each element. Maybe ICall is doing this hence you calling ICall_free etc, but it would be good to verify this.
  • Hi Evan,

    thank you for your answer. Firstly, one task will put message to this queue and another one task will wait for events with timeout. If timeout occurs or event occurs it will remove messages using some spesific pattern if any message is available in queue. So in here, one supplier/ one consumer methodology is available.

    My enqueue function is that;

    void ACK_H_enqueueOutgoingMsg(uint8_t event, uint8_t *data, uint8_t len)
    {
        sbpUARTEvt_t *pMsg;
        queueRec_t *pRec;
    
        //Enqueue message only in a connected state
        if (isBLEConnected())
        {
            // Create dynamic pointer to message.
            if (pMsg = ICall_malloc(sizeof(sbpUARTEvt_t)))
            {
                pMsg->event = event;
                pMsg->pData = (uint8 *) ICall_allocMsg(len);
                if (pMsg->pData)
                {
                    memcpy(pMsg->pData, data, len);
                }
                pMsg->length = len;
                // Enqueue the message.
                if ((pRec = ICall_malloc(sizeof(queueRec_t))))
                {
                    pRec->pData = (uint8*) pMsg;
                    // This is an atomic operation
                    Queue_put(outgoingMsgQueue, &pRec->_elem);
                    Event_post(ackEvtHandle, ONGOING_MSG_EVT);
                }
                else
                {
                    ICall_free(pMsg);
                }
            }
        }
    }
    

    I allocate memory for each message. I disassamle the problem and these are what i get.

    Decoded exception    
    Decoded    Hard Fault: FORCED: BUSFAULT: IMPRECISERR
    Exception context    
    $addr    N/A
    $type    ti.sysbios.family.arm.m3.Hwi.ExcContext
    threadType    Task
    threadHandle    0x20001a20
    threadStack    0x20001a70
    threadStackSize    512
    r0    0x10000
    r1    0x80000024
    r2    0x80000024
    r3    0x20003500
    r4    0x200019f8
    r5    0x20003518
    r6    0xffffffff
    r7    0x6010207
    r8    0xffffffff
    r9    0xffffffff
    r10    0xffffffff
    r11    0xffffffff
    r12    0x20003714
    sp    0x20001c18
    lr    0xa7cd
    pc    0x1001bf66
    psr    0x81000000
    ICSR    0x414803
    MMFSR    0x0
    BFSR    0x4
    UFSR    0x0
    HFSR    0x40000000
    DFSR    0x0
    MMAR    0xe000edf8
    BFAR    0xe000edf8
    AFSR    0x0
    Exception call stack    
    0 ti_sysbios_knl_Queue_remove__E at Queue.c:219 :    PC=0x1001BF66
    1 ACK_H_application_taskFxn at ack_handler.c:175 :    PC=0x0000A7CC

    This is raw registers when cortex goes to Hard fault.

    Program counter in memory:

    Link register in memory:

    Everything looks fine but program crashes after some time when i traverse linked list.

    Regards.

  • Hey there,

    Thanks for the extra details! I think i know the issue. After you call ICall_free(pRec); pRec should not be used as it is used within the for loop as well and you would be trashing pRec for the rest of your for loop iterations.

    You don't need the check for empty either assuming you're popping everything off, not just when it has a pMsg. If that's not true, the logic would change a bit but make sure to get pRec = Queue_next(pRec) before you free pRec.

    This code below should be roughly what you're looking for.

    Queue_Elem *pRec; 
    while (pRec = Queue_head(outgoingMsgQueue) != (Queue_Elem *) outgoingMsgQueue) {; 
    { 
        queueRec_t * questr = (queueRec_t*) pRec; 
        sbpUARTEvt_t *pMsg = (sbpUARTEvt_t *) questr->pData; 
        Queue_remove(pRec); // assuming you always want to remove it, not just it has a message
        ICall_free(pRec);  
        if (pMsg) 
        { 
                ICall_freeMsg(pMsg->pData); 
                ICall_free(pMsg); 
        } 
    } 

  • Hi Evan,

    I want to check time of messages in queue and if time of message is expired i will remove this message. So, i will not remove every message in queue.
    But the way you suggest is very logical. I will apply this to my methodology and i will remove 1 message every time. So queue will not be crashed.
    Thank you for your support.

    Best regards.