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.

MSP432P4011: TI-RTOS using pThread freezes while scheduling new events

Part Number: MSP432P4011
Other Parts Discussed in Thread: SYSCONFIG

Hello forum, I'm developing an application with MSP432 using TI-RTOS - 
Part - MSP432P4011
TI-RTOS version - We are using the Simplelink MSP432P4 SDK, version 3.30.0.13
CCS v9.2.0.00013

The design has 2 threads - Thread 1: SensorThread with priority 1 (lower) and Thread 2: DataCaptureThread with priority 2 (higher). The idle thread has priority 0.
We have used the POSIX and pThread architecture to schedule RTOS events within a thread and to pre-empt or trigger the other thread. SensorThread is the main thread in the application, which gathers data through ADCs, talks to 2 SPI slaves and reads data etc. DataCapture thread is a high priority thread that needs to be triggered when certain conditions are detected.

For configuring the GPIOs, ADCs, SPI etc, we are using the sysconfig tool.  Individually, we have developed and tested the low-level SPI/ADC drivers through this application in the thread initialization phase and it works fine. The problem is arising when we try to integrate it with the RTOS scheduler using semaphores.

Here's my code - 

The file main_tirtos.c has

/*
 *  ======== main ========
 */
int main(void)
{
    /* Call driver init functions */
    Board_init();

    SensorThread_createTask();

    DataCaptureThread_createTask();

    BIOS_start();

    return (0);
}

The SensorThread.c looks like this - 

void SensorThread_createTask(void)
{
    pthread_attr_t pAttrs;
    struct sched_param priParam;
    struct mq_attr attr;
    int retc;
    int detachState;

    /*
     *  Message Queue to send messages to sensor thread.
     *  It is non-blocking to allow it to be called by ISRs (e.g. GPIO and
     *  Timer callbacks).
     */
    attr.mq_maxmsg = ST_MSG_NUM;     //Defined as 6
    attr.mq_msgsize = ST_MSG_SIZE;   //Defined as sizeof(stEvt_t)
    attr.mq_flags = 0;
    appMsgQueue = mq_open("sensor", O_RDWR | O_CREAT | O_NONBLOCK, 0664, &attr);
    if (appMsgQueue == (mqd_t)-1) {
        /* mq_open() failed */
        while (1);
    }

    /* Semaphore to notify sensor thread that msg is present. */
    retc = sem_init(&appMsgSem, 0, 0);
    if (retc == -1) {
        while (1);
    }

    /* Set priority and stack size attributes */
    pthread_attr_init(&pAttrs);
    priParam.sched_priority = ST_TASK_PRIORITY;

    detachState = PTHREAD_CREATE_DETACHED;
    retc = pthread_attr_setdetachstate(&pAttrs, detachState);
    if (retc != 0) {
        /* pthread_attr_setdetachstate() failed */
        while (1);
    }

    pthread_attr_setschedparam(&pAttrs, &priParam);

    retc |= pthread_attr_setstacksize(&pAttrs, ST_TASK_STACK_SIZE);
    if (retc != 0) {
        /* pthread_attr_setstacksize() failed */
        while (1);
    }

    /* Create Sensor Thread with priority = 1 */
    retc = pthread_create(&sensorthread_handler, &pAttrs, SensorThread_taskFxn, NULL);
    if (retc != 0) {
        /* pthread_create() failed */
        while (1);
    }
}
/*
 *  ======== sensorThread ========
 */
