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.

TM4C1290NCPDT: TI RTOS with UART Hwi

Part Number: TM4C1290NCPDT
Other Parts Discussed in Thread: EK-TM4C1294XL, SYSCONFIG

I believe I have properly setup the UART Hwi (see code below). I want to have a TX and RX interrupt. My interrupt handler is getting executed, but it's always due to the RX timeout. I have tried enabling the FIFO, but it made no difference. What do I need to do to get the TX and RX interrupts to function as expected?

#define OPERATOR_TASK_STACK_SIZE   512

Task_Struct operator_task_struct;
Char        operator_task_stack[OPERATOR_TASK_STACK_SIZE];

//  Hwi_Struct used in the operator_uart Hwi_construct call
static Hwi_Struct operator_uart_hwi_struct;

/*------------------------------------------------------------------------------------------
 *  Function name:      Operator_Task
 *  Created by:         Bryan Radke
 *  Date created:       01-07-2020
 *
 *  Description:
 *      Handles all operations for the operator.
 *
 *  Input:
 *      arg0    -   Task repeat time in ms.
 *      arg1    -   Not used.
 *
 *  Output:
 *      none
 *
 */
void Operator_Task( UArg arg0, UArg arg1 )
{
    //  Text TX interrupt
    UARTIntEnable( UART2_BASE, UART_INT_TX );
    UARTCharPut( UART2_BASE, 0x73 );

    while( 1 )
    {
        Task_sleep((unsigned int)arg0 );

        //  TBD
    }
}

/*------------------------------------------------------------------------------------------
 *  Function name:      Operator_UART_Int_Handler
 *  Created by:         Bryan Radke
 *  Date created:       01-07-2020
 *
 *  Description:
 *      UART interrupt handler for the operator communications.
 *
 *  Input:
 *      none
 *
 *  Output:
 *      none
 *
 */
static void Operator_UART_Int_Handler( UArg arg )
{
    uint8_t byte;
    uint32_t uart_int_status;

    //  Get the interrupt status
    uart_int_status = UARTIntStatus( UART2_BASE, true );

    //  Clear the asserted interrupts
    UARTIntClear( UART2_BASE, uart_int_status );

    if ( uart_int_status & ( UART_INT_RX | UART_INT_RT ))
    {
        while ( UARTCharsAvail( UART2_BASE ) )
        {
            byte = UARTCharGetNonBlocking( UART2_BASE );
        }
    }
    else if ( uart_int_status & UART_INT_TX )
    {
        uart_int_status = uart_int_status;
        UARTIntDisable( UART2_BASE, UART_INT_TX );
    }
}

/*------------------------------------------------------------------------------------------
 *  Function name:      Operator_Task_Init
 *  Created by:         Bryan Radke
 *  Date created:       01-07-2020
 *
 *  Description:
 *      Initializes the operator task.
 *
 *  Input:
 *      none
 *
 *  Output:
 *      none
 *
 */
void Operator_Task_Init( uint32_t cpu_clk )
{
	Task_Params operator_task_params;
	Error_Block operator_uart_eb;
	Hwi_Params  operator_hwi_params;

	//  Enable UART module
	SysCtlPeripheralEnable( SYSCTL_PERIPH_UART2 );

	//  Disable UART
	UARTDisable( UART2_BASE );

	//  Configure port settings
	UARTConfigSetExpClk( UART2_BASE,
	                     cpu_clk,
	                     9600,
	                     ( UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE ));

	//  Setup the FIFO levels
	//UARTFIFOLevelSet( UART2_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8 );

	//  Enable UART FIFO
	//UARTFIFOEnable( UART2_BASE );

	//  Register UART interrupts
	UARTIntEnable( UART2_BASE, UART_INT_RX | UART_INT_RT );

	//  Create a Hwi for UART2
	Error_init( &operator_uart_eb );
	Hwi_Params_init( &operator_hwi_params );
	Hwi_construct( &(operator_uart_hwi_struct), INT_UART2,
	                          Operator_UART_Int_Handler,
	                          &operator_hwi_params,
	                          &operator_uart_eb);

	//  Check for errors constructing the Hwi
    if ( Error_check(&operator_uart_eb) )
    {
        System_abort( "Couldn't construct operator UART hwi!" );
    }

	//  Enable UART interrupts
	IntEnable( INT_UART2 );

	//  Enable the UART
	UARTEnable( UART2_BASE );

	//  Construct operator task
	Task_Params_init( &operator_task_params );
	operator_task_params.arg0 = 10;
	operator_task_params.stackSize = OPERATOR_TASK_STACK_SIZE;
	operator_task_params.stack = &operator_task_stack;
	operator_task_params.priority = 3;
	Task_construct( &operator_task_struct, (Task_FuncPtr)Operator_Task, &operator_task_params, NULL );
}

  • Hi Bryan,

      I'm not a TI-RTOS expert but let me see if I can help you here. If not, I will forward your post to our TI-RTOS experts. 

      I have some questions and comments.

      - You create a task Operator_Task that enables TX interrupt and writes data value 0x73 to the bus. First of all, if you place a breakpoint in Operator_Task(), does the processor halt in this function? If you have a scope, do you see 0x73 put on the bus?

      - In the Operator_Task() you put the task to sleep for 10 ticks before waking up the task. Any reason why don't use the semaphore_pend() to pend the Operator_Task and use the ISR to unblock the task with semaphore_post()?

      - In your ISR, you have else if ( uart_int_status & UART_INT_TX ). Is it possible that you are constantly getting the RT interrupt and it never take the else if clause? What if you make the ( uart_int_status & UART_INT_TX ) as an independent if clause?

      - What is your hardware setup? What is connected to the UART2? Are you receiving data on the RX pin? A scope or logic analyzer will be very helpful to understand what is going on. 

  • Hey Charles,

    Charles Tsai said:

      - You create a task Operator_Task that enables TX interrupt and writes data value 0x73 to the bus. First of all, if you place a breakpoint in Operator_Task(), does the processor halt in this function? If you have a scope, do you see 0x73 put on the bus?

    The processor does not halt on the write function. I have verified with a scope that the data is truly getting clocked.

    Charles Tsai said:

      - In the Operator_Task() you put the task to sleep for 10 ticks before waking up the task. Any reason why don't use the semaphore_pend() to pend the Operator_Task and use the ISR to unblock the task with semaphore_post()?

    We are starting a new development project, and in the end design, this function will need to be loosely time based. I thought you couldn't use RTOS utilities like a semaphore in hardware interrupts?

    Charles Tsai said:

      - In your ISR, you have else if ( uart_int_status & UART_INT_TX ). Is it possible that you are constantly getting the RT interrupt and it never take the else if clause? What if you make the ( uart_int_status & UART_INT_TX ) as an independent if clause?

    You bring up a good point that I shouldn't be using an else if there. I had debug code in the handler before to trip if the interrupt status was anything other than the receive timeout and normal RX flags. I was never tripping on the TX interrupt. Just to quickly verify, I modified the code to make the TX a separate check, and I am still not hitting the TX flag.

    Charles Tsai said:

      - What is your hardware setup? What is connected to the UART2? Are you receiving data on the RX pin? A scope or logic analyzer will be very helpful to understand what is going on. 

    I am currently using the EK-TM4C1294XL launchpad for pre-development testing. I am using PA6 and PA7 for the UART. I currently have the TX pin tied back to the RX pin to do loop back validation. I have verified that I get the expected data on the RX and the interrupt handler processes the data as expected.

    For our end design we will be transmitting packets to a RS232 device whether the packet payload will be greater than the FIFO size. I would like to use the TX interrupt to trigger on a single byte transmission completing so I can ready up the next byte to TX until the entire packet is sent.

    Previously I had the FIFO enabled for a two byte level, and I attempted to send two or three bytes, but never got the TX interrupt to trip.

  • For what it's worth, I create a simple non-RTOS project to setup the UART interrupt and I can replicate the issue.

  • Hi,

      Can you post your non-RTOS project so I can take a look?

  • #include <stdbool.h>
    #include <stdio.h>
    #include <string>
    
    //  Driverlib Header Files
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    
    //  Hardware Init Header Files
    #include "pinout.h"
    
    //  Hardware Init Header Files
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    
    uint32_t g_ui32SysClock;    //  System clock frequency in Hz
    uint32_t interrupt_count = 0;
    
    static void Operator_UART_Int_Handler( void )
    {
        uint8_t  byte;
        uint32_t uart_int_status;
    
        interrupt_count++;
    
        //  Get the interrupt status
        uart_int_status = UARTIntStatus( UART2_BASE, true );
    
        //  Clear the asserted interrupts
        UARTIntClear( UART2_BASE, uart_int_status );
    
        if ( uart_int_status & ( UART_INT_RX | UART_INT_RT ))
        {
            while ( UARTCharsAvail( UART2_BASE ) )
            {
                byte = UARTCharGetNonBlocking( UART2_BASE );
            }
        }
        if ( uart_int_status & UART_INT_TX )
        {
            uart_int_status = uart_int_status;
            UARTIntDisable( UART2_BASE, UART_INT_TX );
        }
    }
    
    /**
     * main.c
     */
    int main(void)
    {
        //  Run from the PLL at 120MHz
        g_ui32SysClock = SysCtlClockFreqSet(( SYSCTL_XTAL_25MHZ |
                                              SYSCTL_OSC_MAIN |
                                              SYSCTL_USE_PLL |
                                              SYSCTL_CFG_VCO_480 ),
                                            120000000 );
    
        //  Configure the device pins.
        PinoutSet();
    
        //  Enable UART module
        SysCtlPeripheralEnable( SYSCTL_PERIPH_UART2 );
    
        //  Disable UART
        UARTDisable( UART2_BASE );
    
        //  Configure port settings
        UARTConfigSetExpClk( UART2_BASE,
                             g_ui32SysClock,
                             9600,
                             ( UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE ));
    
        //  Register UART interrupts
        UARTIntEnable(UART2_BASE, UART_INT_RX | UART_INT_RT);
        UARTIntRegister(UART2_BASE, Operator_UART_Int_Handler);
    
        //  Enable UART interrupts
        IntEnable( INT_UART2 );
    
        //  Enable the UART
        UARTEnable( UART2_BASE );
    
        while(1)
        {
            SysCtlDelay( g_ui32SysClock/3 );
    
            //  Test TX interrupt
            UARTIntEnable( UART2_BASE, UART_INT_TX );
            UARTCharPut( UART2_BASE, 0x73 );
        }
    
    	return 0;
    }
    

  • Output of sysconfig:

    void
    PinoutSet(void)
    {
        //
        // Enable Peripheral Clocks 
        //
    	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
    	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    
        //
        // Configure the GPIO Pin Mux for PE3
    	// for AIN0
        //
    	MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
    
        //
        // Configure the GPIO Pin Mux for PE1
    	// for AIN2
        //
    	MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1);
    
        //
        // Configure the GPIO Pin Mux for PE2
    	// for AIN1
        //
    	MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);
    
        //
        // Configure the GPIO Pin Mux for PE0
    	// for AIN3
        //
    	MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);
    
        //
        // Configure the GPIO Pin Mux for PB4
    	// for AIN10
        //
    	MAP_GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_4);
    
        //
        // Configure the GPIO Pin Mux for PN1
    	// for GPIO_PN1
        //
    	MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);
    	MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0x0);
    
        //
        // Configure the GPIO Pin Mux for PN0
    	// for GPIO_PN0
        //
    	MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);
    	MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0x0);
    
        //
        // Configure the GPIO Pin Mux for PF4
    	// for GPIO_PF4
        //
    	MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_4);
    	MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 0x0);
    
        //
        // Configure the GPIO Pin Mux for PF0
    	// for GPIO_PF0
        //
    	MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0);
    	MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0x0);
    
        //
        // Configure the GPIO Pin Mux for PJ0
    	// for GPIO_PJ0
        //
    	MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_0);
    	MAP_GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_PIN_0, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    
        //
        // Configure the GPIO Pin Mux for PJ1
    	// for GPIO_PJ1
        //
    	MAP_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_1);
    	MAP_GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_PIN_1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    
        //
        // Configure the GPIO Pin Mux for PA6
    	// for U2RX
        //
    	MAP_GPIOPinConfigure(GPIO_PA6_U2RX);
    	MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_6);
    
        //
        // Configure the GPIO Pin Mux for PA7
    	// for U2TX
        //
    	MAP_GPIOPinConfigure(GPIO_PA7_U2TX);
    	MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_7);
    
    }

  • Hi,

      I couldn't get your code to generate TX interrupt. However, if I enable the FIFO I'm able to get the TX interrupt going. I will need to investigate why the non-FIFO mode not generate the TX interrupt.

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    //  Hardware Init Header Files
    #include "drivers/pinout.h"
    
    //  Hardware Init Header Files
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    
    uint32_t g_ui32SysClock;    //  System clock frequency in Hz
    uint32_t interrupt_count = 0;
    
    static void Operator_UART_Int_Handler( void )
    {
        uint8_t  byte;
        uint32_t uart_int_status;
    
        interrupt_count++;
    
        //  Get the interrupt status
        uart_int_status = UARTIntStatus( UART2_BASE, true );
    
        //  Clear the asserted interrupts
        UARTIntClear( UART2_BASE, uart_int_status );
    
        if ( uart_int_status & ( UART_INT_RX | UART_INT_RT ))
        {
            while ( UARTCharsAvail( UART2_BASE ) )
            {
                byte = UARTCharGetNonBlocking( UART2_BASE );
            }
        }
        if ( uart_int_status & UART_INT_TX )
        {
            uart_int_status = uart_int_status;
            UARTCharPut( UART2_BASE, 0x73 );
            UARTCharPut( UART2_BASE, 0x73 );
            UARTCharPut( UART2_BASE, 0x73 );
            UARTCharPut( UART2_BASE, 0x73 );
    
        }
    }
    
    /**
     * main.c
     */
    int main(void)
    {
        //  Run from the PLL at 120MHz
        g_ui32SysClock = SysCtlClockFreqSet(( SYSCTL_XTAL_25MHZ |
                                              SYSCTL_OSC_MAIN |
                                              SYSCTL_USE_PLL |
                                              SYSCTL_CFG_VCO_480 ),
                                            120000000 );
    
         //
         // Enable the peripherals used by this example.
         //
         ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
         ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        //  Enable UART module
        SysCtlPeripheralEnable( SYSCTL_PERIPH_UART2 );
    
        //
        // Set GPIO A0 and A1 as UART pins.
        //
        GPIOPinConfigure(GPIO_PA6_U2RX);
        GPIOPinConfigure(GPIO_PA7_U2TX);
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);
    
        //  Disable UART
        UARTDisable( UART2_BASE );
    
        //  Configure port settings
        UARTConfigSetExpClk( UART2_BASE,
                             g_ui32SysClock,
                             115200,
                             ( UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE ));
    
        UARTFIFOEnable(UART2_BASE);
        UARTFIFOLevelSet(UART2_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
    
    
        //  Register UART interrupts
        UARTIntEnable(UART2_BASE, UART_INT_RX | UART_INT_RT | UART_INT_TX);
        UARTIntRegister(UART2_BASE, Operator_UART_Int_Handler);
    
        //  Enable UART interrupts
        IntEnable( INT_UART2 );
    
        ROM_IntMasterEnable();
    
    
        //  Enable the UART
        UARTEnable( UART2_BASE );
    
        UARTCharPut( UART2_BASE, 0x73 );
        UARTCharPut( UART2_BASE, 0x73 );
        UARTCharPut( UART2_BASE, 0x73 );
        UARTCharPut( UART2_BASE, 0x73 );
    
    
        while(1)
        {
    
        }
    
        return 0;

  • I got the non-FIFO mode to generate interrupt too if I add UARTTxIntModeSet(UART2_BASE, UART_TXINT_MODE_EOT). See below code.

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    //  Hardware Init Header Files
    #include "drivers/pinout.h"
    
    //  Hardware Init Header Files
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    
    uint32_t g_ui32SysClock;    //  System clock frequency in Hz
    uint32_t interrupt_count = 0;
    
    static void Operator_UART_Int_Handler( void )
    {
        uint8_t  byte;
        uint32_t uart_int_status;
    
        interrupt_count++;
    
        //  Get the interrupt status
        uart_int_status = UARTIntStatus( UART2_BASE, true );
    
        //  Clear the asserted interrupts
        UARTIntClear( UART2_BASE, uart_int_status );
    
        if ( uart_int_status & ( UART_INT_RX | UART_INT_RT ))
        {
            while ( UARTCharsAvail( UART2_BASE ) )
            {
                byte = UARTCharGetNonBlocking( UART2_BASE );
            }
        }
        if ( uart_int_status & UART_INT_TX )
        {
            uart_int_status = uart_int_status;
            UARTCharPut( UART2_BASE, 0x73 );
    //        UARTCharPut( UART2_BASE, 0x73 );
    //        UARTCharPut( UART2_BASE, 0x73 );
    //        UARTCharPut( UART2_BASE, 0x73 );
    
        }
    }
    
    /**
     * main.c
     */
    int main(void)
    {
        //  Run from the PLL at 120MHz
        g_ui32SysClock = SysCtlClockFreqSet(( SYSCTL_XTAL_25MHZ |
                                              SYSCTL_OSC_MAIN |
                                              SYSCTL_USE_PLL |
                                              SYSCTL_CFG_VCO_480 ),
                                            120000000 );
    
         //
         // Enable the peripherals used by this example.
         //
         ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
         ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        //  Enable UART module
        SysCtlPeripheralEnable( SYSCTL_PERIPH_UART2 );
    
        //
        // Set GPIO A0 and A1 as UART pins.
        //
        GPIOPinConfigure(GPIO_PA6_U2RX);
        GPIOPinConfigure(GPIO_PA7_U2TX);
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);
    
        //  Disable UART
        UARTDisable( UART2_BASE );
    
        //  Configure port settings
        UARTConfigSetExpClk( UART2_BASE,
                             g_ui32SysClock,
                             9600,
                             ( UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE ));
    
    //    UARTFIFOEnable(UART2_BASE);
    //    UARTFIFOLevelSet(UART2_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
    
        UARTTxIntModeSet(UART2_BASE, UART_TXINT_MODE_EOT);
    
    
        //  Register UART interrupts
        UARTIntEnable(UART2_BASE, UART_INT_RX | UART_INT_RT | UART_INT_TX);
        UARTIntRegister(UART2_BASE, Operator_UART_Int_Handler);
    
        //  Enable UART interrupts
        IntEnable( INT_UART2 );
    
        ROM_IntMasterEnable();
    
    
        //  Enable the UART
        UARTEnable( UART2_BASE );
    
        UARTCharPut( UART2_BASE, 0x73 );
    //    UARTCharPut( UART2_BASE, 0x73 );
    //    UARTCharPut( UART2_BASE, 0x73 );
    //    UARTCharPut( UART2_BASE, 0x73 );
    
    
        while(1)
        {
    
        }
    
        return 0;
    }