Обновить
50
3.3
Вадим Петряев@ptr128

Архитектор ИС

Отправить сообщение

Вот только как Вы собрались передавать владение контроллеру DMA и обучить его отдавать владение коду на CPU?

вы хотите без копирования

Не я хочу без копирования, а жесткие ограничения на доступную память и производительность при разработке для встроенных систем требуют избегать копирования.

можно выбрать МК с большим количеством ножек

При чем тут количество "ножек", если речь идет о портах? Мне даже интересно стало, что же Вы предложите вместо ESP32-C2/C3/H2/C6, у которых всего один порт? Вообще отказаться от них, если нужно управлять более, чем одним пином GPIO? А если нужно управлять тремя пинами GPIO, то вообще отказаться от продукции Espressif, так как я не знаю у них ни одного МК, имеющего более двух портов?

Очень странное заявление от разработчика встраиваемых систем. Менять - это не обязательно один раз изменить состояние пина, но, в том числе, и сформировать последовательность сигналов с заданными временными характеристиками и, возможно, достаточно существенной длительностью.

Очень странное утверждение. Например, если у Вас на двух пинах двумя потоками выполняется управление двумя матрицами обычных WS2812, то ±150ns, которые требует их протокол, синхронизируясь между потоками сможете обеспечить только на очень производительных МК. Или же будете полностью блокировать второй поток, пока не выведете всю последовательность сигналов, что будет заметно даже визуально.

В общем случае, когда для обработки различных внешних событий требуются разные потоки. Например, в случае, если менять значения этих пинов нужно по HTTP (TCP, UDP и т.п.) запросу от клиентов. Теоретически, для примера, можно перейти на bare metall умудрившись написать свой функционал, включая LwIP, в однопоточном исполнении. Но по универсальности такое решение будет существенно уступать многопоточному. Тем более, если речь идет о МК с несколькими ядрами, как тот же ESP32-S3.

Естественно речь именно о тех случаях, когда вынужденно нарушаются инварианты для достижения необходимой производительности, путем исключения операций, который алгоритм не требует.

Я как раз наоборот, утверждаю, что несмотря на то, что в unsafe коде нет ошибки, из-за его использования можно допустить ошибку в совершенно другом месте. И даже привел пример с MaybeUnint. Не выполнение инициализации буфера, предназначенного для чтения откуда-то - еще не ошибка. А вот чтение из этого буфера до того, как туда была произведена запись - уже ошибка.

Но без копирования я не вижу, как это написать безопасно даже в С.

Я и указываю, что это написать "безопасно" не получится. Особенно, если это существенный поток, например, на уровне 100К SPS с ADC.

разнести логически связанные пины по разным портам GPIO

Чаще всего это невозможно. Даже на 8-битных МК, не говоря уже о 32-битных.

Если бы всё можно было делать "безопасно", то и usafe в Rust был бы не нужен )

Другой вопрос, что безопасную работу с памятью потенциально можно обеспечить с аппаратной поддержкой. Например, частично это уже обеспечивается SSM.

У большинства роутеров при их герцовке эффективный радиус метров 20 в лучшем случае.

У меня Zyxel LTE7240-M403 позволяет регистрировать на нем ESP32-C3 с антенной на печатной плате на расстоянии свыше 500 метров.

Направленный в противоположном направлении Tenda O1V1.0 не сильно ему уступает, добивая на 300 метров. Но у него и столб ниже.

Так что всё очень сильно зависит от роутера, его исполнения и высоты размещения на столбе.

Иными словами, предлагаете вообще отказаться от написания критического к времянке кода на Rust? Агитируете за C/С++? )))

Как это нет, если этот объект затем передается, например, в функцию чтения в этот буфер?

Пусть каждый раз спрашивает разрешения.

Что приведет к катастрофической деградации производительности. Представьте себе, что на MK мы следим за сигналом с ADC на 100К SPS по DMA. Ваш код на подавляющем большинстве МК просто не успеет обрабатывать такой поток, если на каждый sample будет запрашивать доступ.

Так не экспортируйте в safe блок памяти, пока туда что-то не записано.

Вы предлагаете останавливать DMA после каждой транзакции и инициализировать его заново? А зачем он тогда вообще нужен?

могу содержимое памяти по указателю передать в safe код, который не должен заботиться, правильно ли всё сделано

Можете. Но потеряв в производительно на лишнее копирование память-память, что для MK на батарейном питании может привести вообще к невозможности решения поставленной задачи.

Ну верифицировали, что есть специально не инициализированный объект. Вы же сами выше писали, что никаких гарантий отсутствия UB это не даст )))

А теперь попробуйте менять значения пинов на одном порту из разных потоков без издержек межпоточного взаимодействия, так как требования по времянке таких издержек не позволяют )

И даже в столь простых примерах: https://github.com/search?q=repo%3Artic-rs%2Frtic+path%3A%2F^examples\%2F%2F+%2Funsafe+%2F&type=code

DMA читает буфер по кольцу по словам или по байтам. Задача программы писать в этот буфер новые данные до того, как до них дойдет DMA и не переписывать данные, которые DMA ещё не успел считать.

Можно, но с дополнительными издержками, что может быть терпимо в проблемных программах, но уж никак не в ядре или на МК,

Я привел конкретный пример, в котором для оптимизации производительности не выполняется операция инициализация того, что по логике работы программы не должно читаться до того, как туда будет что-то записано. Туда вообще не CPU может писать, а DMA. Но исключить при этом ошибку, когда оттуда читается до записи нельзя. Вот и приходится верифицировать весь код.

И примеров таких масса. Например, изменять значения пинов у MK на конкретном порту из разных потоков безопасно никак не получится, потому что значение конкретного пина изменяется накладыванием маски на весь порт. А устраивать взаимодействие между потоками производительность МК может не позволять.

Вы читать умеете? Вы только подтверждаете мои слова, что при наличии usafe блоков необходимо верифицировать ВЕСЬ КОД, так как одного их наличия достаточно для того, что Rust не мог контролировать безопасность.

А уже причины того, почему и как используется usafe блоки - совершенно отдельная тема.

Попробуйте написать без unsafe код на Rust для МК. Особенно если это no_std

Информация

В рейтинге
992-й
Откуда
Москва, Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность