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.

TM4C1294NCPDT: How to prematurely trigger ping-pong buffer?

Part Number: TM4C1294NCPDT

Hello,

I am using the uDMA peripheral on a TM4C1294 microcontroller to automatically move data from a UART FIFO to a 64-byte buffer in memory. I have the uDMA configured as a ping-pong buffer, which should work great when I'm getting a constant stream of data, because an interrupt is triggered when the primary buffer is full and uDMA automatically switches to filling the alternate buffer. However, there will come a time when the data stream will stop, but there will probably be data left over in one of the buffers. When this happens, I would like to prematurely swap the buffers so that any future incoming bytes go into the empty buffer. Then I can safely dig through the partially-full buffer, copy out the data I need, and be on my merry way.

So here's my question: what is the best way to trigger this buffer-swap behavior? Is it as simple as setting XFERMODE to STOP in the DMA channel control word? If so, is there any danger in dropping a byte if I set it to STOP while uDMA is in the middle of transferring a byte? Or will it automatically swap to the other buffer and continue adding incoming data to that instead?

Thanks!

  • Hello Adevries,

    In general I would think you'd want to setup some sort of 'watchdog' mechanism. Each time you flip buffers, set a flag that a timer clears, and then if the timer finds the flag isn't set it could trigger your desired data fetching.

    I'm not really sure about the way to go about this though as the ping pong mode is really usually used for continuous data transfers. I've never really considered this particular use case. 

    I think there would be risk that if you set STOP at the wrong time, you'll lose data because ping-pong mode isn't really configured to handle the interruption in between.

    Let me talk with my colleague some tomorrow and see what we can come up with that would work for your application.

    Best Regards,

    Ralph Jacobi

  • Hi Ralph,

    Thanks for the reply! Yes, I'm curious what ideas you or your colleagues may have. Overall, I'm looking for an efficient way to move bytes I'm receiving on UART to a USBBuffer to be transmitted. I'm open to other ways to accomplish this besides ping-pong mode too.

    If it helps, I think these are my requirements, starting with the highest priority:

    1. All data must be moved from UART to USBBuffer accurately and in the right order (i.e. cannot drop bytes and cannot flip the order of bytes)

    2. Use as few processor cycles as possible to accomplish this.

    3. Bytes do not need to be moved immediately from UART to USBBuffer. There can be a slight delay (50-100ms) as long as requirement #1 is met.

    Currently, I'm thinking about using uDMA in burst mode only (xfer = 8 and arb size = 8) to move most of the data (so I know exactly how many bytes were written each time the interrupt is called), then have a tick function called every 50ms, and if no more data is written to the buffer between two tick function calls, it will clear out any bytes remaining in the UART FIFO. But I don't have all the details of that worked out, and I'm not sure if it'll work. 

    Looking forward to your ideas!

  • Hello Adevries,

    Currently, I'm thinking about using uDMA in burst mode only (xfer = 8 and arb size = 8) to move most of the data (so I know exactly how many bytes were written each time the interrupt is called), then have a tick function called every 50ms, and if no more data is written to the buffer between two tick function calls, it will clear out any bytes remaining in the UART FIFO. But I don't have all the details of that worked out, and I'm not sure if it'll work. 

    That implementation may work for a lot of cases but I feel that there may be corner cases that could impact it. I don't know how much control you have over the external systems.

    One suggestion we think could possibly work would depend on if you can ensure that the UART data comes with a packet header on the first transfer to indicate a transfer size.

    If so, maybe using Scatter Gather mode is a better option due to this:

    In Memory Scatter-Gather mode, the primary control structure is used to program the alternate control structure from a table in memory

    So in theory you could get a header with how many bytes will be received and use that to configure the alternate structure accordingly. Then after all bytes are received, you set it up to wait for the next transfer to go to the primary structure.

    Our thoughts are this would be a better way to do it than rely on timeouts because its hard to determine if a transfer has stopped for long enough / wouldn't start again.

    Best Regards,

    Ralph Jacobi

  • Hi Ralph,

    Unfortunately, I can't really control the incoming UART data for this application. But I will keep that in mind the next time I'm solving this issue.

    Our thoughts are this would be a better way to do it than rely on timeouts because its hard to determine if a transfer has stopped for long enough / wouldn't start again.

    Yeah, I ran into the same questions when I was trying to code my first and second ideas haha. For the moment, the solution I've settled on uses DMA for the outgoing UART data, but no DMA for the incoming data. I'm just using the Rx FIFO, receive interrupt, and receive timeout interrupt to get all the data from UART. So far, that doesn't seem to be slowing down the rest of my code noticeably, but I'm sure I'll be back if that changes.

    Thanks for all your help! I appreciate it!

  • Hi Adevries,

    Yeah I've often seen that it can be challenging to manage UART when you can't get a packet header. Sounds good for now, thanks for closing the loop. Glad my offered insights were helpful.

    Best Regards,

    Ralph Jacobi