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.

uPP DMA issues

Other Parts Discussed in Thread: OMAP-L138, OMAPL138

I'm working with an OMAP-L138 using the UPP peripherial in receive mode.  A FPGA drives the UPP bus.  The ARM is running linux  I've observed two issues that seem to be related.  After a reboot either the upp is perfectly fine and I receive data indefinitely or the upp fails.  When it fails it either never generates interrupts (either EOL or EOW) or it generates interrupts but the data is continually misaligned (the data is offset by 9 16-bit words).  A upp "failure" can be correctly predicted by reading the UPPCR->DB register bit after the peripheral has been initialized by the DSP and before the FPGA starts clocking the UPP signals.  Below is a code snippet which initialized the UPP.  

When the failure mode is mis-aligned data with interrupts I can re-init the UPP peripheral by calling initUppPeripheral() and recover.  When the failure mode is "no interrupt" I can't seem to recover.  

My first question is can the UPP's internal DMA become active even though there is no activity on the UPP signals?  Is there a better way to reset the UPP peripheral so I can recover from this failure?  Of course I would like to avoid the failure all together, so if there is a suggestion or clue as to what I may be doing wrong that would be very much appreciated.

void initUppPeripheral()

{

    volatile int i;

    /* reset the uPP */

    CSL_FINST(uppRegs->UPPCR, UPP_UPPCR_EN, DISABLE);

    while(CSL_FEXT(uppRegs->UPPCR, UPP_UPPCR_DB)){};

    CSL_FINST(uppRegs->UPPCR, UPP_UPPCR_SWRST, RESET);

    if (BIOS_getThreadType() == BIOS_ThreadType_Task)

    {

        Task_sleep(TICKS_PER_MSEC * 5); // test with a very long time

    }

    else

    {

        for(i = 0; i < 400; i++){}; //wait at least 200 clock cycles for reset.

    }

    CSL_FINST(uppRegs->UPPCR, UPP_UPPCR_SWRST, RUNNING);

    /*

     * uPP Channel Control Register

     * - Receive Mode

     * - Single Channel Mode

     * - Single Data Rate

     * - 16-bit Interface

     */

    uppRegs->UPCTL = CSL_FMKT(UPP_UPCTL_MODE, RECEIVE)

                   | CSL_FMKT(UPP_UPCTL_CHN, ONE)

                   | CSL_FMKT(UPP_UPCTL_SDRTXIL, DISABLE)

                   | CSL_FMKT(UPP_UPCTL_DDRDEMUX, DISABLE)

                   | CSL_FMKT(UPP_UPCTL_DRA, SINGLE)

                   | CSL_FMKT(UPP_UPCTL_IWA, 16BIT)

                   | CSL_FMKT(UPP_UPCTL_DPWA, FULL);

    /*

     * uPP Interface Configuration Register

     * - StartA is active high

     * - EnableA is active high

     * - StartA signal is enabled for receive

     * - EnableA signal is enabled for receive

     * - ClockA is normal (i.e. signals align on rising edge of clock)

     *

     * Note: When initializing the uPP peripheral, the uPP interface

     * configuration register (UPICR) must be programmed using a single,

     * 32-bit write.  Writing UPICR fields one-by-one can lead to

     * unexpected results (reference SPRUGJ5B section 2.6.1)

     *

     * Note 2: The clock polarities are confusing; "signals

     * align on the rising edge of clock" means other signals

     * transition on the falling edge of the clock (i.e. start, data)

     * and data is sampled on the rising edge.

     */

    uppRegs->UPICR = CSL_FMKT(UPP_UPICR_STARTPOLA, NORMAL)

                   | CSL_FMKT(UPP_UPICR_ENAPOLA, NORMAL)

                   | CSL_FMKT(UPP_UPICR_STARTA, ENABLE)

                   | CSL_FMKT(UPP_UPICR_ENAA, ENABLE)

                   | CSL_FMKT(UPP_UPICR_CLKINVA, NORMAL);

    /*

     * uPP Threshold Configuration Register

     * - Read threshold for I channel set to 64 bytes

     */

    uppRegs->UPTCR = CSL_FMKT(UPP_UPTCR_RDSIZEI, 64B);

    /*

     * uPP Interrupt Enable Set Register

     * - Enable Channel I (i.e. A) End-of-Line interrupt

     * - Enable Channel I (i.e. A) End-of-Window interrupt

     */

    uppRegs->UPIES = CSL_FMKT(UPP_UPIES_EOLI, SET)

                   | CSL_FMKT(UPP_UPIES_EOWI, SET);

    CSL_FINST(uppRegs->UPDLB, UPP_UPDLB_BA, DISABLE);

    CSL_FINST(uppRegs->UPDLB, UPP_UPDLB_AB, DISABLE);

    /*

     * uPP Peripheral Control Register

     * - Set the EN bit to turn on the uPP peripheral

     */

    CSL_FINST(uppRegs->UPPCR, UPP_UPPCR_EN, ENABLE);

    programUppDmaDescriptor();

}

