Check if the RCC and or the MODER registers are applied correctly.
Try to add some delay after setting the RCC register.
Maybe your compiler optimizes something and the following condition is not met:
When the peripheral clock is not active, the peripheral registers read or write accesses are not supported.
The enable bit has a synchronization mechanism to create a glitch free clock for the peripheral.
After the enable bit is set, there is a 2 clock cycles delay before the clock be active.
Caution:
Just after enabling the clock for a peripheral, software must wait for a delay before accessing the peripheral registers.
Edit:
Note: The following is a solution approach and appeared to be wrong.
See comments for details.
I'm just compiled the above init_adc_gpio function and my compiler generates the following assembler instructions (-O3):
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN; // Enable clock for GPIOC
0x080004d0 ldr r3, [pc, 60] ; (0x8000510 <init_adc_gpio+64>)
GPIOE->MODER &= (uint32_t)0x000FFFFFU; // Pins 10-15 of E -> input (6 least significant bits of ADC data)
0x080004d2 ldr r0, [pc, 64] ; (0x8000514 <init_adc_gpio+68>)
0x080004d4 ldr r2, [r3, 76] ; 0x4c
GPIOH->MODER &= (uint32_t)0xFFFFFFFCU; // Pin 0 of H -> input (ADC data ready flag)
0x080004d6 ldr r1, [pc, 64] ; (0x8000518 <init_adc_gpio+72>)
0x080004d8 orr.w r2, r2, 4
void init_adc_gpio(void) {
0x080004dc push {r4}
0x080004de str r2, [r3, 76] ; 0x4c
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOEEN; // GPIOE
0x080004e0 ldr r2, [r3, 76] ; 0x4c
GPIOC->MODER &= (uint32_t)0x0FFFFFFFU; // Pins 14-15 of C -> input (2 most significant bits of ADC data)
0x080004e2 ldr r4, [pc, 56] ; (0x800051c <init_adc_gpio+76>)
0x080004e4 orr.w r2, r2, 16
0x080004e8 str r2, [r3, 76] ; 0x4c
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOHEN; // GPIOH
0x080004ea ldr r2, [r3, 76] ; 0x4c
0x080004ec orr.w r2, r2, 128 ; 0x80
0x080004f0 str r2, [r3, 76] ; 0x4c
0x080004f2 ldr r3, [r4, 0]
0x080004f4 bic.w r3, r3, 4026531840 ; 0xf0000000
0x080004f8 str r3, [r4, 0]
0x080004fa ldr r3, [r0, 0]
}
0x080004fc ldr.w r4, [sp], 4
0x08000500 ubfx r3, r3, 0, 20
0x08000504 str r3, [r0, 0]
0x08000506 ldr r3, [r1, 0]
0x08000508 bic.w r3, r3, 3
0x0800050c str r3, [r1, 0]
0x0800050e bx lr
0x08000510 .word 0x40021000 ; [RCC]
0x08000514 .word 0x48001000 ; [GPIOE]
0x08000518 .word 0x48001c00 ; [GPIOH]
0x0800051c .word 0x48000800 ; [GPIOC]
As you can see the compiler reorder the instructions. Therefore the registers are not set properly.
Note: Actually the sequence is right. The way how the disassembler show it can mislead someone.
To solve this problem you can use a explicit compiler barrier wich prevents the compiler to reorder the commands:
void init_adc_gpio(void) {
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN; // Enable clock for GPIOC
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOEEN; // GPIOE
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOHEN; // GPIOH
asm("" ::: "memory"); // prevent instruction reordering
GPIOC->MODER &= (uint32_t)0x0FFFFFFFU; // Pins 14-15 of C -> input (2 most significant bits of ADC data)
GPIOE->MODER &= (uint32_t)0x000FFFFFU; // Pins 10-15 of E -> input (6 least significant bits of ADC data)
GPIOH->MODER &= (uint32_t)0xFFFFFFFCU; // Pin 0 of H -> input (ADC data ready flag)
}
A simple nop instructions before setting the MODER registers should do it also.
Note: The compiler barrier leads to a slightly different assembler code. But both still correct.