juvf 17 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба описание SPI_FLAG_BSY и декларации SPI1 где?Вы мои посты читаете? все описания и декларации в приведённом коде. Как одна из возможных причин:....Я же говорю, вы не читаете мои посты. Смотрите код. Наверно на си не понятно, напишу на русском. CS - нет. СПИ-мастер. 1)спим секунду. если что-то и было в спи, то давно вышло. 2)готовим данные.... 3)проверяем бизи - waitSpi() 4)записываем в SPI1->DR данные. Данные пишутся в тх регистр, и потом копируются в шифтРегистр. в этот момент должен встать флаг бизи. 6)если ещё есть данные для передачи, goto 2) с момента записи в SPI1->DR до waitSpi() проходит не 1 такт цпу. Тут один поток...проверка на кол-во переданых данных, подготовка данных не быстрая, спешить не куда, всё равно ждать waitSpi(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба CS - нет. СПИ-мастер. 1)спим секунду. если что-то и было в спи, то давно вышло. 2)готовим данные.... ... Суть в том, что вы замели проблему под ковёр, не разбираясь в причинах. В условиях цейтнота такое бывает оправдано, а вообще это некрасиво, не говоря уже о том, что эта проблема может вылезти в будущем. Плюс опыт - он ведь сын ошибок трудных. Вот, собственно, и всё. Лезть глубже в вашу систему сейчас едва ли продуктивно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба PS: Если хотите чтобы Вас понимали однозначно, излагайте свои мысли ясно. Дык, вы же заявляете: "Я не смотрю на имена файлов тем более пути". Может, вам стоит более вдумчиво читать, что тут пишут, вместо упражнений в фантазировании? (которое уже даже не смешно). Сейчас вам ясно, что виноват компилятор, а не я? Сказанное "В приведённом Вами примере баг в Вашем коде, а не в компиляторе" не желаете опровергнуть и извиниться? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Вот такой тип багов и называется "гонки". Как я выше и писал. И он конечно ваш, а не оптимизатора. :laughing:Допустим, гипотетически.... записал в спи-сд данные, что-то сделал пусть будет проверка for(), проверил бизи. между записью и бизи было времени достаточно для выставлдения флага бизи. нужно 1 мкс, f было 10 мкс. Код рабочий, глюков нет. Может такой код перваться прерыванием и 10 мкс могут только увеличиться.... до 100, до 200.... код от этого не упадет и всё будет работать. Гипотетически! for() { waitSpi(); spi->sd = data_out; somethinkDo(); } Допустим такой код работает без оптимизации..... включили оптимизацию и появилась ваша гонка.... опять же гипотетически.... Вот вы взяли асм.... и начали исследовать, что там не так... и нашли ГОНКУ!!! Как её убрать? не нужно сразу читать SR, а нужно подождать начало передачи. Что делать? Поставить паузу.... Т.е. поставите оптимизатор, чтоб было быстрее, и потом поставите паузу, чтоб не было гонки? Я просто отключу оптимизатор в нужном месте и всё. В таком случает я считаю нет ошибки в неоптимизированном исходном коде и нет ошибки компилятора. Есть одно - при включении оптимизатора код перестает работать. Я вам не пытаюсь доказать, что есть ошибка компилятора. я не знаю. я говорю, что при включении оптимизатора на весь код, на код без ошибок и без глюков - код может лечь. И это не ошибка кода. Суть в том, что вы замели проблему под ковёр, не разбираясь в причинах. В условиях цейтнота такое бывает оправданоВ чем то я с вами соглашусь.... Про цейтнот согласен, про проблему под ковром - нет. Дело в том, что проблема такая "оптимизированный waitSpi() не работает". Тут два пути: 1 - не использовать оптимизированный waitSpi(), 2 - искать причину в оптимизированном waitSpi(). Посмотрите код waitSpi - там по сути оптимизация не нужна. Там нужно указать volatile, что делается в SPL. Весь код функции - одна строчка. Я пошел по пути наименьшего сопротивления. Тоже самое можно сказать про црц и про другие случаи (не буду всё сюда валить). У меня ещё не было случаев, чтобы оптимизатор оголял ошибки в коде. Если есть ошибка в коде - она находится без всяких оптимизаторов. Горе программист, которому для нахождения ошибки нужен оптимизатор. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Дело в том, что проблема такая "оптимизированный waitSpi() не работает". Тут два пути: 1 - не использовать оптимизированный waitSpi(), 2 - искать причину в оптимизированном waitSpi(). Это совсем поверхностный взгляд на проблему. "Когда мокрые пальцы сую в розетку - бьёт током, а когда сухие - не бьёт. Буду совать в розетку сухие пальцы." :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Т.е. поставите оптимизатор, чтоб было быстрее, и потом поставите паузу, Именно. Без for(delay = 0; delay < 20; delay++) __NOP(); не работает складно в железе, ибо таймер питается частотой с предделителя и запись в регистр MDR_TIMER3->CH1_CNTRL1 не приводит к должному результату, если после записи MDR_TIMER3->CH1_CNTRL не установить нужное число NOPов. MDR_TIMER3->CH1_CNTRL1 = CH_CNTRL1_FORCE_0; MDR_TIMER3->CH1_CNTRL = (0 << MDR_TIMER_CH_CNTRL_OCCM); MDR_TIMER3->CCR1 = last_cnt + temp; MDR_TIMER3->CH1_CNTRL = (3 << MDR_TIMER_CH_CNTRL_OCCM); for(delay = 0; delay < 20; delay++) __NOP(); MDR_TIMER3->CH1_CNTRL1 = CH_CNTRL1_WAIT_RISE; //for(delay = 0; delay < 20; delay++) __NOP(); MDR_TIMER3->STATUS = ~(1 << MDR_TIMER_STATUS_CCR_REF1_EVENT); //for(delay = 0; delay < 20; delay++) __NOP(); MDR_TIMER3->IE |= (1 << MDR_TIMER_IE_CCR_REF1_EVENT_IE); pulse[0].state = PULSE_STATE_WAIT_RISE; Телепаты в курсе, что это миландровский К1986ВЕ92 попил мою кровушку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Телепаты в курсе, что это миландровский К1986ВЕ92 попил мою кровушку. А не лучше ли вот так: MDR_TIMER3->CH1_CNTRL = NEW_VALUE; while (MDR_TIMER3->CH1_CNTRL != NEW_VALUE); ??? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба А не лучше ли вот так: MDR_TIMER3->CH1_CNTRL = NEW_VALUE; while (MDR_TIMER3->CH1_CNTRL != NEW_VALUE); ??? Не пройдет. Я так понял, что там это не просто регистр, а какой-то командный центр. Запишется-прочитается на HCLK, но реальное железо отработает, только когда на него клок придет с предделителя. Вроде, с RTC такое бывает - там нужно ждать синхронизации с блоком 32кГц, но там и битик есть, что синхронизация состоялась. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Я же говорю, вы не читаете мои посты. Смотрите код. Наверно на си не понятно, напишу на русском. Да пишите хоть на китайском, мне ваш код безразличен, это ведь не у меня при включении/выключении оптимизации он то работает, то нет. Мои исходники работают вне зависимости от того включена оптимизация или нет, у меня таких проблем нет. 1)спим секунду. если что-то и было в спи, то давно вышло. 2)готовим данные.... 3)проверяем бизи - waitSpi() 4)записываем в SPI1->DR данные. Данные пишутся в тх регистр, и потом копируются в шифтРегистр. в этот момент должен встать флаг бизи. 6)если ещё есть данные для передачи, goto 2) Должен да не обязан. Где между п.4 и п.6 проверка, что бизи установился? "Вы мои посты читаете"? Я о таком кривом подходе как здесь ещё несколько постов назад написал. Вот как раз такой код и будет работать в зависимости от уровня оптимизации, количества передаваемых данных, фаз луны.... А, ну да, зачем читать и думать, ведь всё уже выяснено - компилятор виноват! :laughing: Сказанное "В приведённом Вами примере баг в Вашем коде, а не в компиляторе" не желаете опровергнуть и извиниться? Нет, не желаю так как причина баг не найдена. Вы не доказали никак вину компилятора. Да собственно там у вас и не баг в выполнении программы, а ошибка компиляции. Допустим такой код работает без оптимизации..... включили оптимизацию и появилась ваша гонка.... Гонки у Вас всегда есть, а не только при вкл. оптимизации. Почитайте в инете что это такое. Надо писать код, свободный от такого. Как её убрать? не нужно сразу читать SR, а нужно подождать начало передачи. Что делать? Поставить паузу.... Т.е. поставите оптимизатор, чтоб было быстрее, и потом поставите паузу, чтоб не было гонки? Я просто отключу оптимизатор в нужном месте и всё. Правильно тут уже написали про Ваш стиль: Вместо подумать и понять как сделать правильно, замести проблему под ковёр. :biggrin: В том цикле достаточно всего лишь после записи данных в SPI, дождаться начала их передачи (выставления бизи). Но конечно это кривой метод, так как потребует запрета прерываний (чтобы вся передача не проскочила за время внезапно возникшего прерывания). А чтобы написать правильно и корректно нужно вообще весь алгоритм этот изменить, использовать другие флаги, прерывания и пр. Горе программист, которому для нахождения ошибки нужен оптимизатор. Ещё горше тот, которому оптимизатор её нашёл, указал, а он прячет голову в песок. Телепаты в курсе, что это миландровский К1986ВЕ92 попил мою кровушку. И DSB/DMB не спасают? Запишется-прочитается на HCLK, но реальное железо отработает, только когда на него клок придет с предделителя. Тогда должны быть какие-то статусные биты, говорящие о завершении операции периферией. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Правильно тут уже написали про Ваш стиль: Вместо подумать и понять как сделать правильно, замести проблему под ковёр.Нет, не правильно. Есть задача - написать текст. Есть 2 карандаша. Один пишет, другой не пишет. Я не буду тратить время на выяснение, почему не пишет один карандаш, если я могу обойтись без него. Я другим карандашом текст напишу. Вы выяснили и устранили, почему при вкл холодильника виснет CCS? Вы замелм пролему под ковёр заменили кабель усб и продолжили работать. Ещё горше тот, которому оптимизатор её нашёлУ меня оптимизатор ошибок не нашел. мне ваш код безразличенЗачем вы просили код в студию? Хотели найти в нем ошибку. Нашли? Или чтоб написать "мне ваш код безразличен"? при включении/выключении оптимизации он то работает, то нетГде я писал, что "то работает то нет"? У меня такого кода нет. А, ну да, зачем читать и думать, ведь всё уже выяснено - компилятор виноват!Что компилятор виноват - это ваши слова, не нужно их мне приписывать. Я же говорю вы не читаете мои посты, не вижу смысла дальнейшей дискуссии с вами по этому поводу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Нет, не желаю так как причина баг не найдена. Вы не доказали никак вину компилятора. Да собственно там у вас и не баг в выполнении программы, а ошибка компиляции. Если компилятор не может собрать корректный код, то по вашему это не баг компилятора? Вы понимаете, что компилятор, компилируя esp8266.c, создал временный s-файл, в котором смещение им же считается неверно? А при эквивалентной перестановке строк в Си-исходнике он может собирать или не собирать исходник. В этом я виноват? И DSB/DMB не спасают? Очевидно же нет, т.к. у таймера как у периферийного блока своя собственная частота. Пример из errata на этот проц привел в скрине. "Обеспечивать необходимую задержку" тупо NOP`ами. Насчет MDR_TIMER3->CH1_CNTRL там же есть бага 0013: "В регистре есть бит, но он всегда читается как 1, при этом запись в него корректно задает режим". Тогда должны быть какие-то статусные биты, говорящие о завершении операции периферией. А если их нет? В данном случае их нет, и производитель в аналогичной ситуации рекомендует "обеспечивать необходимую задержку". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Вместо стольких слов достаточно посмотреть листинг одной строчки, чтобы увидеть виноват ли оптимизатор. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 21 июня, 2018 Опубликовано 21 июня, 2018 · Жалоба Вместо стольких слов достаточно посмотреть листинг одной строчки, чтобы увидеть виноват ли оптимизатор. Я об этом неоднократно тут говорил. Но товарищ, винивший оптимизатор, так и не привёл этот самый листинг. Может он не знает что это такое? B) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 22 июня, 2018 Опубликовано 22 июня, 2018 · Жалоба Посмотрите сколько лишних операций в for у ТС! какие-то приведения типов, операторы, << и |, дополнительный j, операции j++!!! УЖАС!!! И что? Современные оптимизаторы творят чудеса. И им по-барабану Ваши жалкие потуги заменить операции индексирования на указатели и подобное - они это и сами хорошо делают, даже ещё и лучше. Так что если бы код автора не был такой кривой, результат работы оптимизирующего компилятора мог быть лучше memcpy(). Попробуйте когда-нить попробую обязательно. Добрый день фантазёры, эльфы, а также программисты. Совсем недавно (2017-2018 год) занимался оптимизацией кода в STM8. Ручные потуги оптимизации давали очень хороший результат. Оптимизатор конечно оптимизировал код, но некоторый несложный рефакторинг давал значительно лучший результат. Может стм8 сырой? может арм действительно рулит? Проверил на арме.... собрал код ТС, улучшенный код ТС, а также просто memcpy(). В трёх случаях заполнял массив uin16_t [16] из массива uin8_t[32]. Измерял осциллографом. улучшенный код ТС выглядит так: #define SIZ 32 uint8_t dataOut[SIZ+2]; uint16_t buffer[SIZ/2]; uint8_t *p1 = (uint8_t*)buffer; uint8_t *p2 = (uint8_t*)&dataOut[0]; ... GPIO_SetBits(GPIOA, GPIO_Pin_5); //ТР2 = 1 //оптимизированный варинат ТС for(int i = 0; i < SIZ; i++) p1[i] = p2[i]; GPIO_ResetBits(GPIOA, GPIO_Pin_5); Результат - (код TC с "<<", "|", "++", "j") / (улучшенный код ТС) / (говноmemcpy() ) Не оптимизированный код дал результат 8/5/1.3 мкс с оптимизацией по скорости -Ohs результат 3/0.5/0.5 мкс кагбэ в примере всё выровнено к 4. Но серийные данные не всегда выровнены, поэтому усложнил задачу МК и приблизил к реальности, uint8_t *p2 = (uint8_t*)&dataOut[1]; получил без оптимизациии 8/5/2мкс, с оптимизацией -Ohs 3/2/1.7 мск Результат на лицо. Априори. Вот вам и наряд в не очереди современные оптимизаторы!!! ps проверял на стм32ф103, компилятор иар. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 22 июня, 2018 Опубликовано 22 июня, 2018 · Жалоба Добрый день фантазёры, эльфы, а также программисты. Совсем недавно (2017-2018 год) занимался оптимизацией кода в STM8. Ручные потуги оптимизации давали очень хороший результат. Оптимизатор конечно оптимизировал код, но некоторый несложный рефакторинг давал значительно лучший результат. Может стм8 сырой? Кстати, стм8 - особый случай. Там нет выдающихся компиляторов. Яр на уровне исходника умеет выкидывать лишние переменные и т.д., но машинный код делает плохенький. Видимо, избрана плохая стратегия генерации кода, и/или реализация подкачала. Они там придумали виртуальные регистры, предположительно, чтобы компилятору было удобнее. Результат так себе. Недавно попробовал космик, там код генерится практически в лоб, строчка исходника - несколько инструкций. Каждая локальная переменная выделяется на стеке. Результат в целом лучше, чем у яра. Ну и зная о прямом соответствии исходника и машинного кода, простор для микрооптимизаций на уровне исходника огромный. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться