How to read from peripheral I / O register using C / gcc?

I have interrupt service routing on the AVR32. I need to read from the interrupt status register to cancel the interrupt. However, I do not use the reading result. I would prefer not to use the asm instruction, but I am worried that gcc optimizes reading in a dummy variable. What is the right way?

I currently have:

uint32_t tmp = *(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS; 

Should tmp be volatile? I am worried that gcc will simply skip reading if tmp is not used.

+6
source share
1 answer

Reading the interrupt state register using the pointer passed to (volatile uint32_t *) tells the compiler that reading this expression (a variable at the specified address) creates side effects, so you should always evaluate this expression.

Since your tmp variable is unstable, the compiler can optimize the storage time of your register value in the variable.

I think that chapter 5.1.2.3 of standard C (see here) is quite relevant.

Additionally, chapter 6.7.3 explains:

An object that has a mutable type can be modified in ways that are unknown to the implementation or have other unknown side effects. Therefore, any expression that refers to such an object is evaluated strictly in accordance with the rules of an abstract machine, as described in 5.1.2.3. In addition, at each point in the sequence, the last value stored in the object agrees with what is prescribed by the abstract machine, with the exception of cases of unknown factors mentioned earlier. 116) What constitutes access to an object that is of an unstable type is determined by the implementation.

In fact, you can omit tmp and just write:

 *(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS; 

It will just read the uint32_t register located in INTERRUPT_STATUS_REG_ADDRESS;

+6
source

Source: https://habr.com/ru/post/977002/


All Articles