I have just started exploring STM32 MCUs. I want to blink the LED on the BluePill(having STM32F103C8T6 MCU) board. I suspect I have been mislead by something. As per the Reference Manual of F1 series, There are 3 main steps:
I have written the code in KEIL MDK as per the manual but after it is loaded, The code do not run, I press the reset button and then LED turns ON, even though I have changed Settings to RESET & RUN in KEIL.
Here is the code and The parts of reference manual.
#include<stm32f10x.h>
int main(){
RCC->APB2ENR |= 1<<4; //PORTC is on APB2 bus
GPIOC->CRH |= (1<<20);
while(1){
GPIOC->ODR |= 0x00002000;
for(int i = 0; i < 500000;i++); //dummy delay
GPIOC->ODR &= ~0x00002000;
for(int i = 0; i < 500000;i++); // dummy delay
}
}
When I am using the Debug mode, I noticed one thing that the clock is not enabled for PORTC after execution of RCC->APB2ENR |= (1<<4)
.
The LED does not blink. I am unable to find the error in this whole process.
When you write a dummy delay loop, a smart compiler will usually figure out that there is nothing worthwhile happening in this piece of code and optimize the whole thing away.
If you want to know this has happened, the best way is to take a look at the disassembly of the generated binary.
Thankfully, C provides the volatile
keyword to get around exactly this sort of problem. It tells the compiler explicitly to not optimize memory accesses to variables declared with this qualifier.
Here you can see some sample code that shows the difference between generated assembly code with and without volatile
keyword using the excellent godbolt tool. Without volatile, the for loop gets optimized to nothing and no incrementing or checking of i
ever happens.
Hence the loops should have been written as:
for(volatile int i = 0; i < 500000; i++); //dummy delay
You may run into this kind of issue on embedded systems also in other instances such as when you have a variable being accessed from multiple contexts/threads.