Форум РадиоКот https://radiokot.ru/forum/ |
|
While компилируется в вечный цикл https://radiokot.ru/forum/viewtopic.php?f=59&t=162359 |
Страница 1 из 1 |
Автор: | Волосатый [ Пн апр 15, 2019 01:50:10 ] |
Заголовок сообщения: | While компилируется в вечный цикл |
Доброго времени суток. Cтолкнулся с такой проблемой, код вида Код: while (flag){}; компилируется в вечный цикл, ассемблерный код этой строчки выглядит так:Код: 08004242: ldrb r3, [r4, #0] 08004244: cmp r3, r5 08004246: bne.n 0x800424a 08004248: b.n 0x8004248 Погуглив выяснил, что команда "bne.n" это переход, если z = 0, а команда "b" - безусловный переход. То есть получается, если flag = 0 и мы заходим в цикл ожидания, процессор сразу из него выходит, а если зайти в цикл, когда flag отличается от нуля, мы попадем в вечный цикл. Такая история появляется только в одной большой функции, где нужно после получения команды с юсарт подождать, пока не завершится какое-то действие. в программе у меня много где такой цикл используется, но никогда не было проблем. Объявление переменной: Код: volatile u8 flag = 0; Волатильная, не волатильная - ничего не меняется. flag гарантировано возвращается в 0 по ходу работы программы (смотрел дебаггером). Среда CooCox 1.7.6, gcc 4.8 2014q3 |
Автор: | uldemir [ Пн апр 15, 2019 04:04:19 ] |
Заголовок сообщения: | Re: While компилируется в вечный цикл |
Проверьте "видимость" этой переменной. Не случается ли так, что меняется одна локальная, а опрашивается другая локальная переменная с тем же именем. Чудес не бывает. А подобные баги компилятора вылавливаются на уровне альфатестирования. И переменная должна быть волатильной, иначе оптимизатор её примет равной нулю всегда. |
Автор: | ARV [ Пн апр 15, 2019 06:33:12 ] |
Заголовок сообщения: | Re: While компилируется в вечный цикл |
Автор: | BOB51 [ Пн апр 15, 2019 11:03:24 ] |
Заголовок сообщения: | Re: While компилируется в вечный цикл |
Так правильно и скомпилировалось - ежли flag равно нулю - прыгаем за пределы цикла. |
Автор: | Волосатый [ Пн апр 15, 2019 12:08:08 ] |
Заголовок сообщения: | Re: While компилируется в вечный цикл |
Еще раз. Флаг волатильный, = 0 в его инициализации, в процессе работы программы он меняется 10000000% У меня не только с этой переменной проблема. Добавлено after 5 minutes 59 seconds: Так же этот косяк всплывает со строчкой Код: while (mseconds >= 98){}; Ассемблер тот же, проваливается в бесконечный цикл, если на момент попадания в цикл, mseconds больше или равен 98. Эту переменную так же делал волатильной, а инициализация нулем отсутствует. |
Автор: | Аlex [ Пн апр 15, 2019 12:24:59 ] |
Заголовок сообщения: | Re: While компилируется в вечный цикл |
Волосатый, Вы нам рассказываете про чудеса. volatile должен (даже обязан) решить эту проблему, причём независимо от того, чем инициализирована переменная. |
Автор: | Волосатый [ Пн апр 15, 2019 12:48:46 ] |
Заголовок сообщения: | Re: While компилируется в вечный цикл |
Ну я же не придумываю... Вот нагляднее пример. Код: void usart(void){ volatile sec_tmp; ... ... switch (comand){ case TSET: sec_tmp = ds3231_rtc_data.seconds; // ТУТ ЗАПИСЫВАЕТСЯ ВРЕМЯ while (sec_tmp == ds3231_rtc_data.seconds); // ожидаем, пока в прерывании не поменяется время // ОТСЫЛАЕМ ОТВЕТ break; } } На первый раз выполняется правильно, на второй раз виснет на ожидании. Спасибо за внимание, сделал ds3231_rtc_data.seconds тоже волатильной и оно заработало. А с флагом хз что было)) но тоже работает. Магия какая-то. |
Автор: | Reflector [ Пн апр 15, 2019 13:00:57 ] |
Заголовок сообщения: | Re: While компилируется в вечный цикл |
Спасибо за внимание, сделал ds3231_rtc_data.seconds тоже волатильной и оно заработало. У тебя в цикле может меняться ds3231_rtc_data.seconds, а sec_tmp не может, она вообще локальная, ее извне никак не поменяешь, потому второй volatile лишний. |
Автор: | VladislavS [ Пн апр 15, 2019 13:15:24 ] |
Заголовок сообщения: | Re: While компилируется в вечный цикл |
Ну вот, так всегда, как начинают код светить, так чудеса куда-то сами растворяются... |
Автор: | Волосатый [ Пн апр 15, 2019 14:00:58 ] |
Заголовок сообщения: | Re: While компилируется в вечный цикл |
У меня логика была такая, что sec_tmp мы только что приравняли к ds3231_rtc_data.seconds и тут же их сравниваем, компилятор то не знает, что ds3231_rtc_data.seconds может где-то измениться. |
Автор: | qbit [ Вт апр 16, 2019 22:23:06 ] |
Заголовок сообщения: | Re: While компилируется в вечный цикл |
Ваша беда в поголовном использовании while. Переходите на иную стилистику программирования - программные автоматы. Поясню на пальцах на вероятный "баг" в приведенном Вашем фрагменте кода. Код: // ТУТ ЗАПИСЫВАЕТСЯ ВРЕМЯ Вы уверены, что тут изменилась переменная ds3231_rtc_data.seconds. Но т.к. работает с внешнем тайкиппером, то Вы должны допускать вероятность, что переменная может не измениться и Вы попадете в while . |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |