То, что изменяемые извне переменные должны объявляться с модификатором volatile -- это не я считаю. Это единственный способ избежать множества дивных эффектов в случайные моменты времени.
Далеко не единственный. Странно, что вы этого не знаете.
Я в самом начале уже сказал все, что хотел. Словами и иллюстрациями.
Вы так и не ответили. Приведение типа volatile массива к не volatile при передаче в функцию HAL_SPI_Receive_DMA приводит к сбою в работе программы?
a5021 писал(а):
Теперь помогаю тем, кто ни прочесть, ни в картинках разглядеть никак не способен.
Пишите так как будто это нужно нам, а не вам. Научитесь пользоваться volatile чтобы понимать в каких случаях он действительно нужен. Не дело везде объявлять переменные с модификатором volatile и паниковать когда это не получается.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Это единственный способ избежать множества дивных эффектов в случайные моменты времени
Не единственный. Например, если никто не мешает Вам заблокировать работу с буфером, пока DMA в него пишет.
А надеятся, что добавление volatile к аргументу чудесным образом всё решает - это неправильно.
Например, возьмём буфер из 10 volatile элементов. Допустим, DMA читает из этого буфера их последовательно, и процесс чтения в данный момент времени - на 5-м элементе. В это время параллельно (по прерыванию, например), изменяются элементы 2 и 7. Какие могут быть варианты:
1. volatile. Из индекса 2 мы уже прочитали - тут ничего не попишешь, ну а из индекса 7 будет прочитано новое число. Есть повод задуматься, хорошо ли это, что данные пришли из разных по сути выборок. 2. не volatile. Есть очень малый шанс, что из индекса 7 будет прочитано прежнее число, а не свежезаписанное (малый потому, что вряд ли весь массив будет предварительно скопирован в рабочие регистры и тем самым "закэшируется" локально). Но если и так - то плохого в этом ничего нет.
Оба варианта имеют свои недостатки. А делать принудительно весь аргумент функции как volatile - это лишь лишить себя (и компилятор) дополнительной возможной оптимизации.
Вместо этого, если Вам действительно нужна атомарность работы со всем буфером, Вы, как программист, должны обеспечить её другим способом - каким-нибудь аналогом mutex-а. В случае микроконтроллера без ОС - это может быть какой-нибудь банальный флаг типа (volatile bool isBusy). Напишите свою HAL_SPI_Receive_DMA_Locked() функцию, в которой будет вызов уже стандартной HAL-овской, обёрнутый этим флагом, и обеспечьте другую часть своего кода на проверку этих флагов, чтобы они и не думали лезть в этот буфер, пока он залочен.
Последний раз редактировалось WiseLord Вс сен 20, 2020 01:17:58, всего редактировалось 1 раз.
Собственно, я и пытаюсь сказать, что volatile с атомарностью никак не связан. А a5021, видимо, их ассоциирует именно так.
Volatile по большому счёту лишь предотвращает помещение переменной в какой-нибудь из регистров, который затем используется на протяжении всей функции в качестве кэша этой переменной.
Но в случае массивов - я сильно сомневаюсь, что будет кэшироваться сразу несколько его элементов.
P.S. В случае упомянутой выше HAL_SPI_Receive_DMA функции каждый элемент буфера затрагивается только один раз - когда он из периферийного регистра попадает в элемент массива. Каких-то множественных обращений (которые могли бы вызвать разные странные эффекты) к нему там нет. Поэтому volatile тут и не нужен.
И ещё раз нет. Компилятор не видит как в буфер пишутся данные, поэтому считает, что в нём всегда что-то известное на этапе компиляции лежит. И может "почикать" обращения к буферу вовсе. volatile это про оптимизацию.
Натыкать volatile ума много не надо. Куда интереснее заставить компилятор просчитать оптимальный код или его отсутствие на этапе компиляции.
так никто и не ответил, каким образом может измениться поведение этой функции с/без volatile, если данные по указателю эта функция не использует? как всегда спор теоретегоф...
VladislavS писал(а):
И может "почикать" обращения к буферу вовсе
меня всегда интересовало: а вообще бывают случаи, когда в выражении a = b + b + b; необходимо учитывать, что это самое бэ может каждый из трех раз иметь другое значение? вот чисто алгоритмически - бывают?
Добавлено after 3 minutes 44 seconds:
VladislavS писал(а):
что в нём всегда что-то известное на этапе компиляции лежит
по-моему, вы ошибаетесь: не известное на этапе компиляции, а неизменное между точками исполнения (или как там эти участки генерации кода компилятором называются правильно).
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
меня всегда интересовало: а вообще бывают случаи, когда в выражении a = b + b + b; необходимо учитывать, что это самое бэ может каждый из трех раз иметь другое значение? вот чисто алгоритмически - бывают?
Не зная что такое а и b предположить можно что угодно. Про перегрузку операторов слышали?
по-моему, вы ошибаетесь: не известное на этапе компиляции, а неизменное между точками исполнения (или как там эти участки генерации кода компилятором называются правильно).
Я имел в виду именно известное на этапе компиляции. Вот в этом коде компилятор сгенерирует запись константы 2 в порт. То что buf может измениться из прерывария или с помощью DMA он не ожидает.
слышать слышал, но при чем тут перегрузка, если переменная "бэ" одна и та же, значит, как бы операторы не перегружались, а обрабатывать они будут одно и то же.
VladislavS писал(а):
То что buf может измениться из прерывария или с помощью DMA он не ожидает
а если ожидает - разве он сможет это как-то учесть?
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
так никто и не ответил, каким образом может измениться поведение этой функции с/без volatile, если данные по указателю эта функция не использует?
А зачем отвечать на странные вопросы, которые к теме в данном случае отношения не имеют? С тем же успехом вы бы могли требовать ответа на вопрос, как влияет частое употребление модификатора volatile на состав кишечных газов.
Априори полагая, что volatile - правильно, а без него - какие-то выдуманные глюки и страдания будут.
Чтобы не было глюков и страданий, нужно просто перестать всякими "халами" пользоваться!
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 43
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения