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.

LM4F120: UART1/2

Hi together,

 
I am trying to get UART working on my Stellaris Launchpad (LM4F120H5QR) using the onboard PIN headers (UART1/2) instead of the USB cable (UART0). This is how my code looks like (based on uart_echo from StellarisWare). I am using a FOCA tiny break-out board (integrating a FT232 IC) to receive the data on my terminal software. Currently, I am trying to set up UART1 and GPIOB (PB0 / PB1). However, I do not receive anything on my temrinal software, while using the standard uart_echo code for UART0 it works properly.
 
Can somebody tell me what I am missing? If this works, I am getting closer to my actual goal, which is enabling and using UART1/2 in ASM.
 
Best regards

uart_echo.c

uart_echo.c 
int main(void)
{
    //
    // Enable lazy stacking for interrupt handlers.  This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    //
    ROM_FPUEnable();
    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 GPIO port that is used for the on-board LED.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    //
    // Enable the GPIO pins for the LED (PF2).  
    //
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);

 
		//
    // Enable the peripherals used by this example.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

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

    //
    // Set GPIO A0 and A1 as UART pins.
    //
    GPIOPinConfigure(GPIO_PB0_U1RX);
    GPIOPinConfigure(GPIO_PB1_U1TX);
    ROM_GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Configure the UART for 115,200, 8-N-1 operation.
    //
    ROM_UARTConfigSetExpClk(UART1_BASE, ROM_SysCtlClockGet(), 115200,
                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                             UART_CONFIG_PAR_NONE));

    //
    // Enable the UART interrupt.
    //
    ROM_IntEnable(INT_UART1);
    ROM_UARTIntEnable(UART1_BASE, UART_INT_RX | UART_INT_RT);

    //
    // Loop forever echoing data through the UART.
    //
    while(1)
    {
				UARTSend((unsigned char *)"Hello World!\n", 13);
    }
} 

And I changed the corresponding values in the Startup file to the following values:

startup_rvmdk.S

