
Прошу помощи. Не могу найти документацию на плату. Купил когда-то на а**-э*****сс, но к ней не было в комплекте вообще ничего. За время поисков удалось найти только два фрагмента схемы. Мб есть у кого такая....

Типизированный язык программирования

Прошу помощи. Не могу найти документацию на плату. Купил когда-то на а**-э*****сс, но к ней не было в комплекте вообще ничего. За время поисков удалось найти только два фрагмента схемы. Мб есть у кого такая....
MiniFilter и Protector/Rejector (ObCallback) в одном драйвере с управлением через C#
В продолжение этого поста.
Предлагаю вашему внимаю мою поделку основанную на MiniFilter, ObCallback и Avalonia
Можно грабить корованы защищать от закрытия, регулировать доступ к файлам и запрещать запускать процессы.
C# код для управления драйвером:
using System;
using System.Diagnostics;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Threading;
using SharpMiniFilter.Driver.MiniFilter;
using SharpMiniFilter.Driver.Protector;
namespace SharpMiniFilter.Protected;
public partial class MainWindow : Window
{
private bool allowClose = false;
public MainWindow()
{
InitializeComponent();
this.Closing += (sender, args) =>
{
args.Cancel = !allowClose;
if (!args.Cancel)
{
ProtectorClient.ReplaceProtectList(Array.Empty<string>());
ProtectorClient.ReplaceRejectList(Array.Empty<string>());
MiniFilterClient.CloseConnection();
MiniFilterClient.DriverFilter -= DriverClientOnDriverFilter;
}
};
MiniFilterClient.DriverFilter += DriverClientOnDriverFilter;
if (MiniFilterClient.Connect())
{
ProtectorClient.ReplaceProtectList(new[] { $"PID:{Process.GetCurrentProcess().Id}" });
ProtectorClient.ReplaceRejectList(new[] { "*cmd.exe" });
Log_TextBox.Text += "Added current process to protection list." + Environment.NewLine;
Log_TextBox.Text += "Added cmd.exe to reject list." + Environment.NewLine;
}
else
{
Log_TextBox.Text += "Connection to driver failed." + Environment.NewLine;
MiniFilterClient.DriverFilter -= DriverClientOnDriverFilter;
}
}
private void DriverClientOnDriverFilter(MinifilterEventArgs e)
{
Dispatcher.UIThread.Invoke(() =>
{
if (e.Path.Contains("test.txt"))
{
if (!Process.GetProcessById((int)e.ProcessId).ProcessName.ToLower().Contains("notepad"))
{
e.SetHandled(true);
Log_TextBox.Text += "Minifilter: test.txt blocked" + Environment.NewLine;
}
else
{
e.SetHandled(false);
Log_TextBox.Text += "Minifilter: test.txt not blocked for notepad.exe" + Environment.NewLine;
}
}
});
}
private void Button_OnClick(object? sender, RoutedEventArgs e)
{
allowClose = true;
this.Close();
}
}Бонусом - создание .cab файла для отправки в Microsoft на сертификацию при Release сборке.
Ссылка на репозиторий.
P.S. Если вам будет интересно, а у меня силы и карма - то расскажу, что там и как в отдельной статье. А теперь и ответ на всех мучающий вопрос: "Почему пингвин пошёл в горы?"
UTF-8 Everywhere.

На неделе вспомнил про wchar_t в Си, пока в очередной раз работал с Unicode, но в Windows. Штука… Неоднозначная.
Часть WinAPI жёстко завязана на WCHAR (wchar_t). Но в Windows он до сих пор определён размером в 16 бит. Тот же GCC на Debian мне говорит, что у него wchar_t — все 32 бита.
Т.е. перевод строки из char в wchar_t генерирует валидный UTF-16 в Windows, но UTF-32 в Linux…
Кажется, char32_t должен решить эту чехарду в будущем… Хотя бы с точки зрения размерности… Пусть это и не исправит проблемы WinAPI…
Но действительно ли так часто нужно работать с полноценным code point в Unicode? Зачем? Только чтобы посчитать общее количество символов? Это же просто сделать и на основе char!
Авторы UTF-8 Everywhere дают развёрнутый ответ на этот и многие другие вопросы. Идея хорошо проработана, есть даже прекрасный FAQ для любопытных.
На этой веб-странице собрали самые веские доводы для использования исключительно UTF-8. Везде. Всегда.
Веб-сайт UTF-8 Everywhere: https://utf8everywhere.org/
Что нового появилось в PVS-Studio в 2025 году

