2016-08-22 6 views
7

Иногда мне нужен какой-то код, который будет выполняться процессором точно так же, как я положил его в исходный код. Но у любого компилятора C есть алгоритмы оптимизации, поэтому я могу ожидать некоторые трюки. Например:Как мне сказать «компилятору», что код не должен быть оптимизирован?

unsigned char flag=0; 

interrupt ADC_ISR(){ 
    ADC_result = ADCH; 
    flag = 1; 
} 

void main(){ 
    while(!flag); 
    echo ADC_result; 
} 

Некоторые компиляторы, безусловно, сделать while(!flag); цикл инфинитив, как это будет предполагать, flag равно ложь (!flag поэтому всегда верно).

Иногда я могу использовать ключевое слово volatile. И иногда это может помочь. Но на самом деле в моем случае (AVR GCC) volatile ключевое слово заставляет компилятор размещать переменную в SRAM вместо регистров (что плохо по некоторым причинам). Кроме того, многие статьи в Интернете предлагают использовать ключевое слово с большим вниманием, поскольку результат может стать нестабильным (в зависимости от компилятора, его настроек оптимизации, платформы и т. Д.).

Так что я определенно предпочел бы как-то указать инструкцию по исходному коду и сообщить компилятору, что этот код должен быть скомпилирован точно так, как есть. Например: volatile while(!flag);

Есть ли какая-либо стандартная инструкция C для этого?

+1

Конечно, переменная 'volatile' переходит в ОЗУ! Регистры предназначены для временных значений. Прерывание может происходить в любое время. Я бы рекомендовал сделать еще несколько исследований параллельности, особенно обработчиков прерываний и разработки встроенного программного обеспечения.Например, для логического флага вы должны использовать булевский стандартный тип. – Olaf

+1

Volatile означает, что значение переменной не может быть кэшировано между чтениями (и что записи не могут перемещаться). Да, это обычно приводит к разгрузке в ОЗУ каждый раз. Если вы думаете, что можете сделать лучше, вам следует попробовать [встроенную сборку] (http://www.ethernut.de/en/documents/arm-inline-asm.html). – Cubic

+0

@Cubic: Какое изменение сделало бы встроенную сборку для переменных? OP, похоже, даже не думает о плохо оптимизированном коде, а об использовании ресурсов. Единственным решением для этого было бы написать ** все ** в Assembler, чтобы он мог контролировать регистр CPU и распределение памяти на 100%. Микроуправление в лучшем виде. Я делал это много лет и очень рад, что у нас есть компиляторы, которые заботятся об этом. – Olaf

ответ

3

Вы действительно должны использовать volatile как answered by David Schwartz. См. Также this глава документации GCC.

Если вы используете последнюю GCC компилятор, вы можете отключить оптимизацию в одной функции, используя соответствующую function specific options pragmas (или некоторые optimize функции attribute), например

#pragma GCC optimize ("-O0"); 

перед вашим main. Я не уверен, что это хорошая идея.

Возможно, вы хотите extended asm statements with the volatile keyword.

8

Единственный стандарт C - volatile. Если это не так, как вам нужно, вам нужно использовать что-то конкретное для вашей платформы.

+0

Нет необходимости в чем-то «специальном». – Olaf

1

У вас есть несколько вариантов:

  1. компилируется без оптимизаций. В отличие от некоторых компиляторов, GCC по умолчанию не оптимизируется, поэтому, если вы не сообщите ему об оптимизации, вы должны получить сгенерированный код, который очень похож на ваш источник C. Конечно, вы можете оптимизировать некоторые файлы C, а не другие, используя простые правила make.

  2. Вывести компилятор из уравнения и записать соответствующие функции в сборке. Тогда вы можете получить точно сгенерированный код, который вы хотите.

  3. Использовать volatile, что не позволяет компилятору делать какие-либо предположения относительно определенной переменной, поэтому для любого использования переменной в C компилятор вынужден генерировать LOAD или STORE, даже если это необязательно.