collapse

Author Topic: Volatile Interrupts  (Read 3394 times)

bdk6

  • Guest
Volatile Interrupts
« on: October 30, 2016, 08:33:44 PM »
If you want to write any interrupt code for Arduino or other C or C++ based microcontroller, you need to know about the keyword "volatile."  Without it, you are likely to be in for some fruitless head scratching and hair pulling.  In this tutorial, I hope to explain what "volatile" is, why we need it, and how to use it.  I also hope to save some of your hair.

The keyword "volatile" is a modifier used with variable declarations.  It is basically an instruction to the compiler telling it to do exactly what you say with the variable because it doesn't know everything it thinks it does about it.  In a basic variable declaration, the keyword goes just before the rest of the declaration, like this:
volatile int x;   // declare x as a volatile int
In some cases, if you have more complex declarations, the keyword may need to be in a different place.  For example, if you have a pointer to an int, and the pointer itself is what needs to be volatile, then you would put the keyword to the right of the pointer operator:
int * volatile x; // a volatile pointer to an int.
The website http://cdecl.org/ cdecl.org is your friend for any complex or confusing c and c++ declarations

Now that we have seen how to use "volatile," let's discuss when and why we need it.   The short answer is any variable that is used both inside and outside an interrupt routine should be declared volatile.  Without declaring the variable as "volatile" the compiler is free to get rid of accesses to the variable that it "thinks" are unnecessary.  By using "volatile" we tell the compiler, "HEY!  You don't know everything you need to know about this.  So every time I write code to access it, you do just as I say."   Let's see an example.

Let's just suppose that we want to keep performing some action in a loop until some external event has happened a number of times.  The external event is sensed by an interrupt routine and we can set a variable to the number of times we want it to happen.  This is a rather contrived example, but it will illustrate the point.

Our variable declaration and interrupt routine might look something like this:

int events = 0;

void INTERRUPT_ROUTINE()
{
   if(events > 0)
   {
      events = events - 1;
   }
}

So far so good.  Whenever the event happens and the interrupt routine runs, it checks to see if the variable is positive and if so, decreases it by one.  Now, our main code might look like this:


// set number of events to wait for
events = 5;

// main program loop
while(1)   // do forever until we "break" out of loop
{
   // do some cool processing stuffs
   if(events == 0)
   {
      break;   // if 5 events have happened, exit the loop
   }
  // do some other cool processing stuffs
}

The compiler sees only one function at a time. The function that
has the above block of code that sets events to 5 and goes into the while loop is compiled all by itself.  The compiler looks VERY closely at that code, trying to find ways to simplify it and make it smaller and run faster (optimization.)  It sees that the variable events is set to 5 before entering the loop and that nowhere else in the loop is the value changed.  So, it naturally "assumes" that the line "if(event == 0)" can NEVER be true, since it can't see any place the value could be changed from 5. 

So the compiler will throw out the entire if statement, including the checking of the variable (events) and the break statement.  With normal code, that would be perfectly fine.  BUT!  We also modify that variable in the interrupt routine, which can happen at ANY time, even in the middle of that while loop!

But, remember what we said the "volatile" keyword tells the compiler: it says "you don't know everything about this."  And, it tells the compiler to ALWAYS check the variable if our code says to.  Don't assume anything.  By placing the keyword "volatile" in front of the declaration:
volatile int events;
the compiler knows it must always check the variable, even if it seems there is no point.  In which case, our code will work just find.

I hope this tutorial was helpful.  Interrupt code is somewhat difficult to write and get it correct.  if the compiler is going behind you taking out code you need, it gets even worse.  Learn when and why to use the "volatile" keyword and save some of your hair.


 

Bajdi

  • Member
  • *
  • B
  • Posts: 86
Re: Volatile Interrupts
« Reply #1 on: October 31, 2016, 05:06:07 PM »
Very interesting, thanks for taking the time to write this.
In the beginning you talk about pointers? Uhh, what actually are they? But I think it's not something I have to worry about when programming 8bit AVR's (Arduino)?

bdk6

  • Guest
Pointers and such -- Re: Volatile Interrupts
« Reply #2 on: October 31, 2016, 07:12:57 PM »
Hi Bajdi,

