juvf 17 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба При отладке одно из главнейших правил: ПРИ ПРОЯВЛЕНИИ БАГА НЕ СЛЕДУЕТ СТАРАТЬСЯ ДОБИТЬСЯ ТОГО, ЧТОБЫ ОН НЕ ПРОЯВЛЯЛСЯ. НАДО НАОБОРОТ - ЗАКРЕПИТЬ УСЛОВИЯ, ПРИ КОТОРЫХ ОН ПРОЯВЛЯЕТСЯ, ДОБИТЬСЯ ЕГО ПОВТОРЯЕМОСТИ И ИСКАТЬ ЕГО ПРИЧИНУ И УСТРАНИТЬ! И пока этого не сделано - двигаться дальше нельзя.так я нашел причину и устранил. )) inline void waitSpi() { while( (SPI1->SR & (uint8_t)SPI_FLAG_BSY));} - вот этот код не работает с оптимизацией в пустом хороводе. И не изредка - а всегда. 100 раз из 100. А без оптимизации работает как часы. ни каких сбоев в обмене по SPI замечено не было. Ведь не тот баг страшен, который чётко проявляется, а тот - что проявляется иногда, внезапно и хаотично.У меня црц считается с ошибкой всегда, когда вкл оптимизация, не изредка, а всегда. И всегда считается правильно с отключенной оптимизацией. Нету хаотичных и внезапных сбоев. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Любопытства ради и самообразования для, не могли бы вы привести код црц и чем копилируете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба inline void waitSpi() { while( (SPI1->SR & (uint8_t)SPI_FLAG_BSY));} - вот этот код не работает с оптимизацией в пустом хороводе. И не изредка - а всегда. 100 раз из 100. А без оптимизации работает как часы. ни каких сбоев в обмене по SPI замечено не было. Я так понимаю, версия про "volatile" была проверена и не подтвердилась? Опять же, конкретно в этом случае чтение листинга дизассемблера не затруднило бы нисколько. Из оправданий - только лень. Кстати, бывают баги, зависящие от задержек. Скажем, регистр SPI1->SR нужно начинать читать не сразу, а через пару тактов, без оптимизации задержка получалась сама собой - как вариант. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Любопытства ради и самообразования для, не могли бы вы привести код црц и чем копилируете? читайте выше. там и код и чем компилирую. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба ээээ.... а разве при переполнении стека программа аварийно не завершается? При переполнении стека симптомы могут быть какие угодно: может fault вылететь, а могут просто данные испортиться. А без оптимизации шагается но и работает без ошибок. Я уже писал выше что можно сделать. Скомпилить данную функцию с оптимизацией. А потом вырезать её ассемблерный листинг и вставить в код компилируемый без оптимизации (как асм-функцию). И проверить работу кода теперь. И по асму шагать не надо, надо выучить ассемблер и "глазами" аналитически сравнить си-исходник с асм-результатом. И только если в этом случае будут найдены несоответствия между ними - только в этом случае можно однозначно говорить о вине компилятора. Что-то я не пойму.... Вот, вы же сами утверждаете, что оптимизатор может сломать работу программы написанной без ошибок. Я о том же. Если Вы считаете, что в недостаточном объёме выделенной под стек памяти виноват оптимизатор, а не "пейсатель" кода, то больше разговаривать не о чем..... :smile3046: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба И по асму шагать не надо, надо выучить ассемблер и "глазами" аналитически сравнить си-исходник с асм-результатом. И только если в этом случае будут найдены несоответствия между ними - только в этом случае можно однозначно говорить о вине компилятора. Советую взять современный GCC и дать ему ключики -Os -flto. При любом более-менее нетривиальном коде "аналитическое сравнение" легко способно перейти в бессонные ночи :biggrin: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба компилятор генерит правильный s-файл. Иначе генерит таблицу, в которой смещения не помещаются. Где тут моя ошибка? Где ошибка компилятора я разобрался и на всякий случай сменил компилятор (была сборка arm-kgp-eabi-procyon). Из Вашего описания я понял, что асм-файл писали Вы сами.... Для таких малопопулярных ядер как ESP8266, вполне допускаю что компилятор гораздо более сырой, чем для main stream Cortex-M например. Советую взять современный GCC и дать ему ключики -Os -flto. При любом более-менее нетривиальном коде "аналитическое сравнение" легко способно перейти в бессонные ночи :biggrin: У juvf функция очень тривиальная и маленькая. В худшем случае будет бессонный час. :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Для таких малопопулярных ядер как ESP8266, вполне допускаю что компилятор гораздо более сырой, чем для main stream Cortex-M например. Пожалуйста, похожая история с Cortex-M: тыц. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба У меня црц считается с ошибкой всегда, когда вкл оптимизация, не изредка, а всегда. И всегда считается правильно с отключенной оптимизацией. Нету хаотичных и внезапных сбоев. Это не устранение причины. Это как вместо лечения причины болезни, бороться с её симптомами. Если Вы подозреваете, что виноват компилятор, то устранение бага в таком случае - замена компилятора. Ведь если он косячит в данной функции, то где гарантия что не косячит в других местах? Просто эти косяки сейчас не проявляются (например - по этим веткам ветвления не проходит управление, но при каком-то стечении обстоятельств в будущем оно пройдёт и баг получит уже пользователь). Но вину компилятора сперва нужно однозначно доказать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба При переполнении стека симптомы могут быть какие угодно: может fault вылететь, а могут просто данные испортиться.я же писал, данные не портятся, в фолаут не вылетаю, а црц считает с ошибкой. Если Вы считаете, что в недостаточном объёме выделенной под стек памяти виноват оптимизатор, а не "пейсатель" кода, то больше разговаривать не о чем..... :smile3046:Я достаточно выделил памяти на стек. Без оптимизации глубины стека хватает с запасом. Если оптимизатор удвоил запросы ОЗУ на стек, то мне такой оптимизатор не нужен. :laughing: Во вторых, бывало вылазил за стек.... на разных проекта.... либо фолаут, либо данные портились. Это быстро обнаруживается. Тут идет подсчет црц, но неправильный. Ни чего не портиться и не падает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Пожалуйста, похожая история с Cortex-M: тыц. Да я не спорю, что и в компиляторах есть косяки. Я даже сам несколько лет назад выкладывал сюда на форум описание одного из них. Но я чётко доказал, что это именно косяк компилятора (это был IAR вроде v6.20 или v6.40). И выложил и фрагмент си-кода и результат компиляции (ассемблер) и ключи компиляции, при которых этот результат получен. Чтобы каждый смог лично проверить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Ведь если он косячит в данной функции, то где гарантия что не косячит в других местах? Нет гарантии. Все места проверяются глубоким тестированием. А если компилятор оптимизатор не косячит - то нет ни какой гарантии, что нет косяков пейсателя/компилятора в других местах. Все места проверяются глубоким тестированием, стрестестами и т.п. , Это касается любого компилятора/оптимизатора, любого кода. Я так понимаю, версия про "volatile" была проверена и не подтвердилась? ....конечно первым делом volatile. SPI1->SR нужно начинать читать не сразу, а через пару тактов, без оптимизации задержка получалась сама собой - как вариант.Чуть не написал "Слона не увидел", но слона нет. Во первых в даташите про это ни чего не говориться, во вторых.... сначала готовлю данные, потом их отправляю в спи, не дожидаясь завершения ..... на русском сложно писать, написшу на си sleepMs(1000); for() { //подготовка данных waitSpi(); //запись данных в спи регистр. } в waitSpi() с оптимизацией не задерживаюсь ни когда, а должен не задерживаться только первый раз. После отправки данных до чтения регистра SPI1->SR проходит много времени, но меньше, чем выход 8 бит в спи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба inline void waitSpi() { while( (SPI1->SR & (uint8_t)SPI_FLAG_BSY));} - вот этот код не работает с оптимизацией в пустом хороводе. И не изредка - а всегда. 100 раз из 100. А без оптимизации работает как часы. ни каких сбоев в обмене по SPI замечено не было. Описание типов данных, какое ядро/МК, описание SPI_FLAG_BSY и декларации SPI1 где? Асм-результат с оптимизацией где? Или с декларациями что-то не так или у вас в этом коде например гонки или куча других причин. :laughing: И опять - пример никак не свидетельствует о вине компилятора. Вот приведу такой случай из своей практики: Писал я как-то под CC5502 (TI DSP). Был простейший цикл типа Вашего выше: просто в цикле опрашивался флаг, типа: while (!flag); Этот flag в состояние !=0 устанавливался в ISR завершения DMA-транзакции (цикл ждал завершения DMA). И вот у меня возникла ситуация подобная Вашей: без оптимизации или с минимальной оптимизацией всё работает, а с полной оптимизацией - виснет в бесконечном ожидании в этом цикле и через некоторое время вылетает в bus-fault в DMA-контроллере. А дальше стало ещё хуже - выяснилось, что при добавлении/убирании строчек кода из совершенно других мест си-исходника, этот код иногда начинает работать. Причём работать 100%! Но при следующем редактировании исходника опять начинает падать в bus-fault (внимание adnega - очень знакомое поведение, не правда-ли? :rolleyes: ) Видимо Вы бы уже сложили ручки и обвинили во всём компилятор. Но я продолжил рыть. И в конце-концов нашёл причину! Оказалось, что при полной оптимизации код цикла получался такой короткий и быстрый, что CPU всё время был занят подкачкой команд в буфер предвыборки, только загрузил в конвеер команду условного перехода, пока грузил следующий пакет предвыборки за ней, то команда успевала выполниться, шёл сброс конвеера и загрузки предвыборки из начала цикла. Вобщем - тело цикла было длиной всего 2-3 такта. И если получалось что тело цикла располагалось на границе сегментов предвыборки (смещение начала цикла в памяти & 3 было == определённым значениям), то процессор полностью загружал шину к памяти своими запросами. А у него приоритет доступа к шине был выше чем у DMA-контроллера. DMA-контроллер считав данные из периферии, делал 512 попыток запроса доступа к шине ОЗУ у арбитра, не получал доступа и в конце концов останавливал работу с выставлением fault-а. При добавлении/удалении строк кода в разных местах исходника, весь код сдвигался, соответственно - чтение тела цикла иногда влезало в 1 сегмент prefetch (требовало на 1 такт меньше времени) и код чудесным образом начинал работать (DMA-контроллер в этот 1 освободившийся такт успевал пролезть на шину и записать данные в ОЗУ). Вот такой пример из практики. И что же - тут виноват компилятор? Нет, виноват конечно был я - не надо было располагать DMA-буфер и код в одном сегменте ОЗУ (МК не позволял задать для DMA приоритет доступа к шине выше чем CPU) :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Из Вашего описания я понял, что асм-файл писали Вы сами.... Как телепат телепату, откройте секрет, где в моем сообщении можно хоть как-то прийти к такому выводу? В строчке make.EXE: *** [obj_sw/esp8266.o] Error 1 видим, что не собирается цель esp8266.o А ошибку видим в s-файле с роботским именем C:\Users\user\AppData\Local\Temp\ccShzzAY.s в месте похуже корзины. Т.е. вы решили, что мой проект лежит в Temp, я сам написал asm-файл и дал ему имя ccShzzAY.s, а затем как-то заставил компилятор ругаться при сборке esp8266.o причем русским языком ниже сказано про Си-исходник? КАК? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба в waitSpi() с оптимизацией не задерживаюсь ни когда, а должен не задерживаться только первый раз. После отправки данных до чтения регистра SPI1->SR проходит много времени, но меньше, чем выход 8 бит в спи. Как одна из возможных причин: Загружаете данные в буферный регистр SPI. Флаг DLY при этом не выставляется. А выставляется он только после того, как данные из буфера попадут в сдвиговый регистр. А попадут они туда после того как пройдёт некая задержка от завершения предыдущего SPI-фрейма (предыдущего поднятия CS=high), выдержки межфреймовой паузы (при CS=high), выдержки паузы после CS=fall и началом первого клока SCLK. Вот в этот момент возможно данные переместятся в сдвиговый регистр и выставится флаг DLY. Т.е. - от момента записи данных в буферный регистр SPI до момента выставления флага DLY может пройти существенное время (в зависимости от частоты SCLK). А у Вас в программе возможно вы после записи очередной порции данных в буферный регистр SPI сразу переходите к waitSpi() и считаете что данные уже передались (так как флага нет), а они по-настоящему ещё и не начинали передаваться. При запрете оптимизации же, код выполняется медленнее и DLY успевает выставиться, поэтому и работает. Вот такой тип багов и называется "гонки". Как я выше и писал. И он конечно ваш, а не оптимизатора. :laughing: PS: Это как возможный вариант причины бага. Причина может быть и другой. Так как всего кода я не вижу и как работает SPI в вашем МК - не знаю. А ошибку видим в s-файле с роботским именем C:\Users\user\AppData\Local\Temp\ccShzzAY.s в месте похуже корзины. Т.е. вы решили, что мой проект лежит в Temp, я сам написал asm-файл и дал ему имя ccShzzAY.s, а затем как-то заставил компилятор ругаться при сборке esp8266.o причем русским языком ниже сказано про Си-исходник? КАК? Я не смотрю на имена файлов тем более пути. Достаточно только расширения. И про си-исходник там сказано только что что-то в нём меняете. Как вариант: после смены там функция становится больше, перемещается в другое место в памяти и эта функция вызывается из асм между метками .L274, .L276 - и команда вызова становится длиннее и расстояние между .L274 и .L276 увеличивается. PS: Если хотите чтобы Вас понимали однозначно, излагайте свои мысли ясно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться