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 16x8 FIFO what?

Guru 54057 points
Part Number: EK-TM4C1294XL

Datasheet Figure 16-1 makes no sense relative to register 1 text 12 bit FIFO and full/empty interrupt levels also have no basis in diagram 16-1 or REG1.

Are FIFO's 16 bit x 8 deep or (16 deep x 8 bit DATA registers)? Figure 16-1 relates 12 bit FIFO being REG1 UARTDR? How are the status bits OE,BE,PE,FE, of REG1 getting into Fig.1 UARTDR? Point being UARDR REG1 does not have details specifically relate (Fig.1) visually for software data read/writes as it has been drawn.  Are FIFO's 16 bit or are they 8 bit? Datasheet does not explain the FIFO in Written detail as to how it's architecture is drawn in Figure 1. Oddly Tivaware casts uint32_t bit wide data read from UARTCharGet() when REG1 is only 12 bits wide and we only desire 8 bit data POP into the C+ Array[N]. Very how difficult without a BUFFER data stream retrieval is compared to Arduino simple Serial calls coded in line transparent to FIFO!

Compounding the issue is any SW invoking  (uartstdio.c) with UART_BUFFERED does not allow multiple instance UARTS to be configured or use the same module. Yet there are 8 UARTS and the code written for Tivaware is way outdated compared to other industry products such as Arduino. Perhaps time to invest resources re-write uartstdio.c so multiple UARTprintf() calls to several configured  UARTs with PEAK ability!

Register 1: UART Data (UARTDR), offset 0x000:

