Update: Solved! Here’s what finally worked for TIM1_CH1 → DMA on every PE9 rising edge
The key was turning the CC1 events into TRGO pulses and wiring that into a trigger‐DMA stream.
Here’s the summary of what I changed:
1. TIM1 Initialization + Start DMA
static void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_SlaveConfigTypeDef sSlaveConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
/* USER CODE BEGIN TIM1_Init 1 */
/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 65535;
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();
}
// 1) Input-Capture on CH1 so we get CC1 events from TI1FP1
if (HAL_TIM_IC_Init(&htim1) != HAL_OK) {
Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1) != HAL_OK) {
Error_Handler();
}
// 2) External clock mode 1: TI1FP1 (PE9 rising edge) → counter + CC1
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;
sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;
sSlaveConfig.TriggerFilter = 0;
if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK) {
Error_Handler();
}
// 3) Make CC1 mismatches ALSO generate a TRGO
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1; // TRGO on CC1
sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */
// 4) Arm the trigger-DMA (TIM1_TRIG) to copy GPIOE->IDR → portE_samples[]
// and install your half/full callbacks in MSP-init.
if (HAL_DMA_Start_IT(&hdma_tim1_trig,
(uint32_t)&GPIOE->IDR,
(uint32_t)portE_samples,
PORT_E_SAMPLES_BUFFER_SIZE) != HAL_OK)
{
Error_Handler();
}
__HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_TRIGGER);
// 5) Finally start the timer itself
HAL_TIM_Base_Start(&htim1);
/* USER CODE END TIM1_Init 2 */
}
2. DMA (Triggered by TRGO)
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(htim_base->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
/**TIM1 GPIO Configuration
PE9 ------> TIM1_CH1
*/
GPIO_InitStruct.Pin = L_CLK_RX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(L_CLK_RX_GPIO_Port, &GPIO_InitStruct);
/* TIM1 DMA Init */
/* TIM1_TRIG Init */
hdma_tim1_trig.Instance = DMA1_Stream1;
hdma_tim1_trig.Init.Request = DMA_REQUEST_TIM1_TRIG;
hdma_tim1_trig.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_tim1_trig.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim1_trig.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim1_trig.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_tim1_trig.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_tim1_trig.Init.Mode = DMA_CIRCULAR;
hdma_tim1_trig.Init.Priority = DMA_PRIORITY_HIGH;
hdma_tim1_trig.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_tim1_trig) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_TRIGGER],hdma_tim1_trig);
/* USER CODE BEGIN TIM1_MspInit 1 */
extern void HAL_DMA_RxHalfCpltCallback(DMA_HandleTypeDef *hdma);
extern void HAL_DMA_RxCpltCallback(DMA_HandleTypeDef *hdma);
// Register your callbacks now, before you ever start the DMA:
HAL_DMA_RegisterCallback(&hdma_tim1_trig,
HAL_DMA_XFER_HALFCPLT_CB_ID,
HAL_DMA_RxHalfCpltCallback);
HAL_DMA_RegisterCallback(&hdma_tim1_trig,
HAL_DMA_XFER_CPLT_CB_ID,
HAL_DMA_RxCpltCallback);
// Enable the IRQ line for that stream
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
/* USER CODE END TIM1_MspInit 1 */
}
}
Result
PE9 rising edge → TI1FP1 external clock tick
CC1 match → Because CC1S=01, the timer captures and also generates TRGO (MMS=OC1)
TRGO → Fires the TIM1_TRIG DMA request
DMA (Circular) → Reads GPIOE->IDR into portE_samples[]
HAL_DMA_RxHalfCpltCallback / HAL_DMA_RxCpltCallback now fire as expected!
Hope this helps anyone else wrestling with TIMx + trigger-DMA on the H7 series.