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.

TM4C1294NCPDT: TI RTOS UART detect end of trame to select RX or TX on RS485

Part Number: TM4C1294NCPDT

Hi,

I am a newbie on the TI RTOS but my system have got 6 UART and Ethernet. I must manage the system with OS.

On TI RTOS, I would like to detect the end on the trame to select RX or TX on RS485

A lot of post about this topic without a real answer.

For begining I modified the mutex example.

/*
 * Copyright (c) 2015-2016, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *  ======== mutex.c ========
 */

#include <stdbool.h>

/* XDC module Headers */
#include <xdc/std.h>
#include <xdc/runtime/System.h>

/* BIOS module Headers */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Semaphore.h>

/* TI-RTOS Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/UART.h>
#include <ti/drivers/uart/UARTtiva.c>

#include "inc/hw_uart.h"
#include "driverlib/uart.h"
#include "utils/ringbuf.h"
#include "utils/uartstdio.h"

#include "inc/hw_uart.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"

#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/interrupt.h"

/* Example/Board Header files */
#include "Board.h"

#define TASKSTACKSIZE   512

Void task1Fxn(UArg arg0, UArg arg1);
Void task2Fxn(UArg arg0, UArg arg1);

Int resource = 0;
Int finishCount = 0;
UInt32 sleepTickCount;

Task_Struct task1Struct, task2Struct;
Char task1Stack[TASKSTACKSIZE], task2Stack[TASKSTACKSIZE];
Semaphore_Struct semStruct;
Semaphore_Handle semHandle;

char input = 0x9;
UART_Handle uart;

void UART00_IRQHandlerWrite(UART_Handle handle, void *buffer, size_t num);
/*
 *  ======== main ========
 */
Int main()
{
    /* Construct BIOS objects */
    Task_Params taskParams;
    Semaphore_Params semParams;


    UART_Params uartParams;
 //   const char echoPrompt[] = "\fEchoing characters:\r\n";

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



    /* Construct writer/reader Task threads */
    Task_Params_init(&taskParams);
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack = &task1Stack;
    taskParams.priority = 1;
    Task_construct(&task1Struct, (Task_FuncPtr)task1Fxn, &taskParams, NULL);

    taskParams.stack = &task2Stack;
    taskParams.priority = 2;
    Task_construct(&task2Struct, (Task_FuncPtr)task2Fxn, &taskParams, NULL);

    /* Construct a Semaphore object to be use as a resource lock, inital count 1 */
    Semaphore_Params_init(&semParams);
    Semaphore_construct(&semStruct, 1, &semParams);

    /* Obtain instance handle */
    semHandle = Semaphore_handle(&semStruct);

    /* Create a UART with data processing off. */
    UART_Params_init(&uartParams);
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.baudRate = 115200;
    uartParams.dataLength = UART_LEN_8;
    uartParams.stopBits = UART_STOP_ONE;
    uartParams.parityType = UART_PAR_NONE;
//    uartParams.writeTimeout = UART_WAIT_FOREVER;
    uartParams.writeMode = UART_MODE_CALLBACK;//UART_MODE_BLOCKING;//UART_MODE_CALLBACK; // the uart uses a read interrupt
    uartParams.writeCallback = &UART00_IRQHandlerWrite; // function called when the uart interrupt fires
    HWREG(UART0_BASE + UART_O_CTL) |= UART_TXINT_MODE_EOT;

    //uart = UART_open(Board_UART0, &uartParams);

     UARTTiva_open(uart, &uartParams);


    if (uart == NULL) {
        System_abort("Error opening the UART");
    }

   // UART_write(uart, echoPrompt, sizeof(echoPrompt));

    /* We want to sleep for 10000 microseconds */
    sleepTickCount = 10000 / Clock_tickPeriod;

    BIOS_start();    /* Does not return */
    return(0);
}

/*
 *  ======== task1Fxn ========
 */
Void task1Fxn(UArg arg0, UArg arg1)
{
    UInt32 time;

   while(1) {
        System_printf("Running task1 function\n");

        if (Semaphore_getCount(semHandle) == 0) {
            System_printf("Sem blocked in task1\n");
        }

        GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 1);
        UART_write(uart, &input, 1);


        /* Get access to resource */
        Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
        //while((UARTBusy(Board_UART0)));
        //GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_0,0);


        /* Do work by waiting for 2 system ticks to pass */
        time = Clock_getTicks();
        while (Clock_getTicks() <= (time + 1)) {
            ;
        }

        /* Do work on locked resource */
        resource += 1;
        /* Unlock resource */

        Semaphore_post(semHandle);

        Task_sleep(sleepTickCount);
    }
}

/*
 *  ======== task2Fxn ========
 */
Void task2Fxn(UArg arg0, UArg arg1)
{
    while(1) {
        System_printf("Running task2 function\n");

        if (Semaphore_getCount(semHandle) == 0) {
            System_printf("Sem blocked in task2\n");
        }

//        GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0);

        /* Get access to resource */
        Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);

        /* Do work on locked resource */
        resource += 1;
        /* Unlock resource */

        Semaphore_post(semHandle);

        Task_sleep(sleepTickCount);

        finishCount++;
        if (finishCount == 5) {
            System_printf("Calling BIOS_exit from task2\n");
            BIOS_exit(0);
        }
    }
}

void UART00_IRQHandlerWrite(UART_Handle handle, void *buffer, size_t num)
{

   // GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0);



    {
     //  ++ucEndOfFrame;
     //
     //  Write the next character into the transmit FIFO.
     //
     //  UART_write(uart, &input, 1);
     //  UARTCharPut(MODBUS_UART_BASE, RingBufReadOne(&g_sTxBuf));

    }

   //while(UARTBusy(Board_UART0))


    //while(  (UARTIntStatus(UART0_BASE,UART_RIS_TXRIS)) == 1)
    {
       //      GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_0,0);
        //while((UARTBusy(Board_UART0)));
        //GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_0,0);

        Semaphore_post(semHandle);
    }
}

I used the EOT bit without success

Could I use HWI or UART_OPEN()?

Thanks in advance

