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.

BOOSTXL-CC2650MA: Additional SYS/BIOS task terminating unexpectedly

Part Number: BOOSTXL-CC2650MA
Other Parts Discussed in Thread: SYSBIOS

Starting with the updated SPP_BLE_Server example from Github, I have two separate tasks I've added, one of which loops with a variable delay for Task_sleep() blocking it for a bit at the end.  Each time through, it checks a static file-scope flag to see if the connection state has changed.

When sppbleserver.c:SPPBLEServer_processStateChangeEvt() gets the GAPROLE_CONNECTED case, it calls a function that sets said flag.  Once it does this, the task in question enters a "terminated" state, according to the classic ROV.

I had initially forgotten to make the flag variable volatile, but correcting this didn't help, and the debugger started to complain at breakpoints, "Cortex_M3_0: Error: (Error -1170 @ 0x0) Unable to access the DAP."  I also tried queuing the information for better synchronization, but then all I see in the Debug panel when I halt after the "flag" function is called are:

* ti_sysbios_hal_Hwi_HwiProxy_Object__delete__S_mangled__(),

and

* ti_sysbyos_knl_Task_SupportProxy_swap__E__mangled__(),

and it's now SPPBLEServer_taskFxn is the one that's terminated.

Also according to ROV, stackPeak is not exceeding stackSize, so I'm a bit puzzled.  Still new to the TI-RTOS environment, so not sure what additional info to provide up front.

  • Hi,

    Would you like to share a code snippet of the task that is terminated unexpectedly? 

    Could you please specify if the new stack access the BLEStack (i.e. calls some ICall functions)?

    Best regards,

  • Hi Clément,

    The new stack does include ICall functions, via calls to SerialPortService_SetParameter() and SDITask_sendToUART().  The task is essentially a shim between the UART and BLE interfaces -- it receives ASCII commands over BLE (collected in a ring buffer by the other task I mentioned), queries the "primary" micro over the UART, pends on a semaphore for the response, and formats an ASCII response and reports back over BLE.

    I do call ICall_registerApp() before the loop begins, though I don't actually use either of the structs passed to it.

    I should be able to pare down to shareable essentials:

    // This is called by SPPBLEServer_processStateChangeEvt() on GAPROLE_ADVERTISING or GAPROLE_CONNECTED cases
    
    void ui_connect_notify(bool b_connected)
    {
        connstat.b_connected_status = b_connected;
        Queue_enqueue(connstat_q, &(connstat.elem));
    }
    
    
    void ui_update (UArg arg0, UArg arg1)
    {
    
    
        ICall_registerApp(&ui_entity, &ui_sem);
    
    
        for(;;)
        {
            b_waiting = false;
            set_ms_delay(100);  // default value for Task_sleep() at end of loop
    
            if (!Queue_empty(connstat_q))
            {
                p_connstat = Queue_dequeue(connstat_q);
                b_connected_status = p_connstat->b_connected_status;
    
                if (b_last_connect_status != b_connected_status)
                {
                    b_substate_reset = true;
                    bt_state = b_connected_status ? BT_STATMSG : BT_IDLE;
                    b_last_connect_status = b_connected_status;
                    
                    if (b_connected_status)
                    {
                        Task_sleep(1000 * TICKS_PER_MS);
                    }
                }
            }
    
            if (!b_waiting)
            {
                b_state_changed  = (bt_state != current_state);
                current_state    = bt_state;
                
                switch (bt_state)
                {
                    case BT_IDLE:
                    {
                    }
                    break;
    
                    case BT_STATMSG:
                    {
                        bt_state = bt_status_message();
                    }
                    break;
                    
                    default:
                    break;
                }
            }
            
            // the full function has other cases that may modify sleep_delay via set_ms_delay()
            Task_sleep(sleep_delay);
        }
        
        
    static bt_state_t bt_status_message(void)
    {
        static uint8_t  msgnum = 0;
        uint16_t        iter   = 0;
    
        bt_state_t next_state = BT_STATMSG;
    
        if (b_state_changed)
        {
            msgnum = 0;
        }
    
        switch (msgnum)
        {
            case 0:
            {
                // Calls to comctl_get_set configure a packet sent over UART via SDITask_sendToUART(), and pend on a semaphore for the response.
                // The return value is a union of all used sizes of signed/unsigned ints, and pointers thereto
                uint8_t sysmode = comctl_get_set(ATT_SYSMODE, ATT_SYSMODE_MODE, NULL, 0, false).u08;
    
                //capitalize "mode" when authorized
                sprintf(g_uartTXBuf, "%code: ", (BTauth != 0) ? 'M' : 'm');
    
                sprintf(&g_uartTXBuf[6], 
                        ((sysmode < NUM_SYS_MODES) ? &s_sysmode[sysmode][0] : (const uint8_t *) "Undefined\r\n"));
                ble_transmit_string(&g_uartTXBuf[0]);
                msgnum = (SYS_MODE_ERROR == sysmode) ? 1 : 0;
                set_ms_delay((msgnum != 0) ? 300 : 1000);
            }
            break;
    
            case 1:
            {
                uint32_t widemap = 0;
                bool b_code_found = false;
                static uint8_t mask_index = 0;
    
                widemap = comctl_get_set(ATT_FAULTS, ATT_FAULT_ACTIVE, NULL, 0, false).u32;
    
                if (0 == widemap) // in error mode, but no flags
                {
                    sprintf(g_uartTXBuf, "Unspecified error\r\n");
                    ble_transmit_string(g_uartTXBuf);
                    mask_index = NUM_ERRCODES;
                }
                else
                {
                    for (iter = 0; iter < NUM_ERRCODES; ++iter)
                    {
                        if ((fault_bitmask[iter] & widemap) != 0)
                        {
                            sprintf(g_uartTXBuf, "Error: %s\r\n", s_errorcode[iter]);
                            error_details_append(iter, g_uartTXBuf);
                            ble_transmit_string(g_uartTXBuf);
                        }
                    }
                }
    
                set_ms_delay(1000);
                mask_index = 0;
                msgnum = 0;
            }
            break;
    
            default:
            {
                msgnum = 0;
            }
            break;
        }
    
        return next_state;
    }
    
    static void ble_transmit_string(uint8_t * p_data)
    {
        int32_t len = strlen((const char *) p_data);
    
        if (len > RX_BUFFER_LENGTH)
        {
            len = RX_BUFFER_LENGTH;
        }
    
        if (SerialPortService_SetParameter(SERIALPORTSERVICE_CHAR_DATA, len, p_data) == 0)
        {
    #if 0
            SerialPortService_AddStatusTXBytes(len);
    #endif
        }
    }

  • ui_update() is the task in question, and I included an abridged bt_status_message() for additional context.

    Interestingly, whatever is actually happening has some small degree of delay.  Stepping through the code, task termination happens after ui_connect_notify() executes, but left to run at normal speed, status case 0 executes and outputs to BLE, and status case 1 transmits the query on the UART, but stops short of outputting the result over BLE.

  • Additionally, this was originally working before I opened #3861641, when I could get linking to complete.  Part of the solution in that ticket was upgrading the compiler, but reverting to the original did not restore the desired behavior of the project.

  • Hi James,

    What is the ticket number you're referring to? Can you provide a link?

    Best,

    Nate

  • Please let me know if there's any other information I can provide.

  • Haven't heard anything in almost a week; have I missed something, or overlooked any information that was requested of me?

  • Hi Nathan,

    Haven't heard from TI in over two weeks; don't know if I've slipped through the cracks or what.

    I reverted to the last working version of the project, and fixed the omitted file that was causing my linking issues, without any of the other changes from that ticket, and it works.

    However, this is not the first time these symptoms have presented, and I'd like to understand what's happening or how to troubleshoot the next time it crops up.

  • Hi James,

    I apologize for the delayed response. This definitely slipped through the cracks. The fact that you fixed a different file to get the device working though indicates to me that the problem may be elsewhere. Let me confer with my colleagues and get back to you with a response by tomorrow.

    Best,

    Nate

  • Hi James,

    After reviewing the thread, our experts believe it may be related to creating additional iCall enabled tasks vs. non-iCall enabled tasks (ex. making API calls via iCall in the context of a Stack callback function). Is it possible this task is not registered with iCall? If so, you cannot call iCall functions in its context.

    At the same time, this could also be related to a memory issue, please take a look at this post from Jeff:

    https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/429180/sensortag-2015-loop/1533668#1533668

    If you're interested and willing, feel free to send us your complete project (set up to run on a launchpad) and we will take a look.

    Best,

    Nate

  • The iCall registration was one of the first lessons I learned after starting with the TI-RTOS environment, and have not had any issues since where that's concerned.

    At the time, I thought perhaps there might be an overflow as described in the ticket you just linked, but couldn't definitively identify one occuring.  Pretty sure I was following the tips in the programming guide, too, but I'll review again should the need arise.

    There's probably a revision reproducing the issue in Git, but I'd have to find it, and either pare it down to something I can share, or get an NDA set up, and I unfortunately don't have the bandwidth for either right now.