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 problem when work in receive mode

Other Parts Discussed in Thread: AM1808, OMAP-L138

I have some problems while using the upp in receive mode

1:Before I program the dma register,I check the UPIS2 register,the PEND bit was 0,,but after I program UPID0-UPID2 one by one,the DPE interrupt occured;

2:When a dma transfer finished,we can get an end of window interrupt,but the ACTIVE bit in UPIS2 register and DB bit in UPPCR register were still 1,while PEND bit in UPIS2 was zero. If I start a new dma task,I found the new one should have a large window size,otherwise the task would not be finished,the end of line and end of window interrupt of the dma task did't occure.

Any suggestion ?

  • What values are you programming into the UPIDx registers?  The DPE interrupt could indicate that you are specifying an invalid transfer.  Also, when programming the UPIDx registers, it's best to program each register with a single write.  Using multiple read/modify/write operations to set individual register fields separately could cause an error.  Here's an example of the correct way to program the UPIDx registers:

    UPID0 = windowAddr;
    UPID1 = (lineCount << 16) | lineSize;
    UPID2 = lineOffset;

    ... and here's a way that I would not recommend:

    UPID0 = windowAddr;
    UPID1 = lineCount << 16;
    UPID1 |= lineSize;
    UPID2 = lineOffset;

    Regarding question #2: how small can your window be set before you see the problem?  Your procedure sounds correct, but it's easy for the CPU to fall behind when the uPP is operating on small buffers at high speeds.  In this case the culprit may actually be the ISR, which can mask interrupts if they occur too quickly.

    Hope this helps.

  • Thanks for your help.

    1:I do program the dma registers as you recommend,like this:

    UPID0 = 0xce600000;

    UPID1 = 0x00011000;

    UPID2 = 0x00001000;

    But after  write UPID2,DPE interrupt got.

    2:question #2:I don't think it's an interrupt lost,because I monitor the UPIS0-UPIS2 registers, it's looks like when I start a new dma task,the upp kernel process the old one.

        For example,I start a 1024 bytes transfer(start address 0x00000000),after a while,I got the end-of-window interrupt,and the PEND BIT in UPIS2 was 0,but the UPIS2.ACTIVE bit and UPPCR.DB bit was 1,I check the 1024 bytes data the upp reveived,they were correct.So I  start a new dma task,assume a 4096 bytes transfer,the start address is 0x00000400,after finished the UPIDx registers program,I found the UPIS0 register's value was still 0x00000080,smaller than 0x00000400,the new transfer overwrite the old block's data,That looks like the old task run again, so if the new task's windows size smaller,it could not finish.

    My question is why the old task process again?

     

  • The DPE interrupt could be caused by using an incorrect sequence of events to initialize the uPP peripheral.  Are you following the procedure established in section 2.6.1 of the uPP User Guide?  Specifically, you should not program the UPIDx registers until after the peripheral has been configured and enabled.

    Regarding question #2, is the problem just that the UPIS0 register displays an incorrect value, or can you tell that the DMA is actually writing to a memory location that it shouldn't?  Also, are these addresses (0x00000000 and 0x00000400) just given as an example?

  • Thanks a lot!

    Here's my initialization sequence:

    UPPR->UPPCR |= 0x00000010;

    udelay(10);       // wait more than 200 clock cycles

    UPPR->UPPCR &= ~0x00000010;

    UPPR->UPCTL = 0x00000000;

    UPPR->UPICR = 0x10181018;

    UPPR->UPIVR |= 0x0BBB0BBB;

    UPPR->UPIES |= 0x00000808; 

    UPPR->UPPCR |= 0x00000008;

    I got DPE interrupt events after USPIDx registers has been programmed as in previous posts. Any suggestions?

     

  • For question #2:I mean that as the old task finished,I program the new tone,but the old task run again,not only the UPIS0 display an incorrect value,but also the target memory of the old task  has been wrote agin.This can be confirmed.

    My UPP tranfer task real address are 0xc3600000 and 0xc3600400(Base address of the DDR is 0xc0000000),but it's looks like 0xc3600000 - 0xc36003ff has been writen twice.

  • Your initialization sequence looks correct.  If you haven't done so already, I recommend taking a look at one of the uPP that TI provides for DSP/BIOS to compare what may be different between our code and yours.  One driver is included with the BIOS PSP, and the other is available on the TI wiki:

    The above page also includes a link to the BIOS PSP download page.  The source code for the non-PSP driver is smaller and may be easier to understand.

    I want to focus on resolving the first question, since the DPE interrupt could also be the root cause of your problems programming subsequent transfers.

  • Hi,joe!

        I have look at the source code you suggested,the initialization and dma programming code almost the same as mine.The difference is we wrote the upp transfer driver based on the Linux kernel.

        So we do the same upp transfer work on the U-BOOT, it's work! There were not get a DPE interrupt after DMA programming,and the transfer can be finished as expected.

        We still not fnd the key difference between linux and uboot which leads to the result,perhaps the other peripherals can influence on the upp module?we enable emac,uart,flash,pru,emifa,edma ,usb and other modules while linux booting.

    Can give me some advice?

     

    By the way:I found the upp version NO.  read form the register is different from the RM(http://focus.ti.com.cn/cn/lit/ug/sprufw4/sprufw4.pdf) described,form register is 0x4423 1100,which is 0x4423 0100 in the RM.(Our chip is am1808)

  • It's interesting that you only encounter this issue under Linux.  I have never tested uPP under Linux, but there are a few things that I could see interfering with normal uPP operation:

    • The scheduler could break up your uPP operations and insert unexpected delays between them (especially if other applications or threads are active)
    • The DMA registers may not accept virtual addresses for data buffers

    The second one seems more likely to pose a problem.  Typically, pointers in Linux applications contain virtual addresses instead of actual, physical memory addresses.  The uPP peripheral can only understand physical addresses, so you should not program virtual addresses to the UPIDx registers.  Also, buffers allocated using malloc() or similar APIs under Linux may not be contiguous buffers.  This will also cause problems since the uPP DMA assumes the buffers are contiguous.

    If you haven't done so already, I suggest using the CMEM module to allocate contiguous data buffers for use with uPP.  CMEM also includes APIs to convert between virtual and physical addresses for any buffer that it allocates.  This will be a big help for using uPP in a Linux context.

    CMEM may not be included with the SDK for your device, but the CMEM release targeting OMAP-L138 should be compatible with AM1808.  Hope this helps.

  • Thanks for your reply!

        For your first suggestion,I disable all interrupt while init  the upp module and program the upp dma transfer task,but the result is the same as before,DPE is still got.

        For the second,I do write a physical address to the UPID0 register,not it's virtual address,and I mentioned above that the first transfer after a rest Operating can finished,and the data are correct too,but if I program another dma task,the first task run again,and the memory address we programed in the first task  would be overwrite.  

     

  • Hi joe!

     I know why the DPE occured.

    I define a structure as below to access the upp module ctrl registers:

    struct UPPR

    {

    volatile unsigned int UPVER;

    volatile unsigned int UPPCR;

    ....

    }__attribute__((packed));

     

    As you see,I use the key word "packed",so my instruction like "UPPR->UPID2 = 0x0" was translated to 4  machine instructions to write the UPID2 register in bytes,so the DPE occured.It's work correct after I remove the "packed" key word of my structure. 

    Thanks for all your help!

  • I'm glad to hear that your problem is resolved.  Thanks for sharing the solution; I'm sure other people could run into this problem in the future.