cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7S3V8T6 timer triggered DMA

JShro
Associate III

Hi All, 

Trying to setup timer triggered DMA for the STM32H7S3V8T6 micro and cannot seem to get it working

I have tried a number of things and eventually resorted to asking chatGPT but so far no dice... What I want to achieve
1. Timer 1 toggles CH1 output (PA8) this works 
2. I want the DMA to trigger off of the TIMER_CH1 and shove the word into GPIOA->BSRR to toggle the GPIOA pins 0,1,2,3
Here's my main. c code - really stumped as to what is causing this to not work... Any thoughts??

 

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : STM32H7S3 GPIO output driven by TIM1 using GPDMA1 linked-list
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include <stm32h7rsxx_hal_dma_ex.h>

/* Private variables ---------------------------------------------------------*/
DMA_HandleTypeDef handle_GPDMA1_Channel0;
TIM_HandleTypeDef htim1;

/* USER CODE BEGIN PV */
ALIGN_32BYTES(uint32_t waveform[] ) = {
    0x00000001, 0x00010000,   // PA0 high / low
    0x00000002, 0x00020000,   // PA1 high / low
    0x00000004, 0x00040000,   // PA2 high / low
    0x00000008, 0x00080000    // PA3 high / low
};
#define WAVEFORM_WORDS (sizeof(waveform)/sizeof(waveform[0]))

DMA_NodeTypeDef Node;
DMA_QListTypeDef List;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
static void MPU_Config(void);
static void MX_GPIO_Init(void);
static void MX_GPDMA1_Init(void);
static void MX_TIM1_Init(void);

/* USER CODE BEGIN PFP */
/* USER CODE END PFP */

int main(void)
{
    /* MPU Configuration */
    MPU_Config();

    /* HAL Initialization */
    HAL_Init();
    SystemCoreClockUpdate();

    /* Initialize peripherals */
    MX_GPIO_Init();
    MX_GPDMA1_Init();
    MX_TIM1_Init();

    /* Clean D-Cache for DMA buffer */
    SCB_CleanDCache_by_Addr((uint32_t*)waveform, sizeof(waveform));

    /* Build DMA linked-list node */
    DMA_NodeConfTypeDef NodeConfig;
    NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
    NodeConfig.Init.Request = GPDMA1_REQUEST_TIM1_CH1;
    NodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
    NodeConfig.Init.Mode = DMA_NORMAL;
    NodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
    NodeConfig.Init.DestInc = DMA_DINC_FIXED;
    NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
    NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
    NodeConfig.Init.SrcBurstLength = 1;
    NodeConfig.Init.DestBurstLength = 1;
    NodeConfig.Init.TransferEventMode = DMA_TCEM_LAST_LL_ITEM_TRANSFER;
    NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
    NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
    NodeConfig.SrcAddress = (uint32_t)waveform;
    NodeConfig.DstAddress = (uint32_t)&GPIOA->BSRR;
    NodeConfig.DataSize = WAVEFORM_WORDS;

    if(HAL_DMAEx_List_BuildNode(&NodeConfig, &Node) != HAL_OK) Error_Handler();
    if(HAL_DMAEx_List_InsertNode_Tail(&List, &Node) != HAL_OK) Error_Handler();
    if(HAL_DMAEx_List_SetCircularMode(&List) != HAL_OK) Error_Handler();

    /* Initialize GPDMA1 channel 0 */
    handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
    handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT;
    handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
    handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
    handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_LAST_LL_ITEM_TRANSFER;

    if(HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0) != HAL_OK) Error_Handler();
    if(HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List) != HAL_OK) Error_Handler();
    __HAL_LINKDMA(&htim1, hdma[TIM_DMA_ID_CC1], handle_GPDMA1_Channel0);


    /* Start DMA linked-list */
    if(HAL_DMAEx_List_Start_IT(&handle_GPDMA1_Channel0) != HAL_OK) Error_Handler();

    /* Enable TIM1 CC1 DMA request and start timer */
    __HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_CC1);
    if(HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1) != HAL_OK) Error_Handler();

    /* Infinite loop */
    while (1) {}
}

/* GPDMA1 Initialization Function */
static void MX_GPDMA1_Init(void)
{
    __HAL_RCC_GPDMA1_CLK_ENABLE();
    HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);
}

/* TIM1 Initialization Function */
static void MX_TIM1_Init(void)
{
    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

    htim1.Instance = TIM1;
    htim1.Init.Prescaler = 0;
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim1.Init.Period = 5000;
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim1.Init.RepetitionCounter = 0;
    htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    if(HAL_TIM_Base_Init(&htim1) != HAL_OK) Error_Handler();

    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    if(HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) Error_Handler();

    if(HAL_TIM_OC_Init(&htim1) != HAL_OK) Error_Handler();

    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    if(HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) Error_Handler();

    sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
    sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
    if(HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) Error_Handler();

    sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
    sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
    sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
    sBreakDeadTimeConfig.DeadTime = 0;
    sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
    sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
    sBreakDeadTimeConfig.BreakFilter = 0;
    sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT;
    sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
    sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
    sBreakDeadTimeConfig.Break2Filter = 0;
    sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT;
    sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
    if(HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK) Error_Handler();

    HAL_TIM_MspPostInit(&htim1);
}

/* GPIO Initialization Function */
static void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

/* MPU Configuration */
static void MPU_Config(void)
{
    MPU_Region_InitTypeDef MPU_InitStruct = {0};
    HAL_MPU_Disable();
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER0;
    MPU_InitStruct.BaseAddress = 0x0;
    MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
    MPU_InitStruct.SubRegionDisable = 0x0;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
    MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
    MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
    MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

/* Error Handler */
void Error_Handler(void)
{
    __disable_irq();
    while (1) {}
}
1 REPLY 1
Saket_Om
ST Employee

Hello @JShro 

Please make sur that the dma work fine when trigged by software before adding TIM trigger. 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om