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.

UART FIFO on AM335x StarterWare 02.00.00.05

Other Parts Discussed in Thread: AM3358

Hi all.

I'm testing the uartEcho example from the StarterWare 02.00.00.05 on the AM3358 evaluation kit.

It works.

When I change the uart FIFO TRANSMITTER trigger level (txTrigLvl) with a value like 3, the uart Tx Fifo doesn't wait 3 characters to send data but sends each byte immediatly.

I tried to call UARTFIFOEnable(baseAdd) without success.

Any suggestions ?

  • Hello Mickael,

    The UART Interrupt application in its current state uses a Transmitter trigger level of 1.

    If the Transmitter Trigger Level  has to be changed, then an appropriate value (from 1 to 63) has to be programmed in the parameterized macro ‘UART_FIFO_CONFIG’ which in turn is passed as an argument to the API UARTFIFOConfig().

    In the present case that you are discussing about, the Transmitter Trigger Level is 3. Therefore, you have to send 3 bytes in the ISR for every Transmitter Interrupt.

    I have myself tested this locally and a code snippet of the appropriate changes is given below.

     

    #define UART_TX_TRIGGER_LVL       (3)

     

    main()

    {

    ……………………….

    ………………………

    ………………………..

    UartFIFOConfigure()

     

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

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

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

     

    }

     

    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,

                                                                     UART_TX_TRIGGER_LVL,

                                                                     1,

                                                                     1,

                                                                     1,

                                                                     UART_DMA_EN_PATH_SCR,

                                                                     UART_DMA_MODE_0_ENABLE);

     

        /* Configuring the FIFO settings. */

        UARTFIFOConfig(SOC_UART_0_REGS, fifoConfig);

    }

     

     static void UARTIsr(void)

    {

        static unsigned int txStrLength = sizeof(txArray);

        static unsigned int count = 0;

        unsigned int lIndex = 0;

        unsigned char rxByte = 0;

        unsigned int intId = 0;

     

        /* Checking ths source of UART interrupt. */

        intId = UARTIntIdentityGet(SOC_UART_0_REGS);

     

        switch(intId)

        {

            case UART_INTID_TX_THRES_REACH:

     

                if(txStrLength > 0)

                {

                    for(lIndex = 0; lIndex < UART_TX_TRIGGER_LVL; lIndex++)

                    {

                        UARTCharPut(SOC_UART_0_REGS, txArray[count]);

                        txStrLength--;

                        count++;

                        if(0 == txStrLength)

                        {

                            break;

                        }

                    }

                }

     

                else

                {

                    /* Disabling the THR interrupt. */

                    UARTIntDisable(SOC_UART_0_REGS, UART_INT_THR);

                }

           break;

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

            ………………………………………………

             ………………………………………………

     

           }

  • Thanks for your answer.

    I did this modification, like in your example.

    I can see this behavior : After each call of "UARTCharPut()" in the IRQ function, a character is send on the line.

    Is it the correct behavior ?

    Normaly, with a FIFO, we have to write into the FIFO buffer (in the main function for example). When the Tx FIFO treshold is reached, an interrupt is set and we send the FIFO buffer.

    How can I have this behavior ?

  • Hello Mickael,

    Firstly, I would like to briefly explain the structure of the UART Interrupt application (uartEcho), though the flow is quite obvious.

    • The main() function does the operations like configuring the functional clock, pin multiplexing, FIFO configuration, Baud Rate configuration, Line Characteristics configuration and enabling Interrupts.
    • The Interrupt Service Routine (ISR) is dedicated for transferring bytes on a Transmit Interrupt, receiving bytes on the Receive Interrupt and also on some error conditions.

     The idea that I am trying to stress here is that if interrupts are enabled, the data is written/read from the FIFO in the ISR.  This is usually followed as a standard practice.

     Transmit Trigger Level

    Secondly, I would like to briefly explain the meaning of Transmit Trigger Level.

    The Transmit Interrupt is raised when the number of bytes in the Transmit FIFO is less than the Transmit Trigger Level. Once sufficient numbers of bytes are written to the Transmit FIFO so that the number of bytes crosses the Transmit Trigger Level, the Transmit interrupt is de-asserted. It is again asserted if the number of bytes falls short of  the Transmit Trigger Level. The following figure explains it well.

     

     

     UARTCharGet() transmits single bytes

    True. The above function transmits single bytes. This is used in the ISR because the Transmit trigger level used is 1. If multiple bytes are required to be transmitted, then use  the utility function UARTPuts().

    This function can be found in ‘utils/uartStdio.c’.

    I have rewritten the ISR using UARTPuts() which I think would help you.

    static void UARTIsr(void)

    {

        static unsigned int txStrLength = sizeof(txArray);

        static unsigned int count = 0;

        unsigned char rxByte = 0;

        unsigned int intId = 0;

        /* Checking ths source of UART interrupt. */

        intId = UARTIntIdentityGet(SOC_UART_0_REGS);

         switch(intId)

        {

            case UART_INTID_TX_THRES_REACH:

                if(txStrLength > 0)

                {

                    /* Transmitter FIFO length is 64 bytes. */

                    if(txStrLength < 64)

                    {

                        UARTPuts(txArray + count, txStrLength);

                        txStrLength = 0;

                    }

                   else if(txStrLength >= 64)

                    {

                        UARTPuts(txArray + count, 64);

                        count += 64;

                        txStrLength -= 64;

                    }

                }

                else

                {

                    /* Disabling the THR interrupt. */

                    UARTIntDisable(SOC_UART_0_REGS, UART_INT_THR);

                }

             break;

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

              ………………………………

              ………………………………

          }

    By writing 64 bytes to the TX FIFO at one shot, we are actually buying good amount of time for the processor to do other tasks before we get another Transmit Interrupt. The next transmit interrupt is generated when the UART transmits bytes and the byte count drops below the trigger level.

    Thus, irrespective of the Transmit Trigger Level, the TX FIFO could be filled to the brim if there are sufficient numbers of bytes to be transmitted.

    Please revert back if you have any queries.

    Thanks and Regards.

    Gurudutt.

  • Thank you, your answer was helpful.

    Now I'm trying to use UART1 by using the J10 RS232 connector on the Daugther board of the EVM3358 evaluation kit.

    I changed, in the uartEcho project, the "UART0ModuleClkConfig" by the "UART1ModuleClkConfig" (see below) , the "UARTPinMuxSetup(0)" function code (see below) and all Uart base addresse ("SOC_UART_0_REGS" by "SOC_UART_1_REGS").

    Result : The programme goes in the "UARTIsr" interrupt function, send all characters but nothing appends in my PC terminal (same BaudRate, Stopbit, parity...)

    I tryed each profiles (with the profile selection switch on the DaugtherBoard of the EVM3358 evaluation kit).

    Have you any programs which use UART1 ?

    Code modifications :

    void UART1ModuleClkConfig(void)
    {
       HWREG(SOC_PRCM_REGS + CM_PER_L3S_CLKSTCTRL) |=
                                CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

       while((HWREG(SOC_PRCM_REGS + CM_PER_L3S_CLKSTCTRL) &
        CM_PER_L3S_CLKSTCTRL_CLKTRCTRL) != CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

       HWREG(SOC_PRCM_REGS + CM_PER_L3_CLKSTCTRL) |=
                                CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

       while((HWREG(SOC_PRCM_REGS + CM_PER_L3_CLKSTCTRL) &
        CM_PER_L3_CLKSTCTRL_CLKTRCTRL) != CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

       HWREG(SOC_PRCM_REGS + CM_PER_L3_INSTR_CLKCTRL) |=
                                CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE;

       while((HWREG(SOC_PRCM_REGS + CM_PER_L3_INSTR_CLKCTRL) &
                                  CM_PER_L3_INSTR_CLKCTRL_MODULEMODE) !=
                                      CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE);

       HWREG(SOC_PRCM_REGS + CM_PER_L3_CLKCTRL) |=
                                CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE;

       while((HWREG(SOC_PRCM_REGS + CM_PER_L3_CLKCTRL) &
           CM_PER_L3_CLKCTRL_MODULEMODE) != CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE);

       HWREG(SOC_PRCM_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) |=
                                CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

       while((HWREG(SOC_PRCM_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) &
                                 CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL) !=
                                   CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

       HWREG(SOC_PRCM_REGS + CM_PER_L4LS_CLKSTCTRL) |=
                                CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

       while((HWREG(SOC_PRCM_REGS + CM_PER_L4LS_CLKSTCTRL) &
                                CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL) !=
                                  CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

       HWREG(SOC_PRCM_REGS + CM_PER_L4LS_CLKCTRL) |=
                                CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE;

       while((HWREG(SOC_PRCM_REGS + CM_PER_L4LS_CLKCTRL) &
         CM_PER_L4LS_CLKCTRL_MODULEMODE) != CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE);

       HWREG(SOC_PRCM_REGS + CM_PER_UART1_CLKCTRL) |=
                                CM_PER_UART1_CLKCTRL_MODULEMODE_ENABLE;

       while((HWREG(SOC_PRCM_REGS + CM_PER_UART1_CLKCTRL) &
         CM_PER_UART1_CLKCTRL_MODULEMODE) != CM_PER_UART1_CLKCTRL_MODULEMODE_ENABLE);

       while(!(HWREG(SOC_PRCM_REGS + CM_PER_L3S_CLKSTCTRL) &
               CM_PER_L3S_CLKSTCTRL_CLKACTIVITY_L3S_GCLK));

       while(!(HWREG(SOC_PRCM_REGS + CM_PER_L3_CLKSTCTRL) &
               CM_PER_L3_CLKSTCTRL_CLKACTIVITY_L3_GCLK));

       while(!(HWREG(SOC_PRCM_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) &
              (CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L3_GCLK |
               CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L4_GCLK)));

       while(!(HWREG(SOC_PRCM_REGS + CM_PER_L4LS_CLKSTCTRL) &
              (CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK |
               CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_I2C_FCLK)));
    }

    New "UARTPinMuxSetup" code :

    /* RXD */
                    HWREG(SOC_CONTROL_REGS + 0x0980) =
                    (CONTROL_CONF_UART0_RXD_CONF_UART0_RXD_PUTYPESEL |
                     CONTROL_CONF_UART0_RXD_CONF_UART0_RXD_RXACTIVE);

    /* TXD */
                    HWREG(SOC_CONTROL_REGS + 0x0984) =
                    CONTROL_CONF_UART0_TXD_CONF_UART0_TXD_PUTYPESEL;

    Thanks for your help.

  • Correction for the"UARTPinMuxSetup" code modification part. I using CONTROL defined for UART1.

    New "UARTPinMuxSetup" code :

    /* RXD */
                    HWREG(SOC_CONTROL_REGS + 0x0980) =
                    (CONTROL_CONF_UART1_RXD_CONF_UART1_RXD_PUTYPESEL |
                     CONTROL_CONF_UART1_RXD_CONF_UART1_RXD_RXACTIVE);

    /* TXD */
                    HWREG(SOC_CONTROL_REGS + 0x0984) =
                    CONTROL_CONF_UART1_TXD_CONF_UART1_TXD_PUTYPESEL;

  • Hi,

    • First I corrected the UART1 clock function at the last instruction :
      • Before :

    while(!(HWREG(SOC_PRCM_REGS + CM_PER_L4LS_CLKSTCTRL) &
              (CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK |
               CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_I2C_FCLK)));

    • Now :

    while(!(HWREG(SOC_PRCM_REGS + CM_PER_L4LS_CLKSTCTRL) &
                                     (CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK |
                                      CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_UART_GFCLK)));

    • I still have the same problem with the UART1, I can't set a communication with a PC. Do you have any informations about UART1 ?

    • I tried with the UART2.
    • I can send and receive characters by using the J12 RS232 connector on the Daugther board of the EVM3358 evaluation kit.
    • I'm using a clock configuration close to the UART1 (I changed "CM_PER_UART1_CLKCTRL", "CM_PER_UART1_CLKCTRL_MODULEMODE" and "CM_PER_UART1_CLKCTRL_MODULEMODE_ENABLE" for "CM_PER_UART2_CLKCTRL", "CM_PER_UART2_CLKCTRL_MODULEMODE" and "CM_PER_UART2_CLKCTRL_MODULEMODE_ENABLE".
    • I can't send data through DMA (No DMA interrupt function call after a DMA transfer realised by the "UartEDMATxConfTransfer" function )

    I think than the UART1 clock function seems ok (it's close of the UART2 clock function).

    Could you help me ? Don't hesitate if you need more informations ?

  • Hello Mickael,

    Firstly, I am sorry that I did not reply to your queries within time. I was involved in other tasks and could not devote time to this query thread.

    I understand that you want to use UART1 in your application. Though you have configured the functional clocks and performed the necessary Pin Multiplexing for UART1, you are not able to see any characters on the serial console of the host PC.

    As an alternative, you tried to use UART2 instance making pre-requisite configurations based on the ones you did for UART1.

    Now that you have moved the status of the above query to Verified state, have your issues been resolved? Do you have any related issues for which you need help from our side?

    If you were able to resolve the issue that you faced, I request you to share the fix in this thread. This will help other engineers facing the same or similar issues in travelling to their solution.

    Please revert back for any queries.

    Thanks and Regards.

    Gurudutt.

  • Hi,

    I am sorry but, I selected "Verify answer" by mistake.

    I still have an issue with the UART1 (no data received on the PC hyperterminal) and with the UART2 (No data send when we use the DMA).

  • Hi,

    I found a solution for the UART2 and DMA using.
    The problem came from the DMA clock initialisation perform after the UART2 clock initialisation.
    Issues state :
    • UART0 : OK (all profiles)
    • UART1 : KO (profile 1), nothing is transmit or receive with a PC terminal
    • UART2 : OK (profile 3)
    • UART3 : Only Transmition is available (profile 5), data is send to a PC terminal but nothing is receive from a PC terminal
  • the UARTPuts you are using in the isr, it was used at non-FIFO mode,  you can track UARTPuts , it uses the UARTCharPut( uart_irda_cir.c), and this function, haven't using the advantage of fifo, it waiting for the empty of THR register and shift register.

    so ,in your code ,it was wrong.

  • Hi Gurudatt,

      We are also facing similar problem . Could you please post the clock settings and any other  changes for UART1.

    Thanks

    Ramprasad