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.

UART Fifo Transmit Interrupt

I am trying to implement UART Transmit Interrupt in FIFO mode at 1/8 level.

My understanding is since level is set at 1/8, it means at every (1/8)x16bytes = 2 bytes, interrupt is generated.

My code for above is given below:

static uint8_t FIFOCount;

 

//UART Handler ----------------------

void UARTIntHandler(void)

{

    uint32_t ui32Status;

 

    //

    // Get the interrrupt status.

    //

    ui32Status = UARTIntStatus(UART0_BASE, true);

 

    //

    // Clear the asserted interrupts.

    //

    UARTIntClear(UART0_BASE, ui32Status);

 

    if(ui32Status & UART_INT_TX) {

       FIFOCount++; //Add

    }

}

//End of UART Handler -------------------------

 

//--------------------------------------------

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

        //

//        if(UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++));

//        else {

//            //clear Tx FIFO

//            UARTDisable(UART0_BASE);

//            UARTEnable(UART0_BASE);

//            UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++);

//

//        }

       UARTCharPut(UART0_BASE, *pui8Buffer++);

    }

}

 

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

int

main(void)

{

unsigned char TxBuffer[80] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-!@#$0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-!"; //80

    ROM_FPULazyStackingEnable();

 

    // Set the clocking to run directly from the crystal.

    ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

 

    // Enable the peripherals used by this example.

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

 

    // Enable processor interrupts.

    ROM_IntMasterEnable();

 

    // Set GPIO A0 and A1 as UART pins.

    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

 

    // Configure the UART for 115,200, 8-N-1 operation.

    ROM_UARTConfigSetExpClk(UART0_BASE, ROM_SysCtlClockGet(), 115200,

                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |

                             UART_CONFIG_PAR_NONE));

 

    // Enable the UART interrupt.

    //

    UARTDisable(UART0_BASE);

    UARTFIFODisable(UART0_BASE);

    ROM_IntEnable(INT_UART0);

    UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8); //Add

 

    UARTTxIntModeSet(UART0_BASE, UART_TXINT_MODE_FIFO);

 

    UARTIntEnable(UART0_BASE, UART_INT_TX | UART_INT_RX); //Add

 

    UARTEnable(UART0_BASE);

    UARTFIFOEnable(UART0_BASE); //Add

 

    UARTSend((uint8_t *)TxBuffer, 70);

    UARTSend((uint8_t *)FIFOCount, 1);

 

    while(1);

}

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

/************ END OF CODE **********************/

The issue is I am not getting interrupt after the desired 2 bytes in FIFO.

The FIFOCount is 4 incase I transmit 80 chars and 2 in case if I transmit 35 characters.

I am not sure where I am going wrong. Help needed seriously.

