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: uart receive interrupt

Part Number: EK-TM4C1294XL

Tool/software: TI-RTOS

I am continuing to troubleshoot a setup with two EK-TM4C1294XL.

Both EKs are set up to in 8 bit uart mode, interrupt on uart receive. I have the interrupts

for the uart and timer set up in the startup_ccs.c file.

EK1 sends a byte every 10 seconds, determined by a periodic timer. I have an LED set up

to blink when EK2 receives this byte. This LED toggles state once and not every 10 seconds

as expected. Why is the uart receive interrupt not repeatedly triggering?  I have attached both

the transmitter and receiver EK files. On the scope, I can see the transmitted byte from EK1,

no byte visible on the scope from U5Rx on EK2.

Thanks,

Priya

EK1 transmitter:

//*****************************************************************************
//
// uart_echo.c - Example for reading data from and writing data to the UART in
//               an interrupt driven fashion.
//
// Copyright (c) 2013-2017 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2.1.4.178 of the EK-TM4C1294XL Firmware Package.
//
//*****************************************************************************

#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"
#include "driverlib/timer.h"
#include "utils/uartstdio.h"

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>UART Echo (uart_echo)</h1>
//!
//! This example application utilizes the UART to echo text.  The first UART
//! (connected to the USB debug virtual serial port on the evaluation board)
//! will be configured in 115,200 baud, 8-n-1 mode.  All characters received on
//! the UART are transmitted back to the UART.
//
//*****************************************************************************

//****************************************************************************
//
// System clock rate in Hz.
//
//****************************************************************************
uint32_t g_ui32SysClock;

unsigned char txcomplete = 0;
unsigned char timerComplete = 0;
static uint8_t TrxBuffer[1] = {0x43};
uint8_t i = 0;
void UARTSend(const uint8_t *pui16Buffer, uint32_t ui32Count);

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{

#endif

//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************
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.

        ROM_UARTCharPutNonBlocking(UART5_BASE, *pui8Buffer++);

    }
}


//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
void
UARTIntHandler(void)
{
    uint32_t ui32Status;

    //
    // Get the interrrupt status.
    //
    ui32Status = UARTIntStatus(UART5_BASE, true);

    //
    // Clear the asserted interrupts.
    //
    ROM_UARTIntClear(UART5_BASE, ui32Status);

    if( ( (UART_INT_RX & ui32Status) == UART_INT_RX ) || ( (UART_INT_RT & ui32Status) == UART_INT_RT) ){

        // Receive uart char
             while(ROM_UARTCharsAvail(UART5_BASE))
             {
                 //
                 // Read the next character from the UART and write it back to the UART.
                 //

                 ROM_UARTCharGetNonBlocking(UART5_BASE);


                 //uint32_t c = UARTCharGet(UART5_BASE);

                 //
                 // Blink the LED to show a character transfer is occuring.
                 //
                 if(GPIOPinRead(GPIO_PORTN_BASE, GPIO_PIN_1))
                             {
                                 GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0);
                             }
                 else
                             {
                                 GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 2);
                             }
             }


       }

}

void Timer2IntHandler(void)
{
    // Clear the timer interrupt
    ROM_TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
    i = 0;

    UARTSend(TrxBuffer, 1);

    // Blink the LED to show a character transfer is occuring.
    //

    if(GPIOPinRead(GPIO_PORTN_BASE, GPIO_PIN_1))
                {
                    GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0);
                }
    else
                {
                    GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 2);
                }

    timerComplete = 1;

}

//*****************************************************************************
//
// This example demonstrates how to send a string of data to the UART.
//
//*****************************************************************************
int
main(void)
{
    uint32_t ui32Period;

    //
    // Set the clocking to run directly from the crystal at 120MHz.
    //
    g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                             SYSCTL_OSC_MAIN |
                                             SYSCTL_USE_PLL |
                                             SYSCTL_CFG_VCO_480), 120000000);
    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    //
    // Enable the GPIO pins for the LED (PN0).
    //
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0|GPIO_PIN_1);


    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
    ROM_IntMasterEnable();

    //TimerConfigure(TIMER2_BASE, TIMER_CFG_ONE_SHOT);
    ROM_TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC);

//    ui32Period = g_ui32SysClock/200; // 5 ms one shot timer

    ui32Period = 5*g_ui32SysClock;
//    ui32Period = 3*g_ui32SysClock;
    ROM_TimerLoadSet(TIMER2_BASE, TIMER_A, ui32Period);

    ROM_IntEnable(INT_TIMER2A);
    ROM_TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);


    ROM_TimerEnable(TIMER2_BASE, TIMER_A);


    //
    // Enable the peripherals used by this example.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART5);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);


    //
    // Set GPIO A0 and A1 as UART pins.
    //
    ROM_GPIOPinConfigure(GPIO_PC6_U5RX);
    ROM_GPIOPinConfigure(GPIO_PC7_U5TX);
    ROM_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_6 | GPIO_PIN_7);


    //
    // Configure the UART for 9600, 8-N-1 operation.
    //
    ROM_UARTConfigSetExpClk(UART5_BASE, g_ui32SysClock, 9600,
                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                             UART_CONFIG_PAR_NONE));


    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    UARTStdioConfig(0, 9600, g_ui32SysClock);

