Luis Possatti
Luis Possatti

Reputation: 133

compiler execution sequence

I am programming a microcontroller in C language and I’ve faced the following situation: To enable/disable the internal clock generator, I need to first write a protection key to a specific register and after make the enable/disable operation, writing in another register. The user manual specify the following about this operation: snip from user manual

As you can see in the highlighted part of the text, the piece of code that make this two operation (writing protection key and enable the oscillator) is very sensitive, because any operation should be executed between this two register access. Therefore, I start to concern about any situation that could led to a non sequential execution of this two operations. I know that it is common to temporary disable interruption while executing sensitive piece of codes, but I was wonder if there is any compiler optimization that could insert another operation between this two register access. So, in C programming, there is any compiler directive to ensure that it will not happen?

Actually, I even do not know if make sense to think that the compiler will mix the sequence of instructions written in C language. I remember to have already heard that it could happens sometimes, in the speed optimization process. If I am wrong, sorry about and thanks in advance for the clarification.

Upvotes: 2

Views: 628

Answers (1)

The process of toggling bits in C involves a read-modify-write sequence of instructions. Some unwanted operations may happen between those instructions and the usual approach is to either disable the interrupts or to use bit-banding.

What bit-banding is, it allows to you toggle bits using one instruction(without going into details how it happens).

If your microcontroller allows you to use bit-banding, then that should fix all your problems.

If you can't use bit-banding, then you have to sit and think what interrupts may cause problems to you and temporarily disable them.

To get back to the core of the question - you must declare all of your registers volatile for two main reasons:

  1. Unlike ordinary memory that is only modified by the program itself, the value stored in those memory mapped registers can change at any time, what the compiler will do is just optimize away all reads and writes to the register. Volatile prevents this.By declaring a variable volatile, you're effectively asking the compiler to be as inefficient as possible when it comes to reading or writing that variable. Specifically, the compiler should generate code to perform each and every read from a volatile variable as well as each and every write to a volatile variable even if you write it twice in a row or read it and ignore the result. Not a single read or write can be skipped. In other words, no compiler optimizations are allowed with respect to volatile variables.
  2. In a nutshell, the order of accesses of volatile variables A and B in the object code must be the same as the order of those accesses in the source code. The compiler is not allowed to reorder volatile variable accesses for any reason. (Consider what might go wrong if the referenced memory locations were hardware registers like in this case). Volatile guarantees you that everything happens in the sequence you specify in your code and no reorderings are being made.

To sum it up - use bit-banding and declare the registers volatile.

Upvotes: 1

Related Questions