Новый 2026 год уже вовсю идёт, и мы решили оглянуться назад и вспомнить, что интересного появилось в PVS-Studio за богатый на изменения 2025 год:
десятки новых диагностических правил, включая проверки, ориентированные на безопасность;
обновления интеграций в популярные IDE, CI/CD-системы, ASOC и сборочные системы;
улучшения анализа;
расширенная поддержка стандартов.
Всё это и многое другое описано в новой статье в нашем блоге.
Надоело искать парные вкладки (.h/.cpp) в VS Code? Я навайбкодил расширение, которое их магнитит.
Привет! Меня всегда немного раздражала одна мелочь в VS Code.
Открываешь Source.cpp, хочешь посмотреть заголовок, а Source.h открыт где-то в конце списка вкладок или вообще затерялся среди десятка других файлов. Приходится глазами искать его или тянуться к дереву проекта.
Стандартные методы сортировки тут не помогают, поэтому я написал Tab Magnet.

Как это работает:
Вы просто кликаете на файл в Explorer-е. Tab Magnet проверяет, открыта ли его "пара" (например, .h для .c или .html для .component.ts), и если да - автоматически переносит её поближе, чтобы они стояли бок о бок.
Функционал:
Знает, что заголовки лучше держать справа, а тесты — рядом с кодом.
Поддерживает из коробки C/C++, C#, Web (JS/TS/HTML/CSS) и Angular.
Можно настроить свои правила (например, для Go тестов или специфичных структур папок).
vscode marketplace: Tab Magnet
GitHub: tab-magnet
Книга Modern C.

В течении нескольких последних дней активно почитывал книгу Дженса Густеда “Modern C”.
Книга будет хороша как общий справочник, набор best practices кодинга на C, да и просто посмотреть, какие трюки в C23 можно делать.
Удивительно, что столь детальную и кропотливую работу можно найти в свободном доступе. Распространяется книга по лицензии CC 4.0 в вариации BY-NC-ND. Это очень радует.
Книга структурирована по уровню вовлечённости в C. От самых базовых элементов до многопоточных программ.
Для опытных разработчиков больше всего будут интересны Takeaways. Они резюмируют текст и позволяют фокусироваться на самом интересном. В конце книги есть листинг всех Takeaways, разбитый по разделам книги.
Рекомендую для любителей C.
Книга на сайте HAL Open Science: https://inria.hal.science/hal-02383654v2/file/modernC.pdf
Тестовый фреймворк для Си.

Иногда может показаться, что для тестирования программ нужно обязательно взять монструозный фреймворк, внедрить его в свою систему сборки, а потом при каждой проверке искать, какие же assert он умеет делать.
На практике это не всегда так.
Да, мир Си — дикий запад. Но, тем лучше, всегда есть выбор.
Джон Брюер приводит превосходный пример того, каким может быть минималистичный фреймворк для тестирования. Всего пара макро и одна переменная, восхитительно!
Статья на сайте Джона Брюера: https://jera.com/techinfo/jtns/jtn002
Нативный драйвер OLED-дисплеев для RP2040
Только что в один из своих проектов на микроконтроллере RP2040 понадобилось интегрировать графический дисплей для отображения погодной информации. Выбор пал на распространенные монохромные OLED-дисплеи разрешением 128х64 точки.
Из плюсов этих дисплеев для меня: высокая яркость и контрастность, простота интерфейса, дешевизна и высокая плотность информации в небольшом размере.
Контроллер у всех этих дисплеев стандартный - SH1106.
Свои проекты я пишу на С с использованием нативной Pico SDK. Поиск библиотеки для нужной платформы на С результатов не дал. Все, что на данный момент есть, - различные ардуино-библиотеки и микропитон.
В итоге было принято решение портировать на RP2040 одну из реализаций для STM32. Эта библиотека умеет рисовать графические примитивы в виде вертикальных и горизонтальных линий, прямоугольников пустых и заполненных, растровых изображений а также есть различные функции вывода текста и числовой информации.
Библиотека позволяет задать разрешение экрана а разворачивать экран на 90/180/270 градусов.
Изначально библиотека включала в 2 шрифта с размерами знакомест 5х7 и 7х10 точек.
Для своих целей я самостоятельно разработал большой шрифт 12х16 точек (на фото он).

Репозиторий проекта: https://gitflic.ru/project/svperchenko/sh1106_for_rp2040. Всем, кому надо, можно пользоваться.
Всем привет, это снова stalker320. Делаю что-то вроде анонса, я тут изучаю что появилось в C23 и думаю записать пару уроков с помощью него, так как пара новых функций выглядят теперь довольно интересными, к примеру, при объявлении перечисления теперь можно указать размер поля (: char). Вот он в исходном виде:
enum ColorChannel : char {RED, GREEN, BLUE, ALPHA};Добавлены атрибуты:
#include <stdlib.h>
[[nodiscard]] char* makeCharArray(int length) {
return reallocarray(NULL, length, sizeof(char));
}
int main(int argc, [[maybe_unused]] const char* argv[argc+1]) {
makeCharArray(10); // warning: ignoring return value of 'makeCharArray'
return 0;
}И многое другое.
P. S. используемые мною программы:
GCC: 15.2.0
CMake: 4.2.1
P. P. S. Про отсутствующее при проверке:
В моём компиляторе, функция reallocarray по неизвестным мне причинам отсутствует.
Компьютерное зрение для кода: что PVS-Studio разглядел в OpenCV
Что общего у компьютерного зрения и статического анализа? Оба ищут смысл в данных. OpenCV находит образы среди миллионов пикселей, а PVS-Studio — ошибки среди тысяч строк кода. Изучим же исходники крупнейшей библиотеки компьютерного зрения.

На примере 14 фрагментов кода из OpenCV предлагаю посмотреть, как статический анализ помогает избежать попадания багов в релиз и облегчить жизнь разработчикам.
Давайте посмотрим на кусок кода из проекта:
template<typename T>
struct Ptr : public std::shared_ptr<T>;
// ....
Ptr<FlannNeighborhoodGraph> FlannNeighborhoodGraph::create(....)
{
return makePtr<FlannNeighborhoodGraphImpl>(....);
}
void Utils::densitySort (const Mat &points, int knn,
Mat &sorted_points, std::vector<int> &sorted_mask)
{
// ....
FlannNeighborhoodGraph &graph = // <=
*FlannNeighborhoodGraph::create(....);
std::vector<double> sum_knn_distances (points_size, 0);
for (int p = 0; p < points_size; p++) {
const std::vector<double> &dists = graph.getNeighborsDistances(p);
for (int k = 0; k < knn; k++)
sum_knn_distances[p] += dists[k];
}
// ....
}
Если вы думаете, что использование умных указателей раз и навсегда решает проблему "висячих" ссылок и доступов к памяти, то здесь всё пошло не так. Давайте разбираться. Сейчас код работает следующим образом:
Функция create создаёт и возвращает умный указатель на тип FlannNeighborhoodGraphImpl, и его счётчик ссылок на объект равен единице;
Создаётся ссылка graph на значение этого умного указателя, при этом счётчик ссылок на объект не изменяется;
Указатель является временным объектом, и поэтому после завершения инициализации счётчик ссылок уменьшится до нуля, что приведёт к освобождению управляемого объекта. Теперь ссылка указывает на разрушенный объект;
В цикле for происходит обращение к невалидной ссылке.
В итоге код, который казался правильным, приводит к неопределённому поведению. Кроме того, эту проблему находит не только PVS-Studio, но и санитайзер. Пруф.
Для исправления необходимо сохранить умный указатель, тогда объект типа FlannNeighborhoodGraph будет жить до конца блока. Можно сделать так:
std::vector<double> sum_knn_distances (points_size, 0);
{
// get neighbors
auto graph = FlannNeighborhoodGraph::create(....);
for (int p = 0; p < points_size; p++) {
const std::vector<double> &dists = graph->getNeighborsDistances(p);
for (int k = 0; k < knn; k++)
sum_knn_distances[p] += dists[k];
}
}
Дополнительно ограничили область видимости graph, чтобы ресурс освободился после выполнения циклов.
Хотите узнать больше?
Статический анализ выявляет скрытые дефекты даже в больших работающих проектах. Какие ещё опасные фрагменты кода мы нашли в коде OpenCV? Полный разбор можно найти в отдельной статье.
Коллега обнаружил забавный момент, который идёт в копилку "PVS-Studio — двигатель прогресса".
Слышали ли вы про то, что злобные C и C++ компиляторы могут удалить вызов memset в конце функции во время оптимизаций? У нас даже про это есть диагностика V597.
Это давно известная, но при этом живучая потенциальная уязвимость CWE-14: Compiler Removal of Code to Clear Buffers. В следующем коде компилятор удалит заполнение памяти нулями (вызов memset), так как после этого буфер не используется. Раз не используется, то заполнение буфера с точки зрения языка C++ не имеет каких-либо наблюдаемых эффектов и, следовательно, является лишим. Т. е. его можно и нужно удалить с целью оптимизации.
void sha1_hmac( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[20] )
{
sha1_context ctx;
sha1_hmac_starts( &ctx, key, keylen );
sha1_hmac_update( &ctx, input, ilen );
sha1_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
}Код позаимствован из статьи про проверку проекта PPSSPP.
Проблема насущная, и для её решения в стандарт C23 внесли новую функцию memset_explicit, которая теперь обязательна для реализации в стандартной библиотеке вместо memset_s. Так вот, автор предложения (Miguel Ojeda, P1315) в своём документе сослался на нашу диагностику (ссылка N3).

