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.

TMS570LC4357: How to configure SCI+DMA for receiving varying sized packets?

Part Number: TMS570LC4357

In a multitasking environment we want to use the SCI at 921kbps.

To avoid overloading the processor, we want to use DMA.

On the transmit side, it seems easy.

Store packets in a packet buffer, and send each packet using DMA.

When the packet transmission is complete, take an interrupt, and send the next packet.

On reception, it is more difficult.

What you would like to do is to implement a ring buffer, letting the DMA fill the ring buffer.
At the end of the ring buffer, the DMA should  reset to the start of the ring buffer.
Some solution is needed to guarantee, the ring buffer does not overflow.
Alternatively, the DMA should stop at the end of the buffer, and generate an interrupt.
In the interrupt, the DMA is reconfigured to start at the beginning of the buffer.
(The SCI then probably need to have a FIFO allowing the interrupt to be processed
without losing characters)

A "getc" routine would check the current status of the DMA to determine if any characters
have been received, and if so, return the character  or else, a negative status.

Since there appears to be no way to determine the status of the DMA, since
the Working Area is only updated when channels are changed, and appears not to
be updated with the last transfer, this seems not to be possible.

So how do you reliably use the DMA with SCI on receiving varying sized packages?

Is it possible to set frame size to '1', and block size to the size of the ring buffer?

Would the Working Area be updated every time a frame (one character) is received?

  • Hello,

    To reduce CPU load when Receiving or Transmitting data in interrupt mode or DMA mode, the SCI/LIN module has eight separate Receive and transmit buffers. Multi buffered mode is enabled by setting the MBUF MODE bit. The length of the multi-buffer is 8 bytes.

  • I know about that, but I would like to be able to stay around from a significant number of interrupts for a millisecond a time at 1 Mbps.

    During that time I can receive 100 characters.

    Is there no way to use the DMA and check how far the DMA has proceeded?

  • Hi,

    There are 4 DMA interrupts:FTC (frame complete), LFS (last frame start), HBC (half block complete), and BTC (block complete).

    For block transfer,

    • If the number of frames n is odd, then the HBC interrupt is generated at the end of the frame when (n+1) / 2 number of frames are left in the block.
    • If the number of frames n is even, then the HBC interrupt is generated at the end of the frame after n/2 number of frames are left in the block.
  • I am aware of this, but I do not see why this would solve the problem.

    The sender can in an y-modem communication send packets if size 1, 2, 133 and 1029 characters.

    You do not know in advance which type of packet you will receive.

    If You set up the interrupt to receive 129 characters in a frame, you will never get an interrupt,

    when the sender sends a 1 or 2 byte packet.

    If the sender does send a 129 byte packet, and a character is lost, you will not get an interrupt.

    If the sender sends a 1029 byte packet, you will receive 7 interrupts, but the remainder of the packet is 98 bytes,

    so you will not receive the final interrupt.  (7x129 + 98 = 1029).

    You cannot read the ”current” RAM because this will only be updated when a DMA channel is swapped out.

    When the final part of the packet is received, the DMA channel appears to drop the transfer, since there is nothing left to do.

    Why would the HBC interrupt be useable?

  • Hello Ulf,

    The easy way is that the transmitter sends a header first. The header contains the information of the following data packet. The 1st byte of ymodem is STX or SOH, etc. STX means the data packet size is 1028 bytes, and SOH means the packet size is 128 Bytes (excluding the CRC1, CRC2, etc). The data packet is smaller than 128, fill the packet to 128 with 0x00. I don't have other idea to handle thdynamic packet length.

  • Yes, you can know from the header the length of the packet.
    The problem is that when you are running the serial port at 1 Mbps, a character is coming in every 10 us.

    Assume you have some critical processing, where you disable the interrupts for 100 us
    and want to run Y-Modem in the background.

    If you wait to enable the DMA until you have checked the first character, you may lose up to 9 characters
    due to disabled interrupt, so your Y-Modem packet will be corrupted.

    If you have the DMA enabled, you would like to start parsing any incoming data.
    The problem is that you might have received the SOH or STX character, but the the stuff is still inside the DMA
    controller, and the Current RAM has not been updated, you cannot tell that a character has been received.

    The other end might send a cancel message, in which case you are again screwed.

    I suspect that there is no other solution than to add an external UART which adds cost and board space.

    My suggestion is that you T.I. create an Errata for the part explaining that the DMA controller is broken
    when you try to receive varying size packets.

    What is the status of this part?
    We only plan to go into production end of next year, so there would be time to fix the errata in the DMA.

  • Hello Ulf,

    The DMA on our devices doesn't have the feature to support variable packet size. It is not a bug. Do you know which device supports this feature?  

  • You could look at the PDC on the Atmel (Microchip) Arm microcontrollers.

    PDC = Peripheral DMA Controller.

    It is not as advanced as the Hercules DMA controller,

    but all those fancy features with FIFOs and Burst Access etc, are wasted

    when you receive one character every 10 us.

    It does exactly what is needed.

    Each PDC is dedicated to a single serial port, and each serial port has two PDCs.

    One for transmit and one for receive.

    The PDC has two sets of registers: "Current" and "Next".

    Each register set has a single address, and a byte counter.

    When the byte counter reaches zero, the "Current" register set is loaded from the "Next" register set.

    This means it inherently supports a circular buffer for receive.

    You do not need to reprogram the "Next" register set ever.

    When you start reception, you initialize the PDC and a "Read Pointer" which is maintained in S/W.

    Whenever you want to read a character from the serial port, the "getchar" routine will compare

    the PDC address register with the "Read Pointer". If they are the same, then no characters have been received.

    If the PDC address register differs, then you read one character at the time,

    until the "Read Pointer" and the PDC address register are the same.

    The only thing you have to keep track on is to avoid overflow.

    That can be done in a timer tick.

    If the timer tick occurs each millisecond, it should set a flag, which is cleared every time

    the getchar routine reads from the serial port.

    If there is enough space in the circular buffer for a complete Y-Modem packet,
    then you should never lose characters, because the PDC will stop due to lack of data.

    For transmit, you maintain a linked list of transmit buffers in software.

    You set up the PDC to "Current" register set to send one packet,

    and set up the "Next" register set to send the next packet.

    When the "Current" packet has been sent, the PDC immediately starts sending
    the "Next" packet, by writing the "Next" value to "Current". Then an interrupt
    is generated, allowing the CPU to program the 3rd packet into the "Next" register.

    You always have the time to send a new packet to reprogram the PDC for the forthcoming packet.

    If the packets are 100 bytes, your interrupt response time must be less than one millisecond,
    which is all the time in the world.

    I hope that you realize that when you are saying that the Hercules DMA does not support

    varying sized packets, customers like me are hearing that:

    "the Hercules Serial port does not support high speed communication".

    "the Hercules chip does not support anything that requires long latencies"

    The UART1 and UART2 at least have 8 level FIFOs, but the UART3 and 4 does not
    if I understand things correctly.

    We have two critical functions, which needs the two UARTs with FIFOs.

    We want to use one of the other serial ports for a console and software downloads.

    One issue that came up is that when you are typing some keys on a PC keyboard
    it may send THREE characters in a sequence, which may cause overruns in the serial port
    even if you type only one key per second.

    We may have to reduce the speed to a lot lower, to guarantee that we can handle
    interrupts beeing disabled for extended times.

    I know you cannot do a lot about the current chip, but you should be aware that it does have deficiencies
    making the chip (and any other chip using the same IP block) unattractive for certain applications.