Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Компилятор ICC AVR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
lolful
Логка программы. В определенном месте кода ждать пока функция не вернет "1".
Пишу:
Код
while(!URXFind_("OK", 2));
И что же происходит? Функция возвращает "1" в тот момент, когда не должна. Сейчас поясню.
Далее исправляю эту сточку на:
Код
while(!(temp = URXFind_("OK", 2)));
...и все начинает работать так, как надо. Когда надо функция возвращает "1", когда надо - "0". Что это за подводный камень? Ума не приложу как такое имеет место быть...
zhevak
Забавный случай. Но хотелось бы видеть

1. Прототип функции URXFind_(), конкретно, что она возвращает -- bool или число?
2. Ассемблерный код обоих фрагментов.
Палыч
Возможно, это - "гримасы" оптимизации. Посмотрите ассемблерный код, который генерится в первом и втором случае. Наверное будет ясно в чем дело
lolful
Код
unsigned char URXFind_(unsigned char* buf, unsigned char len, unsigned char* pos);
В первом посте намеренно упустил 3й параметр. В коде он присутствует. Функция возвращает 1 или 0.

Код

while(!URXFind_("OK", 2, &temp));

0240           L51:
0240                   .dbline 125
0240           L52:
0240                   .dbline 125
0240 22E0              ldi R18,2
0242 30E0              ldi R19,0
0244 00E0              ldi R16,<L54
0246 10E0              ldi R17,>L54
0248 0E940000          xcall _URXFind_
024C 402F              mov R20,R16
024E 4423              tst R20
0250 B9F3              breq L51
0252                   .dbline 126
0252 88E0              ldi R24,8
0254 28B0              in R2,0x8
0256 2826              eor R2,R24
0258 28B8              out 0x8,R2
025A                   .dbline 127
025A 01E0              ldi R16,1


Код
while(!(temp = URXFind_("OK", 2, &temp)));

0240           L51:
0240                   .dbline 125
0240           L52:
0240                   .dbline 125
0240 22E0              ldi R18,2
0242 30E0              ldi R19,0
0244 00E0              ldi R16,<L54
0246 10E0              ldi R17,>L54
0248 0E940000          xcall _URXFind_
024C 0030              cpi R16,0
024E 0107              cpc R16,R17
0250 B9F3              breq L51
0252           X5:
0252                   .dbline 126
0252 88E0              ldi R24,8
0254 28B0              in R2,0x8
0256 2826              eor R2,R24
0258 28B8              out 0x8,R2
025A                   .dbline 127
025A 01E0              ldi R16,1
zhevak
Здесь вопросов не возникает. Возвращаемый байт четко определяется на ноль в последовательности mov-tst-breq. Может быть Вы возвращаете не 0x00, а символ нуля '0' ?
Код

while(!URXFind_("OK", 2, &temp));

0240           L51:
0240                   .dbline 125
...
0248 0E940000          xcall _URXFind_
024C 402F              mov R20,R16
024E 4423              tst R20
0250 B9F3              breq L51

Таким образом, прога бегает по кругу до тех пор, пока функция возвращает ноль (0x00).
Все в полном соответствии с си-шным текстом.

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

while(!(temp = URXFind_("OK", 2, &temp)));

0240           L51:
0240                   .dbline 125
0248 0E940000          xcall _URXFind_
024C 0030              cpi R16,0
024E 0107              cpc R16,R17
0250 B9F3              breq L51


Скорее всего, Вы что-то не то возвращаете из функции URXFind_().
Либо сами далее разбирайтесь, либо аоказывайте ее сишный код.
lolful
temp - это unsigned char. Функция возвращает именно число 0 или 1, а не их ASCII-код.
Но проблема то в том, что в первом случае чушь происходит, а во втором - все отлично работает.

PS Ой-ой! Что это тут написано! temp = URXFind_("OK", 2, &temp) - temp как параметр и как возвращаемое значение. Так не должно быть, хотя на работу это не влияет.

Ладно, буду сам разбираться. Придется вспоминать ассемблер...
Палыч
Цитата(zhevak @ Sep 16 2008, 10:21) *
Скорее всего, Вы что-то не то возвращаете из функции URXFind_().
Наверное, так и есть. Поскольку ассемблерные коды отличаются только числом регистров, проверяемых на ноль: в первом случае - один регистр (R16, байт), во втором - два (R16 и R17, слово). Поскольку функция URXFind_() возвращает байт, то проверки R16 должно было бы хватать. Поскольку проверки одного байта не хватает, то с функцией URXFind_() что-то не в порядке...
zhevak
Цитата(lolful @ Sep 16 2008, 13:32) *
temp - это unsigned char. Функция возвращает именно число 0 или 1, а не их ASCII-код.


Обратите внимание, во втором случае ветвление зависит от двубайтовой переменной
Код
024C 0030              cpi R16,0
024E 0107              cpc R16,R17

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

Удачи!

ЗЫ. Отключите всю оптимизацию нафиг, на данном этапе она только вредит.
lolful
Бррр...Я перепутал местами ассемблерный код, когда писал 2й пост...

Вобщем вот к чему я пришел. Если написать
Код
while(!(unsigned char)(URXFind_("OK\r\n", 2, &temp)));
...то все работает. Видать компилятор думает, что функция возвратит не unsigned char, а нечто вроде int и лезет в регистр, который занят чем-то. Таким образом в обоих регистрах почти 100% вероятность того, что там будет не 0. Ошибка банальна - я не прописал прототип в заголовочном файле. Дурак. twak.gif
zhevak
Цитата(lolful @ Sep 16 2008, 13:46) *
Бррр...Я перепутал местами ассемблерный код, когда писал 2й пост...
....
вероятность того, что там будет не 0. Ошибка банальна - я не прописал прототип в заголовочном

Бывает. smile.gif

Цитата
Дурак. twak.gif

эт-лишнее.
lolful
Цитата(zhevak @ Sep 16 2008, 13:50) *
эт-лишнее.

Не-не. Я не отчаиваюсь. biggrin.gif В следующий раз буду умнее.

Спасибо всем за помощь.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.