И похоже, что он давно про нас знает, т. к. умудрился вставить ссылку ещё аж на старый сайт viva64.
Не зря столько лет говорим про memset. Приятно, что нас уже в proposal-ы затаскивают :)
Предлагаю вашему вниманию запись вебинара "Особенности разработки встроенного ПО по требованиям ФБ". Слайды презентаций.
Вместе с экспертами из "ФанкСэйфети" разбирались с такими сущностями, как ГОСТ Р МЭК 61508, уровнями SIL, стандартом MISRA C, сертификацией по функциональной безопасности и т. д.
В конце была активная дискуссия, во время которой отвечали на интересные вопросы. По её итогу приводим дополнительную информацию и ссылки.
Примечание 1. Говоря про безопасные и сертифицированные компиляторы, стоит отметить, что в 2024 году появился ГОСТ Р 71206-2024: "Разработка безопасного программного обеспечения. Безопасный компилятор языков С/С++. Общие требования". Также см. пост из цикла разбора РБПО: Процесс 12 — Использование безопасной системы сборки программного обеспечения и вебинар на эту тему.
Примечание 2. Инструменты SAST и DAST не обязаны быть сертифицированы. Из методической рекомендация ФСТЭК № 2025-07-011 | Уровень критичности: 3:
Область: Инструментальный анализ
Тип недостатка: Необоснованный выбор инструментов, в том числе инструментов статического анализа исходного кода, для выстраивания и выполнения процессов РБПО.
Описание: В настоящий момент ФСТЭК России не предъявляет требования наличия сертификата соответствия к большинству типов инструментов анализа кода и архитектуры. При этом к инструментам предъявляются следующие требования: ...
См. также выдержку из эфира AM Live "Разработка безопасного программного обеспечения (РБПО)". Анализатор PVS-Studio участвует в инициативе ФСТЭК по испытаниям статических анализаторов кода, но это другая история.
Примечание 3. Был вопрос, связанный с объединением требований ФБ и ИБ в одном стандарте. Некоторые усилия в этом направлении предпринимаются, см. примеры ГОСТов ниже:
ГОСТ Р 59506-2021/IEC TR 63074:2019. Безопасность машин. Вопросы защиты информации в системах управления, связанных с обеспечением функциональной безопасности.
ГОСТ Р 71452-2024/IEC/PAS 63325:2020. Требования к функциональной безопасности и защите системы контроля промышленной автоматизации (IACS) на протяжении жизненного цикла.
Однако необходимо понимать, что у ФБ и ИБ разные цели и разные подходы, поэтому объединение технических требований может создать путаницу, и сейчас меры по объединению некоторых аспектов ФБ и ИБ носят, прежде всего, организационный характер.
Как анализировать C и C++ код без привязки к сборочной системе на Windows

