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.

  • 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.

  • In reply to Robert Adsett:

    Hello Robert,

    Thank you for your suggestion.

    I changed the handler such that it reads the buffer and it worked.

    Now the handler gets called each time I send a character, however the only problem is at startup, as I reset the processor, the first time i have to send two characters to get the handler called.

    void UART0ISR(void)
    {
    
        UARTCharGetNonBlocking(UART0_BASE);
        UARTIntClear(UART0_BASE, UART_INT_RX);
        UARTprintf("UART0ISR called..!\n\r");
        delay_clocks(900000);
    
        //UARTsendString("UART0ISR called..!\n\r");
    }

  • In reply to Chester Gillon:

    So i tried to see which character triggers the handler and it turned out that the handler is called on the previous character. 

    The code is;

    void UART0ISR(void)
    {
    
        UARTprintf("\n%c\n",UARTCharGetNonBlocking(UART0_BASE));
        UARTIntClear(UART0_BASE, UART_INT_RX);
        UARTprintf("UART0ISR called..!\n\r");
        delay_clocks(900000);
    
        //UARTsendString("UART0ISR called..!\n\r");
    }

    for example if I press "a" and then "b" and then "c" 

    On pressing "b" the handler (above) will print the previous character "a", and pressing "c", it prints the previous character "b" and so on...

     

    Please keep in mind I reading the buffer at the initialization time so to remove if there is any character etc. As shown in the following;

        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);
        delay_clocks(2);
        UARTCharGetNonBlocking(UART0_BASE);

    Looks like the it acknowledges buffer is flow and serves the ISR ONLY when called the next time ??

  • In reply to Sahil:

    Sahil

    So i tried to see which character triggers the handler and it turned out that the handler is called on the previous character. 

    The code is;

    void UART0ISR(void)
    {
    
        UARTprintf("\n%c\n",UARTCharGetNonBlocking(UART0_BASE));
        UARTIntClear(UART0_BASE, UART_INT_RX);
        UARTprintf("UART0ISR called..!\n\r");
        delay_clocks(900000);
    
        //UARTsendString("UART0ISR called..!\n\r");
    }

    for example if I press "a" and then "b" and then "c" 

    On pressing "b" the handler (above) will print the previous character "a", and pressing "c", it prints the previous character "b" and so on...

    You are misinterpreting what you are seeing.

    The interrupt occurs when the FIFO threshold is crossed. In your case when b is pressed. At that point there are two characters in the FIFO to be read (you should read until the FIFO is empty).

    You are also probably not monitoring both the receive interrupts. There is the FIFO interrupt which you are responding to. In addition you should turn on the receive time out interrupt (RTI I think). This will provide an interrupt when a character has been received into the FIFO but the FIFO has not filled past the threshold and no further character has been received within a time period. You should treat both sources in exactly the same fashion: read the FIFO until it is empty.

    Robert

    One final note: those prints and delay in the ISR are a very bad idea.

  • In reply to Robert Adsett:

    Agree to your final note, the delay and prints are only at the time of code development to make it working... Later I want to use the handler only to capture the received byte and store it in my own defined string array buffer for further manipulation. However I can do so only once I make the code working.

    Isnt there a way that I get interrupt only when i receive one byte. I would rather avoid the time out idea unless that is the only way to make it work ?

    Thanks

  • In reply to Sahil:

    Hello Robert,

    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT); //only enable RX FIFO and RX TimeOut interrupts

    Added the above modification as you suggested. It is working fine now. You can ignore the previous silly question as well :P

    Thank you for your help.

    Thank you all for your time and assistance.

  • In reply to Sahil:

    The previous question isn't silly, just missing a point about the FIFO. If you disable the FIFO then there is no buffering and every received character will generate an interrupt.

    The reason FIFOs are added is two fold, first to reduce the number of interrupts (and associated overhead) and second to increase the amount of CPU time you have before you have a character overrun if you don't respond to an interrupt.

    Robert
  • In reply to Robert Adsett:

    Yes It is very useful feature so to reduce the cpu interruption frequency this way. I may implement to make use of it later.
    Thank you, wishing you a happy year...

  • In reply to Sahil:

    May it be noted that "Robert's post" of "2:49 today" is the one which, "Resolved your issue?"

    His writing - now quoted, "You are also probably not monitoring both the receive interrupts," clearly  led to your success!      Alas - Robert's guiding post "sits unawarded"  - while your post -  simply following Robert's direction - is the one awarded, "This post resolved."     (which it clearly - did not - it was "derivative" at best...)

    It is quite easy for you to award the (proper) "This post Resolved" to Robert's post - as identified herein.     (your "self-award" will remain - once "granted" - those "awards" cannot be negated...)

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.