STM32 gotchas
131.Undefined AF in GPIO may turn pin to output

STM32 GPIO (except in the 'F1 family) features a matrix, through which for individual pins, if set to Alternate Function in the respective GPIOx_MODER field, one of the available peripheral functions for that pin is connected. This selection is performed by a field in GPIO_AFRL/AFRH registers.

GPIO_AFRL/AFRH has 4 bits per pin, so there are maximum 16 peripheral functions per pin available. However, the matrix is sparse, and there is probably no single pin in any STM32 which would have all 16 functions implemented.

The original intention was, that each of the 16 options will be assigned to a group of functions - e.g. AF0 is for system functions such as JTAG/SWD or MCO, AF1 is for TIM1, AF2 for TIM2-TIM5, AF4 for all the I2C, etc. This scheme can clearly be seen in 'L1, where the bus matrix was first introduced, and the also for the first 'F2/'F4; but starting with 'F0/'F3 the functions got more mixed up; and by now in the newer STM32 if there still is some hint of a scheme it has so many exceptions that it can't be relied upon anyway and each function's AF for a pin has to be looked up individually.

What happens, if one inadvertently1 assigns a "reserved" AF number to a pin set to Alternate Function?

This (similarly to other details of GPIO matrix implementation) is not documented. However, experiments indicate, that the matrix has been optimized during the design process, and there is no "neutral/parking" position of the matrix multiplexer, rather, if an "unassigned" AF number is selected in GPIOx_AFR[], then one of the "existing" peripheral connections is chosen. And, if that peripheral pad happens to be an output or switched to output, it may hapen, that the pin in question turns to output, resulting in surprising behaviour and potential damage.


1. For example, if pin is set to Alternate Function in GPIOx_MODER, before the respective GPIOx_AFR[] field has been set. Default value of the majority of GPIOx_AFR[] fields is 0b0000 i.e. AF0 is selected, which may be "unassigned" for given peripheral. How do I know? :-)