2014-10-20 1 views
6

У меня есть маршрутизация службы прерываний на AVR32. Мне нужно прочитать из регистра состояния прерывания, чтобы отменить прерывание. Однако я не использую результат чтения. Я бы предпочел не использовать инструкцию asm, но я обеспокоен тем, что gcc оптимизирует прочтение в фиктивной переменной. Каков правильный путь?Как читать из периферийного регистра ввода-вывода с использованием C/gcc?

В настоящее время у меня есть:

uint32_t tmp = *(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS; 

Если TMP быть неустойчивыми? Я беспокоюсь, что gcc просто пропустит чтение, если tmp не используется.

+0

Я не знаком с AVR32, но вы уверены, что вам нужно прочитать регистр статуса прерывания? По моему опыту, вам просто нужно очистить единый флаг прерывания в соответствующем регистре (часто это делается путем записи 1 в соответствующий бит). Кроме того, что вы используете для этого? –

+0

Да, это просто чтение регистра статуса сравнения PWM для очистки IRQ. 'uint32_t temp = AVR32_PWM.isr2;' – Robotbugs

ответ

6

Чтение регистра состояния прерывания с помощью указателя, переданного в (volatile uint32_t *), говорит компилятору, что чтение этого выражения (переменной по указанному адресу) создает побочные эффекты, поэтому всегда необходимо оценить это выражение.

Поскольку ваша переменная tmp не является изменчивой, компилятор может свободно оптимизировать, сохраняя значение вашего регистра в переменной.

Я думаю, что глава 5.1.2.3 стандарта C (see here) достаточно актуальна.

Дополнительно глава 6.7.3 объясняет:

Объект, который имеет летучий квалифицированный типа может быть изменен таким образом, неизвестными реализации или имеют другие неизвестные побочные эффекты. Поэтому любое выражение, относящееся к такому объекту , должно оцениваться строго в соответствии с правилами абстрактной машины , как описано в 5.1.2.3. Кроме того, в каждой точке последовательности последнее значение, хранящееся в объекте , согласуется с тем, что предписывается абстрактной машиной, за исключением измененных неизвестных факторов, упомянутых ранее. 116) Что представляет собой доступ к объекту, который имеет тип , имеет тип, определяемый реализацией.

Вы можете на самом деле опустить TMP и просто написать:

*(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS; 

Это просто читать uint32_t регистр находится в INTERRUPT_STATUS_REG_ADDRESS;

+0

Спасибо, это странно видеть кусок кода, который, кажется, ничего не делает. Я действительно не был уверен, что такое может сработать. – Robotbugs

+1

Да, это выглядит странно, поэтому, вероятно, полезно написать макрос или функцию с пояснительным именем для чтения периферийных регистров. – dbrank0