2017-10-31 01:32 PM
My project involves sending packets of bytes out of the serial port using DMA. I am using an STM32F417 with DMA2 using USART3. DMA transmit buffer is set to The packets that stream the current head position (live) are 66 bytes and stream at 10Hz. Occasionally, longer packets of camera head moves that were previously recorded to flash are sent. This is where I started to notice problems in the DMA output.
00 00 00 00 00 00 00 00 00 00 00 00 00 00 15 23 56 89
00 00 00 00 00 00 00 00 00 00 00 00 00 00 16 23 56 89
00 00 00 00 00 00 00 00 00 00 00 00 00 00 17 23 56 89
00 00 00 00 00 00 00 00 00 00 00 00 00 00 18 23 23 56 89
00 00 00 00 00 00 00 00 00 00 00 00 00 00 19 23 56 89
00 00 00 00 00 00 00 00 00 00 00 00 00 00 1A 23 56 89
00 00 00 00 00 00 00 00 00 00 00 00 00 00 1B 23 56 89
00 00 00 00 00 00 00 00 00 00 00 00 00 00 1C 23 56 89
The above packets are frames from a camera move and at frame 18 (which is hex, so that's frame 24), there is an extra byte inserted (in this case, an extra '23'). This happens every time the frame number is 0x
To check out the whole buffer, I filled the buffer with 398 sequential bytes. Here are the results.
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D
The numbers rolled over, which was expected, but the duplicate '19's were not expected.
The duplicate bytes were verified to not be in the transmit buffer before sending. The same is true with the packets above.
I'm not sure how to troubleshoot this because the programmer doesn't have access to internal buffers that the dma uses.
Any suggestions on what the problem may be or how to troubleshoot? Thanks!
#packets #dma #stm32f4 #duplicate Note: this post was migrated and contained many threaded conversations, some content may be missing.Solved! Go to Solution.
2017-11-01 10:06 AM
DMA is dedicated to serial communication via USART, so there are no other peripheral to turn off.
The address? It's 0x20007FDC
The 256 boundary thing was for transferring sequential bytes with a full transfer buffer. When transferring buffer-loads of frames (transferring a recorded move), the duplicate byte is repeated at any offset of 0x1201 bytes (4609 bytes).
I will look outside the system to connecting parts. I can break out the test equipment as well. Thanks!
2017-11-01 10:46 AM
Are you certain that the data in the buffer does not include the duplicated bytes? Put a break point in and look at the memory. From your description, the 25th (0x19 == 25) addition of *something* leads to a glitch. You've done blocks of 1 and blocks of 18. What happens if you send blocks of 10 bytes each? 20 bytes each? What is the code doing that adds data to your TX buffer? I think a minimal example intended to demonstrate the issue is the way to go. I suspect you will have an Aha! moment while doing this. Pretty sure the DMA stuff just works.
I am using DMA for UART TX of variable length packets. Every packet is treated as a separate transfer. There is no advantage to concatenating packets except that I would have fewer TC interrupts. The code would be more complicated. The packet data is memcpy'd into a holding buffer, and the transfers are queued. The TC interrupt does basically what your SetupDMA2Transmit() does with the item at the front of the queue, if there is one:
// Called from ISR on TC and from thread mode on append packet.
void UsartDriver::tx_isr()
{
DisableInterrupts di;
// Prevent starting another DMA transfer if we are in the middle of one.
if (DMA_GetCmdStatus(m_res.dma_tx.stream) != DISABLE)
{
return;
}
// Clean up now that the transfer is complete.
if (DMA_GetITStatus(m_res.dma_tx.stream, m_res.dma_tx.tc_flag))
{
DMA_ClearITPendingBit(m_res.dma_tx.stream, m_res.dma_tx.tc_flag);
const UsartData& dma = m_tx_queue.front();
tx_remove(dma.length); // Moves get address in holding buffer.
m_tx_queue.pop();
}
// If there is more data pending, start another DMA transaction.
if (m_tx_queue.size() > 0U)
{
const UsartData& dma = m_tx_queue.front();
// Start the DMA transfer
m_res.dma_tx.stream->M0AR = (uint32_t)dma.data;
m_res.dma_tx.stream->NDTR = (uint32_t)dma.length;
DMA_Cmd(m_res.dma_tx.stream, ENABLE);
}
}
2017-11-01 11:43 AM
Sorry everybody! It turned out to be the version of Hyperterminal that I was using.
I set up the same test using just USART3 and got the same results (still using Hyperterminal), so that ruled out the DMA part of the problem.
I ran the same tests (working backwards from USART only transfers) and had no problems with any of the packet transfers or tests using RealTerm3.
Much thanks to those who contributed and to Jan, who nudged me in the right direction to look outside the system for some other cause.
Just for reference, I was using version 5.1.2600.0 of HT from 2001. It's a free version that has been kicking around the office here for years, but I guess it's always good to re-evaluate your tools from time to time!
Cheers!
2017-11-01 01:01 PM