DMA from SRAM Buffer to UART TX adding/missing characters

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
ThBe_4703766
Level 1
Level 1
First question asked First reply posted Welcome!

Hi,

I've setup a DMA transfer from a software buffer (which is filled via an Ethernet receive) to the TX of a UART. I've set it up so when the TX interrupt is fired, it will send a software request to the DMA when the TX FIFO is not full and TX complete are satisfied. I've set it up using a software request as I couldn't seem to get it working from a direct interrupt.

The DMA is initialised each time the Ethernet receives data (due to having a dynamic buffer size). The DMA is setup as 1 TD which is disabled once the transfer count has been completed. This is followed by an NRQ which turns off the UART TX interrupt and tells main.c that the DMA is "free".

This all seems to work fine for the most part. Except, I'm having an issue which I believe is related to the DMA and TX FIFO. If I send a 4MB file down the Ethernet and then check it at the other end of the UART TX, there seem to be characters which are out of place. For example in the below extract from a log, you can see that the word "across" has become malfomed and "he" is missing an "r":

"her feet, for it flashed acrosr he mind that she had never"

It appears from the above that the "r" character has happened 4 bytes before it was supposed to happen and in turn replacing the "s" in "across". Another example is the following below:

Either the well was very deep, or she fell very slowly, fo,r she

In this example, you can see that the "," after "slowly" has appeared again 4 bytes later in "fo,r" but this time didn't replace the "r". My TX UART buffer is of size 4 bytes so this may just be a coincidence but I'm not sure why this is happeneing? There are cases with lower sized files where no errors happen at all but it will always error 10 or so times when sending a large file across the Ethernet to the UART TX. Any ideas why this might be happening would be appreciated?

I've attached a minimal stripped back version of the project if you'd like to view the settings etc.

0 Likes
3 Replies
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

ThBe,

The project is too convoluted to test it. I think that issue might be in UART_Tx interaction with DMA. It is my understanding that currently all interaction between UART_Tx and DMA is performed by means of interrupt:

DMA-UART_01a_A.png

I believe that instead the DMA transfer should be directly controlled by UART_Tx interrupt hardware line. The DMA Hardware request should be set to LEVEL, so it will automatically keep UART_Tx FIFO populated (until finished). I am not sure what is going to happen with ISR_UD2_TX, it is possible that it will no longer be needed in this case.

DMA-UART_01a_B.png

/odissey1

0 Likes
lock attach
Attachments are accessible only for community members.

Hi BoTa,

I gave your suggestion a go of moving away from the software triggered DMA request via the ISR method. I connected everything up as you show in your second picture. This didn't seem to work. It led to only the first 3 or 4 charcters being correct and then the rest was garbage. There were also cases where if the message was longer than 5 characters, it would cause the project to deadlock (as it is waiting for the current DMA to finish in which it never does).

I did try connecting the ISR_UD2_TX to the TX Interrupt also. I then found that if I have a CyDelay(1) within that ISR, then the DMA functioned correctly but still left me with the problem in my original post.

To try to make the project more testable for someone else, I tried adding in a UART which would act almost like the Ethernet. So any input on that UART would all be read in then passed to te DMA to output on the other UART TX. With this build however, I ran into another problem where only the 2nd, 3rd and 4th characters get DMA'd to the other UART's TX. For example, if I send the word "thing", I get: "hin" on the other end. It also only seems to work if I put a breakpoint on line 147: if (bytesOnEthRx > 0)

I've attached both builds. Thanks for your help so far.

0 Likes
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

ThBe,

I've taken a look at your first project upload.

I have a few questions.

Do you have some flow control on the Ethernet Rx comm?

You've got the SPI Rx data rate for the Ethernet at 18Mbps.  However your UART is at 115.2Kbps.   If you don't have Ethernet flow control, you could run into a SRAM buffer overrun condition.

The UART is using "Tx FIFO Not Full" to drive the DMA.  What are you using to stop the UART Tx transfer?
"Tx FIFO Not Full" signal will be valid even when the SRAM buffer is empty.  You have the ISR_UD2_TX set to "LEVEL".   I recommend changing it to "RISING EDGE".  In the ISR you can check the UART Tx status to see if the Tx_FIFO is Full or not.   Note:   This can get tricky if the SRAM buffer is finished and the FIFO is still empty.  You would need a buffer Tx counter to not over-Tx the SRAM buffer.

What signal are you using to know when the UART Tx is complete?  ISR_DMA_W5200_UD2_NRQ?  This is a bit confusing.

Why are you using "disabled" as the Hardware Request for DMA_W5200_UD2?

Is the Ethernet data Rx'd in chunks?  If so, you might consider a SRAM double-buffer approach.  
In this approach, let's say you:

  1. Ethernet Rx 1000 bytes in SRAM buffer #1 to UART Tx.  
  2. You set up a DMA configuration for the UART Tx for ONLY 1000 bytes from SRAM buffer #1.  Start this DMA.
  3. Set the Ethernet Rx SRAM to buffer #2.   Any further Rx data gets put in this buffer.
  4. Ethernet Rx 750 bytes in SRAM buffer #2 and is done before the UART Tx for buffer #1 is done.  Stop the Ethernet Rx.   This is where a method of Ethernet flow control would be useful.
  5. When UART Tx of buffer #1 is finished then start a new UART Tx DMA from buffer #2.
  6. Since UART Tx of buffer #1 is done and buffer #2 is started, Set the Ethernet SRAM buffer to #1. 
  7. Restart the Ethernet Rx into buffer #1.
  8. Repeat from step one.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes