Regarding
/* enable the clock for the GPIOA/B/C/D/E peripherals */
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN | RCC_AHB2ENR_GPIOBEN | RCC_AHB2ENR_GPIOCEN | RCC_AHB2ENR_GPIODEN | RCC_AHB2ENR_GPIOEEN;
__DMB():// data memory buffer stops all memory operation(read/write) until previous memory operations are finished its the //optimised version of __DSB(); which stops all instructions until previous memory operations are finished ,
RCC->AHB2ENR;
... access the newly enabled peripherals ...
Below is my humble understanding regarding STM32 AHB2ENR clock enabling.
[ Please correct me if anything is incorrect or if I missed something. ]
The __DMB() instruction has no effect in this context. While its purpose is to prevent memory reordering, Cortex-M cores do not reorder loads or stores to Device Memory anyway, even within dual-issue pipelines. In this code fragment, the read-back sequence (RCC->AHB2ENR;) is what actually guarantees the write buffer is drained before the CPU moves on.
The actual governing factor is the time the clock tree needs to stabilize after writing to AHB2ENR. As soon as the read-back finishes and clears the hazard stall, execution continues. On high-speed cores, the CPU might try to access the newly enabled peripheral (e.g. GPIO) on the very next cycle. Even though the bus keeps everything in order, the newly enabled peripheral itself may not yet be ready.
The required delay depends on how the peripheral is clocked:
* AHB bus peripherals (GPIOs): Need 2 AHB clock cycles.
* APB bus peripherals: Need a dynamic delay of 1 + (AHB/APB prescaler) AHB clock cycles.
Because this delay scales with the slower bus clocks instead of CPU speed, you can end up needing a substantial number of processor cycles of delay if you are using a clock prescaler and/or running a high-performance STM32 MCU at high core frequencies.
Special case: If the AHB clock matches the CPU clock, the read-back sequence alone should generate a sufficient timing buffer to meet the stabilization requirements of AHB peripherals.