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.

CCS/TM4C123GH6PM: UARTCharGet working on UART0 but on no other modules

Part Number: TM4C123GH6PM
Other Parts Discussed in Thread: EK-TM4C123GXL

Tool/software: Code Composer Studio

Although I have UARTCharGet working when it's from UART0, it gets stuck at the point in the code where that same function is called but for UART1, UART2, UART3, etc.  UARTCharPut does work on these modules so I am certain I have configured them correctly.  I should note that I am using the MAP version of these functions and that the project's overall build options, configurations, .map, .bin, etc comes from the example project "hello" which means that it was originally configured to work only with UART0.  Are there any differences in the way that UART module 0 is set up compared to the others which could point me in the direction of a solution?  What is possibly causing the program to get stuck waiting for input at UARTCharGet only on module 3 but not 0?  If there is any other information (snippets of code, build options, etc) which I could provide, please let me know.  Thank you very much for your help, it's greatly appreciated.

  • Hello Tai,

    UARTCharGet works for all UART modules. Can you please share the code for both UART configuration and your function calls for UARTCharGet where you are seeing the failure? I suspect the issue is with the C code, maybe I can spot the 'gotcha' that is hanging things up quickly. 

  • Hello Ralph,

    All of your points are valid - but I'd 'hazard the guess' that poster is employing the 'ICDI' to reach the 'outside world.'    And that of course is hard-routed only to UART0.

    Charles & I have exchanged (exactly) on this point - while such is 'mentioned' - it is my (and others') belief that it is not 'effectively' mentioned - and posters repeatedly fall to this trap...

    [edit]  from the, 'It pays to read the post 'all the way thru' - prior to opening big mouth file.'   Just noted, "UARTCharPut does work on these modules!"    So - that KILLS my sense of the 'more usual' 'UART0 ONLY ONE to WORK' result.

    I still have a 'fix' - wager 10 (USD) that 'Pull-Up resistor' placed upon UARTn's  'RX Pin' will restore UARTCharGet()'s functionality...   (where n>0)    This proves so (at least usual) as the normal UART 'Recognizes the Start-Bit via the transition from 'Logic High to Logic Low' upon UART_RX.'   

    When floating - that transition is too often muted - and/or missed.   (never mentioned is the fact that the ICDI connection provides such 'High logic level (only to UART0) - likely via a 'WPU' internal resistor... as no such (external) pull-up resistor is visible w/in the LPad's schematic.)      In the unlikely event that the use of such pull-up resistor (w/UARTn_RX) fails to immediately correct - then a description of the (external UART Source Device) should be provided.    Note that 'normal' RS232 & RS485 line-drivers 'insure' that UART_RX is indeed made to 'idle at Logic High!'

  • Hi Ralph, cb1_mobile,

    Thank you both for such prompt responses.  cb1, you are correct in thinking that I am using the ICDI for UART0.  As I am using the EK-TM4C123GXL evaluation board, I am accessing UART0 through the exposed pads provided while I am accessing the other channels via their respective pins (e.g. PC6 and PC7 for UART3).  I have tried pull-up resistors of various values (4.7k, 1k, 100k) and although the thinking behind it seems solid, it has unfortunately not resolved my issue.  The external UART source device is the adafruit "USB to UART" board and I am simply talking to it from my laptop. However, I doubt that this is the issue as I have been able to communicate to UART0 effectively through this external UART source device.  I attach a snippet of the code below.  This is the member function in which I call UARTCharGet.  Note that this function is taken almost line-by-line from uartstdio's UARTgets with a few minor adjustments.  Here the attribute channel_base is assigned when the UART_channel object is initialised.

    int UART_channel::read(char storage_string[], uint32_t Length)
    {
        uint32_t Count = 0;
        int32_t cChar;
        static int8_t bLastWasCR = 0;
    
        //
        // Check the arguments.
        //
        ASSERT(storage_string != 0);
        ASSERT(Length != 0);
        ASSERT(channel_base != 0);
    
        //
        // Adjust the length back by 1 to leave space for the trailing
        // null terminator.
        //
        Length--;
    
        //
        // Process characters until a newline is received.
        //
        while(1)
        {
    MAP_UARTCharPut(channel_base, 'K');
    // // Read the next character from the console. // cChar = MAP_UARTCharGet(channel_base); // // See if the backspace key was pressed. // if(cChar == '\b') { // // If there are any characters already in the buffer, then delete // the last. // if(Count) { // // Rub out the previous character. // write("\b \b"); // // Decrement the number of characters in the buffer. // Count--; } // // Skip ahead to read the next character. // continue; } // // If this character is LF and last was CR, then just gobble up the // character because the EOL processing was taken care of with the CR. // if((cChar == '\n') && bLastWasCR) { bLastWasCR = 0; continue; } // // See if a newline or escape character was received. // if((cChar == '\r') || (cChar == '\n') || (cChar == 0x1b)) { // // If the character is a CR, then it may be followed by a LF which // should be paired with the CR. So remember that a CR was // received. // if(cChar == '\r') { bLastWasCR = 1; } // // Stop processing the input and end the line. // break; } // // Process the received character as long as we are not at the end of // the buffer. If the end of the buffer has been reached then all // additional characters are ignored until a newline is received. // if(Count < Length) { // // Store the character in the caller supplied buffer. // storage_string[Count] = cChar; // // Increment the count of characters received. // Count++; // // Reflect the character back to the user. // MAP_UARTCharPut(channel_base, cChar); MAP_UARTCharPut(channel_base, 'r'); } // else if (Count == Length){ // break; // } } // // Add a null termination to the string. // storage_string[Count] = 0; // // Send a CRLF pair to the terminal to end the line. // write("\r\n"); // // Return the count of int8_ts in the buffer, not counting the trailing 0. // return(Count); }

    Below here, is the initialisation function (constructor for the class):

    UART_channel::UART_channel(uint32_t PortNum, uint32_t ui32Baud,
                               uint32_t ui32SrcClock)
    {
    
        //
        // Select the base address of the UART. (Don't want this global at the moment.
        //
        channel_base = UARTBase[PortNum];
    
        //
        // Check the arguments.
        //
        ASSERT((PortNum >= 0) && (PortNum <= 7));
        ASSERT(channel_base != 0);
    
        //
        // Check to make sure the UART peripheral is present.
        //
        if(!MAP_SysCtlPeripheralPresent(UARTPeriph[PortNum]))
        {
            return;
        }
    
        //
        // Enable the GPIO Peripheral used by the UART.
        //
        MAP_SysCtlPeripheralEnable(UARTGPIOPeriph[PortNum]);
    
        //
        // Enable the UART
        //
        MAP_SysCtlPeripheralEnable(UARTPeriph[PortNum]);
    
        //
        // Configure GPIO Pins for UART mode.
        //
        MAP_GPIOPinConfigure(UARTRxPin[PortNum] | UARTTxPin[PortNum]);
        MAP_GPIOPinTypeUART(UARTGPIOBase[PortNum], UARTPins[PortNum][0] | UARTPins[PortNum][1]);
    
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        MAP_UARTClockSourceSet(UARTBase[PortNum], UART_CLOCK_PIOSC);
    
        //
        // Configure the UART for 115200, n, 8, 1
        //
        MAP_UARTConfigSetExpClk(UARTBase[PortNum], ui32SrcClock, ui32Baud,
                                (UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE |
                                 UART_CONFIG_WLEN_8));
    
        //
        // Enable the UART operation.
        //
        MAP_UARTEnable(UARTBase[PortNum]);
        MAP_UARTFIFOEnable(channel_base);
    }

    Again, thank you all for your help.  It's greatly appreciated.

    Tai 

  • Hi back,

    And thank you as well for such a quick & 'well detailed' report!     Vendor's Ralph is far better equipped/skilled to, 'Evaluate your code' - I'll stick to the hardware implementation.

    In 'all' such 'Serial Interface Failing and/or Disturbed' cases - the diagnostic effort is greatly enhanced via 'Scope Captures.'    You note (and thanks for that) use of another vendor's 'UART to USB board' and concern rises as these come w/a 'variety of output voltage-level formats.'     Thus, let the '3rd degree' probing begin:

    • Have you confirmed that the output level of Adafruit's Converter span's '0-3V3' - and is not at (destructive) RS232 signal levels?  (±12-15V) 
    • Have you probed the actual UART_RXn pins (where n>0) to insure that the idle state registers as 'Logic High' and that the signal indeed 'toggles' when so directed? (i.e. laptop xmits)
    • Your code's intent is nicely 'broad' - yet that 'Deviates from our beloved 'KISS' - and 'First Order Diagnostics' ALWAYS seeks simplicity & directness!    Might you employ 'Vendor's UART example code' - at least briefly - so that the solution scope is much minimized?
    • While you report 'success' via UARTCharPut() - is it possible that the, 'Incoming (post Adafruit) UART Signal's baud rate does not match your UARTn's set-up value?
    • As always - have you a 2nd such Eval Board - and when the test is repeated - do the results remain the same?
    • As a 'court of last resort' - you may check the, 'Functionality of UART_RXn (n>0)' by (temporarily) switching its function to GPIO input - and joining it to a toggling GPIO (a 2nd pin) to confirm that the pin IS functional.
    • While an (almost) pure 'swag' - does the Adafruit converter include a ground lead - and is that (properly) joined to your Eval Board's ground?
  • Another few good ideas.  After checking many of them, I tried going back to the original example code as you suggested and found that that worked okay.  When I probed deeper, found that there was an additional SysCtlPeripheralEnable(UARTPeriph[PortNum]) line which was repeated.  As it was the exactly same line, I initially omitted it but after including it in my code, it ended up working as intended.  Thank you very much for your help!

  • Thank you - I am mobile - net is 'in/out' - please re-read that last post for (other) 'Failed UART candidates.'

    From our long experience (over 5K ''4C123" MCU designs designed/sold/shipped - this MCU's UART is Rock-Solid!

  • Again - thank you - your feedback & responsiveness are much valued & appreciated.

    That said - perhaps as a 'Public Service' for 'follow-on' readers - might you, 'Confirm or Deny the Requirement for 'pull-up resistors' placed upon UART_RXn' - when exercising UARTn.'   (where n>0)    Our investigation has found that resistor addition to (always) work - when absent ... UART operation proves 'iffy/uncertain/failed!'   (assuming the external UART signal source (or line driver) does not provide, 'Logic High' as 'idle'...)

  • Although the addition of the pull-up resistor might make it more reliable, I found that (at least on the evaluation board), it was not necessary once I got it working.