I am planning to use libopencm3 for my future experiments, any comments on that will be helpful.
Why? (Hope this counts as a comment.)
Also, any suggestion on how to do this bit wise operation better.
// Set Config to 10
GPIOC -> CRH &= ( uint32_t ) ~( 1 << 26 );
GPIOC -> CRH |= ( 1 << 27 );
Note, that there is no "best" in microcontroller programming, as appropriateness of any solution is context-dependent.
This particular snippet can be made "better" by reducing number of reads and writes from/to the GPIO register:
GPIOC->CRH = (GPIOC->CRH & ~(1 << 26)) | (1 << 27); // set CNF to 0b10: Input with pull-up / pull-down
and it can be made somewhat "better" to manipulate the whole bitfield at once, which also reveals the whole you are going to write:
GPIOC->CRH = (GPIOC->CRH & ~(0b11 << 26)) | (0b10 << 26); // set CNF to 0b10: Input with pull-up / pull-down
and it can be made yet "better" by emphasizing, that you want to set this field for PC14:
GPIOC->CRH = (GPIOC->CRH & ~( 0b11 << (4 * (14 - 8) + 2)) | (0b10 << (4 * (14 - 8) + 2)); // set CNF14 to 0b10: Input with pull-up / pull-down
But, in the vast majority of microcontroller applications, you want to set up all the pins at once, at the startup, so that's one single write to the register; i.e.
GPIOC->CRH = 0
// define for other GPIOC pins 0..15 here, otherwise they will be set to Analog mode (MODE=0b00, CNF=0b00
| (0b11 << (4 * (13 - 8) + 0)) // set MODE13 to 0b11: 50MHz output
| (0b00 << (4 * (13 - 8) + 2)) // set CNF13 to 0b00: General purpose output push-pull
| (0b00 << (4 * (14 - 8) + 0)) // set MODE14 to 0b00: Input
| (0b10 << (4 * (14 - 8) + 2)) // set CNF14 to 0b10: Input with pull-up / pull-down
;
You can make this somewhat more readable by writing macros for CNF and MODE fields.
Others may have different ideas about what's *better*.
JW
PS. Disclaimer: there may be errors in the lines above, did not test.