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/EK-TM4C1294XL: problem with the Event and Queue APIs in hardware interrupt

Part Number: EK-TM4C1294XL
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI-RTOS

Hi, 

I came acoross multiple threads about this issue but couldn't really solve it. I have a small application that print the input from the UART in the console using a hardware interrupt for UART, and a Task interrupt to print the message using event and queue API. When I keep pressing on a button, I get the error in the figure. and when I just press one or two buttons, the Task interrupt would be invoked, but crash after initializing the event. Please have a look at the attached main.c and the main.cfg.

Thank you.

Error1:

  

Error2:

/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>
/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/hal/Timer.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Swi.h>
#include <ti/sysbios/knl/Queue.h>
#include <ti/sysbios/hal/Hwi.h>
/* TI-RTOS Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/UART.h>
#include <ti/drivers/uart/UARTTiva.h>
/* Board Header file */
#include "Board.h"
#include <string.h>
#include "driverlib/fpu.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/uart.h"
#include "driverlib/gpio.h"
#include "utils/ustdlib.h"
#include "grlib/grlib.h"
#include "grlib/widget.h"
#include "grlib/canvas.h"
#include "drivers/Kentec320x240x16_ssd2119_spi.h"

#define TASKSTACKSIZE   512

typedef struct MsgObj {
    Queue_Elem elem; /* first field for Queue */
    Char data; /* message value */
} MsgObj;


Task_Struct task0Struct;
Char task0Stack[TASKSTACKSIZE];
Semaphore_Struct sem0Struct;
Semaphore_Handle semHandle;
Event_Struct evtStruct;
Event_Handle evtHandle;
Queue_Handle QueueHandle;
Hwi_Handle HwiUART;

uint32_t g_ui32SysClock;
tContext sContext;

void UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count) {
    // Loop while there are more characters to send.
    while (ui32Count--) {
        // Write the next character to the UART.
        if (!UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++)) {
            SysCtlDelay((0.002 * g_ui32SysClock) / 3);
            UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++);
        }
    }
}

void uart0FuncTask() {

    MsgObj *msg;
    UInt events;

    msg = Queue_get(QueueHandle);
    System_printf("RET msg rec: %c\n", msg->data);

    System_printf("\nmsg uart0FuncTask: %c\n");

    while (1) {
        System_printf("\nmsg while 1\n");
        events = Event_pend(evtHandle, Event_Id_05, Event_Id_NONE, BIOS_WAIT_FOREVER);
        Semaphore_pend(semHandle, BIOS_NO_WAIT);
        if (events & Event_Id_05) {
            Semaphore_pend(semHandle, BIOS_NO_WAIT);
            while (!Queue_empty(QueueHandle)) {
               msg = Queue_get(QueueHandle);
               System_printf("RET msg rec: %c\n", msg->data);
            }
        }
    }
}

void uart0FuncHwi(UArg arg) {

    System_printf("\nHwi: uart0FuncHwi called\n");
    uint32_t ui32Status;
    // Get the interrrupt status.
    ui32Status = UARTIntStatus(UART0_BASE, true);
    // Clear the asserted interrupts.
    UARTIntClear(UART0_BASE, ui32Status);

    char ch;

    // Loop while there are characters in the receive FIFO.
    while (UARTCharsAvail(UART0_BASE)) {
        MsgObj msg;
        ch = UARTCharGetNonBlocking(UART0_BASE); //HWI
        // Read the next character from the UART and write it back to the UART.
        // Blink the LED to show a character transfer is occuring.
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
        // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
        SysCtlDelay(g_ui32SysClock / (1000 * 3));
        // Turn off the LED
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);

        if (ch != '\r' && ch != ' ') {
            // Read the next character from the UART and write it back to the UART.
            System_printf("\n msg : %c\n", ch);
            msg.data = ch;
            Queue_put(QueueHandle, &(msg.elem));
            Semaphore_post(semHandle);
        }
        else if (ch == '\r') {
            System_printf("\nmsg with return\n");
            Event_post(evtHandle, Event_Id_05);
        }
    }
}