-blueshift

  • Hi Blueshift,

    As per the data sheet, the Interrupt is generated when the Number of Bytes in the FIFO crosses the limit. Thus on the transmit side you need to write 3 bytes for the FIFO to start triggering

    Regards

    Amit

  • Hi Amit.
    Thanks for correcting. As per code below, I have set Interrupt on FIFO at 1/8 level.

        UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8); //Add
        UARTTxIntModeSet(UART0_BASE, UART_TXINT_MODE_FIFO);
        UARTIntEnable(UART0_BASE, UART_INT_TX | UART_INT_RX); //Add

    I am sending 35 bytes for transmission. I m still not getting interrupt after 3 bytes. It is giving interrupt after the FIFO overflows.. i.e. after 16 bytes.

    Not sure at what step I m getting wrong. I m using Tiva C TM4C123 Dev board.
  • Hi blueshift,

    The UART module is enabled, so while the code is writing to it, the same is being transmitted as well. There is no FIFO Overflow bit in UART on TX side. Can you check of the UART_0_CTL.EOT bit is clear.

    Regards

    Amit

  • Hi Blueshift

    Apologies for the confusion. On the TX FIFO for 1/8 setting the interrupt shall be fired when there are at least 2 empty spaces. Hence you would need to write 16 bytes first before the interrupt shall come.

    Regards

    Amit

  • Amit,

    I m now having the following sequence of UART initialization.

    ROM_IntMasterDisable();
    UARTDisable(UART0_BASE);
    UARTFIFODisable(UART0_BASE);

    UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8); //Add

    UARTTxIntModeSet(UART0_BASE, UART_TXINT_MODE_FIFO);

    ROM_UARTConfigSetExpClk(UART0_BASE, ROM_SysCtlClockGet(), 115200,
    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    UART_CONFIG_PAR_NONE));

    // Enable processor interrupts.
    ROM_IntMasterEnable();//
    // Enable the UART interrupt.
    ROM_IntEnable(INT_UART0);

    UARTIntEnable(UART0_BASE, UART_INT_TX);
    UARTEnable(UART0_BASE);
    UARTFIFOEnable(UART0_BASE); 

    DELAYMS(5);

    After this, I send my transmit bytes. I checked the EOT bit and it is 0. If I send either 15, 16 or 17 bytes, I get Interrupt after those bytes that means it is giving interrupt after EOT, isn't it?

     

  • Amit,

    We are transmitting data byte by byte. If I have to transmit total 16 bytes, then after first 14 bytes are written, I should get Interrupt, shouldn't I? 

    I am still not getting this. What exactly is the usage of triggering levels at FIFO? When it is ideally used?

  • Hello Blueshift,

    For the interrupt to fire, the threshold has to be first crossed and not just reached.

    Secondly the transmitter is enabled. hence as soon as you write the first byte the transmission would begin. Hence by the time you write the 14th byte, the actual FIFO level would be lower than 14 (based on the baud rate and write to the FIFO)

    The FIFO threshold is more important from uDMA persepctive as uDMA does not check FIFO levels but only transfers X amount of bytes from mem to peripheral (or vice-versa). So the trigger at which the DMA is triggered must match the number of bytes to be written so that overflow does not occur

    Regards

    Amit

  • Amit, thanks for clarifying further. You are right. As transmitter is already enabled it starts as soon as I send values to FIFO. 

    I intend to use FIFO interrupts. If I keep Transmitter disabled, will I be able to put values in 16-byte FIFO by sending bytes to UART Data Register as in function UARTSend() above? What I plan is, I fill the FIFO with Tx disabled. Then as soon as FIFO is filled to a level set, it will give interrupt. In that Interrupt Service routine, UART Tx is enabled and so the bytes in the FIFO are transmitted.

    Is my approach correct? My intention is to keep load on the transmit process low as possible.

    -----------------------

    Another hellp with normal Transmission without using FIFO. I want to have interrupt after every 1 byte sent. I read after EOT is detected, it gives interrupt. But through UARTSend() function, I m getting Interrupt after complete transmission. Please help.

  • Hi blueshift,

    Yes, that should be possible. But since you plan to use the FIFO to send large chunks of data, wouldn't it be more efficient to use the DMA. That will really keep the load on transmit process very load

    Please note that the UART Configuration by default enables the FIFO. I think it is the UARTEnable Function. So you have to have a function which does not enable the FIFO.

    Regards

    Amit

  • Yes. I had analyzed that UARTConfigSet() function. I will have to write my own fucntion disabling the UART.

  • I know this discussion was a long time ago, but I have some questions.

    how do I use the fifo correctelly?
    Based on your code, I wrote this one.

    I can count how many times the fifo interruption was called, but every 16bytes, the uart finishes the communication.

    In my case, Im using the uart0 to the terminal and the uart1 with the serial to usb board.

    It is really hard for me to figure out this alone.

    Thank you!

    Thiago


    //********************************************************************
    //-----------------------------VARIABLES------------------------------
    //********************************************************************

    volatile uint8_t input[] = "Teste";
    volatile uint8_t output[256];
    volatile uint32_t FIFOCount =0;
    //********************************************************************
    //------------------------FUNCTION PROTOTYPES-------------------------
    //********************************************************************
    void ConfigureUART0(void);
    void ConfigureUART1(void);
    void UART1IntHandler(void);
    void UART0IntHandler(void);
    void UART_Transmit(uint32_t ui32UARTBase, const uint8_t *pui8Buffer);


    //********************************************************************
    //-----------------------------INT MAIN-------------------------------
    //********************************************************************
    int main(void)
    {


    //
    // Set the clocking to run at 20 MHz (200 MHz / 10) using the PLL.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);

    // Configure the LED as an output and turn it on.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1);

    //
    // Set up the serial console to use for displaying messages.
    //
    ConfigureUART0();

    //
    //Initilize the Uart port to communicate with the XBee radio at port B0 and B1
    //
    ConfigureUART1();
    //
    //Enable interrupts to the processor
    //
    IntMasterEnable();
    //UART_Transmit(UART0_BASE, (uint8_t *)"\n 7E000F1001000000000000FFFFFFFE0000549F\0");
    //UART_Transmit(UART1_BASE, (uint8_t *)"7E 00 141001000000000000FFFFFFFE000054686961676F97\0");
    UART_Transmit(UART1_BASE, (uint8_t *)"7E00141001000000000000FFFFFFFE000054686961676F97\0");

    while(1)
    {
    UART_Transmit(UART1_BASE, (uint8_t *)"7E00141001000000000000FFFFFFFE000054686961676F97\0");
    while(UARTBusy(UART1_BASE));

    UART_Transmit(UART0_BASE, (uint8_t *)"7E00141001000000000000FFFFFFFE000054686961676F97\0");
    while(UARTBusy(UART0_BASE));
    SysCtlDelay(SysCtlClockGet() / 12);
    }
    }

    //*******************************************************************************
    //-----------------------CONFIGURATION FUNCTIONS---------------------------------
    //*******************************************************************************

    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void ConfigureUART0(void)
    {
    //
    // Enable GPIO port A which is used for UART0 pins.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Enable UART0
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    //
    // Configure GPIO Pins for UART1 mode.
    //
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Use the internal 16MHz oscillator as the UART clock source.
    // Initialize the UART for console I/O.
    //
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));


    UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8); //Add

    UARTTxIntModeSet(UART0_BASE, UART_TXINT_MODE_FIFO);

    IntEnable(INT_UART0); //enable the UART interrupt
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT | UART_INT_TX); //only enable RX and TX interrupts
    UARTFIFOEnable(UART0_BASE);
    }

    //*****************************************************************************
    // Configure the UART1 and pins PB0 - PB1
    // This UART1 is used for the XBee Radio
    //*****************************************************************************
    void ConfigureUART1(void)
    {
    //
    // Enable the GPIO Peripheral used by the UART1.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    //
    // Enable UART1
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);

    //
    // Configure GPIO Pins for UART1 mode.
    //
    GPIOPinConfigure(GPIO_PB0_U1RX);
    GPIOPinConfigure(GPIO_PB1_U1TX);
    GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Use the internal 16MHz oscillator as the UART clock source.
    // Initialize the UART for console I/O.
    //
    UARTConfigSetExpClk(UART1_BASE, SysCtlClockGet(), 115200,
    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

    // IntMasterEnable(); //enable processor interrupts
    IntEnable(INT_UART1); //enable the UART interrupt
    UARTIntEnable(UART1_BASE, UART_INT_RX | UART_INT_RT); //only enable RX and TX interrupts

    }



    //*******************************************************************************
    //-----------------------INTERRUPTION FUNCTIONS----------------------------------
    //*******************************************************************************


    // to receive from uart1
    void UART0IntHandler(void)
    {
    uint32_t ui32Status, i;

    ui32Status = UARTIntStatus(UART0_BASE, true); //get interrupt status

    UARTIntClear(UART0_BASE, ui32Status); //clear the asserted interrupts

    if(ui32Status & UART_INT_TX) {

    FIFOCount++; //Add

    }

    // ui32Bytes = ui32UartMessage;
    i = 0;


    while(UARTCharsAvail(UART0_BASE)) //loop while there are chars
    {
    input[i++]= UARTCharGet(UART0_BASE);

    }
    }

    // to receive from uart1
    void UART1IntHandler(void)
    {
    uint32_t ui32Status, i;

    ui32Status = UARTIntStatus(UART1_BASE, true); //get interrupt status

    UARTIntClear(UART1_BASE, ui32Status); //clear the asserted interrupts
    i = 0;

    while(UARTCharsAvail(UART1_BASE)) //loop while there are chars
    {
    //output[i++]= UARTCharGet(UART1_BASE);
    UARTCharPut(UART0_BASE, UARTCharGet(UART1_BASE)); //echo character


    }
    }

    void UART_Transmit(uint32_t ui32UARTBase, const uint8_t *pui8Buffer)
    {
    //
    // Loop while there are more characters to send.
    //
    while(*pui8Buffer != '\0')
    {
    //
    // Write the next character to the UART.
    //
    UARTCharPut(ui32UARTBase, *pui8Buffer++);
    }
    }