Pointers are one of the most powerful, and most dangerous, parts of C and C++ (and Arduino's mix of the two.)  They are used a lot, even on Arduino, although you may not realize it.  They are used "under the hood" in much of the library code you use every time you write  a sketch.

So, what is a pointer?  It's actually really simple, but it often takes a bit of time to actually grasp it.  I think that is because it is simpler than people are expecting.  A pointer is simply a different type of variable, like an int or a float or a character, but instead of holding the value you are interested in like "regular" variables, it holds the memory address of the value you are interested in.  When you declare a pointer variable, you must give it a data type and mark it as a pointer to that type.  So, if you have the declaration:
int * x;
that tells the compiler that "x" is a pointer (the "*" means "pointer to") to an integer.  A pointer is normally the same size, no matter how large the object is it points to.  It can point to pretty much anything.  Any time you pass arrays or strings around, they are handled as pointers for efficiency.  In C and C++, arrays and pointers are closely related.  If you declare an array and then give that array to a function as a parameter, it actually gets a pointer.  So, if you have this:
int array_of_ints[20];

somefunction(array_of_ints);
The function "somefunction" actually gets a pointer to the block of memory that holds the integers, not the values themselves.  A pointer is normally either 2 or 4 bytes: much smaller than the 40 bytes of the actual array.

Pointers are used for a LOT of things, but one place they are especially useful in small embedded systems like Arduino is to "point to" a hardware peripheral.  You define the registers for the peripheral in a structure ("struct timer_16{ uint8_t reg1 ....}" and then create a pointer to that structure:
struct timer_16 * timer2;
and you can use the pointer to access all the registers:
timer2->reg1 = new_timer_value;
And, if you have more than one of the same peripheral, you just need a pointer for each one, assigning the hardware address where each one is located.

Pointers cover a lot of ground, and I can only scratch the surface here.  But they are very important.  They are, as I mentioned, also very dangerous.  But that's another story.  But the main reason languages like java and C# exist is to have a C-like  or C++ -like language without pointers.

Just to show that pointers really are used in Arduino, here's a bit of code from HardwareSerial.cpp:

HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer,
  volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
  volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
  volatile uint8_t *ucsrc, volatile uint8_t *udr,
  uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x)

Most of those parameters are pointers (notice the "*"s).  Also notice many are declared volatile.

 

* Search


* Recent Topics

The unnamed (yet) quatruped spider project by tinhead
[July 01, 2020, 04:22:11 PM]


"1984 Nixie Time" by 1 what
[May 08, 2020, 01:04:18 AM]


2D Side Scroller Cyberpunk themed by Killer Angel
[February 06, 2020, 06:39:40 AM]


A new wing design for model aircraft / drones by OddBot
[February 06, 2020, 04:42:06 AM]


SDR (Software Defined Radio) by Gareth
[February 02, 2020, 06:15:42 AM]


Circuit Math by ZeroMax
[January 31, 2020, 01:50:18 PM]


NanOMeter by Protowrxs
[January 01, 2020, 12:59:44 PM]


Investigating the VL53L0X Laser Rangefinder by erco
[December 30, 2019, 10:45:44 PM]


PS4 Single Handed Controller Deployed (part 7 of 7) by Gareth
[December 30, 2019, 09:52:29 AM]


"D" -Pad Workio just like Magic (Will Merlin stay or Go) (part 6 of 7) by Gareth
[December 30, 2019, 09:51:27 AM]


PS4 Joystick Digitals 4,5,6,7,10 - Analog's Lx,Ly,Rx,Ry Workio (part 5 of 7) by Gareth
[December 30, 2019, 09:50:37 AM]


Menu Workio ! (part 4 of 7) by Gareth
[December 30, 2019, 09:49:49 AM]


L1 trigger design Workio (Hori controller) (part 3 of 7) by Gareth
[December 30, 2019, 09:48:50 AM]


Hori aka PS4 Joystick Mappings (part 2 of 7) by Gareth
[December 30, 2019, 09:47:17 AM]


PS4 Single Left-Handed Controller (part 1 of 7) by Gareth
[December 30, 2019, 09:44:58 AM]

* Recent Posts

Re: The unnamed (yet) quatruped spider project by tinhead
[July 01, 2020, 04:22:11 PM]


Re: The unnamed (yet) quatruped spider project by jinx
[July 01, 2020, 04:06:19 PM]


Re: "1984 Nixie Time" by 1 what
[May 08, 2020, 01:04:18 AM]


Re: "1984 Nixie Time" by tomasp
[April 13, 2020, 06:03:28 PM]


Re: 2D Side Scroller Cyberpunk themed by Killer Angel
[February 06, 2020, 06:39:40 AM]


A new wing design for model aircraft / drones by OddBot
[February 06, 2020, 04:42:06 AM]


Re: "1984 Nixie Time" by Gareth
[February 02, 2020, 06:23:01 AM]


Re: SDR (Software Defined Radio) by Gareth
[February 02, 2020, 06:15:42 AM]


Re: SDR (Software Defined Radio) by ZeroMax
[January 31, 2020, 01:54:21 PM]


Re: "1984 Nixie Time" by ZeroMax
[January 31, 2020, 01:52:29 PM]


Circuit Math by ZeroMax
[January 31, 2020, 01:50:18 PM]


Re: 2D Side Scroller Cyberpunk themed by ZeroMax
[January 31, 2020, 01:45:33 PM]


NanOMeter by Protowrxs
[January 01, 2020, 12:59:44 PM]


Re: Investigating the VL53L0X Laser Rangefinder by erco
[December 30, 2019, 10:45:44 PM]


PS4 Single Handed Controller Deployed (part 7 of 7) by Gareth
[December 30, 2019, 09:52:29 AM]