• Resolved

Compiler/TM4C129CNCPDT: UART0 RX Interrupt issue

Part Number: TM4C129CNCPDT

Tool/software: TI C/C++ Compiler

Hello Gurus,

I am trying to implement UART0 RX interrupt and can not implement yet. The code compiles successfully without any error. However I am facing two weird problems i.e;

  1. It doesnt capture any interrupt till I send the 8th character. As it receives the 8th character it services the interrupt handler ISR and returns back sucessfully
  2. It services the interrupt only once and never interrupts again no matter how many charter I send.

I have registered the interrupt handler in startup_css.c file already and declared as well.

//*****************************************************************************
//
// External declarations for the interrupt handlers used by the application.
//
//*****************************************************************************
extern void xPortPendSVHandler(void);
extern void vPortSVCHandler(void);
extern void xPortSysTickHandler(void);

extern void UART0ISR(void);


//*****************************************************************************

AND
  IntDefaultHandler,                      // GPIO Port B
    IntDefaultHandler,                      // GPIO Port C
    IntDefaultHandler,                      // GPIO Port D
    IntDefaultHandler,                      // GPIO Port E
    UART0ISR,                      // UART0 Rx and Tx
    IntDefaultHandler,                      // UART1 Rx and Tx
    IntDefaultHandler,                      // SSI0 Rx and Tx
    IntDefaultHandler,                      // I2C0 Master and Slave

My main.c;

#include <stdint.h>
#include <stdbool.h>
#include "main.h"
#include "drivers/pinout.h"
#include "utils/uartstdio.h"


// TivaWare includes
#include "driverlib/sysctl.h"
#include "driverlib/debug.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/gpio.h"
#include "inc/hw_memmap.h"
#include "driverlib/pin_map.h"
#include "driverlib/uart.h"
#include "inc/hw_ints.h"
#include "driverlib/interrupt.h"

// FreeRTOS includes
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"


// Tasks declarations
void LED1Task(void *pvParameters);
void LED2Task(void *pvParameters);
void LED3Task(void *pvParameters);
void LED4Task(void *pvParameters);
void SerialTask1(void *pvParameters);
void SerialTask2(void *pvParameters);
void UART0ISR(void);

