STM32 gotchas
14. GPIO is not toggling at a rate promised by datasheet

In datasheet, GPIO "output frequency" is given, often at a rate equal to the maximum system clock (in I/O AC characteristics table, depending on the respective GPIOx_OSPEEDR setting). Sometimes, users complain that this frequency cannot be achieved, not even close, off by perhaps an order of magnitude.

This results from a misunderstanding of what the given table/characteristics means. It does not mean, that there is a way to toggle a pin from software at the given rate. Rather, it means, that the output signal's edges are fast adequately to a waveform with given frequency. Also, as the same set of transistors drives the output when set to GPIO Out and when set to Alternate Function (in GPIOx_MODER), if some peripheral is set to output a waveform of given frequency (e.g. Timer outputting PWM), this parameter ensures that with appropriate setting of GPIOx_OSPEEDR the given frequency is attainable.

Nonetheless, it is not excluded that software can toggle the pin at that rate, or at least make several successive transitions on one or more pins at that rate; but there are several obstacles to be overcome. The usual reason, why users want to achieve that, is an attempt to bit-bang some interface. Users often write a simple test code similar to this:

  while(1) {
    HAL_GPIO_TogglePin(SOME_PIN);
  }

This is a function call in C, which can compile to quite many instructions, i.e. it takes many machine cycles to execute. Even a loop written in assembler won't allow toggling pin at the maximum frequency in most mcus, given the jump at the end of loop takes some machine cycles to execute, too. There may be also issues associated with executing from potentially slow memory, contention on buses, etc.

As is the case in the 32-bitters, tight timing is best to be solved entirely using hardware. If bit-banging is necessary and tight timing is desired, the user must be aware of all the possible pitfalls and must accept the fact that a certain timing may be subject to jitter, or in a given mcu model, may not be achievable at all.