-
- Так и должно быть! Вставьте между двумя присвоениями вызов
какой-нибудь фиктивной функции или хотя бы NOP. - Bill(13.02.2023 13:05)
- обоснуй - POV(13.02.2023 13:09)
- Вообще-то неплохо было бы на сгенерированный код взглянуть. Я думаю
так. Компилятор копирует переменную systick в какой-нибудь регистр,
а содержимое этого регистра копируется в обе переменные и далее
сразу идёт проверка условия. Другими словами. компилятор может
исходное выражение привести к виду Bill(137 знак., 13.02.2023 13:24 - 13:30)
- Если systick был объявлен как volaitle, то, вне зависимости от того, куда класть его значение, вне зависимости от переменных temp, должно быть обращение к systick принудительно. Простите, без подписей что к чему, в асм-е Nikolay_Po(713 знак., 13.02.2023 14:15, ссылка)
- Топик пошёл по N-ому кругу. Кот уже был, всё там нормально >>> SciFi(1 знак., 13.02.2023 13:28, ссылка)
- А как NOP этот гипотетический сценарий исправит? - POV(13.02.2023 13:28)
- Вообще-то неплохо было бы на сгенерированный код взглянуть. Я думаю
так. Компилятор копирует переменную systick в какой-нибудь регистр,
а содержимое этого регистра копируется в обе переменные и далее
сразу идёт проверка условия. Другими словами. компилятор может
исходное выражение привести к виду Bill(137 знак., 13.02.2023 13:24 - 13:30)
- обоснуй - POV(13.02.2023 13:09)
- Я когда на 51-м прогал, делал две вещи: 1) Обработчик от таймера
использовал отдельные банки регистров. Там их 4 было. 2) При чтении
таймера проверял "атомарный" флаг, который взводился в прерывании,
и если он был сброшен, то запрещал прерывания и считывал. - Звepoящep(13.02.2023 08:27)
- Угу. Хотя первый пункт не обязателен, но очень удобно - symbions(13.02.2023 09:03)
- У вас кейл -51 следовательно MCS-51, следовательно атомарны только
чтения байтов. Вы читаете 4 байта, следовательно чтение не
атомарно, следовательно величина может изменится во время чтения.
При проверке temp!=systick время чтения systick больше чем при
temp2 =systick следовательно операция temp!=systick чаще приводитк
к глюкам, но это не значит что и код temp2 =systick тоже
безглючный. Вам нужно либо прерывания запрещать на время чтений
systick либо организовывать мютекс, Boвa(33 знак., 12.02.2023 10:09)
- И? Во время второго чтения произошло изменение - будет неравенство и новый цикл чтения. Вариант с двумя предварительными чтения вообще железобетонный. - POV(12.02.2023 12:04)
- Думаю - это ответ. - Toчкa oпopы(12.02.2023 11:34)
- А волатиле ваще не про это. Тут, походу, прерывания запрещать. - mse homjak(11.02.2023 23:42)
- волатайл - чтобы компилятор послушно выполненил два чтения в одной
итерации. - POV(12.02.2023 12:05)
- Он это сделает в любом случае. Нужна атомарность, а это с
волатильностью не соотносится никак. - mse homjak(12.02.2023 12:27)
- Не буду спорить, может неправ... но я не вижу связи с
атомарностью... POV(218 знак., 12.02.2023 12:30)
- Тогда уж берите три и мажорируйте. А то при переходе 0x00ffffff -
0x01000000 можно легко получить 0х00000000, после 0x00fffffe,
например. Вариантов масса. А волатильность совсем не при чом. Она
говорит компилеру, что эта переменная не должна подвергнуться
оптимизаццыи. И всё. Смысл её только в отладке, следить за чем-нить
интересным или обращение к порту вывода в адресном пространстве
памяти. Типа, программа только пишет, но не читает, на костёр
ведьму. mse homjak(64 знак., 12.02.2023 13:01)
- Волатильность не позволит компилятору внутри цикла прочитать
переменную один раз, и затем два раз это значение применить. - POV(12.02.2023 13:09)
- ХЗ, конечно, но можэт быть. - mse homjak(12.02.2023 13:21)
- Не выдумывайте, нету там "массы вариантов". Сравнения с предыдущим
чтением достаточно. - SciFi(12.02.2023 13:01)
- Масса вариантов коробления данных. Ну сравнили вы, не совпадла,
дальше что? Каличным можэт оказаться как первое чтение, так и
второе. - mse homjak(12.02.2023 13:04)
- Логика очень простая. Прочитали два раза, если значения совпали - то они верные. Если не совпали - читаем дальше, пока не совпадут. Абсолютно классическое и рабочее решение для чтения из основного потока переменной, изменяемой в прерывании. В обратную сторону, естественно, не работает. - LightElf(12.02.2023 17:12)
- "Не читал, но осуждаю"? Ясно-понятно. - SciFi(12.02.2023 13:06)
- Масса вариантов коробления данных. Ну сравнили вы, не совпадла,
дальше что? Каличным можэт оказаться как первое чтение, так и
второе. - mse homjak(12.02.2023 13:04)
- Волатильность не позволит компилятору внутри цикла прочитать
переменную один раз, и затем два раз это значение применить. - POV(12.02.2023 13:09)
- Тогда уж берите три и мажорируйте. А то при переходе 0x00ffffff -
0x01000000 можно легко получить 0х00000000, после 0x00fffffe,
например. Вариантов масса. А волатильность совсем не при чом. Она
говорит компилеру, что эта переменная не должна подвергнуться
оптимизаццыи. И всё. Смысл её только в отладке, следить за чем-нить
интересным или обращение к порту вывода в адресном пространстве
памяти. Типа, программа только пишет, но не читает, на костёр
ведьму. mse homjak(64 знак., 12.02.2023 13:01)
- Не буду спорить, может неправ... но я не вижу связи с
атомарностью... POV(218 знак., 12.02.2023 12:30)
- Он это сделает в любом случае. Нужна атомарность, а это с
волатильностью не соотносится никак. - mse homjak(12.02.2023 12:27)
- волатайл - чтобы компилятор послушно выполненил два чтения в одной
итерации. - POV(12.02.2023 12:05)
- Я бы с торону стека смотрел. Покажи, что выдаёт компилятор/линкер
после сборки - вот эту строчку: "Program Size: data=129.4 xdata=876
const=285 code=11864" И хорошо бы настройки/опции проекта глянуть:
Target и C51. Costic(1 знак., 11.02.2023 21:19, картинка)
- Я хз.. трудно поймать этот косяк, пару раз всего удалось
запечатлеть в отладке. А проявление его масса выползла... POV(175 знак., 11.02.2023 21:34, картинка, картинка)
- Я ставлю галочки и модель small, но думаю это не принципиально. Я бы три вещи смотрел. 1) Там выше "Вова" про атомарность хорошую мысль подал - DWORD не атомарна. 2) Реентерабельность, т.е. для прерываний хорошо бы написать копию GetCurrentTickISR(). 3) Экономить стек, например, объявить статичными "static volatile temp1, temp2;" 4) Не использовать DWORD. - Costic(12.02.2023 13:54)
- Я хз.. трудно поймать этот косяк, пару раз всего удалось
запечатлеть в отладке. А проявление его масса выползла... POV(175 знак., 11.02.2023 21:34, картинка, картинка)
- Листинг дизассемблера в студию. - SciFi(11.02.2023 21:04)
- Так проблема-то не в этом коде. Он работает. Но иногда что-то
перебивает данные. А прерываний море, как отследить где и кто
портит. POV(7 знак., 11.02.2023 21:12, картинка, картинка)
- Возможно где-то из обработчика прерывания вызывается
нереентерабельная функция. Смутно похожая шняга была недавно.
Обработчик не сохраняет регистры, так как он в своей банке
работает. А вызываемая функа обращается (по прямым адресам) к
регистрам основного банка, считая что регистры сохранены. Ну и
эпизодически чего-то херила в чужих регистрах. - LightElf(12.02.2023 01:01)
- +1 на счет вопроса реентерабельности. Там вся работа с DWORD
получается через какие-то функции компилятора, возможно выбрана не
реентерабельная версия при сборке, если там это вообще выбирается. AlexBi(204 знак., 12.02.2023 09:33)
- В самом листинг все, на мой взгляд, нормально. Хотя volatile у temp
лишний и вредный. Беда где-то в другом месте, возможно в самом
обработчике systick или даже вообще в третьем месте. Keil51
прекрасен, но оверлеинг переменных может приводить к неожиданным
результатам. - LightElf(12.02.2023 17:19)
- +1. Вангую, где-то в другом месте чуйдеса. - SciFi(12.02.2023 18:02)
- В самом листинг все, на мой взгляд, нормально. Хотя volatile у temp
лишний и вредный. Беда где-то в другом месте, возможно в самом
обработчике systick или даже вообще в третьем месте. Keil51
прекрасен, но оверлеинг переменных может приводить к неожиданным
результатам. - LightElf(12.02.2023 17:19)
- +1 на счет вопроса реентерабельности. Там вся работа с DWORD
получается через какие-то функции компилятора, возможно выбрана не
реентерабельная версия при сборке, если там это вообще выбирается. AlexBi(204 знак., 12.02.2023 09:33)
- У меня была проблема такого рода, когда я чужую либу к себе в код прикрутил. В ней было много вызовов функций с большим числом аргументов в виде uint32_t, а также локальных переменных. Стека не хватало. Выкидывал лишнее, типы данных заменил на uint16_t и меньше везде, где можно. - Costic(11.02.2023 21:32)
- Если код ни при чём, зачем он тут? Ну а с прерываниями надо просто отслеживать разделяемые ресурсы и предусматривать защиту там, где возможен конфликт. - SciFi(11.02.2023 21:20)
- Возможно где-то из обработчика прерывания вызывается
нереентерабельная функция. Смутно похожая шняга была недавно.
Обработчик не сохраняет регистры, так как он в своей банке
работает. А вызываемая функа обращается (по прямым адресам) к
регистрам основного банка, считая что регистры сохранены. Ну и
эпизодически чего-то херила в чужих регистрах. - LightElf(12.02.2023 01:01)
- Так проблема-то не в этом коде. Он работает. Но иногда что-то
перебивает данные. А прерываний море, как отследить где и кто
портит. POV(7 знак., 11.02.2023 21:12, картинка, картинка)
- По-моему, действительно глюк компилятора, если systic объявлен volatile. - Nikolay_Po(11.02.2023 21:01)
- Не видно как объявлен systick. Он volatile ? - ЫЫyкпy(11.02.2023 14:59)
- Какая разница? лишь бы не статик. Волатильным его надо делать, если в прерывании в него только пишут. Компилер справедливо рассудит, что в этом нет смысла и похерит. - mse homjak(11.02.2023 23:45)
- да - POV(11.02.2023 15:01)
- volatile должен быть systick, для temp это бесполезно. Дальше надо смотреть что в асме получилось - AlexBi(11.02.2023 14:56)
- Косяки смачные в компиляторах бывают:-) Писал на ПИКе восстановление ошибок посредством БЧХ 31. 21, оказалось что с переменной в 32 бита не работает вариант var32 = var 32 ^ 1. Инверсия младшего бита. Как то иначе сделал. - Visitor(11.02.2023 14:53)
- Так и должно быть! Вставьте между двумя присвоениями вызов
какой-нибудь фиктивной функции или хотя бы NOP. - Bill(13.02.2023 13:05)