STM32F429ZI aborting DMA transfer on USART3 prematurely
On an STM32F429ZI, I'm using USART3_RX to receive information via DMA into a circular buffer. The buffer is 4096 bytes long.
If I send 1 or 2 bytes at a time (i.e. with a delay of ~100ms+ between transfers), things work correctly. By "work correctly" I mean the NDTR register is updated and the values I send appear in the circular buffer.
If I send 3+ bytes at once, the transfer gets aborted:
- Only the first 3 bytes show up in the buffer, and NDTR is decremented by 3
- The stream EN bit is changed from 1 (enabled) to 0 (disabled).
- The DMA1->LISR:TCIF1 bit is set to 1.
In other words, it's as if the microcontroller thinks the transfer is complete. However, it's clearly not complete as NDTR != 0. And it only appears when I send 3+ consecutive bytes with no delay between them.
The values in the DMA register appear to be correctly configured, and do not change apart from EN and NDTR as noted above:
DMA1 stream index 1 detailed description:
- CR: SxCR_CHSEL=100 SxCR_PL=01 SxCR_MINC=1 SxCR_CIRC=1, SxEN=1
- NDTR: SxNDT=0x0FFD
- PAR: SxPAR_PA=0x40004804
- M0AR: SxM0AR_M0A=0x20008C58
- FCR: SxFCR_FS=100This behavior is only affecting USART3. I can change everything over to USART2 or USART1 and it works as expected.
Any ideas? I'm running out of ideas. The behavior is the same with interrupts disabled.
I don't see anything in the errata sheet to explain this but I feel like I'm running into a bug in the silicon.
I've debugged this to the point where I am only monitoring the NDTR register in a loop, so it's very unlikely I'm touching the EN bit somewhere unknowingly.
auto & ndtr = DMA1_Stream1->NDTR;
uint32_t last_ndtr = ndtr;
while (1) {
uint32_t this_ndtr = ndtr;
if (this_ndtr != last_ndtr) {
last_ndtr = this_ndtr;
LOG("\nNDTR=", last_ndtr);
}
}