cancel
Showing results for 
Search instead for 
Did you mean: 

Timer triggered DMA Memory to GPIO output on the STM32G070RB

robert-m-lucas
Associate II

Hello, I have used DMA for timer outputs, input compares, memory to memory, etc. and all has worked fine, however I can't seem to get a timer-triggered DMA from memory to GPIO outputs (as this post seems to have managed).

I have tried using the ODR register, the BSRR register, 16 bit transfers, 32 bit transfers, reordering the initialisation of different components, setting TIM1->DIER = TIM_DIER_UDE in different places, etc. etc. The timer is definitely incrementing and resetting correctly and I am getting a TEIF1 on DMA1.

I am less familiar with DMAMUX (I used the F401 previously) so I may be making a mistake there.

#include <stdio.h>

#include "main.h"

#include "stm32g0xx_hal_tim.h"

void SystemClock_Config(void);

static TIM_HandleTypeDef htim1 = {0};
static DMA_HandleTypeDef hdma = {0};

#define GPIO_BUF_LEN  4

static uint32_t gpio_buf[GPIO_BUF_LEN] = {
  0xFFFFFFFF,
  0x00000000,
  0xFFFFFFFF,
  0x00000000,
};

static void Init_GPIO(void) {
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_TIM1_CLK_ENABLE();
  __HAL_RCC_DMA1_CLK_ENABLE();

  GPIO_InitTypeDef gpio = {
    .Pin   = GPIO_PIN_5,
    .Mode  = GPIO_MODE_OUTPUT_PP,
    .Pull  = GPIO_NOPULL,
    .Speed = GPIO_SPEED_FREQ_MEDIUM,
  };
  HAL_GPIO_Init(GPIOA, &gpio);

  hdma.Instance                 = DMA1_Channel1;
  hdma.Init.Request             = DMA_REQUEST_TIM1_UP;
  hdma.Init.Direction           = DMA_MEMORY_TO_PERIPH;
  hdma.Init.PeriphInc           = DMA_PINC_DISABLE;
  hdma.Init.MemInc              = DMA_MINC_ENABLE;
  hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  hdma.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
  hdma.Init.Mode                = DMA_CIRCULAR;
  hdma.Init.Priority            = DMA_PRIORITY_HIGH;
  HAL_DMA_Init(&hdma);
  __HAL_LINKDMA(&htim1, hdma[TIM_DMA_ID_UPDATE], hdma);

  htim1.Instance               = TIM1;
  htim1.Init.Prescaler         = 3200 - 1;
  htim1.Init.CounterMode       = TIM_COUNTERMODE_UP;
  htim1.Init.Period            = 10000 - 1;
  htim1.Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;

  HAL_TIM_Base_Init(&htim1);
  
  __HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_UPDATE);
  HAL_DMA_Start(&hdma,
                (uint32_t)gpio_buf,
                (uint32_t)&GPIOA->ODR,
                GPIO_BUF_LEN);

  HAL_TIM_Base_Start(&htim1);
}


int main(void)
{
  HAL_Init();
  SystemClock_Config();

  Init_GPIO();

  while (1)
  {
    printf("%i\n", DMA1->ISR);

    // GPIOA->BSRR = (GPIO_PIN_5 << 16);
    // HAL_Delay(500);
    // GPIOA->BSRR = GPIO_PIN_5;
    // HAL_Delay(500);

    // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, (TIM1->CNT < 5000) ? GPIO_PIN_SET : GPIO_PIN_RESET);
    // HAL_Delay(500);
  }
}

Thanks!

 

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Super User

This can't be done. The GPIO ports are not accessible to the DMA on the STM32G0x0.

Screenshot 2026-03-13 090805.png

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

4 REPLIES 4
TDK
Super User

This can't be done. The GPIO ports are not accessible to the DMA on the STM32G0x0.

Screenshot 2026-03-13 090805.png

If you feel a post has answered your question, please click "Accept as Solution".
robert-m-lucas
Associate II

Do you know where this can be found in the datasheet / reference manual, so that I can check whether other CPUs support this?

Search for "system architecture" in the Reference Manual.

If you feel a post has answered your question, please click "Accept as Solution".

Screenshot 2026-03-13 131401.png

I misread this as being connected to AHB 🤦