Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one read from an peripheral IO register using C/gcc?

I have an interrupt service routing on the AVR32. I need to read from the interrupt status register in order to cancel the interrupt. However I don't use the result of the read. I'd rather not use an asm instruction, but I am concerned that gcc will optimize away a read into a dummy variable. What is the right way?

Currently I have:

uint32_t tmp = *(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS;

Should tmp also be volatile? I'm worried that gcc will just skip the read if tmp is not used.

like image 604
Robotbugs Avatar asked Oct 20 '14 21:10

Robotbugs


People also ask

Can you access registers in C?

To access a specific register, the code first needs to write the register number to the device and then perform the required write/read operation. This is not difficult, but needs to be managed carefully.

What is register in C++?

The register keyword is a request to the compiler that the specified variable is to be stored in a register of the processor instead of memory as a way to gain speed, mostly because it will be heavily used.


1 Answers

Reading interrupt status register through pointer cast to (volatile uint32_t*) tells compiler that reading this expression (variable at specified address) produces side effects, so it always needs to evaluate this expression.

As your tmp variable is not volatile, compiler is free to optimize away storing the value of your register to variable.

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

Additionally chapter 6.7.3 explains:

An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3. Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously. 116) What constitutes an access to an object that has volatile-qualified type is implementation-defined.

You can actually omit tmp and just write:

*(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS;

This will simply read uint32_t register located at INTERRUPT_STATUS_REG_ADDRESS;

like image 96
dbrank0 Avatar answered Sep 28 '22 02:09

dbrank0