Skip to main content
Explorer
April 26, 2025
Solved

Using Timer to trigger DMA event to write into GPIO->BSRR

  • April 26, 2025
  • 2 replies
  • 723 views

Hello, I am currently pretty stumped over the behaviour of the DMA triggered by a timer.

I want to use the DMA to toggle a GPIO pin using a timer for the right frequency. I am currently using the DMA driver from Zephyr. MY board is the STM32G071RB.

I want to use the TIM15 update event to trigger a DMA transfer from memory to BSRR to toggle a pin. The code setup is posted below. My problem is that this setup works for a memory to memory setup, e.g tx_data -> rx_data without problem, the callback is called with status 0 and the data is transferred.

However, if I set the dest_address to BSRR, in my case to 0x50000018, nothing happens. No transfer, no callback and no pin toggle whatsoever.

static struct dma_block_config dma_block_cfg = {
 .dest_address = (uint32_t)rx_data,
 .source_address = (uint32_t)0x50000014,
 //.dest_address = (uint32_t)rx_data,
 .block_size = sizeof(tx_data),
 .source_addr_adj = DMA_ADDR_ADJ_INCREMENT,
 .dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE
};

static struct dma_config dma_cfg = {
 .dma_slot = LL_DMAMUX_REQ_TIM15_UP,
 .channel_direction = MEMORY_TO_PERIPHERAL,
 .complete_callback_en = 0,
 .error_callback_dis = 1,
 .source_data_size = sizeof(uint32_t),
 .dest_data_size = sizeof(uint32_t),
 .source_burst_length = 1,
 .dest_burst_length = 1,
 .block_count = 1,
 .channel_priority = 0x03,
 .head_block = &dma_block_cfg,
 .dma_callback = &dma_complete
};

static void link_set_up_timer()
{
 volatile int ret = dma_config(dma, 1, &dma_cfg);
 ret = dma_start(dma, 1);

 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM15);
 LL_RCC_SetTIMClockSource(LL_RCC_TIM15_CLKSOURCE_PLL);
 LL_TIM_SetCounterMode(TIM15, LL_TIM_COUNTERDIRECTION_UP);
 LL_TIM_SetUpdateSource(TIM15, LL_TIM_UPDATESOURCE_COUNTER);
 LL_TIM_SetAutoReload(TIM15, ARR_VALUE);
 LL_TIM_SetCounter(TIM15, 0);
 LL_TIM_SetPrescaler(TIM15, 0);
 LL_TIM_EnableDMAReq_UPDATE(TIM15);
 LL_TIM_EnableIT_UPDATE(TIM15);
 LL_TIM_GenerateEvent_UPDATE(TIM15);
 LL_TIM_EnableAllOutputs(TIM15);
 LL_TIM_SetTriggerOutput2(TIM15, LL_TIM_TRGO2_UPDATE);
 LL_TIM_SetTriggerOutput(TIM15, LL_TIM_TRGO_UPDATE);
 LL_TIM_EnableCounter(TIM15);
 return;

 For me it feels like the GPIO address is not writable by the DMA. I also tried to set the direction to memory to memory and write half_words and bytes with the same result. Can someone please shed some light? That would be very appreciated.

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

    The GPIO ports are not connected to the DMA bus on this chip.

    TDK_0-1745629752342.png

     

    You're probably getting an error flag in the DMA when you start the transfer.

    2 replies

    TDKAnswer
    Super User
    April 26, 2025

    The GPIO ports are not connected to the DMA bus on this chip.

    TDK_0-1745629752342.png

     

    You're probably getting an error flag in the DMA when you start the transfer.

    EssometerAuthor
    Explorer
    April 26, 2025

    Thank you so much. I completely missed that and would have probably sunken so many hours into it.