Skip to main content
Visitor II
May 21, 2025
Solved

Transaction error trying to use DMA to write to GPIO

  • May 21, 2025
  • 4 replies
  • 458 views

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?

    This topic has been closed for replies.
    Best answer by TDK

    > Surely this should work with DMA1 as well?

    There is no link between DMA1 and AHB1, where GPIOD is located. Use DMA2.

    TDK_0-1747839416455.png

     

    4 replies

    Technical Moderator
    May 21, 2025

    Hello @Elin and welcome to the community,

    Please refer to this thread. The OP is using DMA2.

     

    ElinAuthor
    Visitor II
    May 21, 2025

    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?

    Technical Moderator
    May 21, 2025

    Use DMA2 not DMA1. This is what I've indicated in my post.

    TDKAnswer
    Super User
    May 21, 2025

    > Surely this should work with DMA1 as well?

    There is no link between DMA1 and AHB1, where GPIOD is located. Use DMA2.

    TDK_0-1747839416455.png

     

    ElinAuthor
    Visitor II
    May 22, 2025

    I see now. I was trying to find something like that bus matrix table before but didn't know where to look. That makes sense then why it wouldn't work. Now I need to modify our hardware since it's locked into TIM2 which can't be used with DMA2.

    Thanks for the quick help anyway!