Код, написанный на C и C++, может использоваться для самых разных целей. И под каждые из этих целей есть свои инструменты сборки. Например, при разработке программного обеспечения для встраиваемых систем используются специальные компиляторы и сборочные системы.
Иногда бывает так, что появляется целый "зоопарк" самописных скриптов сборки, а его последний "смотритель" уволился ещё в прошлом году (играет Гражданская Оборона — "Зоопарк").
Хотелось бы всё равно как-то анализировать такой код без необходимости разбираться в хрупкой и непонятной системе сборки. Что же делать?
На самом деле, решение есть! Смысл взаимодействия анализатора со сборочной системой состоит в том, чтобы получить необходимую для анализа информацию. Но получить её можно и другим способом: из запущенного процесса компиляции.
В новой статье посмотрим, как воспользоваться этим механизмом для ОС Windows в анализаторе PVS-Studio, и как сделать его использование в процессе разработки удобным.
Ускоренный найм для инженеров C/C++: оффер за 3 дня
Телеком-команда YADRO создает решения для мобильных сетей нового поколения: базовые станции GSM и LTE, а также весь программный стек — от низкоуровневых протоколов до систем управления. Сейчас в команде открылись вакансии инженеров, отбор на которые можно пройти гораздо быстрее, чем обычно.
SPRINT OFFER — это формат ускоренного найма: все этапы отбора проходят всего за три дня. Чтобы попасть в программу, достаточно подать заявку до 19 октября.

Software Engineer (телеком-платформа)
Вам предстоит разрабатывать платформенное решение для телеком-систем. На его основе строятся современные узлы сотовых сетей LTE- и GSM-стандартов — например, базовые станции и системы управления. В это роли вы будете:
Развивать платформу, обеспечивающую middleware-сервисы, высокую доступность и управление узлами для приложений, входящих в состав базовой станции LTE/GSM.
Разрабатывать компоненты платформы в технологическом стеке C++/Linux.
Собирать и анализировать метрики для оценки производительности продукта.
Создавать и оптимизировать высокопроизводительные каналы коммуникации между компонентами, а также работать с подсистемами временной синхронизации, управления конфигурацией инфраструктуры и компонентов.
Поддерживать средства развертывания и обновления приложений.
Разрабатывать API для взаимодействия с аппаратным обеспечением и операционной системой при конфигурации и управлении инфраструктурой.
Обеспечивать качество продукта: исправлять дефекты, писать unit-тесты, проводить код-ревью, разрабатывать техническую документацию.
Создавать инструменты, упрощающие работу других разработчиков.
Участвовать в диагностике и анализе проблем работы системы в тестовых и полевых сценариях.
Подать заявку по ссылке →
Software Engineer C/C++ (LTE/GSM)
Создавайте высоконагруженные системы, которые обеспечивают стандарты связи разных поколений. Работа охватывает три уровня. L1 — низкоуровневое программирование, работа с радиоканалом и сигналами, близкая к железу. L2 — логика, работа с алгоритмами и математическими моделями. L3 — высокоуровневое программирование, бизнес-логика. В этой роли вы будете:
Разрабатывать решения совместно с командой — от этапа исследования и прототипирования до коммерческого внедрения пакетного ядра сети 5 поколения (5G).
Создавать программное обеспечение для базовых станций LTE, реализуя полный стек протоколов 3GPP.
Разрабатывать спецификации и дизайн программного обеспечения.
Интегрировать решения с другими компонентами системы — как программными, так и аппаратными.
Поддерживать и оптимизировать код, обеспечивая стабильность и производительность продукта.
Исследовать и устранять проблемы, влияющие на надежность, производительность и масштабируемость системы.
Узнать больше и подать заявку по ссылке →
Инженер по безопасности компании Fortinet представил экспериментальный инструмент KittyLoader. Это небольшой загрузчик, написанный на C и Ассемблере, который автор сам называет крайне ненадёжным и не предназначенным для практического применения.
Решение KittyLoader задумывалось как учебный проект и демонстрация базовых принципов работы загрузчиков, а не как готовое решение для использования. Исходный код проекта открыт на GitHub, любой желающий может изучить репозиторий и поэкспериментировать с модификациями загрузчика.
По словам автора, проект KittyLoader не стоит рассматривать как инструмент для реальных задач: он создан в первую очередь ради интереса и в образовательных целях. Несмотря на минимализм и очевидные ограничения, KittyLoader может быть полезен исследователям и студентам, которые хотят понять, как устроена загрузка и выполнение программ на низком уровне.

В прошлом году я помог Дмитрию Свиридкину подготовить и опубликовать цикл из 12 статей "Путеводитель C++ программиста по неопределённому поведению". Теперь этот расширенный, доработанный и обобщённый материал доступен в виде печатной книги:
Экскурс в неопределенное поведение C++ / Д. О. Свиридкин, А. Н. Карпов, – СПб.: БХВ-Петербург, 2025. – 384 с. – (Профессиональное программирование)
ISBN 978-5-9775-2073-7
Книга представляет собой обширный справочник типичных, а также очень редко встречающихся ошибок, характерных для программ на C++, Rust и других языках для низкоуровневого и системного программирования, в частности на ассемблере. Все рассмотренные проблемы так или иначе связаны с неопределенным, неуточненным и определяемым реализацией поведением языковых конструкций. Наибольшее внимание уделено неопределенному поведению, возможным признакам его присутствия в программах и методам поиска, диагностики и устранения такого поведения.
Книгу можно найти в offline и online магазинах.
Ещё какое-то количество книг я и коллеги раздадим в качестве сувениров и призов на различных мероприятиях, таких как:
И т.д. Узнать о подобных мероприятиях можно, например, в моём ТГ канале "Бестиарий программирования".
Приятного и вдумчивого чтения!
«Клей» для GPIO в QEMU
В прошлой статье мы пришли к выводу, что QMP — это лучше, чем ничего. Но хочется большего — библиотеку или программу (желательно, уже готовую), которая умеет читать/писать и узнавать об изменении состояния через poll() / pselect() / select() / epoll() / read().
В таком случае для каждой модели GPIO нужен «клей», похожий на тот, что используется с chardev — мы включаем его прямо в модифицированный QEMU. Очевидное название такого «клея» — gpiodev. Вот его основные функции, которые сейчас почти полностью соответствуют GPIO UAPI в Linux:
сообщать количество линий, конфигурацию, название и потребителя каждой линии,
читать и задавать состояние линии,
отслеживать изменения состояния и конфигурации линии (вход/выход, запрос/освобождение).
«Клей» состоит из двух групп, первая — это индивидуальные для каждого модуля GPIO функции, которые gpiodev использует, чтобы запросить специфическую информацию:
LineInfoHandler() — информация о линии: имя, флаги и потребитель,
LineGetValueHandler() — состояние линии: условный 0 или 1,
LineSetValueHandler() — задать состояние линии: 0 или 1.
По аналогии с GPIO UAPI напрашиваются также функции LineGetMultiValueHandler() и LineSetMultiValueHandler() для запроса и выставления линий, но я решил ограничиться минимальным набором.
Можно ли организовать прозрачное взаимодействие с устройствами внутри QEMU — использовать те же библиотеки и инструменты, как и для реальных устройств? Читайте во второй части трилогии о долгом пути до GPIO в QEMU.
Что ты сделал для хип-хопа IT-инфраструктуры в свои годы? Писал UEFI и BMC для высоконагруженного оборудования
В YADRO есть распределенная команда, которая разрабатывает и сопровождает собственные программные реализации UEFI (BIOS) и BMC. Для самого разного оборудования — от серверов до телеком- и клиентского оборудования.