/*************************************************************************/

inline void programUppDmaDescriptor()

{

/*

* If no DMA transfer is Pending program another DMA descriptor.

*

* Program the DMA Descriptor:

* uPP DMA Channel I Descriptor 0 Register

* - starting address of the data buffer (i.e. 64-bit aligned window address)

* uPP DMA Channel I Descriptor 1 Register

* - Number of lines per window = UPP_NUMBER_OF_LINES

* - Number of bytes per line = UPP_LINE_LENGTH * 2 (BCNTH * 2)

* uPP DMA Channel I Descriptor 2 Register

* - offset between lines = UPP_LINE_OFFSET

* (must align on 64 bit boundary, lower 3 bits are zero)

*

* Note: Comments on E2E forum stating not to read-modify-write these register

*/

if (!CSL_FEXT(uppRegs->UPIS2, UPP_UPIS2_PEND))

{

    m_dmaDescCounter++;

    uppRegs->UPID0 = (uint32_t)&m_uppInputBuffer;

uppRegs->UPID1 = CSL_FMK(UPP_UPID1_LNCNT, UPP_NUMBER_OF_LINES)

              | CSL_FMK(UPP_UPID1_BCNTH, UPP_LINE_LENGTH);

uppRegs->UPID2 = (UPP_LINE_OFFSET * sizeof(uint16_t));

}

}

  • Hi David,

    Please provide the following information.

    1. The code you posted here is your customized one or supplied by TI? If it is supplied by TI, mention the package's name and version details.

    2. Which linux you run on ARM? Is it a DAVINCI (PSP) Linux? version details??

    Regards,

    Shankari

  • The code snippets are from DSP code.  In my project the DSP controls the UPP peripheral.  The macros used for register access (e.g. CSL_FINST, CSL_FEXT, etc) are from the chip support library /Texas Instruments/biospsp_03_00_01_00

    What I have noticed is that after a reset and before the UPP signals from the FPGA are active if I read the UPP registers I see two conditions; UPP init success and UPP init failure.  When the UPP init is successful I get register values as listed below (all values in hexidecimal).

    UPPCR = B

    UPCTL = 20000

    UPICR = 18

    UPISR = 0

    UPIER = 0

    UPIES = 18

    UPEOI = 0

    UPIS0 = 11F00000

    UPIS1 = 10000

    UPIS2 = 1

    UPID0 = 11F00000

    UPID1 = 21D4C

    UPID2 = 1D50

    When I observe an UPP init failure the only different in register contents is listed below

    UPPCR = 8B

    UPPIS0 = 11F00xxx (where xxx is always something less than 400)

    UPPIS1 = 10xxx

    UPPIS2 = C1 (the upper nibble varies)

    I can detect this condition and can only seem to recover if I tell the FPGA to provide UPP signals (i.e. start clocking data) and then re-init the UPP peripheral.   The value of UPPIS0 then progresses to 11F00400 and I appear to recover every time.  I'm concerned I don't have a handle on why a DMA transfer appears to false start and my patch work-around is something I won't want to go into production with. 

  • I have been revisiting the above issue and simplified my setup by removing my FPGA board and making use of the DLB mode of the UPP.  I couldn't get the loopback to work unless I program the transmit and receive CLKDIVn register bits (UPICR register) to be the same value even though the receive CLKDIVn should be ignored.  I then found a E2E posting reporting the same issue (see below).  Is this a UPP bug and if so why isn't it included in the latest errata?

    http://e2e.ti.com/support/dsp/omap_applications_processors/f/42/p/136983/504626.aspx#504626

  • I've also have a significant finding regarding my original issue.  I noticed when I configured the UPP port for transmit the UPP clock signal is always active.  My original setup, where I receive on UPPA from a FPGA, the FPGA only generates a clock when the UPP enable signal is asserted.  I made a change to the FPGA to always generate a UPP clock and now my UPP initialization routine works every time.  Any comments or insight you can provide as to why the UPP clock needs to be continually active, or at least during the UPP initialization process?

  • David McCreight,


    You configured uPP as a receive mode with FPGA.
    Here you have used channel-A in receive mode as per your code.
    In this case uPP init gets failed at regular intervel period.
    I think so, it's not correct way to reinit uPP at the time of every uPP failure in the real time.
    Refer the uPP functional block diagram from OMAPL138 TRM for receive mode.
    From 33.2.1.2 Receive Mode (Single Data Rate) section gives the detail for clock setting.
    You will get steps for initializing and running the uPP peripheral in various
    modes,under the section "33.2.6 Initialization and Operation".