Christophe G

  • I am a bit confused by your question. RS485 is an electrical interface specification for asynchronous communication. It is usually half duplex and driven by a UART. What constitutes a frame is defined by the protocol. You did not specify a protocol. Modbus is an example of a set of protocols. Modbus RTU defines the end of frame by 3 and a half characters of silence on the bus. Modbus ASCII ends a frame with a CR/LF pair. Can you be more specific about the protocol you are trying to use?

  • Hello Bob,

    My problem is not that of a protocol although I am using Modbus RTU. This is not the point. In my example, I only send one character only.
    What I want to do and manage to do without TI RTOS is detect the end of the TX send of the frame in the UART using the interrupt on the EOT bit. 
    I can't seem to get an interrupt on this bit using TI RTOS.
    For information, the RS485 is a support and function in Half and full duplex depending on the hardware used.

    Thanks for your help

    Christophe G

  • For MODBUS ASCII you can use UART_open(), but for MODBUS RTU you need to use a HWI. Your interrupt routine will need to examine the data coming back and determine when a complete frame is received based on the message type. You should enable both the receive interrupt and the receive time-out interrupt as you already assumed. However, you cannot rely on the received time-out interrupt signaling the end of frame as the frame may have a length that caused the FIFO receive level interrupt.

    In the code snippet you provided above, it looks like you tried to use UART_open(). That will not work for MODBUS RTU. Make sure you properly register your HWI as described in the Bios_User_Guide (C:\ti\tirtos_tivac_2_16_00_08\products\bios_6_45_01_29\docs\Bios_User_Guide .pdf)

    There is additional information here: http://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/bios/sysbios/6_83_00_18/exports/bios_6_83_00_18/docs/Device_Addendum.html

  • Hello Bob,
    Thank you for your answer but you are off topic. 
    It is not a protocol problem but I will detect the end of sending of the TX frame by an UART interrupt with a TI RTOS.
    I know how to do it without TI RTOS but I do not know how to generate an interrupt on the EOT bit in the UARTCTL registerwith TI RTOS.





    I hope you understand better my problem.
    How could I use this interrupt bit EOT with TI RTOS?

    Best regards
    Christophe G

  • To use EOT interrupt in TI-RTOS, you need to write your own HWI.

  • Hello Bob, Thanks for your answer. Have you got an example with HWI and UART please ? Best regards Christophe G

  • I threw together a simple TI-RTOS project that creates a HWI for UART0. It runs three tasks, two of which output strings on UART0. The third blinks an LED. The tasks that use UART0 use a semaphore to avoid conflicting use of the UART. I used TivaWare 2.2.0.295. You will have to make modifications to the project if you do not have that version installed in the standard place.

    I wanted to zip the project and attach it to this thread, but I am having problems doing that with this new E2E software. I will post the three files instead and follow with the .zip file when the file attach issue has been resolved.

    Main file "TirtosUartHwi.c"

    /*
     * Copyright (c) 2021, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*
     *  ======== empty_min.c ========
     */
    /* XDCtools Header files */
    #include <xdc/std.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    
    /* TI-RTOS Header files */
    #include <ti/drivers/GPIO.h>
    #include <Error.h>
    #include <Hwi.h>
    #include <System.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include <ti/sysbios/knl/Semaphore.h>
    #include "Uart0Hwi.h"
    
    /* Board Header file */
    #include "Board.h"
    
    #define TASKSTACKSIZE   512
    #define UART0_HWI_NUMBER  21
    
    Task_Struct task0Struct;
    Task_Struct task1Struct;
    Task_Struct task2Struct;
    Char task0Stack[TASKSTACKSIZE];
    Char task1Stack[TASKSTACKSIZE];
    Char task2Stack[TASKSTACKSIZE];
    Semaphore_Struct semStruct;
    Semaphore_Handle UART0semHandle;
    
    //*****************************************************************************
    //
    // System clock rate in Hz.
    //
    //*****************************************************************************
    uint32_t g_ui32SysClock;
    
    /*
     *  ======== heartBeatFxn ========
     *  Toggle the Board_LED0. The Task_sleep is determined by arg0 which
     *  is configured for the heartBeat Task instance.
     */
    Void heartBeatFxn(UArg arg0, UArg arg1)
    {
        while (1)
        {
            Task_sleep((unsigned int)arg0);
            GPIO_toggle(Board_LED0);
        }
    }
    
    Void twoSecondFxn(UArg arg0, UArg arg1)
    {
        const char *twoSecondString = {"Two second task\r\n\0"};
        while (1)
        {
            Task_sleep((unsigned int)arg0);
            Semaphore_pend(UART0semHandle, BIOS_WAIT_FOREVER);
            myUartTx(twoSecondString, strlen(twoSecondString));
        }
    }
    
    Void fiveSecondFxn(UArg arg0, UArg arg1)
    {
        const char *fiveSecondString = {"Five second task\r\n\0"};
        while (1)
        {
            Task_sleep((unsigned int)arg0);
            Semaphore_pend(UART0semHandle, BIOS_WAIT_FOREVER);
            myUartTx(fiveSecondString, strlen(fiveSecondString));
        }
    }
    /*
     *  ======== main ========
     */
    int main(void)
    {
        Task_Params taskParams;
        Hwi_Params hwiParams;
        Hwi_Handle myUartTxHwi;
        Error_Block eb;
        Semaphore_Params semParams;
    
        //
        // Run from the PLL at 120 MHz.
        // Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
        // later to better reflect the actual VCO speed due to SYSCTL#22.
        //
        g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                                 SYSCTL_OSC_MAIN |
                                                 SYSCTL_USE_PLL |
                                                 SYSCTL_CFG_VCO_240), 120000000);
        /* Call board init functions */
        Board_initGeneral();
        Board_initGPIO();
    
        /* Construct heartBeat Task  thread */
        Task_Params_init(&taskParams);
        taskParams.arg0 = 1000;
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task0Stack;
        Task_construct(&task0Struct, (Task_FuncPtr)heartBeatFxn, &taskParams, NULL);
    
        /* Construct 2 second Task  thread */
        Task_Params_init(&taskParams);
        taskParams.arg0 = 2000;
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task1Stack;
        Task_construct(&task1Struct, (Task_FuncPtr)twoSecondFxn, &taskParams, NULL);
    
        /* Construct 5 second Task  thread */
        Task_Params_init(&taskParams);
        taskParams.arg0 = 5000;
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task2Stack;
        Task_construct(&task2Struct, (Task_FuncPtr)fiveSecondFxn, &taskParams, NULL);
    
        /* Turn on user LED  */
        GPIO_write(Board_LED0, Board_LED_ON);
    
        /* Custom Initialization here */
        ConfigureUART();
    
        /* Create the UART HWI */
        /* Initialize error block and hwiParams to default values */
        Error_init(&eb);
        Hwi_Params_init(&hwiParams);
        hwiParams.enableInt = true;
        /* Create a Hwi object for UART0 */
        myUartTxHwi = Hwi_create(UART0_HWI_NUMBER, myUart0HwiFxn, &hwiParams, &eb);
        if (myUartTxHwi == NULL)
        {
            System_abort("Hwi create failed");
        }
    
        /* Construct a Semaphore object to be use as a resource lock, inital count 1 */
        Semaphore_Params_init(&semParams);
        Semaphore_construct(&semStruct, 1, &semParams);
    
        /* Obtain instance handle */
        UART0semHandle = Semaphore_handle(&semStruct);
    
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    
    

    File "Uart0Hwi.h"

    /*
     * Uart0Hwi.h
     *
     *  Created on: Apr 7, 2021
     */
    
    #ifndef UART0HWI_H_
    #define UART0HWI_H_
    
    void myUartTx(const char * pcString, unsigned int stringLength);
    void myUart0HwiFxn(void);
    void ConfigureUART(void);
    
    extern unsigned int g_ui32SysClock;
    extern Semaphore_Handle UART0semHandle;
    
    #endif /* UART0HWI_H_ */
    

    File "Uart0Hwi.c"

    /*
     * Uart0Hwi.c
     *
     *  Created on: Apr 7, 2021
     */
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include <ti/sysbios/knl/Semaphore.h>
    #include "Uart0Hwi.h"
    
    static const char *pStaticString;
    static unsigned int staticLength;
    
    // Function to start UART0 string TX
    void myUartTx(const char *pcString, unsigned int stringLength)
    {
    
        while(stringLength != 0u)
        {
            // Load FIFO with characters until full
            if(UARTCharPutNonBlocking(UART0_BASE, *pcString) == false)
            {
                break;
            }
            pcString++;
            stringLength--;
        }
        // save pointer and length left for interrupt routine
        pStaticString = pcString;
        staticLength = stringLength;
        if(stringLength == 0u)
        {
            // if all chars loaded, interrupt after last char sent
            UARTTxIntModeSet(UART0_BASE, UART_TXINT_MODE_EOT);
        }
        else
        {
            // else interrupt when more room in the FIFO
            UARTTxIntModeSet(UART0_BASE, UART_TXINT_MODE_FIFO);
        }
        UARTIntEnable(UART0_BASE, UART_INT_TX);
    }
    
    // UART0 Interrupt Function
    void myUart0HwiFxn(void)
    {
        unsigned int intStatus;
    
        intStatus = UARTIntStatus(UART0_BASE, true);
        if((intStatus & UART_INT_TX) == UART_INT_TX)
        {
            UARTIntClear(UART0_BASE, UART_INT_TX);
            if(staticLength == 0u)
            {
                // release the Mutex
                Semaphore_post(UART0semHandle);
                UARTIntDisable(UART0_BASE, UART_INT_TX);
            }
            else
            {
                while(staticLength != 0u)
                {
                    // Load FIFO with characters until full
                    if(UARTCharPutNonBlocking(UART0_BASE, *pStaticString) == false)
                    {
                        break;
                    }
                    pStaticString++;
                    staticLength--;
                }
                if(staticLength == 0u)
                {
                    // if all chars loaded, interrupt after last char sent
                    UARTTxIntModeSet(UART0_BASE, UART_TXINT_MODE_EOT);
                }
                else
                {
                    // else interrupt when more room in the FIFO
                    UARTTxIntModeSet(UART0_BASE, UART_TXINT_MODE_FIFO);
                }
            }
        }
        if((intStatus & (UART_INT_RX | UART_INT_RT)) != 0u)
        {
            // Add the RX interrupt routine here
        }
    
    }
    
    //*****************************************************************************
    //
    // Configure the UART and its pins.
    //
    //*****************************************************************************
    void
    ConfigureUART(void)
    {
        //
        // Enable the GPIO Peripheral used by the UART.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Enable UART0
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Configure GPIO Pins for UART mode.
        //
        MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
        MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
        MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART0 for I/O.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        MAP_UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, 115200,
                                (UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE | UART_CONFIG_WLEN_8));
        MAP_UARTFIFOEnable(UART0_BASE);
        MAP_UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
        MAP_UARTEnable(UART0_BASE);
    }
    

  • TiRtosUartHwi.zip

    Here is the project in a .zip file. (Use CCS "File" -> "Import" function. It is not necessary to unzip the project.)

    I used

    • CCS version 10.2
    • TI Compiler version 20.2.4
    • TivaWare version 2.2.0.295
    • TI-RTOS version 2.16.00.08
    • XDCtools version 3.32.2.25
  • Hello Bob,

    Thanks a lot about your example. It's exactly my case.

    The UART driver in TI RTOS is generic it does not take all the UART management cases.

    I have got 2 questions  : 

     #define UART0_HWI_NUMBER  21, where do you take 21 ?

    In this example you doesn't define the priority, every ten seconds two tasks  (2 seconds and 5 seconds)  are simultaned.

    What is the priority ? 

    Have a nice day

    Christophe G from France

  • Hi Christophe,

    I am glad the example was helpful. Those are great questions. The HWI number is based off the order of the interrupt vectors in the vector table. You can find this in table 2-9 of the data sheet. Here is a copy of the first part.

    I intentionally made the two tasks such that they would eventually become ready at the same time to demonstrate the need for a semaphore to prevent both task from trying to use UART0 at the same time. I did not care, so I did not change the priority level. Both tasks are by default at priority 1. (By default the priorities range from 1 to 15, with 1 the lowest and 15 the highest.) As written, it looks like the 5 second task is being chosen first:

    Time (s) Message
    2 Two second task
    4 Two second task
    5 Five second task
    6 Two second task
    8 Two second task
    10 Five second task
    Two second task
    12 Two second task
    14 Two second task
    15 Five second task
    16 Two second task

    I can change that order by specifically giving each task a different priority number. Here I give the 2 second task a priority of 2 and the five second task a priority of 1. 

        /* Construct 2 second Task  thread */
        Task_Params_init(&taskParams);
        taskParams.arg0 = 2000;
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task1Stack;
        taskParams.priority = 2u;
        Task_construct(&task1Struct, (Task_FuncPtr)twoSecondFxn, &taskParams, NULL);
    
        /* Construct 5 second Task  thread */
        Task_Params_init(&taskParams);
        taskParams.arg0 = 5000;
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task2Stack;
        taskParams.priority = 1u;
        Task_construct(&task2Struct, (Task_FuncPtr)fiveSecondFxn, &taskParams, NULL);
    
    

    Now at 10 seconds, the 2 second task is run first:

    Time (s) Message
    2 Two second task
    4 Two second task
    5 Five second task
    6 Two second task
    8 Two second task
    10 Two second task
    Five second task
    12 Two second task
    14 Two second task
    15 Five second task
    16 Two second task