For received data, if the FIFO is enabled, the data byte and the 4-bit status (break, frame, parity, and overrun) is pushed onto the 12-bit wide receive FIFO. If the FIFO is disabled, the data byte and status are stored in the receiving holding register (the bottom word of the receive FIFO). The received data can be retrieved by reading this register.

  • We only desire 8 bit data read from UARTDR via calls to UARTCharGet() but a 32 bit wide cast would seemingly retrieve 12 bits (4 status) thus complicates 8 bit data handling. 

    Do we have to examine Tivaware UART calls to UARTCharGet(), UARTCharPut() know they only retrieve 8 bit data into a 32 bit wide register? How does POP of the 8 bit FIFO (UARTDR) into C+ array occur in datasheet context as it relates to 16 LEVELS deep FIFO when it is 1/8, 1/4, 1/2, 3/4, 7/8 interrupting full without a BUFFER! The entire subject has no analysis basis for multiple UART development as it relates to Tivaware basic calls. 

    Again outdated (uarstdio.c) has dropped the ball and complicated SW development and required more time compared to Arduino (inline class) serial calls!

    What is the intended idea or logic behind outdated data register handling by Tivaware library? 

  • Hi BP101,

      I understand that it is a bit confusing in the Fig 16-1 diagram where the FIFO is shown as 16x8 (16 deep x 8bits). It could have shown as 16x12 if that helps clarify. Normally a UART length is limited to 8 bits. The diagram is trying to emphasize the depth of the FIFO which is 16. The status bits associated with the data is what I consider a "sideband" information and therefore not shown in the diagram. When the processor reads from a 32-bit memory, the memory not only return the 32-bit data but also sideband signals such as error status. In a high level block diagram, you will most likely see a memory width of 32 bits instead of something like 37 bits because of 5 bits (i just made this up) of status as part of the response. I think this is the rationale behind showing 16 x 8 instead of 16 x 8.

    It is described in the REG1 as follows. 

    For received data, if the FIFO is enabled, the data byte and the 4-bit status (break, frame, parity,
    and overrun) is pushed onto the 12-bit wide receive FIFO. If the FIFO is disabled, the data byte and
    status are stored in the receiving holding register (the bottom word of the receive FIFO). The received
    data can be retrieved by reading this register.

  • Hi Charles,

    Charles Tsai said:
    The diagram is trying to emphasize the depth of the FIFO which is 16.

    Yet how does SW C+ call retrieve 16 levels deep or the exact level set to interrupt?

    Note Tivaware UARTCharGet() complicates FIFO data  retrieval by NOT masking off the 4 upper bits prior to casting uint32_t. Call needs to be re-written as a separate function or add Bool switch as to disable the upper mask bit 11:8 in return data.

    Also note #include <string.h> or "string.h" does not function CCS to add C+ inline interpreter as Stellaris to Tivaware conversion PDF stated. So the UART call back functions are useless with/for use with inline C+ directives. Code analysis incorrectly marks compiler C+ string directives as bugs!

  • Hi Charles,

    BTW: Example uart.c (blocking) does not strip the extra nibble bits [11:8]  hind sight is not a very good example but only to send multiple single character (!) and Get after terminal CR/LF Put or return single @.  It does not indicate how a C+ array should handle non-blocking UART when interrupts are enabled.

    Added a handler but am confused about the array handling for high speed interrupts, level deep POP relative to trigger level. The RX/TX interrupts appear to work but data from UARTCharGet() and UARTprintf() confirms transfer of known data format is difficult with so little information of 16x8 handling from trigger points being single or level deep even block via UARTCharGet(). The 8 bit data POP array reads were no different than 32 bit, albeit no flags errors seemed to change the odd data read back. It was not what was sent from a confirmed TX serial source running the Baud dot rate. The example confirmed UART2 clocking configuration was correct until adding array to POP the FIFO contents without BUFFER did it all go amuck..... 

    Point being 32 bit POP could hold 4 bytes each get cycle. FIFO level access seems bottle necked by UARTDR register not described in the datasheet as being (circular) other than level sensitive stated in REG1. So what's the point of 16 levels deep if only one 8 bit array POP can occur at any given time?

        /* Set the UART to interrupt whenever the TX/RX FIFO
         * is almost empty or when any character is received. */
        MAP_UARTFIFOLevelSet(UART2_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
    /* Set the FIFO mode TX/Rx level triggered interrupts */ MAP_UARTTxIntModeSet(UART2_BASE, UART_TXINT_MODE_FIFO);

     

  • BP101 said:
    Note Tivaware UARTCharGet() complicates FIFO data  retrieval by NOT masking off the 4 upper bits prior to casting uint32_t. Call needs to be re-written as a separate function or add Bool switch as to disable the upper mask bit 11:8 in return data.

    I think you can call UARTCharGet() and assign to a uint_8 variable to mask out the status bits. Something like below. 

    uint8_t cChar;

    cChar = MAP_UARTCharGet(g_ui32Base);

  • Hi Charles,

    Charles Tsai said:
    I think you can call UARTCharGet() and assign to a uint_8 variable to mask out the status bits

    For now I just do UARTCharGet() & 0xFF) to mask the upper nibble.

    I was using uint8_t GetReg[16] with same results, for larger array unit32_t GetReg[16]. Again the POP array used to get any part of the 16x deep FIFO don't seem to get all the data from defined Interrupt being 1/8 level events even though REG1 is said to be read sensitive. That point needs to be elaborated as to exactly how read sensitive relates to 16x8 levels deep, being either serial shift or parallel stack reads.

    So an array for parallel (16x) level stack might look something like uint32_t GetReg[8,16]  and the application then points to the Get data saved in the array. I have not yet tried such though it seems plausible if indeed the FIFO buffers 16x8 levels deep. The easy way around any logic is to save it to SRAM. Also (uartstdio.c) ignores HW interrupts configuration for levels deep events without SRAM Ring buffer being defined.  It seems to be working on single character configuration in Tivaware without buffer defined as Symbol UART_BUFFERED 

    Again can FIFO 16x8 be POP into an array Without SRAM clocking data by C indirect addressing directives when interrupts are set levels deep?

    #ifdef UART_BUFFERED
        //
        // Set the UART to interrupt whenever the TX FIFO is almost empty or
        // when any character is received.
        //
        MAP_UARTFIFOLevelSet(g_ui32Base, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
    
        //
        // Flush both the buffers.
        //
        UARTFlushRx();
        UARTFlushTx(true);
    
        //
        // Remember which interrupt we are dealing with.
        //
        g_ui32PortNum = ui32PortNum;
    
        //
        // We are configured for buffered output so enable the master interrupt
        // for this UART and the receive interrupts.  We don't actually enable the
        // transmit interrupt in the UART itself until some data has been placed
        // in the transmit buffer.
        //
        MAP_UARTIntDisable(g_ui32Base, 0xFFFFFFFF);
        MAP_UARTIntEnable(g_ui32Base, UART_INT_RX | UART_INT_RT);
        MAP_IntEnable(g_ui32UARTInt[ui32PortNum]);
    #endif
    
        //
        // Enable the UART operation.
        //
        MAP_UARTEnable(g_ui32Base);
    }

  • Hi BP101,

    BP101 said:
    Again can FIFO 16x8 be POP into an array Without SRAM clocking data by C indirect addressing directives when interrupts are set levels deep?

    Can you elaborate what you meant by "POP" into an array?

     The FIFO is 16 x 8-bit physically if you disregard the upper status bits. I'm not sure if I'm understanding your question. If you think that the UARTCharGet() is going to do 4 bytes of read just because the function will return a 32-bit value then it is not going to happen. If you configure for 1/8 of the FIFO to interrupt then once there are at least two data in the FIFO will the interrupt be generated. In the ISR you must perform two reads from the FIFO using UARTCharGet(). In another word, if you configure for 7/8 of FIFO, you will need to call UARTCharGet() 14 times in your ISR to read the data. Again, I'm not clear with your question as to "can FIFO 16x8 be POP into an array Without SRAM clocking data by C indirect addressing directives when interrupts are set levels deep".

  • The interrupt on empty concept seems more relative for TX events than RX events. Application needs service interrupt when RX 16x FIFO is 1/8 FULL for POPing read sensitive REG1 contents of 16x FIFO into an equivalent Array[n]. Single character interrupts seem more relative for TX UARTPutChar() events.

    The TM4C1294 datasheet seems to get REG1 read sensitive events and interrupt level confused between RX & TX data events being the same when perhaps not so relative to Figure 16-1. So it seems level interrupt or CTS interrupt from Host and only when FIFO is 1/8 full is it clear to TX more data. So the interrupt handler may need to check for CTS events too according to datasheet text.

  • Charles Tsai said:
    Can you elaborate what you meant by "POP" into an array?

    POP is TM4C datasheet inferred meaning for retrieving data from read sensitive registers? The word POP may originate from C language for HW calls to addressed data register storage locations. In assembler it was very easy to load for instance the HL register pair with an address to indirectly gain access to the data contents at that address, hence indirect addressing.

    The UART is clocked on to AHB so C calls to UARTGetChar() should indirect address data from 16x levels direct into an C array of similar data length size or POP the read sensitive contents. in this case from read sensitive UARTDR via the C language call to load Array[N] until the 16x data words are retrieved.

    Charles Tsai said:
    If you think that the UARTCharGet() is going to do 4 bytes of read just because the function will return a 32-bit value then it is not going to happen.

    The point of 16x8 FIFO is not for the slower UARTS benefit, rather the C language calls of the application to not bottle neck on the AHB. Looking at uartstdio.c states only one storage array can be assigned BUFFER and race condition occurs, corrupts the index. So it then disables the interrupt in order for single direct memory access reads of RX data from UARTDR. Seemingly read sensitive REG1 loads the circular FIFO (16x) with the next storage location into the pre-defined storage array.

    Should the storage array have greater defined depth [n, n] than a single character [n] then POP array should continue input indirect from UARTDR because the CPU is indirect addressing data at the offset. The UART clock should be doing background shifting of RX/TX data into the 16x FIFO (buffer) seamless of CPU and AHB arbiter access to UARTDR. That said the application should be able to read 16 bytes at a time from UARTDR depending on interrupt set level 1/8, 1/2 etc. and not just read 1 byte each cycle. The CPU and application does the POP of 16x FIFO, seamless to the UART clocking.

  • Charles Tsai said:
    In another word, if you configure for 7/8 of FIFO, you will need to call UARTCharGet() 14 times in your ISR to read the data. Again, I'm not clear with your question as to "can FIFO 16x8 be POP into an array Without SRAM clocking data by C indirect addressing directives when interrupts are set levels deep".

    How about declaring, calling a multi dimensional array 1 time and have two bytes space left over for the next read of UARTDR? The one exception might be the TM4C1294 tool chain may need to evolve from APB into higher speed AHB for back to back indirect addressing. Circular read the UARTn 16x8 FIFO contents seamless to the application call each interrupt cycle. No more bottle neck or unexpected race conditions requiring to disable UART interrupts during reads of the FIFO. That's just interrupt nuts - is not?

  • BP101 said:
    The UART is clocked on to AHB so C calls to UARTGetChar() should indirect address data from 16x levels direct into an C array of similar data length size or POP the read sensitive contents. in this case from read sensitive UARTDR via the C language call to load Array[N] until the 16x data words are retrieved.

    A UARTCharGet() call will only read  one character from the receive FIFO. The UARTDR is only memory mapped to one single address not mirrored to 16 different sequential addresses. 

    30.2.2.7 UARTCharGet
    Waits for a character from the specified port.
    Prototype:
    int32_t
    UARTCharGet(uint32_t ui32Base)
    Parameters:
    ui32Base is the base address of the UART port.
    Description:
    This function gets a character from the receive FIFO for the specified port. If there are no
    characters available, this function waits until a character is received before returning.
    Returns:
    Returns the character read from the specified port, cast as a int32_t.

  • Charles Tsai said:
    A UARTCharGet() call will only read  one character from the receive FIFO. The UARTDR is only memory mapped to one single address not mirrored to 16 different sequential addresses

    Yet UARTCharGetUnblocked();

    Register 1: UART Data (UARTDR), offset 0x000
    Important: This register is read-sensitive. See the register description for details.

    Circular FIFO should unload the entire 16x contents one interrupt time into a defined multi dimensional array. Past used MD's written in VB to burn UVEPROMs via serial UART connections. I still have the VB  program on hand from 1987, runs on windows.

  • Hi Charles,

    Thanks for getting me to think outside the box on how to get robust UART transfers. Testing 2 dim array below with UartGetNonBlocking() POP for 7/8 full FIFO interrupt, seemingly occurs via one interrupt loop. At least the UARTprintf(0) of UART2 RX data input seems to indicate multiple characters are specific to 0xFF signature being compared for print out. I used the WEB example (for int I, int j ) loop to fill the 2 dim array (16 rows, 8 columns) with FIFO read. Oddly return data from UartRxErrorGet() was always 0x0, now check variable &=0xF otherwise a constant RX error occurs for 0x0 length variable assignment. The Rx error check function also &0xF with REG2, if no error/s occurs return = 0x0.

    /* Two dimensional array 16 Rows x 8 Columns deep */
    uint8_t Cchar[16][8]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};

      

  • BP101 said:
    /* Two dimensional array 16 Rows x 8 Columns deep */

    uint8_t Cchar[16][8]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};

    Your array sequence should properly end in '15' - not '16' - should it not?     To your (other) 'points'  -  those left for vendor crüe.    (weekend's arrival (may) be welcomed by some...)

    BP101 said:
    I used the WEB example (for int I, int j ) loop to fill the 2 dim array (16 rows, 8 columns) with FIFO read.

    Which 'Web example?'     There are many...

    Can it be noted that you've regularly generated a slew of 'USB Focused Questions/Postings' - yet your 'Arduino-kick' (now) appears to have, 'Kicked USB to the curb!'   

    Should not a superior thread subject be:  "USB to UART What?"     (same grammar failing continued...)

  • Web link above posted & the 16 array size don't care being simply 1 extra space, now at 256x8 makes no difference.

    It seems UART2 is not seamless to CPU directives (for/while) loops used to fill 16 or even 256 spaces during interrupt handler call to Get RX data. Somehow UART0 used to debug UART2 via report of RX data retrieved can only single step UART2 buffering RX data into multi dimensional array for 7/8 full interrupts. No other UART RX interrupt level is even possible without halting other application parts such as EMAC0 DHCP auto IP assignment. Yet the multi dimensional array is working since the variable names assigned are being printed via UART0 in single steps along with other odd symbols. Appears to be data over run but no error messages printed. The odd characters printed out were often tiny f/f indicating end of string 0xff.

    The RX data is printed but reports only bit/pieces at a time when ever an RX INT or RX timeout is forced as GUI button sends more data to target UART2.   

    Later discovered a while loop not exiting for long periods of time inside INT handler causing the random FIFO loops. Oddly there were 3 breaks in various parts but that didn't matter.