All streams
Search
Write a publication
Pull to refresh
88
0
Вадим Дерябкин @Vadimatorikda

Инженер-программист

Send message
Приятно было почитать) Как раз хотел встроить в одно из домашних устройств этот эмулятор. Чтобы поиграть в ряд игрушек без необходимости их переписывать.
Потому что Java…
Хм. Изучил подробнее про К1894ВГ1Т (вот тут). Если вкратце, то как-то грустно. Так же попытался выйти на контакт — не вышло. Жаль.
K1894 -TF16 в железе IDM-PLUS МИЭТ Зеленоград

Заинтересовали! Попробую изучить. Может свяжусь и получится получить образец. Очень не хотелось бы лезть в ПЛИС, если есть готовые процессоры/микроконтроллеры (ничего против ПЛИС не имею, просто для меня пока сложно).
Так в H7 2 независимых ядра. То же самое, только с удобной связью)
Очень категоричное заявление) Приведу пару доводов против него.
1. Невозможность воткнуть «нормальный процессор с MMU». Особенно стало остро с появление STM32H7. Встречал несколько проектов, где из-за требований к мелким габаритам ставили BGA минимального размера. И еще более мелкую DRAM к нему. RTOS там необходима была. По сути, там была часть для обычного МК +«тяжелые вычисления», которые гонялись на M7. Тут логичнее бы поставить просто одноплатник на QNX (есть требования к реальному времени) + МК, со своим ETH и все на прерываниях. Но увы. Габариты. В итоге все +- норм.
2. Конечные автоматы бывают порой настолько адовыми, что лучше не надо. И в таких случаях я склоняюсь к внедрению вообще виртуальной машины + скриптовые языки.
Сам в принципе против РТОС в МК, но порой это позволяет сделать проект читаемым и легко поддерживаемым. Порой даже приходится дописывать ту или иную РТОС (не ядро, а дополнительные меанизмы), чтобы снизить издержки, но все таки. Ясное дело, что ставить в STM32F030 РТОС не надо)))
о сразу вопрос: а как вы узнаете реальную структуру/лайаут данных для программирования флеша при интеграции? может измениться код, линкер может положить эти данные в другом порядке (сегменты он соритрует по алфавиту насколько мне память не изменяет, а вот сами данные он кладет в сегмент по мере резолвинга их, и совершенно нормальная ситуация когда данные могут поменяться местами)? А что при апдейте происходит (новые сеттинги добавились, какие-то старые удалилсь), CRC-то будет валидным?

С этим уже были проблемы, да. Когда новая прошивка думала, что хранятся валидные значения. Решили созданием утилиты, которая вычитывает старые параметры предварительно запросив у устройства текущую структуру, а потом шьет после перепрошивки в совпадающие по названиям поля обратно после перепрошивки. Во время прошивки новой версии все конфиги сбрасываются (страницы по просту чистятся и при первом старте CRC не совпадает и все затирается начальными значениями из новой прошивки). Вообще вся эта система рассчитана на то, что сама прошивка не меняется. Порой нет права сменить ее, даже если найдены ошибки. Пример… Есть устройство, которое уже 4 года как имеет неактуальный софт. С кучей известных багов. Но обновить ничего нельзя. Потому что уполномоченные люди уже тогда давно приняли устройство с той прошивкой. И ответственность за обновление никто брать не хочет.
Про ваш способ — услышал. Но для текущих задач он избыточен. Но в других случаях я может быть даже бы и воспользовался. Есть ссылка не github?

Про запись. Вообще, правильно было бы иметь внешнюю флешку. Вернее, 2 модуля. На 2-х разных интерфейсах. В виде 2-х разных микросхем. Но тут были 2 блока. Изменяются они крайне редко. Предполагается, что близко к «никогда». На практике раз 5-10 все таки перетерают при интеграции устройства. Ну и далее просто задача иметь валидные даннные для старта. Вот и все.
Надеюсь, что в продолжении как раз будет полноценная библиотека-API. Чтобы можно было через openocd работать полноценно.
Вы предлагаете вести журнал конфигураций. Под это нет памяти. Файловой системы тоже нет. Она в большинстве моих приложений избыточна. Но ваш вариант тоже не плох) Если есть ресурс на него.
«заводском» флеше

Это что? Имеется ввиду flash внутри микроконтроллера или одноразовая память внутри МК?
И при загрузке определяем программным способом, какой из трёх вариантов грузить.
И только после этого можно работать.

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

Ну так тут так и сделано. Линкер сам собирает все сущности (переменные, структуры, массивы...), помеченные как настройки — в одну секцию. И создаются еще их копии в других блоках.
По мне так это усложнение, вместо одной точки входа для работы с сеттингами, я получаю кучу размазанных по глобальному неймспейсу переменных с кучей суфиксов.

Вы используете только то имя, которое написали в макросе. Остальные использовать по внутреннему соглашению нельзя. О них заботится модуль резервирования.
Сразу встает вопрос: когда, каким образом и к каким переменным я могу обращаться в конкретный момент.

К любой, в любой момент времени. До выполнения вашего кода модуль позаботится о том, чтобы там находились валидные данные. Во время сохранения в память позаботится о том, чтобы данные не менялись.
А если прийдет новый человек на поддержку/разработку? Плюс просто человеческая ошибка, использовал переменную с другим префиксом. В 99% случаев эта проблема может лежать очень долго, и оставшийся 1% будет вылетать у клиента при старнных обстаятельствах.

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

Возможно, я неточно описал задачу. Через интерфейсы можно менять только данные в RAM или отдать команду модулю о том, что настало время сделать текущие данные — актуальными при запуске устройства. Если пользователь понаставил данных при конфигурации и понял, что «раньше было лучше», то он просто перезагружает устройство по питанию или отдает команду на восстановление настроек (в этом случа в RAM попадают значения, которые там были при включении и вызываются методы-обработчики разных объектов, которые работают с этими данными, чтобы сделать какие-то действия после обновления в них значений). И все становится как было.
Также если понадобилось резервирование, то это говорит, что есть реальные потери данных, поэтому запись данных всегда в одни и теже страницы памяти может привести к тому, что все копии будут невалидными.

Тут скорее защита от случая, когда началась перезапись настроек и пропало питание. В таком случае, часть настроек запишется, а часть нет. Контрольная сумма не совпадет и будет считаться, что данные не валидны. Тут произойдет восстановление старой конфигурации из соседнего блока.
В ISO не входит.

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

Уже не помню, какие были нюансы с kail, но вроде да. Но вам в любом случае нужно в линкере секции описать. Без этого никак.
При желании можно прагмами задать секции и выравнивание

Первое, чему меня учили, когда я только начинал свой путь инженера — не использовать никаких pragma, кроме как pragma once. Причина — непереносимость кода, в случае надобности.
Плюс пара функций для записи/восстановления структур из флеш в рам. Можно все еще в класс обернуть.

  1. Чтобы задать секции, надо их определить в линкер скрипте. Что я и сделал)
  2. При вашем подходе опять же. Одна структура. Мы обсуждали этот подход выше. Его плюсы и минусы. Можете почитать, если интересно.
