Microcontroller Embedded C Programming Lecture 140| Using volatile to fix issues with the pin-read exercise

  • Post author:
  • Post category:Blog

 

 

Using volatile to fix issues with the pin-read exercise

Now let’s try to use volatile keyword to fix the issue with our code.

Figure 1. 006pin_read example code
Figure 1. 006pin_read example code

 

Figure 1 shows our pin_read example code and this application actually breaks when we activate the O2 optimization level.

When we were debugging this through disassembly we came to know that, the compiler has generated instructions where this code(line 37) is executed only once. So, the processor is not reading the pPortInReg memory address again and again for every iteration to fetch the new value.

So, that’s because a compiler has done an optimization on this pPortInReg address. The compiler has assumed that the data at that memory location will never change. 

 

Now, we have to tell the compiler that the DATA pointed by this pointer may change at any time, so, not to do any optimizations on DATA READ and DATA WRITE operations using this pointer.

That’s why let’s change the declaration of that pointer. Here we have to mention volatile, as shown in Figure 2. 

Using volatile to fix issues with the pin-read exercise
Figure 2. Mention the volatile

 

 

 

 

 

 

 

 

 

 

Now, the compiler will not optimize any read and write operations performed on that pointer. That would solve this issue.

But, whenever you are accessing memory-mapped peripheral registers use volatile generously. That’s why let’s use ‘volatile’ everywhere. ‘volatile’ for the data not for the pointer, like this as shown below.

#include<stdint.h>

int main(void)
{
    uint32_t volatile pClkCtrlReg = (uint32_t*)0x40023830;
    uint32_t volatile pPortDModeReg = (uint32_t*)0x40020C00;
    uint32_t volatile pPortDOutReg = (uint32_t*)0x40020C14;

    uint32_t volatile pPortAModeReg = (uint32_t*)0x40020000;
    uint32_t volatile pPortAInReg = (uint32_t*)0x40020010;

   //enable the clock for GPOID , GPIOA peripherals in the AHB1ENR
      *pClkCtrlReg |= ( 1 << 3);
      *pClkCtrlReg |= ( 1 << 0);

   //configuring PD12 as output
      *pPortDModeReg &= ~( 3 << 24);
   //make 24th bit position as 1 (SET)
      *pPortDModeReg |= ( 1 << 24);

  //Configure PA0 as input mode (GPIOA MODE REGISTER)
      *pPortAModeReg &= ~(3 << 0);

   while(1)
    {
       //read the pin status of the pin PA0 (GPIOA INPUT DATA REGISTER)
       uint8_t pinStatus = (uint8_t)(*pPortAInReg & 0x1); //zero out all other bits except bit 0

      if(pinStatus){
         //turn on the LED
          *pPortDOutReg |= ( 1 << 12);
      }else{
         //turn off the LED
          *pPortDOutReg &= ~( 1 << 12);
}
}
}

Used the volatile keyword

 

So, all these are pointing to memory-mapped peripheral registers. And this should fix the bug.

You check the O2 optimization level and O3 optimization level, and it works. It reads the fresh value from the Port A input data register. And the pin status is changing. So, every time it is read from that address.

That’s how you just fixed a bug in the program using volatile, and in the following article, we’ll see how to use volatile with the interrupt service routine. 

 

FastBit Embedded Brain Academy Courses

Click here: https://fastbitlab.com/course1

 

FastBitLab

The FastBit Embedded Brain Academy uses the power of internet to bring the online courses related to the field of embedded system programming, Real time operating system, Embedded Linux systems, etc at your finger tip with very low cost. Backed with strong experience of industry, we have produced lots of courses with the customer enrolment over 3000+ across 100+ countries.