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.

AM3359 UART4 FIFO threshold trigger not working

Hi,

     We are using AM335X_StarterWare_02_00_00_07 and have been using UART4 in UART Mode using simple polling with no problem. We noticed that on some large incoming data from the UART we were not processing it fast enough so we want to start using the RX FIFO interrupt capability.The FCR register for UART4 is set to 0x00000057 which set the RX and TX FIFO triggers to 16 characters, No DMA mode and the FIFO's are enabled. As I said this works well and you can see data being received by checking the count in RXFIFO_LVL at offset 64h. The problem occurs when IER register is configured to a 0x1, RHR interrupt is enabled. The interrupt begins to go off with no receive data present (RXFIFO_LVL is 0), and even when there should be data there, the RXFIFO_LVL never moves. Is there some other UART/Interrupt configuration that needs to be done/changed that would allow this setup to work?

Thanks,

     John C.

  • Hi John,

    You have told that you are setting the FCR with the value 0x57. The RX and TX Triggers can also be set using Trigger Level Register (TLR). The Supplementary Control Register (SCR) also plays a role in this setting. I suggest you refer to the Table in TRM mentioning the different ways of setting the RX Trigger Level. (In the latest TRM which is spruh73g, refer to the table 19-48 in section 19.5.1.18).

    John Conover said:
    The interrupt begins to go off with no receive data present (RXFIFO_LVL is 0),

     

    By telling interrupt begins to go off, did you mean interrupt was triggered?

    Please refer to the UART Interrupt application for the API calling sequence.

    Thanks and Regards.

    Gurudutt.

  • Hey Gurudutt,

         The trigger levels are set in the TLR by using the StarterWare call UartFIFOConfigure(). We are using the same setup as the StarterWare example of /examples/evmAM335x/uart/uartEcho.c. In this example it is supposed to be using the threshold values to trigger the interrupt. So as long as the StarterWare code adheres to the proper programming of the UART fifo's we should be ok. There are definitely differences between how StarterWare does it as it seems that StarterWare is trying to use a more generic sequence (vs. how the technical manual sets the fifo's in section 19.4.1.1.2.)

         So what we am seeing is that when Rx interrupt is not enabled (bit 1 of the IER register set using UARTIntEnable() call) the RXFIFO_LVL will show the correct amount of bytes being received. When we enable this bit (again by using the UARTIntEnable() call) the isr routine is called but when we break in this routine, there is no count in the RXFIFO_LVL. The code in the isr that checks the source of the interrupt (intId = UARTIntIdentityGet()) shows the reason is a "UART_INTID_RX_THRES_REACH". 

         Is the uartEcho example really using the FIFO threshold ? The isr code only pulls one byte from the rx register yet the threshold value is actually set to 16 bytes. If the example is really not using the threshold levels, does TI have any that do? (We do not see any other UART examples that involve programming both the interrupt and the threshold levels.)

    Thanks,

         John C.

  • Hello John,

    I want to clarify each of your question asked in each of the three paragraphs.

    • Though it might seem that the UART application is not following the programming sequence mentioned in the section 19.4.1.1.2 of TRM, it is doing in reality. The programming sequence suggests the following three overall steps:
      • Software Reset
      • FIFO and DMA settings
      • Protocol, Baud Rate and Interrupt Settings

               If you observe the UART application, you find that this is done in the order mentioned.

               The APIs take care of the different mode switches and the pre-conditions to be set before any operation.

               I also suggest you to not put breakpoints in the RX part of the ISR. The application is correct and there is no need to worry about the amount of data in the RX FIFO.

     

    • I want to clarify to you that the UART application is using a RX Threshold level of 1 and not 16. I suggest you to refer to the comments of UARTFIFOConfig() API to understand the different ways of setting the RX Threshold level. All the settings in the FCR for different RX Threshold have been tested and it works.

     

    Please revert if you have any queries.

     

    Thanks and Regards.

    Gurudutt.

  • Hi Gurudutt,

         I'll respond to each of your paragraph answers:

    • Technically speaking the 19.4.1.1.2 shows an exact example of programming the FIFO's in UART mode (there are no suggestions on how it could be broken apart.) When we observed the application we believe their is an issue with the EFR register bit 4, but have not had time to verify.
    • In our ISR routine we do need to know what the FIFO levels are. (I may have not mentioned but we are running on our own board.) We have not found anything in the Technical guide that would suggest that the RX FIFO level register needs any special sequence to access it. We are also not sure that the example code actually exercises the FIFO level  triggers (as was mentioned before that the ISR only removes one byte when the trigger level is 16.)
    • Yes the RX FIFO level is set to a 1, which is a 16 byte level (it is identical to the example code.)

         I will follow the link and will be able to look at this more in another day as I need to finish a few more things first.

    Thanks,

         John C.

  • Hi Gurudutt,

         The answer to the question you are asking on the link is that with the memory browser window open, the browser is reading the rx register (when you reach the break point), which is pulling the next received character out of the FIFO (so the memory browser is grabbing the missing character.) If you could ask them why the RX FIFO level does not show correctly in the ISR, that would help a lot.

    Thanks,

         John C.

  • Hello John,

    I have two answers to your replies.

    • I believe that the steps mentioned in the TRM have been followed. However if you can point out any shortcomings, it will be welcomed.
    • I want to clarify that the RX FIFO level used in the application is not 16 but 1. Since 1 is programmed to FCR, it might seem that the RX Threshold level is 16. However this is not true in all the cases. The application is using a granularity of 1 for RX and is writing 1 to the RX Threshold field of FCR. This would result in the RX Threshold level being 1. However if granularity of RX Threshold was 4, then setting a 1 in RX Threshold field of FCR would yield a RX Threshold level of 16. I suggest you to refer to the Table 19-48 of the recent TRM for more information. Referring to the table, the application is using the third method of programming the RX Threshold level.

               If the RXFIFO_LVL register has to be read, it could be read in software. The reason I am saying this is that reading through Memory Browser in CCS is creating problems.

    Please refer to the comments of the API UARTFIFOConfig(). It provides support for all the ways to configure the granularity settings and RX Threshold levels that the TRM speaks of.

    Please revert for any queries.

    Thanks and Regards.

    Gurudutt.

  • Hi Gurudutt,

                Our hardware engineer looked into the issue and found that using the uartEcho.c example found in examples/evmAM335x/uart, there was an issue in the UartFIFOConfigure() routine. The original and our modified code show that he found the EFR[4] was not set correctly during initial setup. Part of this can be seen in this other thread. So our fifo is reading correctly now and proper levels can be seen in the ISR (you were correct that our threshold level needed to be modified as this level can be a confusing combination of other registers.)

    http://e2e.ti.com/support/embedded/starterware/f/790/p/210589/877793.aspx#877793

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

    static void UartFIFOConfigure(void)
    {
        unsigned int fifoConfig = 0;

        /* Setting the TX and RX FIFO Trigger levels as 1. No DMA enabled. */
        fifoConfig = UART_FIFO_CONFIG(UART_TRIG_LVL_GRANULARITY_1,
                                      UART_TRIG_LVL_GRANULARITY_1,
                                      1,
                                      1,
                                      1,
                                      1,
                                      UART_DMA_EN_PATH_SCR,
                                      UART_DMA_MODE_0_ENABLE);

        /* Configuring the FIFO settings. */
        UARTFIFOConfig(SOC_UART_0_REGS, fifoConfig);
    }
    --------------------------------------------------------------

    Here is our modified:

    static void UartFIFOConfigure(unsigned int baseAddr,
                                  unsigned int txTrigLevel,
                                  unsigned int rxTrigLevel)
    {
        unsigned int fifoConfig = 0;
        unsigned int enhanFnBitVal;

        /* Setting the TX and RX FIFO Trigger levels as 1. No DMA enabled. */
        fifoConfig = UART_FIFO_CONFIG(UART_TRIG_LVL_GRANULARITY_1,
                                      UART_TRIG_LVL_GRANULARITY_1,
                                      txTrigLevel,
                                      rxTrigLevel,
                                      1,
                                      1,
                                      UART_DMA_EN_PATH_SCR,
                                      UART_DMA_MODE_0_ENABLE);

        /* Needed because UartFIFOConfig fails to set EFR[4] before accessing TCR, TLR, & FCR registers */
        enhanFnBitVal = UARTEnhanFuncEnable(baseAddr);

        /* Configuring the FIFO settings. */
        UARTFIFOConfig(baseAddr, fifoConfig);

        /* Restore EFR[4] value (i.e. set it to '0') */
        UARTEnhanFuncBitValRestore(baseAddr,enhanFnBitVal);
    }

    Thanks,

         John C.

  • Hello John,

    It was great that you discovered the bug and the solution. I should have directed you towards the prevalent issue and the resolution much earlier.

    The resolution you have arrived at is correct. However it would not be a permanent fix since the source of the problem will remain unaltered. The issue is present in the driver and I recommend that you fix it in the driver itself. This would mean fixing the problem at the source. The exact change that our driver has undergone in this regard is shown below.

     

    unsigned int UARTFIFOConfig(unsigned int baseAdd,

                                                          unsigned int fifoConfig)

    {

        …………………………..

        ……………………………

        ……………………………

        unsigned int enhanFnBitVal = 0;

        unsigned int tcrTlrBitVal = 0;

        unsigned int tlrValue = 0;

        unsigned int fcrValue = 0;

     

        /* Setting the EFR[4] bit to 1. */

        enhanFnBitVal = UARTEnhanFuncEnable(baseAdd);

        ………………………..
        ………………………..

     

        /* Restoring the value of TCRTLR bit in MCR. */

        UARTTCRTLRBitValRestore(baseAdd, tcrTlrBitVal);

     

        /* Restoring the value of EFR[4] to the original value. */

        UARTEnhanFuncBitValRestore(baseAdd, enhanFnBitVal);

     

        return fcrValue;

    }

     

    void UARTFIFORegisterWrite(unsigned int baseAdd, unsigned int fcrValue)

    {

        unsigned int divLatchRegVal = 0;

        unsigned int enhanFnBitVal = 0;

        unsigned int lcrRegValue = 0;

     

        ………………………..

     

        /* Set the EFR[4] bit to 1. */

        enhanFnBitVal = UARTEnhanFuncEnable(baseAdd);

     

        /* Writing the 'fcrValue' to the FCR register. */

        HWREG(baseAdd + UART_FCR) = fcrValue;

     

        /* Restoring the value of EFR[4] to its original value. */

        UARTEnhanFuncBitValRestore(baseAdd, enhanFnBitVal);

     

        …………………………….

    }

     

    I hope this helps.

     

    Thanks and Regards.

    Gurudutt.