Какие задачи выполняют в команде BIOS/BMC:
Реализуют программную поддержку новых аппаратных продуктов компании, определяют протоколы и методы взаимодействия между программными и аппаратными компонентами продуктов YADRO.
Проводят верификацию микрокода и выполняют проверку прошивок микросхем всех продуктов компании. Выстраивают стратегию тестирования.
Исследуют новые программные и аппаратные технологии для применения в продуктах. Рефакторят код для повышения производительности.
Придумывают методы безопасного обновления прошивок BIOS и BMC, чтобы обеспечить минимальный или нулевой даунтайм.
Добавляют новые фичи и меняют существующие — от WebUI до политик управления аппаратными компонентами.
Команде нужно больше инженеров — разработчиков на С/C++, тестировщиков, автоматизаторов и техлидов. Знакомься с вакансиями на сайте и вовлекайся в трушные инженерные задачи на современном технологическом стеке.
Последовательность Фибоначчи может конвертировать мили в километры с небольшой погрешностью
5 миль ≈ 8 км (5 и 8 - числа Фибоначчи). Реальность: 5 миль = 8.04672 км.
Почему?
1 миля = 1.609344 километра (точное значение).
Золотое сечение (φ) ≈ 1.618034
Погрешность возникает потому что отношение Fₙ₊₁ / Fₙ стремится к φ ≈ 1.618034, а точное соотношение миля/км = 1.609344.
Относительная погрешность: (1.618034 - 1.609344) / 1.609344 * 100% ≈ 0.54%.
Решил по фану реализовать конвертор милей в километры на C. Ссылка тут.
Advanced distance converter: miles to kilometers
Usage: ./bin/fib_miles2km [OPTIONS] [distance]
Options:
-h, --help Show help information
-f, --fib=ARG Convert miles to km using basic Fibonacci
-b, --basic=ARG Convert miles to km using standard formula
-i, --fib-interp=ARG Convert using Fibonacci interpolation
-c, --fib-cache=ARG Convert using cached Fibonacci
-g, --fib-golden=ARG Convert using golden ratio
Не знаю зачем, но прикольно :)
Как создать простейшую модель GPIO для QEMU
Предлагаю два варианта, которые я условно решил назвать MMIO и PCI. Последний — тоже MMIO, но в QEMU они добавляются разными путями. Начнем с сердца любой MMIO-модели — апертуры.
Апертура и адресное пространство
Как я упоминал в одной из своих статей, любое MMIO-устройство — это MemoryRegion с заданными шириной доступа и размером. Для того, чтобы он был виден CPU или другому устройству, такому как DMA, его нужно разместить в соответствующем адресном пространстве — например, пространстве, назначенном для cpu0:
0x0 0xffffffffffffffff
|------|------|------|------|------|------|------|------|
0: [ address-space: cpu-memory-0 ]
0: [ address-space: memory ]
0x102000 0x1023ff
0: [ gpio ]В любое время можно посмотреть существующие адресные пространства и регионы памяти в мониторе QEMU:
(qemu) info mtree
[...]
address-space: cpu-memory-0
address-space: memory
0000000000000000-ffffffffffffffff (prio 0, i/o): system
0000000000102000-00000000001023ff (prio 0, i/o): gpio
[...]Тогда в модели устройства нам нужно всего лишь создать такой регион и назначить ему соответствующие функции записи и чтения:
static const MemoryRegionOps mmio_mmio_ops = {
.read = mmio_gpio_register_read_memory,
.write = mmio_gpio_register_write_memory,
.endianness = DEVICE_NATIVE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
},
};
[...]
memory_region_init_io(iomem, obj, &mmio_mmio_ops, s,
"gpio", APERTURE_SIZE);
[...]Фактически это означает, что все семейство инструкций Load/Store будет вызывать mmio_gpio_register_read_memory()/mmio_gpio_register_write_memory() при совпадении адреса чтения/записи с адресом региона в адресном пространстве.
static uint64_t mmio_gpio_register_read_memory(void *opaque, hwaddr addr, unsigned size);
static void mmio_gpio_register_write_memory(void *opaque, hwaddr addr, uint64_t value, unsigned size);Передаваемые аргументы и возвращаемое значения интуитивно понятны. Отмечу, что hwaddr addr — это адрес относительно начала нашего региона, а не абсолютный адрес.
Нам остается лишь создать устройство и добавить его регион в файле машины:
gpio = qdev_new(TYPE_MMIO_GPIO);
sysbus_mmio_map(SYS_BUS_DEVICE(gpio), 0, ADDRESS);Почти десять лет назад Никита Шубин, ведущий инженер по разработке СнК в YADRO, сделал возможность чтения и записи GPIO для QEMU. Читайте первую часть трилогии о долгом пути до GPIO в QEMU.