-
- К чему это? Я именно так и считываю 1 байт данных. Другое дело - я
не могу очистить FIFO от мусора перед тем, как считать нужные
данные. Даже если сделать 100 раз вызов (void)SPI2->DR,
получим 0 в RXNE, но лишние нули в FIFO! - Eddy_Em(11.05.2023 16:59)
- Вызов SPI2->DR считывает 16 бит, чтобы считать только 8 бит
надо указать это явно компилятору. - Costic(11.05.2023 19:22)
- А мне не нужно считывать 8 бит: мне сначала нужно очистить принимающий FIFO! Eddy_Em(35 знак., 11.05.2023 19:30)
- Кстати, да. Почему бы не заменить (void)SPI2->DR на
(void)*(uint8_t volatile*)&SPI2->DR ? А вдруг? - SciFi(11.05.2023 20:03)
- я в стм-ах не силён. но если в описании регистра указана его
разрядность - то чтение/запись АППАРАТНО в(из) него производится
именно с "этой" разрядностью ВСЕГДА. В моём случае (какоето ядро
арм) все регистры 32бит (периферии) (и отсутствует байтный доступ
аппаратно). А вот приведение типа в сторону уменьшения может
привести к злостным побочным эффектам. уж лучше читать/писать
полностью регистр, а модифицировать в отдельных переменных. (это
общее правило, из которого может Zoro(17 знак., 11.05.2023 23:37)
- Архитектура ARM позволяет к одной и той же области памяти (к
области ввода вывода периферии в частности) обращаться с разной
разрядностью. Для некоторых регистров особо оговариваются условия
разрядность доступа, а к некоторым (к большинству?) можно
обращаться как угодно. Всё зависит от реализации периферийного
модуля - как он реагирует на сигналы шины, к которой подключён. Так
что доступ возможен с любой разрядностью, а вот реакция периферии
на этот доступ зависит от Nikolay_Po(21 знак., 11.05.2023 23:49)
- Тут можно пример привести не из АРМ... POV(512 знак., 11.05.2023 23:55)
- не без этого. у 51 периферия регистры 8 бит, а по смыслу пару
регистров образует "единый регистр " и тут (бывает) важен порядок
чтения/записи. Но зачем искать приключения там где можно "тупо"
считать целиком регистр модифицировать значение и записать обратно
? накой ляд приводить тип данных/регистра разной размерности? - Zoro(12.05.2023 00:37)
- Способ, порядок, момент записи могут иметь значение для модуля периферии. А приведение типа к другому размеру как раз меняет способ доступа. Был (volatile uint16_t) - доступ выполнялся ассемблерной командой доступа к слову, с выравниванием 16 бит. Переопределили тип в (volatile uint8_t) - компилятор, для того же адреса, использует другую команду ассемблера - для доступа к байту, с байтовым выравниванием. - Nikolay_Po(12.05.2023 00:46)
- не без этого. у 51 периферия регистры 8 бит, а по смыслу пару
регистров образует "единый регистр " и тут (бывает) важен порядок
чтения/записи. Но зачем искать приключения там где можно "тупо"
считать целиком регистр модифицировать значение и записать обратно
? накой ляд приводить тип данных/регистра разной размерности? - Zoro(12.05.2023 00:37)
- Тут можно пример привести не из АРМ... POV(512 знак., 11.05.2023 23:55)
- Архитектура ARM позволяет к одной и той же области памяти (к
области ввода вывода периферии в частности) обращаться с разной
разрядностью. Для некоторых регистров особо оговариваются условия
разрядность доступа, а к некоторым (к большинству?) можно
обращаться как угодно. Всё зависит от реализации периферийного
модуля - как он реагирует на сигналы шины, к которой подключён. Так
что доступ возможен с любой разрядностью, а вот реакция периферии
на этот доступ зависит от Nikolay_Po(21 знак., 11.05.2023 23:49)
- Так я тоже пробовал - но при этом же считывается лишь один байт, а
не два. Eddy_Em(145 знак., 11.05.2023 20:39)
- Сие есть неправда. При приведении типа volatile отваливается,
поэтому его нужно прилеплять заново. - SciFi(11.05.2023 20:43)
- Ну, на этот счет нужно будет проверить. - Eddy_Em(11.05.2023 20:49)
- Тут есть хотя бы интуитивный аргумент: если volatile не
отваливается при явном приведении типа, как же от него избавиться?
Неявным приведением? И кто сказал, что если не отваливается при
явном, то отваливается при неявном? Короче, фигня какая-то
получится. Или вот про const, но суть та же: SciFi(1 знак., 11.05.2023 21:04, ссылка)
- Я глянул листинг - не отваливается у меня volatile при приведении
типов. Да и чего бы ей отвалиться? Eddy_Em(654 знак., 11.05.2023 21:07)
- Каким образом листинг может доказать, что volatile не отваливается?
Правильно, никаким. Потому что в будущей версии шибко умного
компилятора может появиться оптимизация, которая всё поломает.
Скажете, невозможно? Это происходит почти каждый день! - SciFi(11.05.2023 21:16)
- Да элементарно же: у меня в листинге есть чтение из SPI2->DR -
вот и доказательство, что волатильность не отвалилась! Иначе этого
чтения не было бы (т.к. компилятор выкинул бы бессмысленную
конструкцию). - Eddy_Em(11.05.2023 21:26)
- Не откажу себе в удовольствии ткнуть мордой. На -O1 VladislavS.(1 знак., 12.05.2023 07:14, картинка)
- Только очистить буфер перед приемом DMA это почему-то не помогает. Вот перед блокирующим приемом - да, очищает... Eddy_Em(888 знак., 12.05.2023 14:49)
- Ну ни хрена себе... - Eddy_Em(12.05.2023 08:12)
- С нулевой оптимизацией не выкинет. А с ненулевой никто не обязывает
компилятор делать волшебные штуки, которые вы придумали. Он живёт
своей жизнью. - SciFi(11.05.2023 21:29 - 21:31)
- Еще раз: у меня -O2, ничего не выкинул. Если сделать аналогичное с
не-волатильной переменной - выкинет. - Eddy_Em(11.05.2023 21:31)
- А если -O3 --flto? Я только так и собираю проекты для МК с GCC. - Nikolay_Po(11.05.2023 21:54)
- -O3 - слишком круто. А -flto я только в release режиме включаю. В
любом случае, волатильные переменные никуда не "убегут". Eddy_Em(300 знак., 11.05.2023 22:42)
- Перед запуском DMA барьер воткнуть не забыли? __DSB() - LightElf(12.05.2023 01:37)
- Никогда не втыкал и работало... - Eddy_Em(12.05.2023 08:12)
- DMA и SPI, емнип, на разных шинах висят. Есть шанс, что у вас DMA стартует раньше, чем завершается программное вычитывание мусора из SPI. - LightElf(12.05.2023 11:48)
- Не оправдание! Nikolay_Po(252 знак., 12.05.2023 09:36)
- Никогда не втыкал и работало... - Eddy_Em(12.05.2023 08:12)
- Жесть просто какая-то! Eddy_Em(689 знак., 11.05.2023 23:08)
- Он чем-то от СПи в Ф1хх отличается? СПИ на Ф103 у меня только в
путь. С ДМА и без оного. Даже намёка на проблемы не было.. ах да, я
ж SPL использую.. а это неспортивно. - POV(11.05.2023 23:12)
- Ага: там гребаного FIFO нет на RX/Tx. А здесь на Tx трехбайтный
FIFO, а на RX - четырехбайтный. И пляши с этим, как хочешь. Eddy_Em(463 знак., 11.05.2023 23:55, youtube)
- Ну, кстати да, у Ф1 нет в хедере spi никакого упоминания fifo. - POV(12.05.2023 00:03)
- Ага: там гребаного FIFO нет на RX/Tx. А здесь на Tx трехбайтный
FIFO, а на RX - четырехбайтный. И пляши с этим, как хочешь. Eddy_Em(463 знак., 11.05.2023 23:55, youtube)
- Он чем-то от СПи в Ф1хх отличается? СПИ на Ф103 у меня только в
путь. С ДМА и без оного. Даже намёка на проблемы не было.. ах да, я
ж SPL использую.. а это неспортивно. - POV(11.05.2023 23:12)
- Перед запуском DMA барьер воткнуть не забыли? __DSB() - LightElf(12.05.2023 01:37)
- Офигеть. Плясать с бубном вокруг GCC. И кто-то что-то рассказывал
про 21 век :-( - SciFi(11.05.2023 21:57)
- В смысле плясать? Включил максимальную оптимизацию и работай!
Никаких плясок. Это ТС не пользуется всеми прелестями компилятора
и, поэтому, может не замечать упущенных volatile. - Nikolay_Po(11.05.2023 22:36)
- Я-то не пользуюсь? Eddy_Em(487 знак., 12.05.2023 00:02)
- Ну, я о том же. Вы просто не застали - я из раза в раз повторяю:
"Хочешь писать качественный код - всегда включай полную оптимизацию
и LTO! Так больше шансов сразу увидеть баг в коде до того, как он
вылезет потом, по мере усложнения проекта". Нет у компилятора
чрезмерной оптимизации, если не включать флаги быстрой, но неточной
математики и ещё там по мелочи, по умолчанию выключенные. Зато есть
недостаточно тщательно проработанный код. Nikolay_Po(530 знак., 12.05.2023 00:27, ссылка)
- Бывает и проблема при использовании сторонних header-only
библиотек. Кажись, в ранней версии nuklear я на такой косяк при -О3
натыкался. Eddy_Em(187 знак., 12.05.2023 00:34)
- Нет, там по условиям портирования, в документации, функции этого
файла должны по указателю на функцию из прерывания таймера
вызываться. Просто человек, готовивший порт много лет назад, не
использовал оптимизацию в полной мере. И даже у меня в этот код
какое-то время, на начальном этапе, работал, а потом перестал. Стал
копать почему - и нашёл. - Nikolay_Po(12.05.2023 00:38)
- Думаю, тому разработчику STM8 или пики понравились бы: под них есть
только SDCC, а у этой заразы с оптимизацией совсем плохо... - Eddy_Em(12.05.2023 00:41)
- Ну, я для AVR использую AVR-GCC-12. С оптимизациями там порядок, я
так не соптимизирую. И косяки кода становятся явными. Так что
корректная работа кода в полной оптимизации, с LTO - один из
признаков качества. Nikolay_Po(1 знак., 12.05.2023 00:51, ссылка)
- Вот, только что решил таки проверить: а что будет, если собрать не
с -O2, а с -O3? Размер прошивки с 35кБ вырос аж до 44кБ!!! Вот так
мне gcc наоптимизировал (видимо, все, что только можно,
позаинлайнил). Eddy_Em(545 знак., 14.05.2023 12:17)
- По моему, debug, при использовании LTO, не имеет смысла. Разве что повезет, в массив какой заглянуть или конфигурацию регистров периферии глянуть. Остальное - практически без шансов. - Nikolay_Po(14.05.2023 13:18)
- Не только инлайнит, но и циклы разматывает. - SciFi(14.05.2023 12:19)
- Вот, только что решил таки проверить: а что будет, если собрать не
с -O2, а с -O3? Размер прошивки с 35кБ вырос аж до 44кБ!!! Вот так
мне gcc наоптимизировал (видимо, все, что только можно,
позаинлайнил). Eddy_Em(545 знак., 14.05.2023 12:17)
- Ну, я для AVR использую AVR-GCC-12. С оптимизациями там порядок, я
так не соптимизирую. И косяки кода становятся явными. Так что
корректная работа кода в полной оптимизации, с LTO - один из
признаков качества. Nikolay_Po(1 знак., 12.05.2023 00:51, ссылка)
- Думаю, тому разработчику STM8 или пики понравились бы: под них есть
только SDCC, а у этой заразы с оптимизацией совсем плохо... - Eddy_Em(12.05.2023 00:41)
- Нет, там по условиям портирования, в документации, функции этого
файла должны по указателю на функцию из прерывания таймера
вызываться. Просто человек, готовивший порт много лет назад, не
использовал оптимизацию в полной мере. И даже у меня в этот код
какое-то время, на начальном этапе, работал, а потом перестал. Стал
копать почему - и нашёл. - Nikolay_Po(12.05.2023 00:38)
- Бывает и проблема при использовании сторонних header-only
библиотек. Кажись, в ранней версии nuklear я на такой косяк при -О3
натыкался. Eddy_Em(187 знак., 12.05.2023 00:34)
- Ну, я о том же. Вы просто не застали - я из раза в раз повторяю:
"Хочешь писать качественный код - всегда включай полную оптимизацию
и LTO! Так больше шансов сразу увидеть баг в коде до того, как он
вылезет потом, по мере усложнения проекта". Нет у компилятора
чрезмерной оптимизации, если не включать флаги быстрой, но неточной
математики и ещё там по мелочи, по умолчанию выключенные. Зато есть
недостаточно тщательно проработанный код. Nikolay_Po(530 знак., 12.05.2023 00:27, ссылка)
- Вам виднее. - SciFi(11.05.2023 22:38)
- Я-то не пользуюсь? Eddy_Em(487 знак., 12.05.2023 00:02)
- В смысле плясать? Включил максимальную оптимизацию и работай!
Никаких плясок. Это ТС не пользуется всеми прелестями компилятора
и, поэтому, может не замечать упущенных volatile. - Nikolay_Po(11.05.2023 22:36)
- -O3 - слишком круто. А -flto я только в release режиме включаю. В
любом случае, волатильные переменные никуда не "убегут". Eddy_Em(300 знак., 11.05.2023 22:42)
- Вам виднее. Но список предрассудков пополняется. Оставайтесь на линии, будем пытаться лечить. Но это быстро не получится :-) - SciFi(11.05.2023 21:32)
- А если -O3 --flto? Я только так и собираю проекты для МК с GCC. - Nikolay_Po(11.05.2023 21:54)
- Еще раз: у меня -O2, ничего не выкинул. Если сделать аналогичное с
не-волатильной переменной - выкинет. - Eddy_Em(11.05.2023 21:31)
- Не откажу себе в удовольствии ткнуть мордой. На -O1 VladislavS.(1 знак., 12.05.2023 07:14, картинка)
- Да элементарно же: у меня в листинге есть чтение из SPI2->DR -
вот и доказательство, что волатильность не отвалилась! Иначе этого
чтения не было бы (т.к. компилятор выкинул бы бессмысленную
конструкцию). - Eddy_Em(11.05.2023 21:26)
- Каким образом листинг может доказать, что volatile не отваливается?
Правильно, никаким. Потому что в будущей версии шибко умного
компилятора может появиться оптимизация, которая всё поломает.
Скажете, невозможно? Это происходит почти каждый день! - SciFi(11.05.2023 21:16)
- Я глянул листинг - не отваливается у меня volatile при приведении
типов. Да и чего бы ей отвалиться? Eddy_Em(654 знак., 11.05.2023 21:07)
- Тут есть хотя бы интуитивный аргумент: если volatile не
отваливается при явном приведении типа, как же от него избавиться?
Неявным приведением? И кто сказал, что если не отваливается при
явном, то отваливается при неявном? Короче, фигня какая-то
получится. Или вот про const, но суть та же: SciFi(1 знак., 11.05.2023 21:04, ссылка)
- Ну, на этот счет нужно будет проверить. - Eddy_Em(11.05.2023 20:49)
- Сие есть неправда. При приведении типа volatile отваливается,
поэтому его нужно прилеплять заново. - SciFi(11.05.2023 20:43)
- я в стм-ах не силён. но если в описании регистра указана его
разрядность - то чтение/запись АППАРАТНО в(из) него производится
именно с "этой" разрядностью ВСЕГДА. В моём случае (какоето ядро
арм) все регистры 32бит (периферии) (и отсутствует байтный доступ
аппаратно). А вот приведение типа в сторону уменьшения может
привести к злостным побочным эффектам. уж лучше читать/писать
полностью регистр, а модифицировать в отдельных переменных. (это
общее правило, из которого может Zoro(17 знак., 11.05.2023 23:37)
- Кстати, да. Почему бы не заменить (void)SPI2->DR на
(void)*(uint8_t volatile*)&SPI2->DR ? А вдруг? - SciFi(11.05.2023 20:03)
- А мне не нужно считывать 8 бит: мне сначала нужно очистить принимающий FIFO! Eddy_Em(35 знак., 11.05.2023 19:30)
- Вызов SPI2->DR считывает 16 бит, чтобы считать только 8 бит
надо указать это явно компилятору. - Costic(11.05.2023 19:22)
- Насчет volatile ты прав, спасибо. Я у себя подправлю. Всегда так - как только начинаешь преобразовывать тип указателя, обязательно что-то не так сделаешь :-) - il-2(11.05.2023 15:26)
- Этот SPL наркоманы кодили штоле? Нафиг эту фигню в качестве примера
приводить? - SciFi(11.05.2023 15:08)
- Ну, оно работает )) Несколько проектов на ф103 - ни одного косяка.
В паре мест лишь к регистрам обращался когда такты жалко было... POV(93 знак., 11.05.2023 15:35, картинка)
- Уже теплее. Кто-нибудь, сообщите китайцам, что явное приведение к uint16_t не нужно, оно само приведётся. - SciFi(11.05.2023 15:37)
- Во-первых, этот фрагмент кода работает. Во-вторых, лично мне
нравится SPL, а вы можете приводить другие примеры, если у вас
есть. - Costic(11.05.2023 15:31)
- SPL - оно ж deprecated! Зачем им пользоваться? Eddy_Em(1369 знак., 11.05.2023 17:06)
- deprecated - потому как нет поддержки последних камней. и
только-то. - POV(11.05.2023 17:06)
- Оно все равно написано из разряда вон плохо! Eddy_Em(418 знак., 11.05.2023 17:08)
- SPL - лучшая библиотека от ST (imho). А метапрограммирование на
шаблонах тут Владислав_С проповедует/просвещает. Но дубы крепки.
:-) - Costic(11.05.2023 19:30)
- А я - балерина ☺ Eddy_Em(648 знак., 11.05.2023 19:34, ссылка)
- О! Чувак, ты крут! С регистрами работать, ты, пожалуй, умеешь! Заценил! Поднять USB на предельной скорости bare metal - это довольно серьёзно! - Nikolay_Po(11.05.2023 22:41)
- VCP+MSC на SPL (на базе примеров от ST) писал года 3 назад. Накопителем подключил AT45 со своей прослойкой накопителя, и Fat-FS. Чтение/запись - 700/500 кбайт/с. - POV(11.05.2023 19:38)
- А я - балерина ☺ Eddy_Em(648 знак., 11.05.2023 19:34, ссылка)
- Нет там оберток. при flto инлайнит gcc нещадно. Внутри обертки
обращение к одному регистру - значит только это обращение в код и
будет помещено. - POV(11.05.2023 17:10)
- Не стоит забывать еще и об отсутствии культуры написания кода: я
неоднократно встречал записи вида Eddy_Em(1115 знак., 11.05.2023 17:18)
- Оно иногда бывает важно, чтобы именно так. Сначала один бит взводим, потом второй сбрасываем и только потом - взводим третий бит. Конкретно у STM такое не припоминаю, но вообще в однокристаллках - запросто встречается, типо первый бит включает периферийный модуль, второй - сбрасывает установленный флаг прерывания, третий - разрешает прерывания. При попытке сделать одной командой - можно неожиданно улететь в обработчик прерывания с неправильным контекстом. - LightElf(11.05.2023 20:10)
- Насчёт траты лишних тактов: а как ты сделаешь модификацию избранных
бит регистра, не меняя неизвестные остальные биты? Такое часто
встречается. Я оптимизирую так там, где можно записать регистр
целиком за раз, когда нет неизвестных бит, которые надо сохранить -
пишу сразу. Но в универсальном коде, каким является сабж, ты не
имеешь права менять других бит, так как не ты их устанавливал и
предысторией не владеешь. Поэтому и сброс/установка через
маскирование. - Nikolay_Po(11.05.2023 18:38)
- В большинстве случаев инициализации периферии вполне можно и даже желательно писать весь регистр, чтобы получить гарантированное состояние. Но в примерах и библиотеках очень часто по одной функции ставят и вместо одной прямой записи несколько модификаций. А предысторией не владеешь обычно во всяких регистрах включения тактирования, питания...., их не так много. - Andreas(11.05.2023 19:19)
- Для этого я просто считаю содержимое, применю битовую маску и верну взад. Eddy_Em(146 знак., 11.05.2023 18:52)
- Не стоит забывать еще и об отсутствии культуры написания кода: я
неоднократно встречал записи вида Eddy_Em(1115 знак., 11.05.2023 17:18)
- SPL - лучшая библиотека от ST (imho). А метапрограммирование на
шаблонах тут Владислав_С проповедует/просвещает. Но дубы крепки.
:-) - Costic(11.05.2023 19:30)
- Оно все равно написано из разряда вон плохо! Eddy_Em(418 знак., 11.05.2023 17:08)
- deprecated - потому как нет поддержки последних камней. и
только-то. - POV(11.05.2023 17:06)
- SPL - оно ж deprecated! Зачем им пользоваться? Eddy_Em(1369 знак., 11.05.2023 17:06)
- Ну, оно работает )) Несколько проектов на ф103 - ни одного косяка.
В паре мест лишь к регистрам обращался когда такты жалко было... POV(93 знак., 11.05.2023 15:35, картинка)
- К чему это? Я именно так и считываю 1 байт данных. Другое дело - я
не могу очистить FIFO от мусора перед тем, как считать нужные
данные. Даже если сделать 100 раз вызов (void)SPI2->DR,
получим 0 в RXNE, но лишние нули в FIFO! - Eddy_Em(11.05.2023 16:59)