Комментарии 74
Очень приятный текст, а главное - постепенное погружение в недры прошивки. Спасибо тебе!
Прям душу травите)
Когда же уже мне его отправят.
До этого хотелось купить потому что "ну клёво же", а теперь еще и siemens-like интерфейс накрыл ностальгией. Уговорили)
легко может быть такая ситуация, когда забыли освободить что-то вы сейчас, а упадет другое приложение потом.Разработчики flipper'а что-то про MPU говорили, или ни как от этого не защитится?
MPU не защищает от этого. Но у нас есть трекер кучи который по закрытию приложения дампает в консоль репорт. Подразумевается, что при написании приложения, разработчик туда смотрит и если баланс не сходится, то фиксит забытые деаллокации.
Оверхед на трекинг ресурсов будет равен бесконечности. В больших ОС для этого есть интерфейс сисколов и MMU, у нас ничего.
MPU используется для защиты 0x0 от записи.
И получится микроядро.
Вы представляете себе какая потребуется сложность аллокатора и оверхед чтобы заставить это работать в реальности? Какой будет сложность взаимодействия между тасками?
Даже основной код прошивки не поместится после этого в память.
If a program accesses a memory location that is prohibited by the MPU, the processor generates a memory management fault. This causes a fault exception, and might cause termination of the process in an OS environment.
In an OS environment, the kernel can update the MPU region setting dynamically based on the process to be executed. Typically, an embedded OS uses the MPU for memory protection.
Так как вы пользуетесь FreeRTOS, то вынуждены терпеть все её недостатки, которые компенсируются её «универсальностью» ко всем архитектурам, позволяющей лишь видеть знакомые названия API при программировании разных контроллеров. Если хотите чтобы ОС была полноценной, то она должна быть написана конкретно под Cortex M.
Напишите как долно быть и сделайте пул реквест.
Нельзя даже просто залить разработку деньгами и набрать программеров, это не работает. А вы предлагаете сделать тоже самое, но без денег?
Новые программисты — это расходы на введение в курс дела. Например, я с нуля, имея под рукой людей, которых можно спрашивать, потратил три или четыре дня просто на то, чтобы понять, как именно работает описанный в статье кусок апи, хотя до этого имел ощутимый опыт в разработке под МК. Просто потому что другие подходы, другие абстракции, не особо помогает ни опыт разработки под baremetal, ни под *nix. И это маленький кусочек уже написанной кодовой базы, понимания которого недостаточно, чтобы написать что-то не просто рабочее, а пригодное к использованию и сопровождению. Реального обьема того, что надо понять, читая код, прежде чем человек может писать приложения которые можно вливать в мастер, на порядок больше. Кто будет вводить всех этих разрабов в курс дела, учитывая что полноценной документации на внутренние интерфейсы пока нет?
Новые программисты — это расходы на управление и накладные расходы на коммуникацию. Знаете, почему внутренняя ставка разраба в компаниях может быть в два раза больше, чем его зарплата? Не только из-за налогов, но и потому, что занятость разраба тянет за собой занятость менеджеров, им управляющих. Даже не столько на «поставить задачу и проконтролировать», а просто на устранение проблем в коммуникации внутри команды, подпинывание отстающих, чтобы не тормозили команду, чтобы соблюдали кодстайл и так далее. Этих менеджеров надо взять, обучить, платить зарплату. Без них программисты разбредаются и начинают генерировать плюшки для собственного развлечения.
Новые опенсорсные программисты — это люди, пришедшие сюда ради интереса (я много писал об этом вот тут: Как Unix-way убивает десктопный Linux). Они не работают за зарплату, им нельзя поставить KPI, их нельзя вызвать на разговор и сказать «ты сделал плохо, переделай». Они не будут в третий раз переписывать реализацию, потому что вдруг изменился подход в какой-то системной библиотеке. А он будет меняться еще десять раз, потому что софт в стадии развития. А раз они не способны на поддержку своего кода, то он — либо бессмысленная трата времени, потому что он не будет использоваться, либо дополнительная нагрузка на текущих разработчиков, которым придется поддерживать код, сделанный людьми, которые не до конца понимают принципы работы и стиль написания (см. п. 1). Зачастую он такого качества, что проще переписать с нуля, чем отлаживать приложения в попытках найти, где же бага.
Кроме того, вот именно то, что вы предлагаете — раздать разрабам, уже и было сделано на хакатоне, условия которого были очень лайтовые — заявите интересную идею и хоть что-нибудь сделайте. Что там сделали? Из 30 или-сколько-там-человек что-то продолжают писать в ядро и системный функционал — двое или трое. Остальные написали свою аппу, и на этом их разработка закончилась. А, ну еще один, «образующий альтернативную версию ПО», которая идет вразрез с политикой разработчиков флиппера. И хорошо, что их трое, а не 30, потому что см. п. 1 и п. 2, существующие же разрабы зашились бы.
Новые опенсорсные программисты — это люди, пришедшие сюда ради интересаЭтот товар делается в основном для них.
Из 30 или-сколько-там-человек что-то продолжают писать в ядро и системный функционал — двое или трое.Их должно было быть 3000.
А, ну еще один, «образующий альтернативную версию ПО»А этих должно быть не один, а двадцать один.
Flipper должен был стать «пластилином» из которого можно легко создать «тулс своей мечты».
Кроме того, вот именно то, что вы предлагаете — раздать разрабамДа! Это был бы дружественный шаг, на встречу комьюнити. А сейчас ему просто не из чего образоваться.
1) Как решать проблему освобождения памяти когда задача аллоцирует через IPC ресурс в памяти другой задачи\сервиса?
2) Для разделения куч на каждую задачу надо запланировать ее определенный размер и адрес, обеспечивая неперекрываемость адресов размерами из-за некоторых особенностей, см ниже.
3) В MPU может быть только 8 регионов.
4) Гранулярность размера региона задается с шагом в степень двойки (32, 64, 128...), например мы не можем задать регион в 10 килобайт, только в 8 или 16, что обеспечивает очень сложное прогнозирование допустимого размера кучи на задачу.
5) Адрес участка должен быть кратен его размеру. Нельзя защитить восемь килобайт оперативной памяти начиная с третьего килобайта, только с нулевого или с восьмого. Это дает еще больше ада при прогнозировании размеров и адресов куч.
Из-за всех этих особенностей MPU практически неприменим на кортексах-м даже для защиты стека задач.
2) Так это хорошо когда приложению ограничат доступ к общей памяти, оно пусть скажет сколько ему надо, а система подумает пускать его в работу или нет. Иначе оно пойдет в разнос и кому очень надо не достанется.
3) Значит можно выделить 8 независимых heap'ов на процесс, очень даже не кисло. А в M7 даже 16 дают. Некоторые даже все 8 пристроить не могут.
4) Каждый регион может быть разделён на 8 частей — сразу проще стало.
5) Опять же, разделение каждого региона на 8 частей упрощает эту задачу.
Из-за этих особенностей MPU может достаточно легко защитить программы от взаимного повреждения памяти (а так же всех ресурсов МК), и полностью передать её контроль ОС.
1) Сам IPC пишется больно, не представляю (точнее слишком хорошо представляю) боль при том что еще накладываются ограничения на память и передачу указателей. Кстати как решается то что ресурсом должен владеть (пользоваться, читать\писать) и сервис и наша задача? IPC на каждый чих в каждую сторону? Но для IPC так же нужна общая область памяти.
2) Даже прогнозирование стека плохо автоматизируется, а кучу пргнозировать кралтно сложнее. Плюс это невозможно нормально поддерживать в приложении в случае смены размеров каких-то системных обьектов.
По поводу остального, как сделать с такими ограничениями все "легко" я не вижу, так же как и не вижу других проектов (я изучал, очень много изучал разные проекты и подходы к ос) с подобной архитектурой.
IPC на каждый чих в каждую сторонуНу не попиксельно же передавать изображение.
2) Если невозможно спрогнозировать то давать с адекватным запасом. Но отдавать всё что можно сразу — это уже крайность.
я изучал, очень много изучал разные проекты и подходы к осЯ понимаю, но этого недостаточно, нужно экспериментировать, с первого раза и у меня не получилось, но со 1001…
Потому-что это не "приложение". Вся прошивка есть одно большое приложение :)
Плюс, надо понимать что от того, что этот код будет написан в привычном редакторе и при этом разработчик не будет видеть страшных папок с чужим кодом вокруг, сложность самого кода уменьшится несильно: любая серьезная работа с железом потребует вникания в схемотехнику и специфичный для флиппера HAL, попытки нарисовать что-то больше двух кнопок — потребуют работы с вызовами интерфейса. Интерфейс и HAL требуют динамического выделения памяти, а оно требует как минимум понимания, что ты делаешь. А совместимости с ардуиновскими либами и вызовами, как у esp не будет, слишком разная база.
Так что я не очень понимаю, для чего Arduino IDE?
Чтобы не напугать пользователя? Так если его пугает взять готовый каркас приложения и писать в нем, то вряд ли он напишет что-то толковое.
Упростить задачу? А она не упростится, библиотеки переиспользовать нельзя, готовые программы работать не будут, интерфейс надо будет писать с нуля.
Поиграться, написав hello world и поморгав светодиодом? Ну можно, тоже важная штука, но в списке приоритетов далеко не на первом месте.
Большая часть библиотек ардуино не портируется под другой камень даже при наличии интерфейсов, из-за регистров и PROGMEM. Еще большая часть - не портируется в RTOS вообще, из-за подхода к памяти как к единоличному ресурсу.
Пишутся одновременно под все камни. Например https://github.com/FastLED/FastLED/blob/26baf51559a7f09c580b1c0f38ea6c7675663ea9/src/fastspi.h
Или пишутся отдельно под каждый камень, например https://github.com/jkb-git/ESP32Servo
Все возможные существующие библиотеки для Ардуино переписать под Флиппер? Да, сложновато, судя по тому что даже под ESP не все еще переписаны, только самые распространенные.
Скажу как ленивый человек, которому приходилось вылезать из теплого уютного arduino ide.
Ломка проходит очень быстро. И без всех этих digitalWrite и пр., живётся вполне себе нормально. И нет большой разницы, пишешь ли ты код с использованием новой для тебя библиотеки в arduino ide или любой другой си библиотеки.
Если ты не знаешь самых основ, да, становится менее уютно.
ну так то дигитал врайт\реад, wire конечно сложно реализовать, я понимаю
Вам что, надо #define DigitalWrite hal_gpio_write? Так это и сейчас можно сделать.
Еще раз повторю, базовые библиотеки (те что в поставке самой Ардуино) делаются относительно несложно и они у нас в планах. Только они не обеспечат совместимости со всеми остальными библиотеками (те что за пределами поставки Ардуино), так как в каждой библиотеке свой собственный слой совместимости с железом, плюс подходы к работе с железом в этих библиотеках не учитывают ОС, и сделать PR для поддержки нашего железа в каждую библиотеку мы не сможем.
Слой совместимости, к слову, не очень сложно делается. Только на одних analog read и gpio write далеко не уехать, большая часть сложностей в GUI и работе с файлами, и в ардуино для этого нет подходящих абстракций. А если нужно что-то изучать в любом случае, то почему не изучить сразу голый апи Флиппера?
Мне кажется, это изначально было неправильное решение. Иметь ардуино API - означает получить громадный буст к доступности и популярности проекта среди хакеров, самодельщиков и прочих энтузиастов. Ардуино-ядро это, де-факто, уже стандарт в этой экосистеме.
Понятно, что очень сложно вписать в ардуиновскую экосистему архитектуру, где не скетч запускает всё, а ваша система запускает скетч, но в принципе, думаю, возможно. Esp32 тоже использует FreeRTOS и ардиуно-скетч в отдельном таске. Ну, вообще, я уверен, что энтузиасты быстро прикрутят ардуино API, если проект наберёт некоторую критическую массу известности.
Возможно, было бы проще, если бы вы изначально заложили, например, отдельную атмегу для пользователей, как это сделано в некоторых ардуинах с вайфаями и линуксами (типа Yun). В случае с ардуинами это архитектурное убожество, когда атмега является основным процессором, а чип с линуксом и вайфаем всего лишь обслуживает атмегу, но в вашем случае основной функционал все равно будет в STM32.
Например, сразу при старте, даже без запуска других приложений, уже становятся активны 19 тасков
Подскажите, сколько места они занимают изначально, из тех 256 кб оперативки?
Чтобы не нарваться на страйк платежных систем рассылаем постепенно. Использовать свой купон на предзаказ вы можете по этой инструкции https://t.me/zhovner_hub/1516
Полторы недели рассылаем.
Не подскажите более современные аналоги, которые не устарели?
Proxmark всё же больше по части NFC и 125/128 кГц. И ноутбук с линуксом и знанием специфичных команд для него требует, емнип. По крайней мере, я себе 125 кГц чипы запорол, не указав пароль и с тех пор не могу перезаписать. Только NFC остался.
А у флипперва можно хранить коды от домофонов и шлагбаумов во дворе, удобно. И батарейка встроенная сразу, и интерфейс с меню есть. Он, имхо, больше прикладной девайс, чем исследовательский proxmark.
Еще эта реализация не потокобезопасна
Хм, заставило задуматься. На x86 не происходит ничего страшного, если один тред инкрементит значение поля структуры, а второй его по тому же адресу читает для отрисовки. Отрисованное значение всегда будет корректным, актуальным на момент чтения. На ARM'е хуже обстоят дела? Не понимаю за счет чего. Слабая модель памяти вроде не должна повлиять...
Кстати, если так размышлять, то возможна ситуация, когда система захочет перерисовать приложение в процессе запуска и инициализации. А там переупорядочивание инструкций, колбэк на рисование уже выставлен, но нужные поля еще не инициализированы. Возможно такое?
Концептуально нету разницы между армом и x86 для того что мы написали. Есть общие проблемы дизайна lock-free алгоритмов и структур данных. Самый просто пример это когда модель не помещается в машинное слово и её частичное обновление приводит к крашу, в этом случае явно нужно ее гардить каким-либо примитивом синхронизации ОС.
Чтобы не заставлять разработчиков ломать голову над доступом к памяти у нас есть несколько типов моделей представления: без блокировок и с блокировками доступа.
В общем описанная ситуация не возможна: приложение включается в дерево отрисовки только когда оно сказало что готово.
Так в итоге в вашем примере может упасть или нет? Не очень понял.
Навскидку казалось бы, в худшем случае может "проигнорировать" нажатие клавиши, когда тред гуя окажется "посередке" неатомарного инкремента, но эту ситуацию выправит авто-ререндеринг.
Возможно, я что-то не понимаю, но в момент выделения counter_app_alloc и counter_app_free в alloc выделяется память под структуру CounterApp с помощью furi_alloc. А в counter_app_free эта память не освобождается. То есть утекает...
У ребят на сайте сказано, мол
Flipper's main components are written in C, C++, and Rust
Интересно, на двух последних языках процесс разработки приложений что примерно из себя представляет?
Разработка под Flipper Zero: быстрый старт и первое приложение