//    UART9BitAddrSet(UART5_BASE, 0x43, 0xFF);
//    UART9BitEnable(UART5_BASE);

    ROM_UARTEnable(UART5_BASE);
    ROM_UARTFIFODisable(UART5_BASE);
//    UART9BitAddrSend(UART5_BASE, 0x43);

    //
    // Enable the UART interrupt.
    //
    ROM_IntEnable(INT_UART5);

//    UARTIntEnable(UART5_BASE, UART_INT_RX | UART_INT_RT | UART_INT_9BIT);
      ROM_UARTIntEnable(UART5_BASE, UART_INT_RX | UART_INT_RT);
//    ROM_UARTIntEnable(UART5_BASE, UART_INT_TX | UART_TXINT_MODE_EOT | UART_INT_9BIT);
//    ROM_UARTIntEnable(UART5_BASE,UART_INT_TX|UART_TXINT_MODE_EOT | UART_INT_9BIT | UART_INT_RX|UART_INT_RT);


//    UARTSend(TrxBuffer, 1);


//    while(!(txcomplete));
    while(1);
}

EK2 receiver:

//*****************************************************************************
//
// uart_echo.c - Example for reading data from and writing data to the UART in
//               an interrupt driven fashion.
//
// Copyright (c) 2013-2017 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2.1.4.178 of the EK-TM4C1294XL Firmware Package.
//
//*****************************************************************************

#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"
#include "driverlib/timer.h"
#include "utils/uartstdio.h"

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>UART Echo (uart_echo)</h1>
//!
//! This example application utilizes the UART to echo text.  The first UART
//! (connected to the USB debug virtual serial port on the evaluation board)
//! will be configured in 115,200 baud, 8-n-1 mode.  All characters received on
//! the UART are transmitted back to the UART.
//
//*****************************************************************************

//****************************************************************************
//
// System clock rate in Hz.
//
//****************************************************************************
uint32_t g_ui32SysClock;

unsigned char txcomplete = 0;
unsigned char timerComplete = 0;
uint8_t TrxBuffer[1] = {0x21};
uint8_t i = 0;
void UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count);
void Timer3IntHandler(void);


//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************
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.

        ROM_UARTCharPutNonBlocking(UART5_BASE, *pui8Buffer++);
//        UARTprintf("%x ", TrxBuffer[i++]);

    }
}

void Timer3IntHandler(void)
{
    // Clear the timer interrupt
    ROM_TimerIntClear(TIMER3_BASE, TIMER_TIMA_TIMEOUT);

    // Blink the LED to show a character transfer is occuring.
/*
    if(GPIOPinRead(GPIO_PORTN_BASE, GPIO_PIN_1))
            {
                GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0);
            }
    else
            {
                GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 2);
            }
*/
    UARTSend(TrxBuffer, 1);
    i = 0;

    timerComplete = 1;

}

//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
void
UARTIntHandler(void)
{
    uint32_t ui32Status;

    //
    // Get the interrrupt status.
    //
    ui32Status = UARTIntStatus(UART5_BASE, true);

    //

    //
    // Clear the asserted interrupts.
    //
    ROM_UARTIntClear(UART5_BASE, ui32Status);

//    if (interrupt_type == 1){
    if( ( (UART_INT_RX & ui32Status) == UART_INT_RX ) || ( (UART_INT_RT & ui32Status) == UART_INT_RT) ){
        // Receive uart char
             while(ROM_UARTCharsAvail(UART5_BASE))
             {
                 //
                 // Read the next character from the UART and write it back to the UART.
                 //
//                 UARTCharPut(UART5_BASE, UARTCharGet(UART5_BASE));
                 ROM_UARTCharGetNonBlocking(UART5_BASE);
             }

    if(GPIOPinRead(GPIO_PORTN_BASE, GPIO_PIN_1))
        {
            GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0);
        }
    else
        {
            GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 2);
        }
    }

}

//*****************************************************************************
//
// This example demonstrates how to send a string of data to the UART.
//
//*****************************************************************************
int
main(void)
{
    uint32_t ui32Period;

    //
    // Set the clocking to run directly from the crystal at 120MHz.
    //
    g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                             SYSCTL_OSC_MAIN |
                                             SYSCTL_USE_PLL |
                                             SYSCTL_CFG_VCO_480), 120000000);
    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    //
    // Enable the GPIO pins for the LED (PN0).
    //
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0|GPIO_PIN_1);


    //
    // Enable the peripherals used by this example.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART5);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Enable processor interrupts.
    //
    ROM_IntMasterEnable();

