Вадим Дерябкин @Vadimatorikda
Инженер-программист
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
Чем плох? Мы при старте убеждаемся, что все хорошо или делаем, чтобы все было хорошо и далее работаем точно зная, что данные целостны. Хотя, конечно. есть вероятность, что может что-то пойти не так из-за аппаратки. Но это уже не очень понятно как обходить. Конечно, идут проверки на != -1 (либо все 1. Если хоть 1 бит выбился, то не валиден флаг и т.д.). Но таких штук лично я почти не применяю. Не было случая, когда реально пригодилось.
Так вроде я и писал об этом. Ну только если копия повредилась, ее еще по другому экземпляру восстанавливают.
А есть иные варианты, кроме как учеба на живом коде? О многих вещах даже не задумываешься до того, как не столкнешься. А на чтение документации обычно времени практически нет. Ибо в моем случае я не только пишу код, но еще и тесты, требования, и т.д. Хотя хотелось бы как вы, конечно. Просто сидеть и копать в свою область. Это полезно, я считаю.
Хочу обоснований. Я просто осматривал _sbrk. Она не дергалась вроде ничем при работы с плавающей кучей (есть аппаратный блок работы с плавающей точкой). Куда копать?
Вот честно. Даже не знал о существовании такой штуки. Об этом статей не видел. Вот и не знал. Смотрю, вы много знаете нюансов. Был бы рад, если бы хоть писали об этом. С радостью бы почитал (без сарказма).
С просони не так написал. Не MMU, а MPU. MMU нет на тех процессорах, с которыми приходится работать. А вот настроить MPU для той же защиты при переключения контекста FreeRTOS — хотелось бы. А то без дела лежит… Руки не доходят.
Данный вопрос решается просмотром map файла (чтобы убедиться, что все сохраняемые данные в нужных местах).
Пробовали и такое. Все равно есть мега-супер-структура. Мы просто придерживаемся соглашения том, что все переменные должны быть спрятаны внутри одного файла (просто C без объектов когда). А наружу торчать только методы. И сейчас единственное, что не вписывалось в это видение — как раз эта глобальная структура. Тут нет смысла спорить. Все решается принятием удовлетворяющей команду разработчиков общей концепции. И все проекты должны делаться согласное ей.
Описал выше.
Тут полностью согласен. Мы составляем внутреннее ТЗ, в котором явно прописано, что и где должно лежать.
Во время работы нет надобности контролировать RO секцию. Она анализируется только при включении устройства. Устройство должно включаться за очень малый промежуток времени (они на летающем аппарате. Хоть и без людей. Если бы там были люди, то такого вопроса бы вообще не было. Поскольку там была бы внешняя flash, аппаратно продублированная и прочие штуки).
Отписал, почему не согласен (принятое соглашение между разработчиками).
4 секции — это разбиение более высокого требования «Обеспечить отказоустойчивое хранение данных конфигурации устройства.» (+ подпункты про изменяемость при настройке и прочее).
Ни в коем случае. Как писал выше, только то, что может быть изменено человеком, который будет интегрировать устройство в финальный комплекс.
Вот тут отмечу то, чего не было в статье. Да, я не храню копию данных того, что генерирует компилятор. И констант, которые не меняются. Но тут есть нюанс. Дело в том, что я 100% знаю, что весь код моей программы в момент включение — без ошибок (аппаратных). Имею ввиду, что прошивка соответствует той, которая была зашита. Об этом заботится загрузчик при включении. Вся прошивка целиком тоже дублирована. Содержит свою контрольную сумму. В статье же речь именно о изменяемых константах, которые может менять пользователь в отрывае от прошивки (ведь эти параметры лежат совсем в других областях flash. Опять же повторюсь. Если бы речь шла о перевозке людей, тогда все эти данные лежали вообще в отдельных накопителях с аппаратным резервированием. Т.к. нельзя позволить микроконтроллеру писать свою же память. Хоть и в другой странице.).
Это попытка оскорбить или сравнение с типовым случаем?) (типа я тоже студент формально… Хоть и не долго осталось до окончания)
Его трудно найти, легко потерять, и нереально удержать в Красноярске… Тем более за не особо высокую ЗП… Тут уже далеко не технический вопрос. Но и про документацию и прочее. В фирмах, которых мне довелось работать, документация — это последнее, до чего доходят руки. ТЗ иметь на бумаге вот и то редкость. В текущей фирме только начал появляться весь этот задел. Когда сначала ТЗ, потом под-требования, тесты, потом код. И это хорошо. Но фирме больше 7 лет. Что говорить о фирмах, которые «со подрядчики» и т.д.? Довелось работать с людьми, которые разрабатывали многомиллионное оборудование по ТЗ на словах) Тесты — на заказчике. Устройство не серийное. Там устройство не летало. Это оборудование для весьма не маленького предприятия. И… Там двух слойная плата управления без особых защит, никакого резервирования и т.д. При неудачном стечении обстоятельств (вероятность которых в условиях цеха очень высока), оборудование придет в негодность. Ну а надо всем там было срочно, переделывать не надо. работает же. Прототип? И так пойдет… В общем, все зависит тут от конторы. Но я считаю, что чем решение топорнее, тем лучше. Проще будет разгрузиться с себя 100500 разных проектов и технический долг будет хоть капельку меньше.
Не просто про Россию, а про Красноярск) Днем с огнем не сыщешь человека, который бы писал код хоть как-то вменяемо. При этом был готов если что переквалифицироваться в тех. писателя, пусконаладчика и т.д. Фулл-стек ембеддера короче).
Это значит, что человек ушел и не оставил ни строчки пояснений, а его код местами выглядит вот так:
Конечно, иногда помогает вдумчивое чтение документации. Но когда человек «для экономии ресурса» умножает 2 константы из документации и использует как одно число прямо в коде — догадаться об этом ОЧЕНЬ трудно. Да и человек порой писал код этот в свободное от командировок по интеграции устройств время. Так сказать «за чашкой чая». И в то время, когда компания только зарождалась — это было нормально и единственным решением чтобы выжить. Но те времена прошли и настало время уже следующему поколению сотрудников разбираться с этим… кодом) И «одна большая структура, которая лежит типа в оперативной памяти, но под нее зарезервировано с запасом 2 блока, в которые данные не пойми как попадают» — один из примеров. В вашем случае вы действительно их туда кладете. Я же столкнулся с реализацией, когда просто 2 страницы резервировались. И не важно, влезет туда структура или нет (конечно, обычно структуры 1-3 кб, а резервировалось 128, но все же).
3 человека хватит на все))) На каждом из которых куча проектов и задач не связанных непосредственно с программированием (например, понять почему упал борт, почему QNX внезапно начинает видеть битые блоки при включении при определенном стечении обстоятельств и прочие штуки).
Про достаточный уровень — соглашусь. Про нехватку кадров и надобность в более простых по реализации решений, но при этом не уступающим по качеству — отписал выше.
Красиво! Реально интересная тема. Не видел раньше, чтобы так пользовались LD скриптом. Обычно +- редактируют LD из демонстрационного проекта и на этом заканчивают.
Ну это понятно, да. Интересно. Очень интересно.
Ну это следует из такой организации.
Вот тут уже не подскажу, но вроде это нужно только если вы C++ используете. Там конструкторы глобальных объектов и прочее. Если мне память не изменяет. В чистом C вроде не нужно. Но тут не уверен.
Всегда корю себя за то, что пользуюсь стандартными библиотеками. По-хорошему, в настоящей авиации нельзя. Ни printf ничего такого. Пока используем. Но вообще нельзя.
Мне пока так и не удалось кстати настроить MMU + FreeRTOS. Ну это пока никому не требовалось, но вообще сам понимаю, что это необходимо. Просто времени не хватает сделать как положено. Стараюсь эксперементировать с такими штуками дома. А то на работе оправдать то, что ты возился с MMU вместо решения «реальных задач» — достаточно сложно.
Да, при вашем подходе хорошее решение. У меня этим занимается загрузчик. Как и восстановлением, если что-то пошло не так с кодом программы целевого устройства. А сама программа (целевого устройства) считает. что она не повреждена из коробки.
Мы используем стандартный FreeRTOS-овский. Он переопределяет malloc и free. Но вообще в наших устройствах, которые летают нет malloc/free/new/delite. Только статически размеченная ram. В угоду отказоустойчивости.
Поясните. Как «не странно»?
Долгое время на работе работал с этой реализацией. У нее есть следующий недостаток: <<Кучу разных данных, никак не связанных между собой по смыслу требуется описывать в одном месте.>>. Сейчас на работе пришли к тому, чтобы было четкое разделение логики и аппаратной части. Например метод «tim_set_pwm_duty» внутри и «set_lcd_brightness» наружу. В этом случае у tim_set_pwm_duty могут быть настраиваемые параметры на уровне железа (например границы ШИМ), а у set_lcd_brightness — параметры на уровне пользователя (например, допустимый диапазон яркости при текущем режиме работы). Сам код прекрасно разносится по разным уровням абстракции и позволяет не менять логику при переходе на другой микроконтроллер. К нему претензий нет. А вот то, что обе эти функции должны знать о существовании общей глобальной структуры несколько огорчает (да, каждая знает только о своей части в этой структуре. Но глобальная структура на весь проект — не есть хорошо). В моем же подходе можно создавать сущности (переменные, структуры) в совершенно разных местах. При этом всегда в map можно посмотреть, где и что лежит, если требуется. Это основное преимущество.
Отписал выше. Нарушается инкапсуляция и падает логика. Хорошо заметно на больших проектах, когда твоя структура под пару сотен элементов в куче по типу: «границы ШИМ каналов таймеров + параметров интерфейса uart + режим работы USB»…
В подходе, который был на работе, делалось проще. Просто в RAM создавалась структура (та самая, глобальная). Просто пустая. Ее начальные данные в flash. В модуль работы с этим делом из компоновщика передавались указатели на области flash. Все. По сути, это недоработанный ваш метод. Вашим можно еще узнать, сколько заполнено и выводить это. Хотя makefile/CMakeLists будет выглядеть действительно страшно. А я категорически против «интересных» решений в этой области. Это делает код сложно воспринимаемым и ведет к вопросу у тех, кто должен поддерживать это, когда вас нет на рабочем месте или вы вовсе его сменили. Но это делает вас не заменяемым на работе… Настолько, что вам звонят даже после увольнения и просят рассказать, как оно работает… Потому что «нужно поддерживать», а никто не знает почему оно вообще работает… Прошу прощения. Немного накипело на эту тему. Приходилось сталкиваться с очень хитрыми системами сборки.
Что такое «таблица инициализации data, bss...»? Интересно посмотреть.
У вас дикий оверхед на уровне сборки. Чтобы в этом разобраться — придется не слабо повозиться, если изначально не знать всех нюансов. В моем же случае есть небольшой наклодняк со стороны кода (хоть и невидимый для программиста), но никаких проблем на уровне сборки.
При старте МК попадаю в обработчик по reset. Там копирую из области data (во flash) в область data в ram. Область bss, noinit заполняю 0-ми. Но причем здесь это? Тут ведь речь про данные, которые должны быть в отрыве от прошивки МК. Они должны быть в строго определенных местах, чтобы в случае чего можно было снять dump памяти и посмотреть, с какими последними параметрами стартовало устройство.
А нужно 4 по ТЗ. Резервирование. Надежность.
Тем, что то, что попадет в RAM зависит от того, целостны ли данные в момент подачи питание или после перезагрузки в резервированных блоках или их стоит заменить начальными из текущей актуальной прошивки.
Читал. Нигде нет возможности указать явное дублирование в N копий. Вот пример.
Соглашусь. Даже не понял, о ком вы (не очень дружу с историей. Но это к делу не относится)
Но ведь я тут про дополнение linker-скрипта распинался…
Людей, умеющих адекватно работать с ld и прочими низкоуровневыми штуками и так мало… Не надо уменьшать.
Полагаю, вы невнимательно читали статью. Поправьте, если я не прав. Мне нужно, чтобы каждая сущность была продублирована в 4 местах. ТЗ такое. При вашем подходе мне придется явно задавать одну и ту же сущность 4 раза, просто указывая в макросе, в какую секцию стоит положить ее.
У нас обычно структуры задаются с атрибутом упаковки. Так что внутри них может и не быть адекватного выравнивания. Код к этому готов. А вот сами структуры/массивы и прочие в отдельности обязаны быть выравнены на 4. По-умолчанию компоновщик пытается все объявленные переменные через макрос выше складывать подряд. Без выравнивания. Тут атрибут выравнивания скорее дополнительная гарантия, что этого не произойдет. Уже сталкивался на практике с ситуацией, когда переменные лежали без выравнивания, а обращение к ним шло с использованием взятия ассемблерной команды по кратному 4 адресу. И падение в соответствующий обработчик гарантировано.
Но ведь я там их и объявил…
Я получаю из ld скрипта размеры, указатели, чтобы мой собственный модуль произвел инициализацию области RAM валидными данными и далее в процессе работы мог актуальными данными перезаписывать резервируемые блоки, если пользователь захочет изменить настройки при включении.
Не понял смысла предложения. Поясните пожалуйста, что вас не устроило. Я в mem.ld резервирую место под CRC в областях памяти, реализующих резервирование настроек пользователя.
Кому платить? Подводя итог, что именно ужасно? Выше аргументировал каждый пункт вашего недовольства.
Убедитесь, что:
Если это соблюдено, то можно попробовать:
Ну в целом впечатления смешанные. Но безусловно стоит продолжать. Пока еще не совсем ясно, что и зачем. Да, интересно. Да, на вид круто. Но что и куда — не ясно. К тому же не ясно, как даже попробовать это все (тут многие используют Linux...).