There are two volatile variables:

volatile uint32_t a; volatile uint32_t b; 

They are declared as volatile, because they can change both in the main program and in the interrupt handler, and devices on the system bus (such as DMA). If both variables participate in the same expression, for example:

 uint32_t c = a + b; 

then the compiler issues a warning. Order of volatile access is undefined in this statement . As I understand it, this means that it is not known which variable will be loaded into the general purpose register first, and it is possible that the a variable is loaded into the register, the interrupt has been triggered, the variable has changed, and the main program continues to work with the old value. Some sources recommend in such situations to break the expression into parts, for example:

 uint32_t c = a; c += b; 

but in my opinion, this is how we only shut up the compiler, and not eliminate the cause of the problem.

And now the actual question. In the program, interrupt handlers constantly periodically change volatile variables, while the main program performs mathematical transformations. As soon as the new value of the variable has come, the old is no longer interesting. Is it possible to ignore the compiler warning in this case? Does this warning have other sources that I don’t guess?

    3 answers 3

    In C, the order of access to volatile objects, along with calls to I / O functions, is part of the program’s observable behavior. Therefore, this warning simply looks like a warning from the pedantic compiler, which says that the observed behavior of the program in this case is not uniquely defined.

    The compiler is right - it really is not uniquely defined. But the compiler, of course, does not know which facets of the observed behavior are really important for the specifics of your program, and which are not, and gives an abstract pedantic warning.

    If in this case the order of access to these variables is really important for you, then the warning is completely justified. If you see no problems with any possible access order, then rewrite the code purely for the sake of eliminating the warning from the compiler.

    It is clear that in the situation you described, when modifying a and b from independent execution lines (threads, interrupts, etc.) and in the absence of any synchronization, a pronounced data race will be observed. And if this data race is fatal for your application, you know better. If you want to get rid of this data race, then you can’t get by with suppressing warnings - you have to organize some form of synchronization of access to this pair.

      "but in my opinion, this is how we just shut up the compiler, and not eliminate the cause of the problem"

      You cannot eliminate the cause of the problem within the programming language and the compiler ( in principle, the volatile keyword), so just take note of this warning and decide for yourself how important it is in a specific task ...

        As soon as the new value of the variable has come, the old is no longer interesting.

        I had a similar problem. And I solved it like this:

         volatile uint32_t a; volatile uint32_t b; uint32_t a1; uint32_t b1; uint32_t x uint8_t trust; // Запоминаем исходные значения a1=a; b1=b; // Выполняем расчёт нужного значения x = a1+b1; // Проверяем, можно ли доверять этому значению if ( (a == a1) && (b == b1) ) trust = 1; else trust = 0; 

        I understand that from the point of view of theory, this solution is far from ideal. I understand that there will be false assignments of trust, but if only confidence is sufficient. that the result of the calculation really corresponds to the PAIR of the original values, it is almost certain. Not 100%, but such a guarantee is better than none. But if trust == 0, then it will almost 100% protect against false results.