Полная версия этой страницы:
Как обойти глюки оптимизации
Serg_el
Dec 22 2008, 13:25
Есть некая глобальная переменная, которая является счетчиком и инкриминируется в процедуре обработки прерывания таймера. Есть функция выдержки времени, в которой используется эта переменная. Перед функцией я обнуляю переменную-счетчик и жду пока таймер не отсчитает необходимое количество времени, после этого выхожу из функции задержки. Проблема в том, что при включении оптимизации компилятор выкидывает строку обнуления, т.е. (я так понимаю) он не видит, что она меняется в таймере и считает строку обнуления лишней! Как это можно обойти? Вместо обнуления пробовал считывать текущее значение таймера и прибавлять к нему требуемую задержку и далее эту величину подставлять в условие, но там похожая ситуация.
void delay(unsigned int time)
{
while (timer < time);
{
}
}
#pragma vector=TIMERA0_VECTOR
__interrupt void TIMERA0_INT( void )
{
timer++;
}
void function(void)
{
timer = 0;
delay(2200);
}
bloodden
Dec 22 2008, 13:32
При объявлении переменной напишите volatile int timer
forever failure
Dec 22 2008, 13:32
volatile int timer;
А ещё обеспечивать атомарное обращение к этой переменной (если, конечно, она занимает более одного байта).
Dog Pawlowa
Dec 22 2008, 13:41
Цитата(forever failure @ Dec 22 2008, 17:32)

А ещё обеспечивать атомарное обращение к этой переменной
Ручками : запретить прерывания, разрешить прерывания.
Serg_el
Dec 22 2008, 13:46
А что такое атомарное и причем здесь прерывания?
forever failure
Dec 22 2008, 13:54
Это означает, что если переменная, допустим, типа int, и она проверяется в основной программе, в момент проверки, после сравнения, допустим старшего байта происходит прерываие таймера и изменяет эту переменную. В результате в операции сравнения сравнивается старший байт от старого значения, а младший - от нового.
Вот такой получается косячок-с. Для того, чтоб такого не происходило, на время обращения к этой переменной прерывания надо запретить, а потом опять восстановить. (Или одно, конкретное прерывание, которое обновляет переменную).
Цитата(Serg_el @ Dec 22 2008, 16:46)

А что такое атомарное и причем здесь прерывания?
При всём уважении, но Вам надо в форум для начинающих. Эта проблема стара как мир, и компилятор IAR тут ни при чём. Зачем снова отвечать на одни и те же вопросы? Используйте поиск...
Serg_el
Dec 22 2008, 13:58
Спасибо. Буду пробовать
Цитата(forever failure @ Dec 22 2008, 16:54)

Вот такой получается косячок-с. Для того, чтоб такого не происходило, на время обращения к этой переменной прерывания надо запретить, а потом опять восстановить. (Или одно, конкретное прерывание, которое обновляет переменную).
Есть ещё один способ. Считать переменную 2 раза и сравнить старший байт для двух считываний. Если не изменился - всё ОК, иначе - повторить. Есть свои минусы, но зато прерывание не запрещаем.
Serg_el
Dec 23 2008, 15:19
Вот еще один прикол. Прописываю константу limit по фиксированному адресу и присваиваю ей значение.
const unsigned int limit @ 0xE1FE = 29;
Компилятор игнорит, тот факт, что указан конкретный адрес и заменяет все ссылки на нее по тексту программы на ее значение 29.
Константа используется для значения, программируемого извне. А значение 29 присваивал для отладки и пока не закомментил, не хотел компилятор использовать limit.
HARMHARM
Dec 23 2008, 15:42
Цитата(Serg_el @ Dec 23 2008, 17:19)

Вот еще один прикол. Прописываю константу limit по фиксированному адресу и присваиваю ей значение.
const unsigned int limit @ 0xE1FE = 29;
Компилятор игнорит, тот факт, что указан конкретный адрес и заменяет все ссылки на нее по тексту программы на ее значение 29.
Константа используется для значения, программируемого извне. А значение 29 присваивал для отладки и пока не закомментил, не хотел компилятор использовать limit.
Добавьте __root.
rezident
Dec 23 2008, 16:06
Эта тема напоминает торный путь из граблей, по которому ходят все вновьприбывшие.

И каждый вновьприбывший удивляется тому факту, что дорога вроде давно протоптана, а грабли все еще лежат там же

Про
volatile надо писать в FAQ
крупными буквами. А по поводу оптимизации обращения к константе, расположенной по фиксированному адресу, я сам недавно
писал и там же указал решение/обходной путь.
sonycman
Dec 25 2008, 15:13
Цитата(scifi @ Dec 22 2008, 18:06)

Есть ещё один способ. Считать переменную 2 раза и сравнить старший байт для двух считываний. Если не изменился - всё ОК, иначе - повторить. Есть свои минусы, но зато прерывание не запрещаем.
Может наоборот, сравнивать младшие байты? А то ведь старшие могут быть равны, а младший отличаться.
Сергей Борщ
Dec 25 2008, 15:32
Цитата(sonycman @ Dec 25 2008, 17:13)

Может наоборот, сравнивать младшие байты? А то ведь старшие могут быть равны, а младший отличаться.
При этом результат каждого чтения будет содержать
корректное на момент чтения значение пары младшего и старшего байтов. Поскольку прерывание с точки зрения программы атомарно. Т.е. не может сначала изменить младший байт с 0xFF на 0x00, потом дать немного поработать программе и только потом увеличить на 1 старший байт.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.