Skip to main content
Robmar
Senior II
October 16, 2026
Question

Why enabling a timer via DMA write to the CR1 register fails

I have many timers working on out H743VIT6 board, so only have Tim2, 5, 12 and above available.

I have many forms of of timer triggered DMA working, but in this case as the system is near to max capacity, I need a DMA event scheduled for 52uS in the future WITHOUT using IRQs which are not time-stable enough for the purpose.

So I found that timer 16 in table 98 of the RM0433 manual is show connecting to timer 2, but in CubeMX timer 15 shows no trigger source!

So I though I would set up timer 5 to count down 52uS and trigger its DMA stream to write a half word to CR1 of Timer 15, that was setup to pace its own DMA stream.  Now I can get tier 15 triggering and DMA transfering it I enable it via the end of event cllback for timer 5, but DMAing to CR1 of an diabled timer doesn’t seem to work.

It’s a very complicated problem!
 

// Arm one amplitude bank, started by a TIM5 countdown delay to trigger DMA write to enable a target timer with DMA stream
HAL_StatusTypeDef ArmOneBank(uint32_t *pwm_values, uint32_t DataLength, uint32_t delay_ticks)
{
HAL_StatusTypeDef status; // Free timers 2, 5 and 12-up: Timer 15 does not map to Tim5 or Tim2 in Table 98 RM0433 manual inteconnect matrix
// Timers 16 and 17 are interconnected in table 98 to timer 15, but timers 1-17 do not have trigger sources
// TIM15 in normal up-counter mode, NOT waiting for an ITR trigger
__HAL_TIM_DISABLE(&htim15);
__HAL_TIM_DISABLE_DMA(&htim15, TIM_DMA_UPDATE);

__HAL_TIM_SET_COUNTER(&htim15, 0);
__HAL_TIM_CLEAR_FLAG(&htim15, TIM_FLAG_UPDATE);

// Arm amplitude DMA while TIM15 is stopped
status = HAL_DMA_Start_IT(&hdma_tim15_up,
(uint32_t)pwm_values,
(uint32_t)&TIM8->CCR3,
DataLength);

if (status != HAL_OK)
return status;

// Prepare target timer CR1 value to enable it, preserving existing bits
tim15_cr1_start_word = (uint16_t)(TIM15->CR1 | TIM_CR1_CEN); // 0x81 Check correct!!

// Enable amplitude requests before starting TIM15
__HAL_TIM_ENABLE_DMA(&htim15, TIM_DMA_UPDATE);
///__HAL_TIM_ENABLE(&htim15); // <---- THIS LINE ENABLED THE DMA TRANSFER IMMEDIATELY - NOT DESIRED!

// Prepare TIM5 one-shot delay
__HAL_TIM_DISABLE(&htim5);
__HAL_TIM_DISABLE_DMA(&htim5, TIM_DMA_UPDATE);

__HAL_TIM_SET_COUNTER(&htim5, 0);
__HAL_TIM_SET_AUTORELOAD(&htim5, delay_ticks);
__HAL_TIM_CLEAR_FLAG(&htim5, TIM_FLAG_UPDATE);

// Arm one DMA transfer: TIM5 update -> write TIM15 CR1
status = HAL_DMA_Start_IT(&hdma_tim5_up,
(uint32_t)&tim15_cr1_start_word,
(uint32_t)&TIM15->CR1,
1);

if (status != HAL_OK)
{
__HAL_TIM_DISABLE_DMA(&htim15, TIM_DMA_UPDATE);
HAL_DMA_Abort(&hdma_tim15_up);
return status;
}

// Enable TIM5 update DMA requests only after its stream is armed
__HAL_TIM_ENABLE_DMA(&htim5, TIM_DMA_UPDATE);

// Start the one-shot countdown - when tim5 expires it will trigger its DMA
// to write the tim15_cr1_start_word to enable timer 15 but timer 15 does not pave its DMA stream for some reason
__HAL_TIM_ENABLE(&htim5);

return HAL_OK;
}

 

4 replies

ST Technical Moderator
October 16, 2026

Hello ​@Robmar 

Is the TIM15 peripheral clock enabled ?

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Saket_Om
Robmar
RobmarAuthor
Senior II
October 16, 2026

Yes:
 

else if(tim_baseHandle->Instance==TIM15)

{

/* USER CODE BEGIN TIM15_MspInit 0 */



/* USER CODE END TIM15_MspInit 0 */

/* TIM15 clock enable */

__HAL_RCC_TIM15_CLK_ENABLE();



/* TIM15 DMA Init */

/* TIM15_UP Init */

hdma_tim15_up.Instance = DMA2_Stream3;

hdma_tim15_up.Init.Request = DMA_REQUEST_TIM15_UP;

hdma_tim15_up.Init.Direction = DMA_MEMORY_TO_PERIPH;

hdma_tim15_up.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_tim15_up.Init.MemInc = DMA_MINC_ENABLE;

hdma_tim15_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;

hdma_tim15_up.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;

hdma_tim15_up.Init.Mode = DMA_NORMAL;

hdma_tim15_up.Init.Priority = DMA_PRIORITY_VERY_HIGH;

hdma_tim15_up.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

if (HAL_DMA_Init(&hdma_tim15_up) != HAL_OK)

{

Error_Handler();

}



__HAL_LINKDMA(tim_baseHandle,hdma[TIM_DMA_ID_UPDATE],hdma_tim15_up);



/* TIM15 interrupt Init */

HAL_NVIC_SetPriority(TIM15_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(TIM15_IRQn);

/* USER CODE BEGIN TIM15_MspInit 1 */



/* USER CODE END TIM15_MspInit 1 */

}

 

Robmar
RobmarAuthor
Senior II
October 16, 2026

The STM Sidekick is pretty useless I asked it a simple question about what the documents confirm about interconnectivity of timers as it seemed to have been unable to understand the H743 manual:-

My question: In the RM0433 manual page 579, table 98, interconections, it states that : Timer 12 peripheral connects to timer 5 trgo via ITR1 - but in CubeMX Timer 12 does not have a DMA tab!!

Reply:  -Sorry, I do not have complete information to answer this question. Please start a new chat and select the appropriate STM32 series or try rephrasing your question with more specific details. My knowledge is based on the official STM32 documentation. You can also ask your question on the online ST Community to get insights from ST experts and ST Community users. Go to the ST Community-

Robmar
RobmarAuthor
Senior II
October 16, 2026

Any experts?  How about this approach:-

TIM5 update (TIM5_UP)

Delayed trigger at the end of the countdown

DMAMUX1 request generator

Generates the DMA requests for the memory to peripheral (33 words)

DMAMUX1 synchronization

TIM12_TRGO controls DMA pacing at 320 KHz per word transfer to the PWM Tim8->CCR3

DMA2 stream → TIM8->CCR3

Transfers PWMsamples