static void SensorThread_init(void)
{

    /* Initialize Display */
    Display_Params_init(&params_disp);
    handle_disp = Display_open(Display_Type_UART, &params_disp);
    if (handle_disp == NULL) {
        // Display_open() failed
        while(1);
    }


    // Output to Display
    Display_printf(handle_disp, 0, 0, "Display Initialized");

    /* Enable GPIO CallBack Functions */
    /* Call driver init functions */
    GPIO_init();

    // Output to Display
    Display_printf(handle_disp, 0, 0, "GPIO Initialized");

    /* Open and initialize the SPI ports */
    SPI_init();
    SPI_Params_init(&spiParams_ADE);
    spiParams_ADE.bitRate = 5000000;
    spiParams_ADE.frameFormat = SPI_POL1_PHA1;
    spiParams_ADE.mode = SPI_MASTER;
    spiParams_ADE.transferMode = SPI_MODE_BLOCKING;
    spiParams_ADE.dataSize = 8;
    spi_ADE = SPI_open(ADE_SPI, &spiParams_ADE);
    if (spi_ADE == NULL) {
        // Error opening SPI
        Display_printf(handle_disp, 0, 0, "Error opening SPI port for ADE!");
        while (1);
    }

    // Output to Display
    Display_printf(handle_disp, 0, 0, "SPI Port for ADE Open");

    //Do AFE Initializations here
    ADE_Init(&spi_ADE, &handle_disp);

    // Output to Display
    Display_printf(handle_disp, 0, 0, "ADE Initialized");


    SPI_Params_init(&spiParams_Kernel);
    spiParams_Kernel.bitRate = 2000000;
    spiParams_Kernel.frameFormat = SPI_POL0_PHA1;
    spiParams_Kernel.mode = SPI_MASTER;
    spiParams_Kernel.transferMode = SPI_MODE_BLOCKING;
    spiParams_Kernel.dataSize = 8;
    spiParams_Kernel.transferTimeout = 500;
    spi_Kernel = SPI_open(KERNEL_SPI, &spiParams_Kernel);
    if (spi_Kernel == NULL) {
        // Error opening SPI
        Display_printf(handle_disp, 0, 0, "Error opening SPI port for Kernel!");
        while (1);
    }

    // Output to Display
    Display_printf(handle_disp, 0, 0, "SPI Port for Kernel Open");


    /* Toggle GPIO to indicate status*/
    GPIO_write(LED4, 1);
    

    Display_printf(handle_disp, 0, 0, "Setting Gains  to x100");
    //Set gain of 100
    SensorThread_SetGain(1);

    Display_printf(handle_disp, 0, 0, "Initializing ADCs");

    // One-time init of ADC driver
    ADC_init();
    // initialize optional ADC parameters
    ADC_Params_init(&AX_params);
    ADC_Params_init(&AY_params);
    ADC_Params_init(&AZ_params);
    ADC_Params_init(&TEMP_INT_params);
    ADC_Params_init(&TEMP_EXT_params);

    /* Set GPIO Interrupts */
    GPIO_setCallback(MSP_WAKE, SensorThread_WDTCallbackFxn);
    GPIO_enableInt(MSP_WAKE);

    GPIO_setCallback(IRQ, SensorThread_ADE_IRQCallbackFxn);
    GPIO_enableInt(IRQ);

    GPIO_setCallback(REV_PWR, SensorThread_ADE_REVPCallbackFxn);
    GPIO_enableInt(REV_PWR);

    GPIO_setCallback(VOLTAGE_ZX, SensorThread_ADE_VoltageZXCallbackFxn);
    GPIO_enableInt(VOLTAGE_ZX);

    //Activate the WDT by giving it a pulse
    GPIO_write(MSP_DONE, 1);
    Task_sleep(100);                             //Wait for some time (Duration??)
    GPIO_write(MSP_DONE, 0);
    Display_printf(handle_disp, 0, 0, "WDT Activated");

}

static void *SensorThread_taskFxn(void *arg0)
{
    // Initialize application
    SensorThread_init();

    Display_printf(handle_disp, 0, 0, "Sensor Thread has been Initialized");

    stEvt_t msg;
    int retc;



    while (1) {
        /* Wait for a change to occur */
        retc = sem_wait(&appMsgSem);
        if (retc == 0) {
            retc = mq_receive(appMsgQueue, (char *)&msg, sizeof(msg), NULL);
            if (retc != -1) {

                switch (msg.hdr.event) {
                case ST_DUMMY_EVT:
                    break;

                case ST_WDT_EVT:
                    SensorThread_processWDTEvent();
                    break;

                case ST_IRQ_EVT:
                    SensorThread_processADE_IRQEvent();
                    break;

                case ST_REVP_EVT:
                    SensorThread_processADE_REVPEvent();
                    break;

                case ST_VOLTAGE_ZX_EVT:
                    SensorThread_processADE_VoltageZXEvent();
                    break;

                case ST_CAPTURED_DATA_EVT:
                    SensorThread_processCapturedDataEvent((float *)msg.pData);
                    break;

                default:
                    break;
                }
            }
        }
    }
}

The stEvt_t and other data structures are as follows - 

/*********************************************************************
 * TYPEDEFS
 */
typedef struct
{
    uint16_t event; // Event type.
    uint8_t state; // Event state;
}appEvtHdr_t;

// App event.
typedef struct
{
    appEvtHdr_t hdr;  // event header.
    uint8_t *pData;   // Event payload
} stEvt_t

When I run this code, it executes as expected, till it enters the infinite while(1) look in the SensorThread task function - 

I can see all the initalizations happening as expected, but when the code enters the while(1) and if any new "event" is posted, I get an exception in the ROV.

For example, I have registered a callback function on one of the GPIO pins labelled as "MSP_WAKE" in the above code, referenced here - 

    /* Set GPIO Interrupts */
    GPIO_setCallback(MSP_WAKE, SensorThread_WDTCallbackFxn);
    GPIO_enableInt(MSP_WAKE);

The pin configuration has been set in Sysconfig as Interrupt priority - 7 (lowest priority), Mode - input, Pull - Pull Up, Interrupt Trigger - Falling Edge, Callback function - NULL - (This is set to NULL because for some reason, if I try registering the callback here, Sysconfig gives me an error, so I chose to do it in runtime).

The SensorThread_WDTCallbackFxn and EnqueueEvent functions are as - 

static void SensorThread_WDTCallbackFxn(uint_least8_t index)
{
    SensorThread_enqueueMsg(ST_WDT_EVT, NULL, NULL);
}

/*
 * Creates an event message and puts the message in RTOS queue
 */
static void SensorThread_enqueueMsg(uint16_t event, uint8_t state,
                                    uint8_t *pData)
{
    stEvt_t *pMsg;
    int retc;

    // Create dynamic pointer to message.
    if ((pMsg = malloc(sizeof(stEvt_t))))
    {
        pMsg->hdr.event= event;
        pMsg->hdr.state = state;
        pMsg->pData = pData;
    }

    retc = mq_send(appMsgQueue, (char *)pMsg, sizeof(stEvt_t), 0);
    if (retc == -1) {
        // Failed to send to message queue
    }
    retc = sem_post(&appMsgSem);
    if (retc == -1) {
        while (1);
    }

The code enters the while(1) and waits for an event to post. It waits in the idle task, while both other tasks are blocked. If an event is posted (ex, GPIO is triggered), I get an exception. The ROV image is shown below-

 The exact error is

Idle Task - "Invalid task internal state: pend element address (0x0) is not within the task's stack"
Semaphore - "Problem scanning pend queue. Target memory read failed at address 0xBEBEBEBE, length: 8. This read is at an INVALID address according to the application's section map.". This happens on other event triggers as well, like a timer callback function trying to enqueue an RTOS event using the SensorThread_enqueueMsg function.

This error is very similar to 2 prev. E2E posts but I havent been able to resolve it based on the comments posted on those posts - 

1) https://e2e.ti.com/support/legacy_forums/embedded/tirtos/f/355/t/452095
There was no solution posted

2) https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/689774
The solution talks about zero-latency interrupts causing an issue. The resolution posted was to change the HWI disable priority to 16 in the .CFG file. However, there is no .CFG file in my project!!

There is possibly some error in our implementation, but we are unable to pinpoint exactly what is causing this. Is there any way to solve this issue? Help will be greatly appreciated!

  • Hey Shreyas,

    Thanks for the extremely detailed post.  Unfortunately, I'm not a TI-RTOS expert myself but let me see if I can get someone more familiar to provide some input here.

    Thanks,

    JD  

  • Thanks JD! 
    Hopefully this gets resolved soon. 

  • Hi Shreyas,

    I'd recommend using the debug kernel (instead of the Release one). Take a look in the SDK's User Guide for details on the difference and how to use the debug kernel. I'm hoping that with kernel asserts enabled, the problem will be obvious.

    Fyi...you have a memory leak. in SensorThread_enqueueMsg, you don't need to malloc a msg since message queues are copied based. Just have stEvt_t msg; instead (and adjust the rest of the code accordingly).

  • Hi Todd, thanks for the suggestion! I tried out both the things you listed -

    1) Downloaded the debug version from TI-REX, modified it for MSP432P011. Linked my original application project to it.

    2) Removed the malloc operation and modified the Enqueue function to - 

    static void SensorThread_enqueueMsg(uint16_t event, uint8_t state,
                                        uint8_t *pData)
    {
        stEvt_t pMsg;
        int retcc;
        
            pMsg.hdr.event= event;
            pMsg.hdr.state = state;
            pMsg.pData = pData;
            retcc = mq_send(appMsgQueue, (char *)&pMsg, sizeof(stEvt_t), 0);
            
            if (retcc == -1) {
                // Failed to send to message queue
                Display_printf(handle_disp, 0, 0, "Failed to send to message queue");
            }
            retcc = sem_post(&appMsgSem);
            if (retcc == -1) {
                Display_printf(handle_disp, 0, 0, "Failed to post message");
                while (1);
            }
    
    }

    Now I am getting a few more details on the crash, however I havent been able to resolve it fully yet.

    When I run the code in debug mode with breakpoints at various lines in the code, I get the following data in ROV - 

    1) Before I hit the "play" button in the debugger (i.e. the code is halted at the initial point), the SYS/BIOS "scan for errors" console has the following lines - 

    ti.sysbios.heaps.HeapTrack	HeapAllocList	HeapTrack@2000c354	overflow	Error: Memory overflow
    ti.sysbios.family.arm.m3.Hwi	Module	        N/A	                hwiStackPeak	Error fetching Hwi stack info!
    ti.sysbios.family.arm.m3.Hwi	Module	        N/A	                hwiStackSize	Error fetching Hwi stack info!
    ti.sysbios.family.arm.m3.Hwi	Module	        N/A	                hwiStackBase	Error fetching Hwi stack info!
    ti.sysbios.knl.Task	        Module	        N/A	                hwiStackPeak	Error fetching Hwi stack info!
    ti.sysbios.knl.Task	        Module	        N/A	                hwiStackSize	Error fetching Hwi stack info!
    ti.sysbios.knl.Task	        Module	        N/A	                hwiStackBase	Error fetching Hwi stack info!
    ti.sysbios.knl.Clock	        Module	        N/A	                N/A	        Caught exception in view init code: "C:/ti/ccs920/xdctools_3_60_01_27_core/packages/xdc/rov/StructureDecoder.xs", line 518: java.lang.Exception: Target memory read failed at address: 0xbebebec6, length: 32 This read is at an INVALID address according to the application's section map. The application is likely either uninitialized or corrupt
    

    2) Once I hit "play", the errors go away and the RTOS loops in the idle task, waiting for an event to "post". Image below-

    3) When i trigger a GPIO interrupt, following sequence occurs (due to break points in the code)-

    a) Debugger halts at 

    SensorThread_enqueueMsg(ST_REVP_EVT, NULL, NULL);

    and I can see the idle task being pre-empted.

    b) Hitting play again halts the debugger at 

    retcc = mq_send(appMsgQueue, (char *)&pMsg, sizeof(stEvt_t), 0);

    Idle task is still preempted and SensorThread task is blocked.

    c) Hitting play causes the application to crash directly. It does not even enter my breakpoint in the while(1) loop for the task to read from the queued semaphores. i.e. this line is not executed

    retc = mq_receive(appMsgQueue, (char *)&msg, sizeof(msg), NULL);

    The application jumps to exit.c function and is about to enter 

    void abort(void)
    I get the following line on the console
    ti.sysbios.knl.Semaphore: line 292: assertion failure: A_badContext: bad calling context. Must be called from a Task.
    xdc.runtime.Error.raise: terminating execution

    In my Hwi table, I see an active interrupt

    0x200013a8			Dispatched	55	224	7	0	GPIO_hwiIntFxn	0x4	0x2d33e	Enabled, Active, Pending

    There are no SYS/BIOS errors reported in the scan for errors console inROV

    My guess is that the semaphore mq_send function call is being done in a context which is outside of the task context. Question is, how do I fix this? I havent modified anything in the Kernel itself, and the application is basically based off from the MSP432P4111 out-of-box demo version with 4 threads. Is this somehow caused by the zero latency interrupts?

    Any more insight will be greatly appreciated!

  • Hi Shreyas,

    First, it looks like you do not have any zero-latency interrupts. All the Hwi instances have a priority of 32 or higher. Unless you changed the default disablePriority in the .cfg, only interrupts with a priority of less than 32 are zero-latency interrupts. Note: zero-latency interrupts cannot call kernel APIs.

    Based on the "A_badContext: bad calling context." message. It looks like a Hwi or Swi is calling Semaphore_pend with a non-zero timeout. It's fine to call it with a zero timeout. You have the O_NONBLOCK flag on the mq_open, which means a timeout of zero will be used internally in the mq_send. The problem must be somewhere else. While in main(), please open the disassembly window and put "xdc_runtime_Error_raiseX__E" as the address. Put a breakpoint at the beginning of the Error_raiseX function.

    Run the application to get the error and you should hit the breakpoint. Look at the callstack in the debug window to see who is calling the Semaphore_pend with a non-zero timeout.

    Todd

  • Todd, thanks for the detailed steps. I was able to do this and got the following information - 

    The relevant section of code in semaphore.c file is - 

    /*
     *  ======== Semaphore_pend ========
     */
    Bool Semaphore_pend(Semaphore_Object *sem, UInt32 timeout)
    {
        UInt hwiKey, tskKey;
        Semaphore_PendElem elem;
        Queue_Handle pendQ;
        Clock_Struct clockStruct;
    
        /* MISRA.ETYPE.INAPPR.OPERAND.BINOP.2012 */
        Log_write3(Semaphore_LM_pend, (IArg)sem, (UArg)sem->count, (IArg)((Int)timeout));
    
        /*
         *  Consider fast path check for count != 0 here!!!
         */
    
        /*
         *  elem is filled in entirely before interrupts are disabled.
         *  This significantly reduces latency.
         */
    
        /* add Clock event if timeout is not FOREVER nor NO_WAIT */
        if ((BIOS_clockEnabled != 0U)
                /* MISRA.ETYPE.INAPPR.OPERAND.UNOP.2012 */
                && (timeout != BIOS_WAIT_FOREVER)
                && (timeout != BIOS_NO_WAIT)) {
            Clock_addI(Clock_handle(&clockStruct), (Clock_FuncPtr)Semaphore_pendTimeout, timeout, (UArg)&elem);
            elem.tpElem.clock = Clock_handle(&clockStruct);
            elem.pendState = Semaphore_PendState_CLOCK_WAIT;
        }
        else {
            elem.tpElem.clock = NULL;
            elem.pendState = Semaphore_PendState_WAIT_FOREVER;
        }
    
        pendQ = Semaphore_Instance_State_pendQ(sem);
    
        hwiKey = Hwi_disable();
    
        /* check semaphore count */
        if (sem->count == 0U) {
    
            if (timeout == BIOS_NO_WAIT) {
                Hwi_restore(hwiKey);
                return (FALSE);
            }
    
            Assert_isTrue((BIOS_getThreadType() == BIOS_ThreadType_Task),
                            Semaphore_A_badContext);
    
            /*
             * Verify that THIS core hasn't already disabled the scheduler
             * so that the Task_restore() call below will indeed block
             */
            Assert_isTrue((Task_enabled() != FALSE),
                            Semaphore_A_pendTaskDisabled);
    
            /* lock task scheduler */
            tskKey = Task_disable();
    
            /* get task handle and block tsk */
            elem.tpElem.task = Task_self();
    
            /* leave a pointer for Task_delete() */
            elem.tpElem.task->pendElem = (Task_PendElem *)&(elem);
    
            Task_blockI(elem.tpElem.task);
    
            if ((Semaphore_supportsPriority != FALSE) &&
               (((UInt)sem->mode & 0x2U) != 0U)) {    /* if PRIORITY bit is set */
                Semaphore_PendElem *tmpElem;
                Task_Handle tmpTask;
                Int selfPri;
    
                tmpElem = Queue_head(pendQ);
                selfPri = Task_getPri(elem.tpElem.task);
    
                while (tmpElem != (Semaphore_PendElem *)pendQ) {
                    tmpTask = tmpElem->tpElem.task;
                    /* use '>' here so tasks wait FIFO for same priority */
                    if (selfPri > Task_getPri(tmpTask)) {
                        break;
                    }
                    else {
                        tmpElem = Queue_next(&(tmpElem->tpElem.qElem));
                    }
                }
    
                Queue_insert(&(tmpElem->tpElem.qElem),
                        (Queue_Elem *)&(elem.tpElem.qElem));
            }
            else {
                /* put task at the end of the pendQ */
                Queue_enqueue(pendQ, &(elem.tpElem.qElem));
            }
    
            /* start Clock if appropriate */
            if ((BIOS_clockEnabled != FALSE) &&
                    (elem.pendState == Semaphore_PendState_CLOCK_WAIT)) {
                Clock_startI(elem.tpElem.clock);
            }
    
            Hwi_restore(hwiKey);
    
            /* unlock task scheduler and block */
            Task_restore(tskKey);   /* the calling task will block here */
    
            /* Here on unblock due to Semaphore_post or timeout */
    
            hwiKey = Hwi_disable();
    
            if ((Semaphore_supportsEvents != FALSE) && (sem->event != NULL)) {
                /* synchronize Event state */
                Semaphore_eventSync(sem->event, sem->eventId, sem->count);
            }
    
            /* remove Clock object from Clock Q */
            if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) {
                Clock_removeI(elem.tpElem.clock);
                elem.tpElem.clock = NULL;
            }
            
            elem.tpElem.task->pendElem = NULL;
    
            Hwi_restore(hwiKey);
    
            return ((Bool)(elem.pendState));
        }
        else {
            /*
             * Assert catches Semaphore_pend calls from Hwi and Swi
             * with non-zero timeout.
             */
            Assert_isTrue((timeout == BIOS_NO_WAIT) ||
                    ((BIOS_getThreadType() == BIOS_ThreadType_Task) ||
                    (BIOS_getThreadType() == BIOS_ThreadType_Main)),
                    Semaphore_A_badContext);
    
            sem->count = sem->count - 1U;
    
            if ((Semaphore_supportsEvents != FALSE) && (sem->event != NULL)) {
                /* synchronize Event state */
                Semaphore_eventSync(sem->event, sem->eventId, sem->count);
            }
    
            /* remove Clock object from Clock Q */
            if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) {
                Clock_removeI(elem.tpElem.clock);
                elem.tpElem.clock = NULL;
            }
    
            Hwi_restore(hwiKey);
    
            return (TRUE);
        }
    }

    I see that there are 2 Semaphore_pend calls in the in call stack - Semaphore_pend and SemaphoreP_pend. However, I'm unable to pinpoint which entity is calling Semaphore_pend with a non-zero timeout. 

  • Actually, doing a bit more digging into this, I found that the fxn Display_doPrintf() is associated with one of the target memory address errors I got earlier. IN my first post, I showed in the ROV that the error was

    Target memory read failed at address 0xBEBEBEBE, length: 8 This read is at an invalid address according to the application's section map.

    Opening this function -

    /*
     *  ======== Display_doPrintf ========
     */
    void Display_doPrintf(Display_Handle handle, uint8_t line, uint8_t column,
                          char *fmt, ...)
    {
        if (NULL == handle)
        {
            DebugP_log0("Trying to use NULL-handle.");
            return;
        }
    
        va_list va;
        va_start(va, fmt);
    
        handle->fxnTablePtr->vprintfFxn(handle, line, column, fmt, va);
    
        va_end(va);
    }

    If I look at the element handle->fxnTablePtr-> vprintFxn - it is - 

    Name : handle->fxnTablePtr->vprintfFxn
    Default:0xBEBEBEBE
    Hex:0xBEBEBEBE
    Decimal:3200171710
    Octal:027657537276
    Binary:10111110101111101011111010111110b

    This is the same address listed above and is somehow associated with the error.

    The SemaphoreP_pend is being called from DisplayUartMin_vprintf()

    /*!
     * @fn          DisplayUartMin_vprintf
     *
     * @brief       Write a text string to UART with return and newline.
     *
     * @param       hDisplay - pointer to Display_Config struct
     * @param       line - line index (0..)
     * @param       column - column index (0..)
     * @param       fmt - format string
     * @param       aN - optional format arguments
     *
     * @return      void
     */
    void DisplayUartMin_vprintf(Display_Handle hDisplay, uint8_t line,
                                uint8_t column, char *fmt, va_list va)
    {
        DisplayUart_Object  *object  = (DisplayUart_Object  *)hDisplay->object;
        DisplayUart_HWAttrs *hwAttrs = (DisplayUart_HWAttrs *)hDisplay->hwAttrs;
    
        uint32_t strSize = 0;
    
        if (SemaphoreP_pend(object->mutex, hwAttrs->mutexTimeout) == SemaphoreP_OK)
        {
            SystemP_vsnprintf(hwAttrs->strBuf, hwAttrs->strBufLen - 2, fmt, va);
    
            strSize = strlen(hwAttrs->strBuf);
            hwAttrs->strBuf[strSize++] = '\r';
            hwAttrs->strBuf[strSize++] = '\n';
    
            UART_write(object->hUart, hwAttrs->strBuf, strSize);
            SemaphoreP_post(object->mutex);
        }
    }


    But I have no idea how this error is being caused or how this can be resolved :-(

  • Hi Shreyas,

    You can only call Display_printf from a task (or POSIX pthread). You are calling it from an interrupt.

    Please remove the Display_printf from the SensorThread_enqueueMsg function and see if that helps. 

    You can refer to http://dev.ti.com/tirex/explore/node?node=AB7f4Ige5MhJBdj939tqxg__z-lQYNj__LATEST&r=fc2e6sr__3.10.00.04 for more information about restrictions and other debug printing options.

    Todd

  • Todd, thanks for pointing it out. This indeed solved my problem!

    Thank you!

**Attention** This is a public forum