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.

EK-TM4C1294XL: UART : Using interruptions

Part Number: EK-TM4C1294XL

Hi, friends, I'm trying to use the interruption feature of my TM4C1294Xl using UART. In few words, I want to turn on an led, using an ISR , after sending a char.

#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/gpio.h"


/*Global Variables */
uint32_t g_ui32SysClock;

void UART7Isr(void);

int main(void)
{

    /* Set the clocking to run at 120MHz */
    g_ui32SysClock= SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                        SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                        SYSCTL_CFG_VCO_480), 120000000);

    char my_char = 'J';

    
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); 
    GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);
    GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0x00);

    /*Initialize GPIOC for UART*/
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    /*Enabling UART7*/
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART7);

    /*Configuring GPIO pins for port C*/
    GPIOPinConfigure(GPIO_PC4_U7RX);
    GPIOPinConfigure(GPIO_PC5_U7TX);

    /*Setting up GPIOC pins for UART function */
    GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5);

    /*Setting UART7 configurations*/
    UARTConfigSetExpClk(UART7_BASE,g_ui32SysClock,19200,
        (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

    IntMasterEnable();

    UARTIntEnable(UART7_BASE, UART_INT_TX);

    UARTIntRegister(UART7_BASE, UART7Isr);

    UARTCharPutNonBlocking(UART7_BASE, my_char);

    return 0;


}

void UART7Isr(void){
    UARTIntClear(UART7_BASE, UART_INT_TX);
    GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, GPIO_PIN_1);
}

Until now, the led is not turning on.

  • let your code loop around.
  • Unfortunately, that didn't solve the problem
  • Jamelly Ferreira said:
    UARTIntRegister(UART7_BASE, UART7Isr); UARTCharPutNonBlocking(UART7_BASE, my_char); return 0; }

    Consider what happens when UARTCharPutNonBlocking returns.

    Robert

  • "Unfortunately, that didn't solve the problem"

    however big a step it was, it wasn't meant to get you fully to your destination. debugging is a long and joyful journey. so enjoy it.
  • Jamelly,

    First, a suggestion: do not use "return 0", but rather, add a while(1){} at that location. It will allow you to visualize all the registers and variables in your debugger while retaining their state.

    Now, as for the UART TX interrupt, here is the "rule", taken from the datasheet:

    "Transmit (when condition defined in the TXIFLSEL bit in the UARTIFLS register is met, or if the EOT bit in UARTCTL is set, when the last bit of all transmitted data leaves the serializer)"

    There are a couple of things that can go wrong in your program (as in "not make your led turn on"):
    - The program certainly reaches "return 0" long before the UART character leaves the HW FIFO, preventing the interrupt to ever trigger.
    - Your EOL bit is probably not set, hence there is no interrupt expected when the Tx HW buffer becomes empty

    The default use of a TX interrupt is to let the program know that there is "some more space available in the FIFO buffer", not to inform that "the last byte has been sent". Let's say you configure your TX buffer level to 1/8 (that's two bytes out of the 16 that fit the full FIFO). The interrupt instant is when the FIFO counter comes down from "3 pending bytes" to "2 pending bytes" - which will never happen if you just put one byte there!

    Bruno
  • The ops code is too far from working. The general work flow is to clear the flag, enable the interrupt and load up the first char, and advance to the next char. Transmission will start here.

    In the isr, you have to detect if the current char is eol - I typically use 0. If not, load up the current char, and advance to the next.

    If yes, turn off the interrupt.

    You may want to introduce flags so you know if the module is being used or if the transmission has ended.

  • Hi Jamelly,

      Like Bruno said, you only put out one char which never triggers the FIFO interrupt. By default, the FIFO transmit interrupt level is < 1/2 empty. You will need to have 9 -> 8 transition to trigger the interrupt. You can try one the below three options to see your code go into the ISR and set the LED.

      1. Call UARTCharPutNonBlocking() at least 9 times.

      2. Disable FIFO by calling UARTFIFODisable(UART7_BASE).

      3. Call UARTTxIntModeSet(UART7_BASE, UART_TXINT_MODE_EOT)

    Any one of the above should work.

  • Bruno's description of the uart tx interrupt is almost certainly incorrect. Assuming the tx buffer level is set correctly, writtting one char to the transmit buffer will trigger the uart tx isr.

    The work flow I outlined earlier has been tested on various chips, from LM3S, tm4c to other chips.
  • Danny and readers,

    For future reference, be informed that my description posted at XX:39 above is ABSOLUTELY CORRECT. If you read again, you will note that the given example even mentions a setting of the tx level trigger.

    If you refer to the text of your message posted at XX:58 as a "workflow", I unfortunately fail on being able to read those sentences as a logical sequence of programming actions. And they appear to suggest turning off an interrupt inside the very ISR, which would not be my choice of strategy for any interrupts... Maybe you'd like to rewrite your message in a more "visually structured text" so that something which is obvious in your mind can also be understood by us...

    Regards
  • Danny F said:
    Bruno's description of the uart tx interrupt is almost certainly incorrect. Assuming the tx buffer level is set correctly, writtting one char to the transmit buffer will trigger the uart tx isr.

    Nope, Bruno is correct. The UART provides an interrupt on crossing the FIFO threshold. It does not simultaneously support an interrupt on FIFO empty.

    TM4C129 User Manual said:

    End of Transmission This bit determines the behavior of the TXRIS bit in the UARTRIS register.
    Value  Description 

    • 0 The TXRIS bit is set when the transmit FIFO condition specified in UARTIFLS is met.
    • 1 The TXRIS bit is set only after all transmitted data, including stop bits, have cleared the serializer

    So putting one character into the UART FIFO will not result in a transmit interrupt unless you change the interrupt to transmitter empty instead of FIFO threshold crossed. The latter is the default however.

    Robert

  • It is easy to resolve this, just ask yourself two questions.

    1. Under what conditions is the tx flag set?

    2. When you put a char into the fifo, are those conditions met?

    The datasheet has the answers.

    If that's not enough to convince you, maybe you can write a piece of code to show the devices actual behavior?
  • Danny F said:
    It is easy to resolve this, just ask yourself two questions.

    1. Under what conditions is the tx flag set?

    When the Transmit FIFO level crosses the threshold

    Danny F said:
    2. When you put a char into the fifo, are those conditions met?

    No

    Danny F said:
    The datasheet has the answers.

    Yes it does. It matches my answers, although it's less clear than would be useful.

    Danny F said:
    If that's not enough to convince you, maybe you can write a piece of code to show the devices actual behavior?

    It's a fairly frequent question so I can show you other's code already presented to the Forum along with TI's affirmation that it's an issue. See the following thread

    e2e.ti.com/.../321856 transmit interrupt

    Robert

  • Back to the OP.

    Here is an interrupt driven tx routine implemented on pic24.

    It has it's origin I. LM3S work.

    The lm4f120 implementation on driverlib is here.

    Aside from the use of driverlib in the lm4f version, the two isra have identical logic -well, almost as the lm4f version is designed to send the trailing zero and the pic24 version not.

    The same logic can be implemented on other chips or in different flavors: I have one for the lm4f that's built on cmsis structs for example.

    Hope it helps.