This overview uses the STM32F407 family. Every pin has electrical limits and a list of available alternate functions in the device datasheet; a peripheral signal cannot be assigned to an arbitrary GPIO.

Enable the port clock
GPIO registers are not usable until the port’s peripheral clock is enabled. With the HAL:
1 | __HAL_RCC_GPIOE_CLK_ENABLE(); |
Configure a pin
1 | GPIO_InitTypeDef config = {0}; |
The mode register selects input, output, alternate function, or analog. Output type selects push-pull or open-drain. Pull configuration selects none, pull-up, or pull-down. Speed controls output slew capability; choosing the highest speed unnecessarily can increase power and electromagnetic interference.
For an alternate function, configure the correct AF number as well as mode, pull, type, and speed:
1 | config.Mode = GPIO_MODE_AF_PP; |
Important registers
MODERselects mode.OTYPERselects output driver type.OSPEEDRselects output speed.PUPDRselects pulls.IDRreads input state andODRreflects output data.BSRRatomically sets and resets output bits.AFRLandAFRHselect alternate functions.LCKRcan lock configuration until reset under defined conditions.
Use BSRR for concurrent bit updates instead of a read-modify-write on ODR. “5 V tolerant” applies only to explicitly marked pins and under datasheet conditions; it does not mean every mode, analog input, or unpowered state safely accepts 5 V.