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.

RM48 USB device with DMA

Hi there,

I'm trying to set up an USB device with system DMA. On transmit side everything working well. On receive side the DMA itself is working, so I could see that the right amount of data with the right values are transferred from USB to the RAM. However in the Receive FIFO Status Register (RXFSTAT) the length is 0. So it says that no bytes are received.

My first thought was that this register could not be used to check how much data are received in case of DMA transfer, so I wanted to use the DMA channel related working control packet to get the current address of the last transfer. However at the 0xFFF80800 address the data is not the one I expect.
What I do is to set up a DMA channel 0 to transfer from USB DMA_DATA register to a RAM location with element size 8 bit, element count 1, frame count 64. USB is set up to receive 1 transaction in the RX_DMAx register. When 1 byte is sent on USB the EOT transfer interrupt is correctly received. I see in the DMA Port B Active Channel Destination Address Register a destination address of the initial address + 1, but I could not see anything in the DMA working control packet registers. Obviously I could not use the Port B Active Channel Destination Address Register, because in the meantime a different DMA transfer could be executed, that's why I wanted to use the DMA channel related working control packet. But it seems to me, that those area is not updated at all.

In this one byte example the DMA transfer is not finished yet, because there will be 63 frame left, but the same happens if I send 64 bytes on the USB in one packet and the DMA transfer itself finished.

Could you please suggest a solution how to read out the amount of received data from USB in case of DMA?

Thanks in advance!

Peter

  • Peter,

    Your question has been forwarded to our USB expert. He will be back to you as soon as possible.

  • Peter,


    Peter Begella said:
    However at the 0xFFF80800 address the data is not the one I expect.

    Yes, the DMA does not write back the working control packet values to the control packet RAM unless it needs to switch channels.  This is done for performance reasons but it means you can't simple check the DMA's RAM to see how much progress it has made, because there could be work in progress on your transfer that's not yet written back.   Also if it just completes the control packet there isn't any reason to write it back to control packet RAM.  So this isn't a reliable way to do what you want.

    If the data that you are receiving over USB is fixed in size (you used 64) then you can make the DMA generate an interrupt when it finishes the control packet which you would also set for the same size. 

    I haven't ever tried this, but if you need to get the # of bytes before the packet has finished, you could try triggering two different DMA channels off of the same DMA request.   The DMA works on channels in a fixed priority, so let's say the first channel that is USB triggered moved the USB data to RAM and the 2nd channel moved a count from a table in flash (holding 0, 1, 2, 3, etc) to a fixed location in RAM.  Then you could read that 2nd location to see how much data has been transferred.   There could be some race condition here if you have too much else going on in the DMA and you have USB transfers coming in really really fast, but I don't think the latter will be likely especially if the data is coming in on different usb frames 1ms apart.

     

  • Hi Anthony,

    Hmm, now I understand how the working control packets are working. So it is possible to somehow detect, that those "registers" are updated? For example I could use the currently active DMA channel. If it is not the one I used for the transfer than I could assume that the working control packets are updated?

    In my example I used 64 bytes, because the maximum packet size is 64 bytes. However an USB packet could contain less than 64 bytes. In this case if I set up the DMA transfer from my example I'll get a partially done DMA transfer. Of course the interrupt is triggered, while the transfer has ended. ( USB interrupt, I do not use DMA module interrupts )

    So there is no other way to check the amount of received data? Using two DMA transfers seems to me a little bit extreme.

    BR,
    Peter

  • Is there any updates regarding this issue?

    What about transfers with more than 64 bytes data?

  • Peter,

    There isn't any reliable way that I know of to read the working control packets.  I think even if you force them back into memory that you could read, they might get loaded back into the DMA and more transfers could be done by the time you get around to reading fromt that memory.

     

  • Anthony!

    Thanks.

    So there is no other way to now how much data received on USB, except of preparing a second DMA transfer?

    Peter

  • Peter,

    I'm not aware of any better way involving the central DMA controller.

    Have you looked at the EOT interrupt and whether this might be useful for what you are trying to do?

    29.3.27.3 End of Transfer Interrupt (IRQ_SRC.RXn_EOT)
    This interrupt signals that the core has detected an end-of-transfer (EOT). EOT occurs in the two following
    cases:
    • When the last valid transaction to the endpoint is either an empty packet (ACK and buffer empty) or a
    packet whose size is less than the physical endpoint buffer size (ACK and buffer not full)
    • When the number of received transactions has reached the programmed value in the
    RXDMAn.RXn_TC field, if the RXDMAn.RXn_STOP bit has been set by the CPU
    After an end of transfer interrupt, the CPU must set CTRL.SET_FIFO_EN for the endpoint to reenable the
    channel.
    The CPU must not initiate a new RX DMA transfer until it receives an end-of-transfer interrupt.