#if 0
        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);
//        TimerConfigure(TIMER3_BASE, TIMER_CFG_ONE_SHOT);
        TimerConfigure(TIMER3_BASE, TIMER_CFG_PERIODIC);


        ui32Period = g_ui32SysClock/2; // 1 ms one shot timer

//        ui32Period = 5*g_ui32SysClock;
        TimerLoadSet(TIMER3_BASE, TIMER_A, ui32Period-1);

        IntEnable(INT_TIMER3A);
        TimerIntEnable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
        IntMasterEnable();

        TimerEnable(TIMER3_BASE, TIMER_A);
#endif

    //
    // Set GPIO A0 and A1 as UART pins.
    //
    ROM_GPIOPinConfigure(GPIO_PC6_U5RX);
    ROM_GPIOPinConfigure(GPIO_PC7_U5TX);
    ROM_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_6 | GPIO_PIN_7);


    //
    // Configure the UART for 9600, 8-N-1 operation.
    //
    ROM_UARTConfigSetExpClk(UART5_BASE, g_ui32SysClock, 9600,
                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                             UART_CONFIG_PAR_NONE));


    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    UARTStdioConfig(0, 9600, g_ui32SysClock);

//    UART9BitAddrSet(UART5_BASE, 0x43, 0xFF);
//    UART9BitEnable(UART5_BASE);

    ROM_UARTEnable(UART5_BASE);

    ROM_UARTFIFODisable(UART5_BASE);

    //
    // Enable the UART interrupt.
    //
    ROM_IntEnable(INT_UART5);
//    UARTIntEnable(UART5_BASE, UART_INT_RX | UART_INT_RT | UART_INT_9BIT);
    ROM_UARTIntEnable(UART5_BASE, UART_INT_RX | UART_INT_RT);
//    ROM_UARTIntEnable(UART5_BASE, UART_INT_TX | UART_TXINT_MODE_EOT | UART_INT_9BIT);
//    ROM_UARTIntEnable(UART5_BASE,UART_INT_TX|UART_TXINT_MODE_EOT | UART_INT_9BIT | UART_INT_RX|UART_INT_RT);

//    UARTSend(TrxBuffer, 1);


//    while(!(txcomplete));
    while(1);
}

Thanks,

Priya

 

  • Hi Priya,
    1. First of all I see that on the transmit side for EK1, your timer period is 5s not 10s as in ui32Period = 5*g_ui32SysClock;
    , is it correct?
    2. Are you monitoring the LED on the transmit side as well? Suppose you start off with the LED off. When you get a timer interrupt, you will toggle the LED ON after you send a character. However, in your receive interrupt you will toggle the same LED off again. So the duration of the LED ON time will be the length of one UART character transmission. The flicker on the LED will be too short on the human eye if you simply rely on the LED ON time to decipher if the transmission has been successful.
    3. I thought that the EK1 is sending the character based on each timer timeout. In the EK2, it is just receiving the character. If this is the case, why are you setting up the TIMER3? You should not setup timer on the receiving side in EK2. The EK2 should just wait for the character to come in and generate the receive interrupt.
    4. Independent of the LED, did EK2 receive the character from EK1?
  • 1. First of all I see that on the transmit side for EK1, your timer period is 5s not 10s as in ui32Period = 5*g_ui32SysClock;
    , is it correct?

    I may not have the period calculated exactly correct, 5s or 10 s is fine for what I'm currently doing.

    2. Are you monitoring the LED on the transmit side as well? Suppose you start off with the LED off. When you get a timer interrupt, you will toggle the LED ON after you send a character. However, in your receive interrupt you will toggle the same LED off again. So the duration of the LED ON time will be the length of one UART character transmission. The flicker on the LED will be too short on the human eye if you simply rely on the LED ON time to decipher if the transmission has been successful.

    In the transmitter EK1, I do have the LED setup to toggle both in the timer handler interrupt and in the uart interrupt handler.

    3. I thought that the EK1 is sending the character based on each timer timeout. In the EK2, it is just receiving the character. If this is the case, why are you setting up the TIMER3? You should not setup timer on the receiving side in EK2. The EK2 should just wait for the character to come in and generate the receive interrupt.

    I don't have the timer enabled in EK2 receiver. I have a timer in there because I had EK2 also transmit at the end of a periodic timer. When I looked at this transmitted byte on the scope, I could see it clearly.

    4. Independent of the LED, did EK2 receive the character from EK1?
    I am not seeing evidence of this on the scope when I probe EK2 U5 Rx. It seems to me that the uart receive interrupt is not triggering.

    Thank you,
    Priya
  • The jumpers on the EK were totally mixed up due to frequent transportation to use the scope.
    The LED is blinking as it should and I can see the received byte on the scope. I am now
    hoping the same will work in 9 bit mode.
    Thank you,
    Priya
  • Glad your problem is solved!