...
...
DCD     IntDefaultHandler           ; The PendSV handler
DCD     IntDefaultHandler           ; The SysTick handler
DCD     IntDefaultHandler           ; GPIO Port A
DCD     IntDefaultHandler           ; GPIO Port B
DCD     IntDefaultHandler           ; GPIO Port C
DCD     IntDefaultHandler           ; GPIO Port D
DCD     IntDefaultHandler           ; GPIO Port E
;DCD     UARTIntHandler             ; COMMENTED OUT ... UART0 Rx and Tx
;DCD     IntDefaultHandler          ; COMMENTED OUT ... UART1 Rx and Tx
DCD     IntDefaultHandler           ; UART0 Rx and Tx
DCD     UARTIntHandler              ; UART1 Rx and Tx
  • Hi,

        Did you modify UARTSend() as UART1? See, below.

    void
    UARTSend(const unsigned char *pucBuffer, unsigned long ulCount)
    {
        //
        // Loop while there are more characters to send.
        //
        while(ulCount--)
        {
            //
            // Write the next character to the UART.
            //
            ROM_UARTCharPutNonBlocking(UART0_BASE, *pucBuffer++);
        }
    }

    -kel

  • Two contradictory claims in your post:

    • Currently, I am trying to set up UART1 and GPIOB (PB0 / PB1).
    • … while using the standard uart_echo code for UART1 it works properly.

    Is it real or you mixed the names UART0 and UART1? either do not work at all (first claim), either work OK (second claim).

    I did not used FOCA board, but two question/suggestion:
    a) can you send from PC to FOCA board and use an oscilloscope to verify TX pin is working? (i.e. this board is fully transparent and do not need some other preliminary settings).
    b) did you cross-connected the pins for the UART? (i.e FOCA's TX is connected to launchpad's RX?)

    Petrei
  • @Markel: Yes, I did so.

    @ Petrei: Indeed, this was a mistake. I meant: Currently, I do receive correct characters over UART0. I will change it in the original post.

  • I've not tried running it but nothing in your code looks obviously wrong to me assuming you changed UARTSend to use the correct base address. As Petrei suggested, I would take a look with an oscilloscope to see if you are getting the expected signals on the RX and TX pins of the board to make sure there are no bad connections.

  • Note one thing - perhaps over-looked by earlier, others.  UART1 is unque, the most complete (i.e. offers U1RTS & U1CTS) of all such MCU UARTS.  (at least such is the case for our more capable, LX4F231 MCU {not on lunchpad})

    Should this extra capability hold true (your MCU) - and should either of those "extra UART pins" default "active" - and should "fate have conspired - via your board signal/level routing") - your UART1 operation may be gated off.

    Review of the MCU manual - especially the role/enabling of these "special UART pins" - may prove worthwhile.  (this purely a swag - based upon earlier, "facts in evidence.")

    Update: 15:05 CST - others have noted difficulty in harvesting PB0/PB1 as UART1 - your board.  Suggest that you switch to PE0/PE1 (Uart7 - our MCU) or PC4/PC5 (Uart4 - our MCU) as these route to headers & others report success...

  • I was able to enable UART3 using the code below (based on the StellarisWare uart_echo example), However, the output is disordered, byte-wise.

    @cb1_mobile: thanks for pointing out that uart7 might be preferable over the other uarts. I only read about uart2 being special because it has the be unlocked first.

    I will try configuring UART7 next. 

    Slowly I am approaching my goal of enabling UART in ASM.

    #include "test.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_gpio.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include <stdint.h>
    #include <stdbool.h>
    #include <stdint.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.
    //
    //*****************************************************************************
    
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, unsigned long ulLine)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    // The UART interrupt handler.
    //
    //*****************************************************************************
    void
    UARTIntHandler(void)
    {
        unsigned long ulStatus;
    
        //
        // Get the interrrupt status.
        //
        ulStatus = ROM_UARTIntStatus(UART3_BASE, true);
    
        //
        // Clear the asserted interrupts.
        //
        ROM_UARTIntClear(UART3_BASE, ulStatus);
    
        //
        // Loop while there are characters in the receive FIFO.
        //
        while(ROM_UARTCharsAvail(UART3_BASE))
        {
            //
            // Read the next character from the UART and write it back to the UART.
            //
            ROM_UARTCharPutNonBlocking(UART3_BASE,
                                       ROM_UARTCharGetNonBlocking(UART3_BASE));
            
            //
            // Blink the LED to show a character transfer is occuring.
            //
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
            
            //
            // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
            //
            SysCtlDelay(SysCtlClockGet() / (1000 * 3));
            
            //
            // Turn off the LED
            //
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
            
        }
    }
    
    //*****************************************************************************
    //
    // Send a string to the UART.
    //
    //*****************************************************************************
    void
    UARTSend(const unsigned char *pucBuffer, unsigned long ulCount)
    {
        //
        // Loop while there are more characters to send.
        //
        while(ulCount--)
        {
            //
            // Write the next character to the UART.
            //
            ROM_UARTCharPutNonBlocking(UART3_BASE, *pucBuffer++);
        }
    }
    
    //*****************************************************************************
    //
    // This example demonstrates how to send a string of data to the UART.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // Enable lazy stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        ROM_FPUEnable();
        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 GPIO port that is used for the on-board LED.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
        //
        // Enable the GPIO pins for the LED (PF2).  
        //
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
    
        
    		
    		//
        // Enable the peripherals used by this example.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART3);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    
        //
        // Enable processor interrupts.
        //
        ROM_IntMasterEnable();
    
        //
        // Set GPIO A0 and A1 as UART pins.
        //
        GPIOPinConfigure(GPIO_PC6_U3RX);
        GPIOPinConfigure(GPIO_PC7_U3TX);
        ROM_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_6 | GPIO_PIN_7);
    
        //
        // Configure the UART for 115,200, 8-N-1 operation.
        //
        ROM_UARTConfigSetExpClk(UART3_BASE, ROM_SysCtlClockGet(), 115200,
                                (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                 UART_CONFIG_PAR_NONE));
    
        //
        // Enable the UART interrupt.
        //
        ROM_IntEnable(INT_UART3);
        ROM_UARTIntEnable(UART3_BASE, UART_INT_RX | UART_INT_RT);
    
    
    
        //
        // Prompt for text to be entered.
        //
        //UARTSend((unsigned char *)"\033[2JEnter text: ", 16);
    
        //
        // Loop forever echoing data through the UART.
        //
        while(1)
        {
    				UARTSend((unsigned char *)"Hello World!\n", 13);
        }
    }
  • Hi,

    However, the output is disordered, byte-wise.

    Can you illustrate this? What type of data do you receive/send?

    Also, did you realized you access your UART from two different points (interrupt and while(1)) without any correlation/blocking between them? 

    Petrei

  • Believe friend Petrei makes a good point.  (illustration helpful)

    May I suggest that prior to your ASM-Only "goal" - you briefly surrender to plain vanilla C - so that you can establish that your targeted UART successfully makes it to board edge - and then onto your terminal?  This eliminates any board, routing or speed/flow control gremlins from the mix.  (and - by glance @ the disassembly - reveals key register interactions & proper sequence)

  • Hi,

    the output of the "Hello World!\n" inside the while-loop is as follows:

    lrHodeW!lrHolH !lo
    llH deo
    lrH deW
    lrHolHW!loHolH !lo
    llH deW
    lrHodeW!lrHolHW!loHllH deo
    lrH deW
    lrHodHW!loHolH !lo
    llH deo
    lrHodeW!lrHolHW!loHolH !eo
    lrH deW
    lrHodeW!lrHolH !lo
    llH deo

    However, I modified the code to remove the interrupt and use uart7 instead (see code below). This solutions gives a clean and correct output.

    I guess this is a good starting point to look at the dissassembly for starting the work on the ASM code. Actually I already have a reference on using UART0 with ASM, however I want to use the PIN headers. I guess, simply replaceing the offsets form this reference to uart7 and portf will not be sufficient.

    #include "test.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_gpio.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include <stdint.h>
    #include <stdbool.h>
    #include <stdint.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.
    //
    //*****************************************************************************
    
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, unsigned long ulLine)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    // Send a string to the UART.
    //
    //*****************************************************************************
    void
    UARTSend(const unsigned char *pucBuffer, unsigned long ulCount)
    {
        //
        // Loop while there are more characters to send.
        //
        while(ulCount--)
        {
            //
            // Write the next character to the UART.
            //
            ROM_UARTCharPutNonBlocking(UART7_BASE, *pucBuffer++);
        }
    }
    
    //*****************************************************************************
    //
    // This example demonstrates how to send a string of data to the UART.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // Enable lazy stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        ROM_FPUEnable();
        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 GPIO port that is used for the on-board LED.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
        //
        // Enable the GPIO pins for the LED (PF2).  
        //
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
    
        
    		
    		//
        // Enable the peripherals used by this example.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART7);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    
        //
        // Enable processor interrupts.
        //
        ROM_IntMasterEnable();
    
        //
        // Set GPIO A0 and A1 as UART pins.
        //
        GPIOPinConfigure(GPIO_PE0_U7RX);
        GPIOPinConfigure(GPIO_PE1_U7TX);
        ROM_GPIOPinTypeUART(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Configure the UART for 115,200, 8-N-1 operation.
        //
        ROM_UARTConfigSetExpClk(UART7_BASE, ROM_SysCtlClockGet(), 115200,
                                (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                 UART_CONFIG_PAR_NONE));
    
    	/*
        //
        // Enable the UART interrupt.
        //
        ROM_IntEnable(INT_UART0);
        ROM_UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
    */
    
    
        //
        // Prompt for text to be entered.
        //
    
    		ROM_UARTCharPutNonBlocking(UART7_BASE, 'A');
    		ROM_UARTCharPutNonBlocking(UART7_BASE, 'B');
    		ROM_UARTCharPutNonBlocking(UART7_BASE, 'C');
    		ROM_UARTCharPut(UART7_BASE, 'D');
    		ROM_UARTCharPut(UART7_BASE, 'E');
    		
        while(1)
        {
    				
        }
    }
  • Many here "hope" that your project and/or any "deliverables" remain active/desired - when your ASM effort concludes.  The mating of ASM coding w/the "Turtle-like" UART response - seems not especially a, "match - made in heaven..."

    Despite past (rumored) race results - my chip-stack squarely upon the Rabbit!  (i.e. vanilla C code)

    Joseph Yiu's (now near classic), "Definitive Guide to the ARM Cortex..." is a rich ASM resource - for those not under deadline constraints...

  • @cb1_mobile: since I am not a native english speaker, I am a bit puzzled about your point in the first section of your last response. Thus, it would be helpful to me to rephrase your point in clearer and more direct way, possibly without the use of irony (correct me if I got you wrong).

    Best regards