cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 gpio speed problem

garinus
Associate II

Hello everyone,

I am encountering difficulties with a project. I decided to use an STM32H7B0 microcontroller, which I had previously used in other projects, for a new application. However, I have encountered a difficulty due to the signal propagation delays between the core and the GPIO peripherals.

Specifically, I need to wait for the state change of an input and immediately change the state of an output pin at a particular point in the code. The pins are already allocated on two ports and I cannot change them at the moment (the need is for multiple inputs and outputs).

The issue is that the propagation time, besides being excessively long (currently not below 200ns), is not stable.

I am working at 280MHz, have DMA enabled for ADC, and disable interrupts during the execution of this code. I have already tried all levels of optimization:

while (LL_GPIO_IsInputPinSet(INPUT_GPIO_Port, INPUT_Pin) && __HAL_TIM_GET_COUNTER(&htim17) < 250)
{
}

LL_GPIO_ResetOutputPin(OUTPUT_GPIO_Port, OUTPUT_Pin);

It does not seem to depend on the code but rather on the access time to the peripherals.

9 REPLIES 9

The fact that your post does not contain a question indicates that you already understood.

This is an inherent property of the overcomplicated 'H7 architecture and you can't avoid/circumvent it, unless you pull out the functionality you expect entirely in hardware (probably in timer).

JW

 

garinus
Associate II

Hi,

you're right I forgot the question, which was if anyone had a solution or a workaround to limit or avoid the problem. 
Do you think it is possible to use timers to achieve this? Do you know where I can find a guide to perform this type of synchronization?

> Do you think it is possible to use timers to achieve this?

It's hard to tell unless we know what exactly is "this"?

> Do you know where I can find a guide to perform this type of synchronization?

I don't talk about synchronization but about performing the task entirely in hardware.

JW

What is the requirement here? Just "as good as possible" or do you have specific needs?

It's probably not possible to have an exact delay between a generic input and an output. You could significantly improve the code with better code and better optimization settings, but some delay is to be expected. 200ns is pretty small but is probably doable with better code.

If the inputs can be hooked up to the opamp or a timer input, you could likely use some functionality of those peripherals.

If you feel a post has answered your question, please click "Accept as Solution".
garinus
Associate II

the code have to do basically this: 

LL_GPIO_SetOutputPin(OUTPUT_GPIO_Port, OUTPUT_Pin);
while
(LL_GPIO_IsInputPinSet(INPUT_GPIO_Port, INPUT_Pin) && __HAL_TIM_GET_COUNTER(&htim17) < 250) { } LL_GPIO_ResetOutputPin(OUTPUT_GPIO_Port, OUTPUT_Pin);

Where the input pins were currently mapped as GPIO INPUT, but can be configured as 4 channels of TIM3.

While the outputs are GPIO, but can be on TIM2 or TIM1.

I had thought about the COMP but the pins are already occupied for analog signals.

So, something like a single-shot which can be "cancelled" using the input pin? And, as you implement it in loop, I take it you don't need to use different pins *simultaneously*.

Maybe I'd start with generating the 250-cycle pulse on the output pin using PWM + one-pulse-mode on one of TIM1 or TIM2 channel. I'd do this by setting PWM mode 2 and CCRx=1 while ARR=250, so that there is a one-timer-cycle delay until the pulse starts (you can always "speed things up" by manually setting CNT=1 when starting the timer), but more importantly, the idle output level is 0.

Then I'd set up the TIM3_CH1 as TRGO source (unfortunately, this does not work for other TIM3 channels, see below), and then set TIM1/TIM2 as slave of TIM3 in TIMx_SMCR.TS, with TIMx_SMCR.SMS set to 0b0010 for Reset. As soon as trigger arrives, TIM1/TIM2 is reset (causing output going to 0, see above) and due to being in one-pulse-mode, it also stops.

You can use TIM3_CH2 pin as source of TRGO through setting capture on CH1 from the "neighbouring" pin (TIMx_CCMR1.CC1S=0b10). However, there are no such options for TIM3_CH3/CH4, so if those are needed for this, you have to resort to DMA triggered by capture on the given channel, DMA transferring a proper constant to TIM1/TIM2.CCMRx which sets the respective output channel to "forced" inactive level (CCMRx.OCxM=0b100). DMA does have some latency and depending on what is the given busmatrix/APB bus loading also some jitter, but maybe less detrimental than if you access GPIO from the processor.

JW

 


@waclawek.jan wrote:

So, something like a single-shot which can be "cancelled" using the input pin? And, as you implement it in loop, I take it you don't need to use different pins *simultaneously*.

 


yes this is what i need.

I am trying to implement what you suggested above and test it.

However, I have seen that the STM32F777VIT6 microcontroller should be compatible with the STM32H7B0VBT6. The F7 series does not suffer from the same issue as the H7 version, right?

They're different chips. Compatibility is not black and white and, while some parts of the code may be the same, you should expect to make significant code changes when moving from one to the other.

The F7 has quicker GPIO response when controlled directly but it's not clear if it's still quicker if the GPIO is being controlled by a timer directly.

If you feel a post has answered your question, please click "Accept as Solution".
garinus
Associate II

Yes, I know that I have to rewrite some parts of the code (e.g., OctoSPI vs QuadSPI), but on the hardware side, except for the 12-bit ADC, it seems to have all the resources and it is pin-to-pin compatible.