Задокументированный стаж — 5-й год сейчас (официального трудоустройства). Официально устроился до первой сессии на первом курсе. С МК начал работать плотно в 9 классе. То есть, еще 3 года. Но это сложно начать профессиональным занятием. Максимальный прогресс на то время — «умный дом» (тогда было очень модно в моем окружении). Там по сути atmega8 + ассемблерного кода на 2 кб. Работа от часового кварца. Опрос датчиков (пара температурных датчиков), поддержка меню на 7-ми сегментном индикаторе (управление 4-мя нажимными кнопками в режиме матричной клавиатуры) и простенькая логика управления релюшками включения/выключения отопления (электронные клапаны на батареи). Сейчас же, самое сложное из того, что делал именно на работе — это устройство ввода-вывода для беспилотников (генераторы шим, измерения температуры, захват сигналов и прочие бытовые штуки). Тут отказоустойчивость и все дела. И устройство имитации окружающей среды в интеграции с матлабом по UDP. Там F4 принимает по ETH данные из матлаба и имитирует для конкретного комплекса показания температур, углов датчиков положения и прочие штуки (подмена информации с реальных чипов). Как у товарища Sap_ru опыта у меня не было такого. Хотя, теперь есть к чему стремиться.
Под всем текстом: ничего себе! Про перекомпиляцию не знал. Когда я только пришел, мне строго настрого запретили лезть в newlib, ld и прочие штуки. Оно и понятно… Тогда был по сути без опыта работы (сам уже не плохо тогда, ИМХО, кодил, но под keil и знал тонкости работы с периферией МК, но не знал тонкостей работы сборки. Т.к. keil все это скрывал). Потом реальная работа, gcc и т.д. Ну и как мне сказали, что там все настроено и трогать не надо. А потом я узнал, что это просто скопированная папка с гита))) После ваших слов, думаю, что стоит максимально подробно остановиться над этим вопросом и изучить как положено. Кстати. Про интересные глюки… У нас они решались выбором newlib-nano (стандартного под платформу с помощью флагов компоновщика) и вызовом функций типа setvbuf (вроде так называлось), где устанавливалось для всех потоков 1 буфер и подобные костыли. Достаточно костыльно.
Вот, проблема в том, что так делать можно, но не нужно.

Приходится… Ибо не знаю, где можно было бы этому профессионально обучится. Я тут говорил, что почти уже не студент. Но, честно, толку от учебы не было вообще (в плане технического развития). Мы на предмете «микроконтроллеры» 2 семестра смотрели на видео с ютуба по программированию ПЛК на языке графическом LD (нет, не язык скриптов линкера… Погуглите. Эта интересный на вид конструктор. Но никак не программирование).
Качество как гарантировать?

Тестами и внимательным отсмотром кода, когда есть время.
Опять же, писать тесты, и требования это хорошо полезно, но опыт в этом есть или тоже по ходу нарабатывается?

Конечно самостоятельно. Смотреть как делают другие и учиться на примере этого. Набивать свои шишки и продолжать искать нужный путь. Читать литературу, что есть. Не видел у нас мест. где бы этому реально учили.
Т.е контора под видом коммерческого продукта впаривает непонятно что.

В защиту некоторых контор в которых работал скажу, что они хотя бы обеспечивают поддержку и идут на встречу заказчиком. Когда что-то деделывается по месту. Приходилось работать и с теми, что просто клали на все и говорили что-то типа «устройство готово. Доработки — другое устройство. Заказывайте заново».
Это не к вам претензия, это к российским реалиям, в которых я двадцать лет отработал. Плохо то, что в результате многие российские разработчики даже не понимают, как нужно правильно разработку вести и буквально поколениями воспроизводят неправильный опыт.

Ну так… Да)… А что еще остается? Как правило, чем дольше контора живет, тем лучше у нее все с продуманностью. Обычно когда контора закрывается, ее опыт неудач и наоборот успехов уходит вместе с ней. Ну и в опыте сотрудников остается. Которые на новом месте уже пытаются не совершать определенных ошибок, с которыми столкнулись на прошлом месте работы.
С MMU/MPU в мире ARM это вопрос терминологии, кстати. MPU однозначно нужен. Полноценный же MMU с преобразованием адресов нужен в 99% случаев лишь для выполнения функций MPU. Он ставит очень жёсткие требования к структуре программы. Для большинства задач это просто не нужно. Или начинаются костыли, когда зачем-о включают MMU, а потом начинают придумывать, как бы его обойти, т.к. он работе программы мешает. У меня за всю историю было только два проекта на контроллерах, где нужно было преобразование адресов. В одном пришлось сделать полноценную подсистему виртуальной памяти, т.к. был процессор с полноценными многоуровневыми кэшами и для получения необходимой производительности пришлось MMU на полную катушку врубать (т.к. есть регионы память, где вообще кэша не должно быть, есть, где writethrough, есть где witeback и т.п., а управление этим всем потребовало включения страничного преобразования). А во втором был большой сложный многопоточный проект с кучей независимых процессов, который достиг того предела сложности, когда включение MMU позволяет быстрее находить ошибки, но и там можно было обойтись переключением MPU в планировщике задач. Во всех остальных случаях полноценный MMU был не нужен и даже вреден.