void initUARTHwiInt() {

    /* Turn on user LED */
    GPIO_write(Board_LED0, Board_LED_ON);
    Hwi_Params hwiParams;
    Error_Block hwi_eb;
    Error_init(&hwi_eb);

    Hwi_Params_init(&hwiParams);
    hwiParams.arg = (UArg)QueueHandle;
    HwiUART = Hwi_create(21, (Hwi_FuncPtr)uart0FuncHwi, &hwiParams, &hwi_eb);
    if (HwiUART == NULL) System_printf("Hwi create failed\n");
}

void initUARTEvent() {
    Event_construct(&evtStruct, NULL);
    evtHandle = Event_handle(&evtStruct);
}

void initUARTSemaphore() {
    Semaphore_Params semParams;
    Semaphore_Params_init(&semParams);
    semParams.mode = Semaphore_Mode_BINARY;
    Semaphore_construct(&sem0Struct, 0, &semParams);
    semHandle = Semaphore_handle(&sem0Struct);
}

void initUARTQueue() {
    QueueHandle = Queue_create(NULL, NULL);
}

void initUARTTaskInt() {
    Task_Params taskParams;
    Task_Params_init(&taskParams);
    taskParams.stackSize = TASKSTACKSIZE;
    Task_create((Task_FuncPtr)uart0FuncTask, &taskParams, NULL);
}

void configureUART(void) {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    IntMasterEnable();
    // Configure the UART for 115,200, 8-N-1 operation.
    UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    // Enable the UART interrupt.
    IntEnable(INT_UART0);
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
    System_printf("UART is set\n");
}

void configureGUI(uint32_t g_ui32SysClock) {
    FPUEnable();
    FPULazyStackingEnable();
    Kentec320x240x16_SSD2119Init(g_ui32SysClock);
    GrContextInit(&sContext, &g_sKentec320x240x16_SSD2119);
    GrContextForegroundSet(&sContext, ClrWhite);
    GrContextFontSet(&sContext, &g_sFontCm20);
}


/* main */
int main(void) {

    // Set the clocking to run directly from the crystal at 120MHz.
    g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);

    /* Call board init functions */
    Board_initGeneral();
    Board_initGPIO();
    Board_initUART();
    configureGUI(g_ui32SysClock);
    initUARTQueue();

    configureUART();
    initUARTTaskInt();
    initUARTHwiInt();
    initUARTEvent();
    initUARTSemaphore();

    /* SysMin will only print to the console when you call flush or exit */
    System_flush();
    /* Start BIOS */
    BIOS_start();

    return (0);
}
main.cfg

  • You seem to call the event_post only when a \r is received. If you receive non \r characters you will not call the event_post, correct? If event_post is not called then the event_pend in your uart0FuncTask will just block due to the Event_pend.
    You can also use the ROV to find out the status of the tasks and get better insights on what is going on.
  • Hi Charles, 

    I made the event post called every time the hardware interrupt called as you mentioned. but still getting the same error. Here is the message from the ROV:

    In Hwi and Queue:

    error java.lang.exception target memory read failed at address: 0xbebebec6, length: 24 This read is at INVALID address according to the application's section map. The application is likely either uninitialized or corrupt

    In Task:

    error java.lang.exception target memory read failed at address: 0x8, length: 76 This read is at INVALID address according to the application's section map. The application is likely either uninitialized or corrupt

  • Hi,
    How do you know if all the events are met in your Event_pend's AND mask? Is it possible that the AND mask is still false? I will suggest you start with a simple semaphore. When you get a Hwi you will call semaphore_post and in your uart task you will unblock with the semaphore_pend. When unblocking, you will echo what was received from your RX to the TX? Wouldn't this be simpler to start with?
  • Hi Charles, I've changed coupel of things in my code for the semaphore and events, they now work fine. but, the issue seems to be with the Queues. So, here is what I'm doing, I'm calling Queue_put inside the hardware interrupt passing the global Queue_Handle variable. Then in the task, when I try to get the message from the QueueHandle, using Queue_get, I get the error message downbelow. Note that when I remove the queues variables, the semaphore and events work as wanted. please have a look at the c file. the problem occures when I try to get the message in the task with the following line -> msg = Queue_get(QueueHandle). Can you direct me where the issue might be?

    here is the error message:

    ti.sysbios.family.arm.m3.Hwi: line 1095: E_hardFault: FORCED

    ti.sysbios.family.arm.m3.Hwi: line 1172: E_busFault: IMPRECISERR: Delayed Bus Fault, exact addr unknown, address: e000ed38

    Exception occurred in background thread at PC = 0x00003840.

    Core 0: Exception occurred in ThreadType_Task.

    Task name: {unknown-instance-name}, handle: 0x20000fc8.

    Task stack base: 0x20001018.

    Task stack size: 0x200.

    R0 = 0x200020dc  R8  = 0xffffffff

    R1 = 0x20000f88  R9  = 0xffffffff

    R2 = 0x000062cf  R10 = 0xffffffff

    R3 = 0x00000000  R11 = 0xffffffff

    R4 = 0xffffffff  R12 = 0x20001cb4

    R5 = 0xffffffff  SP(R13) = 0x200011f0

    R6 = 0xffffffff  LR(R14) = 0x00003841

    R7 = 0xffffffff  PC(R15) = 0x00003840

    PSR = 0x21000000

    ICSR = 0x00423803

    MMFSR = 0x00

    BFSR = 0x04

    UFSR = 0x0000

    HFSR = 0x40000000

    DFSR = 0x0000000b

    MMAR = 0xe000ed34

    BFAR = 0xe000ed38

    AFSR = 0x00000000

    Terminating execution...

    files:

    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Error.h>
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/hal/Timer.h>
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Swi.h>
    #include <ti/sysbios/knl/Queue.h>
    #include <ti/sysbios/hal/Hwi.h>
    /* TI-RTOS Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/UART.h>
    #include <ti/drivers/uart/UARTTiva.h>
    /* Board Header file */
    #include "Board.h"
    #include <string.h>
    #include "driverlib/fpu.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/uart.h"
    #include "driverlib/gpio.h"
    #include "utils/ustdlib.h"
    #include "grlib/grlib.h"
    #include "grlib/widget.h"
    #include "grlib/canvas.h"
    #include "drivers/Kentec320x240x16_ssd2119_spi.h"
    
    #define TASKSTACKSIZE   512
    
    typedef struct MsgObj {
        Queue_Elem elem; /* first field for Queue */
        Char data; /* message value */
    } MsgObj;
    
    
    Task_Struct task0Struct;
    Char task0Stack[TASKSTACKSIZE];
    Semaphore_Struct sem0Struct;
    Semaphore_Handle semHandle;
    Event_Struct evtStruct;
    Event_Handle evtHandle;
    Queue_Handle QueueHandle;
    Hwi_Handle HwiUART;
    
    uint32_t g_ui32SysClock;
    tContext sContext;
    
    void UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count) {
        // Loop while there are more characters to send.
        while (ui32Count--) {
            // Write the next character to the UART.
            if (!UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++)) {
                SysCtlDelay((0.002 * g_ui32SysClock) / 3);
                UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++);
            }
        }
    }
    
    void uart0FuncTask(UArg arg0) {
    
        System_printf("\nmsg uart0FuncTask\n");
        UInt events;
    
        while (1) {
            events = Event_pend(evtHandle, Event_Id_NONE, Event_Id_05 + Event_Id_06, BIOS_WAIT_FOREVER);
            if (events & Event_Id_05) {
                MsgObj *msg;
                Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
                System_printf("\nRET msg!!!!\n");
                while (!Queue_empty(QueueHandle)) {
                    System_printf("\queue msg!!!!\n");
                    msg = Queue_get(QueueHandle);
                    System_printf("rec: %c\n", msg->data);
                }
                System_flush();
            }
            else if (events & Event_Id_06) {
                Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
                System_printf("\nSPACE msg!!!!");
                System_flush();
            }
        }
    }
    
    void uart0FuncHwi(UArg arg) {
    
        System_printf("\nHwi: uart0FuncHwi called\n");
        uint32_t ui32Status;
        // Get the interrrupt status.
        ui32Status = UARTIntStatus(UART0_BASE, true);
        // Clear the asserted interrupts.
        UARTIntClear(UART0_BASE, ui32Status);
    
        char ch;
    
        // Loop while there are characters in the receive FIFO.
        while (UARTCharsAvail(UART0_BASE)) {
            MsgObj msg;
            ch = UARTCharGetNonBlocking(UART0_BASE); //HWI
            // Read the next character from the UART and write it back to the UART.
            // Blink the LED to show a character transfer is occuring.
            GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
            // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
            SysCtlDelay(g_ui32SysClock / (1000 * 3));
            // Turn off the LED
            GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
    
            if (ch == '\r') {
                System_printf("\nmsg with return\n");
                Event_post(evtHandle, Event_Id_05);
                Semaphore_post(semHandle);
            }
            else if (ch == ' ') {
                System_printf("\nmsg with space\n");
                Event_post(evtHandle, Event_Id_06);
                Semaphore_post(semHandle);
            }
            else {
                // Read the next character from the UART and write it back to the UART.
                System_printf("\n msg : %c\n", ch);
                msg.data = ch;
                Queue_put(QueueHandle, &(msg.elem));
            }
        }
    }
    
    void initUARTHwiInt() {
    
        /* Turn on user LED */
        GPIO_write(Board_LED0, Board_LED_ON);
        Hwi_Params hwiParams;
        Error_Block hwi_eb;
        Error_init(&hwi_eb);
    
        Hwi_Params_init(&hwiParams);
        hwiParams.arg = (UArg)QueueHandle;
        HwiUART = Hwi_create(21, (Hwi_FuncPtr)uart0FuncHwi, &hwiParams, &hwi_eb);
        if (HwiUART == NULL) System_printf("Hwi create failed\n");
    }
    
    void initUARTEvent() {
        Event_construct(&evtStruct, NULL);
        evtHandle = Event_handle(&evtStruct);
    }
    
    void initUARTSemaphore() {
        Semaphore_Params semParams;
        Semaphore_Params_init(&semParams);
        Semaphore_construct(&sem0Struct, 0, &semParams);
        semHandle = Semaphore_handle(&sem0Struct);
    }
    
    void initUARTQueue() {
        QueueHandle = Queue_create(NULL, NULL);
    }
    
    void initUARTTaskInt() {
        Task_Params taskParams;
        Task_Params_init(&taskParams);
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.arg0 = (UArg)QueueHandle;
        Task_create((Task_FuncPtr)uart0FuncTask, &taskParams, NULL);
    }
    
    void configureUART(void) {
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        IntMasterEnable();
        // Configure the UART for 115,200, 8-N-1 operation.
        UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
        // Enable the UART interrupt.
        IntEnable(INT_UART0);
        UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
        System_printf("UART is set\n");
    }
    
    void configureGUI(uint32_t g_ui32SysClock) {
        FPUEnable();
        FPULazyStackingEnable();
        Kentec320x240x16_SSD2119Init(g_ui32SysClock);
        GrContextInit(&sContext, &g_sKentec320x240x16_SSD2119);
        GrContextForegroundSet(&sContext, ClrWhite);
        GrContextFontSet(&sContext, &g_sFontCm20);
    }
    
    
    /* main */
    int main(void) {
    
        // Set the clocking to run directly from the crystal at 120MHz.
        g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    
        /* Call board init functions */
        Board_initGeneral();
        Board_initGPIO();
        Board_initUART();
        configureGUI(g_ui32SysClock);
        initUARTQueue();
    
        configureUART();
        initUARTHwiInt();
        initUARTTaskInt();
        initUARTEvent();
        initUARTSemaphore();
    
        /* SysMin will only print to the console when you call flush or exit */
        System_flush();
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    

    6835.main.cfg

  • Perhaps it may have something to do with the msg pointer that you pass as the argument to the Queue_put. See below example. The example comes directly from the TI-RTOS training workshop.

    //---------------------------------------------------------------------------------
    // Project: Blink TM4C BIOS Using Mailbox/Queue (SOLUTION)
    // Author: Eric Wilbur
    // Date: June 2014
    //
    // Note: The function call TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT) HAS
    //       to be in the ISR. This fxn clears the TIMER's interrupt flag coming
    //       from the peripheral - it does NOT clear the CPU interrupt flag - that
    //       is done by hardware. The author struggled figuring this part out - hence
    //       the note. And, in the Swi lab, this fxn must be placed in the
    //       Timer_ISR fxn because it will be the new ISR.
    //
    // Follow these steps to create this project in CCSv6.0:
    // 1. Project -> New CCS Project
    // 2. Select Template:
    //    - TI-RTOS for Tiva-C -> Driver Examples -> EK-TM4C123 LP -> Example Projects ->
    //      Empty Project
    //    - Empty Project contains full instrumentation (UIA, RTOS Analyzer) and
    //      paths set up for the TI-RTOS version of MSP430Ware
    // 3. Delete the following files:
    //    - Board.h, empty.c, EK_TM4C123GXL.c/h, empty_readme.txt
    // 4. Add main.c from TI-RTOS Workshop Solution file for this lab
    // 5. Edit empty.cfg as needed (to add/subtract) BIOS services, delete given Task
    // 6. Build, load, run...
    //
    // FYI - Part B solution for Queues is actually shown working. Part A solution
    // (Mailbox) is populated below but commented out.
    //----------------------------------------------------------------------------------
    
    
    //----------------------------------------
    // BIOS header files
    //----------------------------------------
    #include <xdc/std.h>  						//mandatory - have to include first, for BIOS types
    #include <ti/sysbios/BIOS.h> 				//mandatory - if you call APIs like BIOS_start()
    #include <xdc/runtime/Log.h>				//needed for any Log_info() call
    #include <xdc/cfg/global.h> 				//header file for statically defined objects/handles
    
    
    //------------------------------------------
    // TivaWare Header Files
    //------------------------------------------
    #include <stdint.h>
    #include <stdbool.h>
    
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "inc/hw_ints.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/timer.h"
    
    
    //----------------------------------------
    // Prototypes
    //----------------------------------------
    void hardware_init(void);
    void ledToggle(void);
    void Timer_ISR(void);
    
    
    //---------------------------------------
    // Globals
    //---------------------------------------
    volatile int16_t i16ToggleCount = 0;
    
    //------------------------
    // for Mailbox - Part A
    //------------------------
    //typedef struct MsgObj {
    //	Int	val;            		// message value
    //} MsgObj, *Msg;
    
    
    //------------------------
    // for Queue - Part B
    //------------------------
    typedef struct MsgObj {
    	Queue_Elem	elem;
    	Int	val;            		// message value
    } MsgObj, *Msg;				// Use Msg as pointer to MsgObj
    
    
    
    
    //---------------------------------------------------------------------------
    // main()
    //---------------------------------------------------------------------------
    void main(void)
    {
    
       hardware_init();				// init hardware via Xware
    
       BIOS_start();				// start BIOS Scheduler
    
    }
    
    
    //---------------------------------------------------------------------------
    // hardware_init()
    //
    // inits GPIO pins for toggling the LED
    //---------------------------------------------------------------------------
    void hardware_init(void)
    {
    	uint32_t ui32Period;
    
    	//Set CPU Clock to 40MHz. 400MHz PLL/2 = 200 DIV 5 = 40MHz
    	SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    
    	// ADD Tiva-C GPIO setup - enables port, sets pins 1-3 (RGB) pins for output
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
    
    	// Turn on the LED
    	GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 4);
    
    	// Timer 2 setup code
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);			// enable Timer 2 periph clks
    	TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC);		// cfg Timer 2 mode - periodic
    
    	ui32Period = (SysCtlClockGet() /2);						// period = CPU clk div 2 (500ms)
    	TimerLoadSet(TIMER2_BASE, TIMER_A, ui32Period);			// set Timer 2 period
    
    	TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);		// enables Timer 2 to interrupt CPU
    
    	TimerEnable(TIMER2_BASE, TIMER_A);						// enable Timer 2
    
    }
    
    
    
    //---------------------------------------------------------------------------
    // mailbox_queue Task() - Run by BIOS_Start(), then unblocked by Timer ISR
    //
    // Places state of LED (msg.val) into a mailbox for ledToggle() to use
    //---------------------------------------------------------------------------
    void mailbox_queue(void)
    {
    
    //---------------------------------
    // msg used for Mailbox and Queue
    //---------------------------------
    	MsgObj msg;													// create an instance of MsgObj named msg
    
    //---------------------------------
    // msgp used for Queue only
    //---------------------------------
    	Msg msgp;													// Queues pass POINTERS, so we need a pointer of type Msg
    	msgp = &msg;												// init message pointer to address of msg
    
    
    	msg.val = 1;												// set initial value of msg.val (LED state)
    
    	while(1){
    
    		msg.val ^= 1;											// toggle msg.val (LED state)
    
    		Semaphore_pend(mailbox_queue_Sem, BIOS_WAIT_FOREVER);	// wait on semaphore from Timer ISR
    
    //------------------------------
    // MAILBOX CODE follows...
    //------------------------------
    //		Mailbox_post (LED_Mbx, &msg, BIOS_WAIT_FOREVER);		// post msg containing LED state into the MAILBOX
    
    
    //------------------------------
    // QUEUE CODE follows...
    //------------------------------
    		Queue_put(LED_Queue, (Queue_Elem*)msgp);				// pass pointer to Message object via LED_Queue
    		Semaphore_post (QueSem);								// unblock Queue_get to get msg
    
    	}
    
    }
    
    
    
    //---------------------------------------------------------------------------
    // ledToggle()  - called by BIOS_Start(), then unblocked by mailbox_queue()
    //
    // toggles LED on Tiva-C LaunchPad
    //---------------------------------------------------------------------------
    void ledToggle(void)
    {
    
    //---------------------------------
    // msg used for Mailbox and Queue
    //---------------------------------
    	MsgObj msg;																		//define msg using MsgObj struct created earlier
    
    //---------------------------------
    // msgp used for Queue only
    //---------------------------------
    	Msg msgp;																		//define pointer to MsgObj to use with queue put/get
    	msgp = &msg;																	//init msgp to point to address of msg (used for put/get)
    
    
    	while(1)
    	{
    
    
    //------------------------------
    // MAILBOX CODE follows...
    //------------------------------
    //		Mailbox_pend(LED_Mbx, &msg, BIOS_WAIT_FOREVER);								// wait/block until post of msg, get msg.val
    
    
    //------------------------------
    // QUEUE CODE follows...
    //------------------------------
    		Semaphore_pend(QueSem, BIOS_WAIT_FOREVER);									// unblocked by mailbox_queue() when Queue has msg
    		msgp = Queue_get(LED_Queue);												// read contents of queue to get value of LED state
    
    
    		// LED values - 0=OFF, 2=RED, 4=BLUE, 8=GREEN
    
    //		if (msg.val)																// MAILBOX "if" - msg.val contains LED state
    
    		if(msgp->val)																// QUEUE "if" - mspg->val contains LED state for QUEUE's the use pointers
    
    		{
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 8);		// turn LED on
    		}
    		else
    		{
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);		// turn LED off
    		}
    
    		i16ToggleCount += 1;														// keep track of #toggles
    
    		Log_info1("LED TOGGLED [%u] TIMES",i16ToggleCount);							// send toggle count to UIA
    
    	}
    }
    
    
    
    //---------------------------------------------------------------------------
    // Timer_ISR()
    //
    // Called by Hwi when timer hits zero
    //
    // TimerIntClear is needed here because THIS fxn is the ISR now
    //---------------------------------------------------------------------------
    void Timer_ISR(void)
    {
        TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT);									// must clear timer flag FROM timer
    
    	Semaphore_post(mailbox_queue_Sem);												// post Sem to unblock mailbox-queue-task
    
    }

  • I've tried actually, still having the same problem when I try to get the message from the queue. Also, if I do Queue_put and Queue_get in the same task, it works fine, but when i use them in different tasks, for weird reason, I get the error mentioned before. 

    Thanks for help anyway.

  • My comments are based on the original main.c you attached.

    1. You should not be calling IntMasterEnable or IntEnable. Let the TI-RTOS dispatcher handle this.

    2. In uart0FuncHwi, you have the following

    void uart0FuncHwi(UArg arg) {
    
        ...
    
        // Loop while there are characters in the receive FIFO.
        while (UARTCharsAvail(UART0_BASE)) {
            MsgObj msg;
            ...
            if (ch != '\r' && ch != ' ') {
                // Read the next character from the UART and write it back to the UART.
                System_printf("\n msg : %c\n", ch);
                msg.data = ch;
                Queue_put(QueueHandle, &(msg.elem));

    So msg is a local variable which is on the stack. You are placing it onto a Queue (via Queue_put). Note: Queue is a simple linked list that does not copy the element. So you placed stack memory onto a linked list. The contents of that address are non-deterministic since the stack is always changing...so bad things will happen.

    Solutions: 

    A. Use Mailbox since it copies

    B. Have a "free" Queue that you pull (Queue_get) elements from in the ISR and place them onto a "full" Queue that the Task pulls from (and then processes). Once done with the element, the task can place it on the "free" Queue with a Queue_put. This is basically what the Mailbox module does. You'll need to add synchronization as required. The Mailbox module has two semaphores (one for the free queue and one for the full Queue).

    Todd