// Main function
int main(void)
{
    // Initialize system clock to 120 MHz
    uint32_t output_clock_rate_hz;
    output_clock_rate_hz = ROM_SysCtlClockFreqSet(
                               (SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |
                                SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480),
                               SYSTEM_CLOCK);
    ASSERT(output_clock_rate_hz == SYSTEM_CLOCK);

    // Initialize the GPIO pins for the Launchpad
    PinoutSet(false, false);

    // Set up the UART which is connected to the virtual COM port
    //UARTStdioInit(0);
    //UARTStdioConfig(0, 115200, SYSTEM_CLOCK);

    /////////////////////////////////////////////////////////////////////////////

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //UARTConfigSetExpClk(UART0_BASE, output_clock_rate_hz, 115200,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));


    UARTIntEnable(UART0_BASE, UART_INT_RX); //only enable RX interrupts
    //IntRegister(INT_UART0, UART0ISR);

    IntEnable(INT_UART0); //enable the UART interrupt
    IntMasterEnable(); //enable processor interrupts

    UARTStdioConfig(0, 115200, SYSTEM_CLOCK);
    ////////////////////////////////////////////////////////////////////////////

    // Create demo tasks
    xTaskCreate(LED1Task, (const portCHAR *)"LED1",
                configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    //xTaskCreate(demoLED2Task, (const portCHAR *)"LED2",
                //configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    xTaskCreate(LED3Task, (const portCHAR *)"LED3",
                configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    //xTaskCreate(LED4Task, (const portCHAR *)"LED4",
                //configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    xTaskCreate(SerialTask1, (const portCHAR *)"SerialTask1",
                configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    xTaskCreate(SerialTask2, (const portCHAR *)"SerialTask2",
                configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    vTaskStartScheduler();

    /// Scheduler should NEVER reach here///
    while(1)
    {
        //UARTprintf("Scheduler Error..!\n\r");
        GPIOPinWrite(CLP_D1_PORT, CLP_D1_PIN, CLP_D1_PIN);
        GPIOPinWrite(CLP_D2_PORT, CLP_D2_PIN, CLP_D2_PIN);
        GPIOPinWrite(CLP_D3_PORT, CLP_D3_PIN, CLP_D3_PIN);
        GPIOPinWrite(CLP_D4_PORT, CLP_D4_PIN, CLP_D4_PIN);
        return 0;
    }



}

and the UART0 handler defination;

void UART0ISR(void)
{
    UARTIntClear(UART0_BASE, UART_INT_RX);
    UARTprintf("UART0ISR called..!\n\r");
}

I am stuck and not able to identify the issue.

Any help/hint will be appreciable.

Thank you all.

  • Please Note the first two codes are from startup_css.c and the laste two codes are from main.c.
    I am using EK-TM4C129EXL launchpad and CCS version 7.4

  • Sahil
    It doesnt capture any interrupt till I send the 8th character. As it receives the 8th character it services the interrupt handler ISR and returns back sucessfully

    Inside the UARTStdioConfig() function there is the following conditionally compiled code:

    #ifdef UART_BUFFERED
        //
        // Set the UART to interrupt whenever the TX FIFO is almost empty or
        // when any character is received.
        //
        MAP_UARTFIFOLevelSet(g_ui32Base, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
    
        //
        // Flush both the buffers.
        //
        UARTFlushRx();
        UARTFlushTx(true);
    
        //
        // Remember which interrupt we are dealing with.
        //
        g_ui32PortNum = ui32PortNum;
    
        //
        // We are configured for buffered output so enable the master interrupt
        // for this UART and the receive interrupts.  We don't actually enable the
        // transmit interrupt in the UART itself until some data has been placed
        // in the transmit buffer.
        //
        MAP_UARTIntDisable(g_ui32Base, 0xFFFFFFFF);
        MAP_UARTIntEnable(g_ui32Base, UART_INT_RX | UART_INT_RT);
        MAP_IntEnable(g_ui32UARTInt[ui32PortNum]);
    #endif

    In your main function the call to UARTConfigSetExpClk() is commented out, and instead UARTStdioConfig() is being called to configure UART0. If UART_BUFFERED is defined when the Tivaware uartstudio.c utility which contains UARTConfigSetExpClk() is compiled, then UARTConfigSetExpClk() will enable the UART FIFO to only interrupt once 8 characters have been received, which could explain your first problem. Not sure if that also explains the second problem.

  • In reply to Chester Gillon:

    Hi
    Thank you for your reply.

    The problem is if I comment out UARTStudionConfig () and instead use UARTConfigSetExpClk(). I can no more use UARTprintf() as it hangs. So I had to use it unless you can suggest an alternative?

  • In reply to Chester Gillon:

    Chester Gillon
    In your main function the call to UARTConfigSetExpClk() is commented out, and instead UARTStdioConfig() is being called to configure UART0. If UART_BUFFERED is defined when the Tivaware uartstudio.c utility which contains UARTConfigSetExpClk() is compiled, then UARTConfigSetExpClk() will enable the UART FIFO to only interrupt once 8 characters have been received

    Oops, I didn't read the code in the UARTConfigSetExpClk() function correctly which means my previous suggestion is wrong. On further inspection:

    a) When compiled with UART_BUFFERED defined, UARTConfigSetExpClk() enables the RX/TX FIFOs (via a call to MAP_UARTEnable) and sets the UART to interrupt when any character is received (via a call to MAP_UARTFIFOLevelSet).

    b) When compiled with UART_BUFFERED NOT defined,UARTConfigSetExpClk() enables the RX/TX FIFOs (via a call to MAP_UARTEnable) but leaves the RXIFLSEL field in the UART Interrupt FIFO Level Select (UARTIFLS) register at its default value which means a receive interrupt will only be asserted when the RX FIFO is >= 1/2 full (i.e. after 8 characters have been received).

    Sahil
    However I am facing two weird problems i.e;
    1. It doesnt capture any interrupt till I send the 8th character. As it receives the 8th character it services the interrupt handler ISR and returns back sucessfully
    2. It services the interrupt only once and never interrupts again no matter how many charter I send.

    I think the first problem is explained by b) above. In which case try adding the following to your main function before the call to UARTConfigSetExpClk():

        //
        // Set the UART to interrupt whenever the TX FIFO is almost empty or
        // when any character is received.
        //
        MAP_UARTFIFOLevelSet(g_ui32Base, UART_FIFO_TX1_8, UART_FIFO_RX1_8);

    I think the second problem is because the UART0ISR() interrupt handler doesn't read any receive characters. The data sheet description of the UARTIFLS register contains:

    The interrupts are generated based on a transition through a level rather than being based on the level. That is, the interrupts are generated when the fill level progresses through the trigger level. For example, if the receive trigger level is set to the half-way mark, the interrupt is triggered as the module is receiving the 9th character.

    Therefore, if no receive characters are read from the receive FIFO then don't think the receive interrupt will ever be re-raised.

  • In reply to Chester Gillon:

    Chester Gillon
    The interrupts are generated based on a transition through a level rather than being based on the level. That is, the interrupts are generated when the fill level progresses through the trigger level. For example, if the receive trigger level is set to the half-way mark, the interrupt is triggered as the module is receiving the 9th character.

  • In reply to Chester Gillon:

    Hi,

    Just tried what you mentioned by adding the line before UARTStdioConfig() as follows;
    What happens is it calls the handler after i send two characters and never calls again any more.

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //UARTConfigSetExpClk(UART0_BASE, output_clock_rate_hz, 115200,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    UARTEnable(UART0_BASE);

    UARTIntEnable(UART0_BASE, UART_INT_RX); //only enable RX interrupts
    //IntRegister(INT_UART0, UART0ISR);

    IntEnable(INT_UART0); //enable the UART interrupt
    IntMasterEnable(); //enable processor interrupts

    MAP_UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8);

    UARTStdioConfig(0, 115200, SYSTEM_CLOCK);

  • In reply to Sahil:

    Sahil
    What happens is it calls the handler after i send two characters and never calls again any more.

    As mentioned above, does the handler read any receive characters from the UART?

  • In reply to Chester Gillon:

    Hi,

    The handler clears the interrupt flag but doesnt read the buffer itself.

    Do you think it should read the buffer i.e. copying it to another buffer or please tell me how to accomplish that?

    Thanks

  • In reply to Sahil:

    Here is the handler code for UART0 ISR.

    void UART0_ISR(void) { UARTprintf("UART0_ISR called..!\n\r"); //UARTCharPut(UART0_BASE, 't'); delay_clocks(20000); UARTIntClear(UART0_BASE,UART_INT_RX); }

    Please clarify what do you mean by reading the buffer as I dont undterstand how will it then clears the interrupt OR please share how to accomplish it.

    Thanks

  • In reply to Sahil:

    Have you read the microprocessor or TIVAWare user manuals yet? I would suggest at least a quick review of the pertinent sections in both.

    You could also check the #bookshelf tag. I believe there is a reference to a book on serial communications there.

    Robert