Интересно. Я просто всегда был уверен, что MMU реально нужен только чтобы QNX/Linux запустить.
Сорри, но по мне ТЗ не полно, и это вызывет вопросы.

Обычно можно сказать спасибо за то, что оно вообще есть)
Для примера: толком не описана работа с копиями и тп. Я понимаю, что используется некий common sense, но…
Зачем столько копий? Зачем усложнять задачу залезая на системный уровень(LD script) если задача решает на прикладном уровне?

Тут как раз идет упрощение, а не усложнение. Конечный программист просто указывает, где хочет, чтобы его данные были. Просто в RAM/FLASH, или же в той области, которая может изменяться с помощью модуля взаимодействия с пользователем с функциями резервирования.
Зачем программисту каждый раз думать какую копию использовать? Можно реализовать всю логику в классе/функциях. И в дальнейшем это переиспользовать в других проектах.
Не очень понятен подход по работе с настройками со стороны самого приложения?

А ему не нужно думать об этом. Он просто ставит макрос, если хочет, чтобы модуль заботился о том, чтобы эти данные резервировались.
И сейчас уже 2020 год, можно же использовать С++? но даже на С все можно решить проще.

Ну есть порт этого метода и на C++. Просто объект, который при инициализации получает данные из переменных LD и далее работает с ними.
Самый простой и может быть самый наглядный способ, это объеденить все пользовательские данные в одной структуре/классе, которая доступна всем модулям, и написать класс который отвечает за загрузку этих данных в память и сохранение этих данных: LoadSettings/SaveSettings. И реализовать работу с копиями данных внутри этого класса.

Собственно, именно это и было сделано раньше. От меня лишь было дополнения, чтобы не пришлось пихать все в одну структуру. А чтобы можно было в любом месте объявить сущность (переменную/структуру...) и она бы обрабатывалась как раз объектом класса, отвечающего за старт и резервирование.
У себя (для ардуинки) я сделал более сложную вещь, сделал маленькую базу данных которая позволяет хранить любое количество сеттингов (в зависимости от размера доступного флеша) по ключу. А данные могут быть простые типы с фиксированным размером как int, float, структ, так и сложные типа строк и массивов. Также это позволяет упростить разработку нескольких приложений на одном девайсе: используя разные ключи можно хранить сеттинги разных приложений не переустанавливая их каждый раз когда переключаешься на другое приложение. Структура хранения одна для всех приложений.
Также этот класс позволит скрыть реализацию для конкретной платформы: для ардуинки это флеш, для 8266 это уже может быть файловая система.

Правильно понимаю, что у вас лежит во flash по сути std::map? И вы прошивали arduino разными прошивками и просто получали по ключу из памяти (полагаю, внешней), свои данные? А данные общие для всех 100500 прошивкок? У меня просто не было такой задачи. Просто нужен был способ красиво сказать. что сущность должна резервироваться. Все.
Вообще, считаю, что достаточно мало информации по таким узким местам, как использование кучи разными стандартными функциями, используемые ресурсы стандартными библиотеками, различные варианты проведений и прочее. Вообще, честно, до ваших примеров был уверен, что все заканчивают «свое развитие» на том, что понимают, как работает стандартный ld скрипт, добавляют в него внешнюю память и все. Теперь вижу, что нет. Был бы рад, если бы порекомендовали литературу на эту тему. Всегда рад изучить вопрос подробнее.

Information

Rating
Does not participate
Location
Красноярск, Красноярский край, Россия
Date of birth
Registered
Activity

Specialization

Software Developer, Embedded Software Engineer
Lead
From 250,000 ₽
C++
STM32
Linux
Circuitry
Python
Assembler
Programming microcontrollers
Embedded system
Software development
Object-oriented design