2014-08-29 9 views
1

Недавно я столкнулся с проблемой, когда переменная изменялась только в обработчике прерываний. Сама переменная не была объявлена ​​нестабильной, поэтому при более высоких уровнях оптимизации компилятор нарушил код. Однако компилятор достаточно умен, чтобы скомпилировать код прерывания, потому что прерывание все еще срабатывает.Почему компилятор не оптимизирует код прерывания?

Так вот мои вопросы:

  1. Если компилятор достаточно умен, чтобы скомпилировать код прерывания, почему он не достаточно умен, чтобы понять, что переменные изменяются внутри, что прерывание?

  2. На более высоких уровнях оптимизации функции, которые не называются, оптимизируются. Поскольку никакой код не вызывает обработчик прерываний, он должен быть оптимизирован. Что заставляет компилятор компилировать код прерывания в любом случае?

+3

Разместите код и, возможно, соответствующий демонтаж – Sinkingpoint

+0

Какой компилятор вы используете (это свежая версия [GCC] (http://gcc.gnu.org/))? Какие флаги оптимизации? Какова целевая платформа и процессор? И почему бы вам не использовать 'volatile' (вы действительно должны в своем случае)? –

+0

Может быть, потому что на него ссылаются, когда вы загружаете векторный контроллер прерываний по адресу? Если ссылается адрес обработчика, то компилятор предположит, что он может быть вызван. –

ответ

5
  1. язык модель исполнения говорит, что обычный (энергонезависимая) переменная не может быть изменен на «внешних сил». То есть если в вашем потоке кода явно не изменяется переменная, то из точки зрения этого потока кода переменная не может измениться. (Кроме того, что определено C11 для многопоточного исполнения). Вы должны вручную «назначить» переменные, которые могут быть изменены обработчиками прерываний.

    Это один из основных факторов, который позволяет эффективно оптимизировать код C. Его нельзя устранить, не оказывая существенного негативного влияния на производительность программ на С.

  2. Во-первых, компиляторы обычно не оптимизируют функции с внешней связью. Объявлен ли ваш обработчик прерываний внешней связью?

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

    Ваша запись вектора прерывания инициализируется каким-то образом при запуске программы, что обычно включает в себя прием адреса функции обработчика. Этого уже достаточно, чтобы защитить эту функцию от оптимизации.

+0

Я использую процессор stm32, а библиотека поддержки производителя скрыла многие детали ссылок на прерывания. Я знаю, что мне нужно написать 'TIM4_IRQHandler', например, где-то в моем коде, и компоновщик помещает этот обработчик в нужное место в векторной секции. Компилятор сохраняет эту функцию, потому что компоновщик разместил адрес «TIM4_IRQHandler» в векторной секции. Это то, что я предполагаю, происходит. – thndrwrks

+0

@thndrwrks: Если ваша реализация предоставляет некоторые скрытые функции «под капотом», которые гарантируют, что ваш 'TIM4_IRQHandler' будет помещен в нужное место в векторе прерывания, то более чем вероятно, что одна и та же функциональность также принимает все необходимое шаги по предотвращению оптимизации «TIM4_IRQHandler». – AnT

+0

Это действительно то, что происходит. Принятие адреса обработчика для VIC означает, что компилятор предполагает, что он может быть вызван. –