cancel
Showing results for 
Search instead for 
Did you mean: 

Input capture maximum frequency

con3
Senior

Im using input capture to move data from the GPIO_IDR to ram.

I'm seeing some missed bits at portions and I'm curious whether this is due to a hardware limit or code bloat (if that makes sense)

The code is generated by cube.

I'm using an stm32f772ze mcu, with DMA handling the requests. The timer is an advanced control timer (Tim8, which is being clocked at 216MHz)

What would the expected limit be for this?

The clock I'm reading the data in with is operating at 16 MHz and when reviewing the data, it works fine and then seems to have a delayed input capture by 2 clock cycles, so the bits are 2 positions off from where they should be.

Thanks in advance for any help

5 REPLIES 5
con3
Senior

Also it should be noted that the timer is set to external clock source using the 16 MHz clock as its ETR, input capture is then done with two DMA's. Both trigger on separate overflows.

One triggers a request on overflow of 8 and the other 15, so every 7 rising edges. This means that data is moved from the GPIO_IDR to RAM at a rate of 2.285 MHz?

This seems quite slow for it to be missing bits considering it's using two DMA streams and is running at 216 MHz

> I'm seeing some missed bits at portions

[...]

> it works fine and then seems to have a delayed input capture by 2 clock cycles, so the bits are 2 positions off from where they should be.

What is the expected behaviour and what are the observed symptoms? Post the waveforms as they appear on the pins, and the related captured data, and show there what's the problem.

> One triggers a request on overflow of 8 and the other 15, so every 7 rising edges.

I don't understand. One timer can overflow only on one value, set to TIMx_ARR. So what do you mean by overflow here? What is the content of the timer's regsiters?

JW

hi @Community member​ ,

Thank you for the reply!

> I don't understand. One timer can overflow only on one value, set to TIMx_ARR. So what do you mean by overflow here? What is the content of the timer's regsiters?

The timer is set up with two active channels, the one overflows at 8 and the other at 15,

The DMA is then chosen as :

hdma_tim8_ch1_ch2_ch3

This is the timer's configuration:

static void MX_TIM8_Init(void) {
 
	TIM_ClockConfigTypeDef sClockSourceConfig;
	TIM_SlaveConfigTypeDef sSlaveConfig;
	TIM_MasterConfigTypeDef sMasterConfig;
	TIM_OC_InitTypeDef sConfigOC;
	TIM_OC_InitTypeDef sConfigOC1;
	TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
 
	htim8.Instance = TIM8;
	htim8.Init.Prescaler = 0;
	htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
	htim8.Init.Period = 15;
	htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
	htim8.Init.RepetitionCounter = 17;
	htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim8) != HAL_OK) {
		_Error_Handler(__FILE__, __LINE__);
	}
 
	sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;
	sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_INVERTED;
	sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
	sClockSourceConfig.ClockFilter = 0;
	if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK) {
		_Error_Handler(__FILE__, __LINE__);
	}
 
	if (HAL_TIM_OC_Init(&htim8) != HAL_OK) {
		_Error_Handler(__FILE__, __LINE__);
	}
 
	if (HAL_TIM_OnePulse_Init(&htim8, TIM_OPMODE_SINGLE) != HAL_OK) {
		_Error_Handler(__FILE__, __LINE__);
	}
 
	sSlaveConfig.SlaveMode = TIM_SLAVEMODE_COMBINED_RESETTRIGGER;
	sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
	sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_FALLING;
	sSlaveConfig.TriggerFilter = 0;
	if (HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig) != HAL_OK) {
		_Error_Handler(__FILE__, __LINE__);
	}
 
	sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
	sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
	sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
	if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig)
			!= HAL_OK) {
		_Error_Handler(__FILE__, __LINE__);
	}
 
	sConfigOC.OCMode = TIM_OCMODE_RETRIGERRABLE_OPM1;
	sConfigOC.Pulse = 8;
	sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
	sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
	sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
	sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
	sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
	if (HAL_TIM_OC_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) {
		_Error_Handler(__FILE__, __LINE__);
	}
	sConfigOC1.OCMode = TIM_OCMODE_RETRIGERRABLE_OPM1;
	sConfigOC1.Pulse = 16;
	sConfigOC1.OCPolarity = TIM_OCPOLARITY_LOW;
	sConfigOC1.OCNPolarity = TIM_OCNPOLARITY_HIGH;
	sConfigOC1.OCFastMode = TIM_OCFAST_ENABLE;
	sConfigOC1.OCIdleState = TIM_OCIDLESTATE_RESET;
	sConfigOC1.OCNIdleState = TIM_OCNIDLESTATE_RESET;
	if (HAL_TIM_OC_ConfigChannel(&htim8, &sConfigOC1, TIM_CHANNEL_3)
			!= HAL_OK) {
		_Error_Handler(__FILE__, __LINE__);
	}
 
	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.Break2State = TIM_BREAK2_DISABLE;
	sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
	sBreakDeadTimeConfig.Break2Filter = 0;
	sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
	if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig)
			!= HAL_OK) {
		_Error_Handler(__FILE__, __LINE__);
	}
 
	HAL_TIM_MspPostInit(&htim8);
 
}

>What is the expected behaviour and what are the observed symptoms? Post the waveforms as they appear on the pins, and the related captured data, and show there what's the problem.

This is the device sending the data to the mcu:

0690X000006CJEwQAO.jpg

So the DRDY is triggers the timer, dclk is free running and is the external clock fed into the timer, the Dout pins are split into 16 lines using a shift register and read in via the gpio. so the data following below shows the correct value of 9 and then incorrect values of 18 and 36 when the timer is delayed enough that the data propagates through the shift register.

Here I've listed the values that I receive:

9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 36, 9, 18, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 9, 9, 9, 9, 9, 9, 9, 9, 9

The 9 is correct and that relates to

0000 0000 0000 1001

but the 18 and 36 shouldn't be there

18 being 0000 0000 0001 0010

36 being 0000 0000 0010 0100

So when it reads 18, it seems to miss it by 1 clock cycle of the external clock and the 36 by 2.

So I can see that it does read in the data and does it quite well for the majority, but every now and then it reads in the data either one clock cycle or two late and the data is slightly shifted.

I hope that makes sense, if you need any more info please let me know!

Thank you again for the help. I really appreciate it

There is a resync circuit on the input than can cause nyquist type aliasing, but that's much higher than 16 MHz. Interrupting will be an issue. You can divide using the INPUT prescaler. For high frequencies using in external counter mode can be used, but won't give you duty.

To overcome the interrupt issue DMA can be used to record capture events, larger buffers permitting decimation of interrupt loading.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I don't understand why did you chose the OPM mode for the counter with nonzero repetition count, and the retriggerable-OPM mode for the channels.

Also, if you set ARR (htim8.Init.Period) =15 and the third's channel's compare value to 16, which means it would never compare (I don't know if it would still create an event for the DMA, I don't use the newer mcus which have the retriggerable-OPM mode which is quite a disruptive one; but I doubt it.)

Nonetheless, I don't see a reason why would sometimes the timer miss a clock. You can relatively easily check the regularity of the process by reversing it: instead of moving data from GPIO to memory, you can move some pattern from memory to a GPIO - it may be a different one than the outputs of the shift registers, and maybe two or three pins would be enough to see clearly the pattern.

JW