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.

CCS/TMS570LC4357: DMA "Current" Addresses not updated.

Part Number: TMS570LC4357
Other Parts Discussed in Thread: HALCOGEN,

Tool/software: Code Composer Studio

I am using the HALCoGen generated code to do a software DMA transfer.

The DMA copies 1 frame of 4 KB from/to external memory.

0x64000000 => 0x64000100

The first 256 bytes are filled with 0x55.

After the DMA transfer, the "Initial" DMA registers at 0xFFF80000 contain

ISADDR = 0x64000000 IDADDR =  0x64000100 ITCOUNT = 0x00010800

The "Current" registers at 0xFFF80800 contain garbage.

CSADDR = 0xa66fcd6d CDADDR = 0x7ee6b6fb CTCOUNT = 0xFFFEB9FF.

Why is that?

Are the "Current" registers accessible somehow?

Best Regards

Ulf

  • Hello,

    Can you check whether this is helpful for you:

    Best regards,
    Miro

  • I have set the MPU 0xF0000000 / 512MB to DEVICE_NONSHAREABLE.

    This I assume means that it is not in the cache.

    To be safe, I call _dCacheInvalidate_(); from HAL code before I print stuff out from the dmaRAMREG->WCP[0..31].xxxxx.

    Still I get only garbage.

  • Maybe it should be DEVICE_SHARABLE?

  • Hello Ulf,

    Did you solve this issue?

    Best regard,
    Miro

  • No, it is not solved.

    I would like to have the recommended setup for the Memory Protection Unit for the ”Current” pointers..

    Do the DMA MPU need a setup for the ”Current” pointers as well?

    I am also confused by the datasheet saying that the TMS570LC4357 having 8 MPU regions, while HALCoGen has 16 regions.

    Which is correct?

    It would be good if HALCoGen supported ”named” regions, and a capability to move a region up and down the list.

    Best Regards,

    Ulf

  • Hello Ulf,

    There are up to 16 MPU regions for CPU. There are separate 8 MPU regions built in DMA unit.

  • Thank You,

    The original problems remain though.

    How shall I configure the MPU to be able to read from the DMA ”Current” pointers?

  • Hello Ulf,

    The primary control packet is used to store the channel information of each channel. When the DMA works on several channels, it needs to save the current context of each channel in the working control packet.

    The working control packets are stored in the local DMA memory. They are memory mapped. The working control packet for channel 0 starts at 0xFFF80800 and the working control packet for channel 1 will start at 0xFFF80810. The working control packet is only updated when a channel is arbitrated out. If you have two channels and configure them in round-robin arbitration then the DMA will make some transfers for channel 0 and arbitrates to channel 1 in a round robin fashion. Each time the channel is arbitrated out, its context is saved in the working control packet. Let's say each channel has 16 elements per frame and you are using 8-bit transfer size. After 4 elements for channel 0 is transferred, the DMA will switch to channel 1. It will save 12 as the transfer count in the WCP for channel 0 so that later when it switches back to channel 0 it knows that there are still 12 elements left to transfer.

  • Hello Ulf,

    The priority scheme is configured in port control register. Initially, the priority list is sorted according to the fixed priority scheme. Writing "1" to bit [1:0] of port control register, the rotation scheme will be used.

  • OK

    In my test, I am only using one DMA channel.
    This means that it is never switched out, and thus the "Current" is never updated.

    This is unfortunate.
    I think that a proper behaviour would be to store the "Current" of the active DMA
    if nothing else is going on.
    I suggest, you update the datasheet with this information.

    One of our applications is to use DMA for the serial ports where we want to
    receive and transmit using DMA to a circular buffer.

    We will send by having the putc routine write to the circular buffer. If it is full
    we should drop the character.

    If the DMA for UART TX is the last DMA to be processed, there is no way to
    find out how many free characters there are in the circular buffer.

    Is there a way to force the "Current" to be updated that *works*?

    What happens if I do a short S/W DMA on another channel?

    Will the "Current" from the original channel be updated, even if that DMA
    access has been completed, or only if it is still in progress?

    We will have a similar thing going on on receive.
    We will setup the DMA to receive to a circular buffer,
    and the method to find out how many characters have been received
    would be to check the "Current" pointer.

    If the "Current" pointer is not updated, because no other DMA is happening
    the receive routine may be stuck waiting for a character which has been received
    but we have no way to find out.

    How should we setup stuff so we can receive arbitrary sized packets
    on the serial port with DMA support?

  • Hello,

    1. Is there a way to force the "Current" to be updated that *works*?

    QJ> the current is updated to work package only when the channel is arbitrated.

    2. What happens if I do a short S/W DMA on another channel?

    QJ> The channels are serviced in an ascending order according to the channel number. The lower the channel number, the higher the priority. A channel will be arbitrated out whenever there is a higher pending channel.


    3. Will the "Current" from the original channel be updated, even if that DMA
    access has been completed, or only if it is still in progress?

    QJ> Only updated when it is arbitrated.

    4. How should we setup stuff so we can receive arbitrary sized packets
    on the serial port with DMA support?

    QJ> A DMA request is generated for each received byte, and data is transferred to the destination buffer.

  • Yes, the UART DMA will receive the character, but there seems to be no way to find out that the DMA has transferred the character.

    In a protocol like y-modem, the sender sends a packet of 133 or 1029 characters, and you do not know in advance how many bytes there will be in a packet, until you have received the header.

    In a generalized problem, the sender can send an arbitrary sized packet so you cannot set a fixed size in the DMA controller.

    The proper way to handle this in most MCUs is to let the DMA write characters to a circular buffer  as characters arrive, the Block Transfer Complete will wrap around the pointer to the circular buffer.

    S/W will maintain a read pointer, and let the ”getc” routine check the DMA current pointers to find out if the circular buffer is empty.

    If the current buffer pointers cannot be read reliably, then the DMA cannot be used.

    Again I ask how you can use DMA with the UART, or rephrased:

    How can you write a getc routine which can read out ALL received UART characters BEFORE the DMA has completed a frame or a block.

    I.E. you set up the DMA to handle a 2048 byte block, receiving a byte at a time.

    After you have received 133 characters, your main routine calls getc 133 times and retreives a character each time.

    How can such a getc routine look like?

  • Hello,

    I didn't use DMA to deal with variable length before. I will think it over and let you my comments later. Sorry for late response.