2025-05-21 7:17 AM
I've been trying to set up a timer and DMA to run a synchronous parallel bus onto a GPIO. The timer works great but the DMA keeps failing with a transaction error interrupt and disables the stream. This is on an STM32F413 chip and using TIM2_CH1 as a PWM output and DMA1 Stream 1 connected to TIM2_UP event. The DMA is configured as below:
static uint16_t _waveform[2];
_waveform[0] = 0x0555;
_waveform[1] = 0x0AAA;
LL_DMA_SetChannelSelection(DMA1, LL_DMA_STREAM_1, LL_DMA_CHANNEL_3);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_1, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_1, LL_DMA_PRIORITY_VERYHIGH);
LL_DMA_SetMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MODE_CIRCULAR);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_HALFWORD);
LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_1, LL_DMA_MDATAALIGN_HALFWORD);
LL_DMA_DisableFifoMode(DMA1, LL_DMA_STREAM_1);
LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_1, (uint32_t)&GPIOD->ODR);
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_1, (uint32_t)_waveform);
LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_1, 2);
LL_TIM_EnableDMAReq_UPDATE(TIM2);
All of GPIOD is configured as outputs and as soon as DMA1 receives the DMA request from the timer I get an interrupt with TEIF1 set. I've been looking around at various similar solutions and I don't think I'm doing anything wrong?
2025-05-21 7:38 AM
2025-05-21 7:53 AM
Yes, I was looking at that post earlier and comparing with my own code and from what I can tell it's pretty much identical except different DMA and Timer. Surely this should work with DMA1 as well?
2025-05-21 7:57 AM
> Surely this should work with DMA1 as well?
There is no link between DMA1 and AHB1, where GPIOD is located. Use DMA2.
2025-05-21 8:04 AM
Use DMA2 not DMA1. This is what I've indicated in my post.