Можно ли запустить ембедед С-проект на базе РТОС в режиме симуляции под Windows?

Если у вас есть эмбедед (embedded) проект и он написан на С или на С++ вы можете попробовать запустить этот проект в режиме симуляции на десктопном ПК и даже под Windows, по крайней мере у нас это получилось.

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

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

Общее описание программно-аппаратной системы, структурные схемы для симуляции.

Достаточно долгое время наша фирма занимается тестированием сложных устройств типа интертеймент-аудио-модулей (из состава мультимедийной системы), например, в автомобилях. Одна из функций которая решается такими модулями, прием упакованных данных из нескольких источников с множеством аудио каналов.

В список задач такой системы входит взаимодействие с модулем визуализации-индикации и извлечение-чтение данных о наличии аудио каналов, данных описания каналов, данных о кодировании каналов, декодирование каналов, формирование данных для навигации и позиционирования по каналам, рендеринг декодированных каналов.

Как видите система получается достаточно сложной если даже просто перечислить всю функциональность высокого уровня, которую эта система должна поддерживать.

С точки зрения тестирования такой сложной системы важно понимать на каком этапе трансляции-преобразования данных происходят сбои. Ведь кроме перечисленных функций, которые реализуются в основном за счет программных средств (парсинг, буферизация, аудио-кодеки, разного рода формирователи-преобразователи структур данных: списков, очередей, потоков, разветвленных структур изменяемых во времени, …) мы должны каким-то образом контролировать работу аппаратной части, которая, в нашем случае, не уступает по сложности оборудованию, на котором крутится софтовая часть нашей системы — процессору с памятью со всеми интерфейсами ввода-вывода и/или управления-контроля-программирования-отладки.

Основная функция аппаратной части в рамках нашей задачи — это преобразование данных с уровня физического представления в виде кодированных радиосигналов (таких как Wi-Fi сигналов, например) в данные доступные для чтения процессором и Программным Обеспечением (ПО), которое выполняется на этом процессоре. Аппаратная часть также предоставляет достаточно сложный интерфейс для управления на этом уровне декодирования и даже, в каком-то смысле, навигации по сигналам и соответственно по данным, упакованным в этих сигналах.

На самом деле наши модули из аппаратной части в чем-то сложнее, а в чем-то проще чем обычный Wi-Fi приемник. Wi-Fi приемник нуждается в некотором специальном уровене ПО так как он возвращает данные протокольного уровня Ethernet, а на уровень приложений надо предоставить пакеты более высокого уровня, например TCP или UDP пакеты, из которых на следующем уровне протокольного ПО предоставляется доступ уже непосредственно к данным внутри этих протокольных пакетов. В нашем случае можно сказать, что эту функцию извлечения данных из протокольных пакетов реализуют несколько интегральных аппаратных приемников под разные типы-форматы сигналов. Соответственно каждый такой приемник является более сложным чем Wi-Fi приемник поскольку он реализует больше уровней протокольной обработки пакетов данных, но, с другой стороны, он поддерживает только определенный тип высокоуровневых пакетов (скажем только UDP) поэтому в этом смысле его функциональность ужЕ, и значит проще. На самом деле наш приемник реализует некоторый проприетарный протокол не TCP и не UDP, обозначим некоторый Х протокол из поддерживаемых у нас как CustX, где X — это порядковый номер в списке поддерживаемых протоколов.  Такому приемнику можно присвоить составное имя в виде, например:

Wi-Fi+CustX приемник, но оставим только CustX для упоминания аппаратных приемников с которыми работает наше ПО.

Получается система с такой структурной схемой:

Структурная схема устройства

Структурная схема устройства

На картинке rFW расшифровывается как receiver FirmWare — это встроенное ПО приемника, которое работает под управлением Операционной Системы Реального Времени (РТОС, у нас используется РТОС подобного типа), которое в первую очередь и подлежит симуляции вместе с функциональностью указанной РТОС, с логикой и временными диаграммами работы прерываний и заполнения регистров периферийных устройств отображаемых в память ввода вывода,

hFW — это встроенное ПО некоторого интерфейсного, управляющего модуля с доступом к тач-панели например, которое непосредственно обеспечивает интерфейс с человеком-пользователем (обычно-например под управлением системы Андроид). Эта часть схемы исключена из симуляции на ПК и заменяется модулями и скриптами тестирования и управления.

Схема, которую нужно реализовать для симуляции работы rFW:

Состав ПО на десктопном ПК

Состав ПО на десктопном ПК

Тут наверно нужно пояснить что у нас есть возможность записывать реальный сигнал который поступает на вход цифровой части аппаратных приемников Cust1 и Cust2 и записывать такие сырые данные в файлы, которые получаются достаточно объемными, так как скорость поступления таких сырых данных составляет примерно 5.5 Мега байт в секунду, то есть 20 секунд записанного трафика формируют файл размером 5.5×20 = 110Мега байт, но для тестирования используются в том числе часовые записи.

Потоковая модель симуляции под Windows

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

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

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

Как построить систему симуляции для эмбедед проекта под управлением РТОС

Мы смогли обмануть эмбедед С-проект подменив ему объекты Операционной Системы Реального Времени объектами системы Windows.

Оказывается, POSIX потоки и объекты синхронизации вполне справляются с функциональностью, которую предоставляет наша РТОС (смотри для примера здесь). Все это начиналось как эксперимент: у нас есть С-проект, который использует внешнюю статическую библиотеку (lib) и вызывает функции из этой библиотеки, пара функций для примера (можно найти в рамках того же описания РТОС для примера):

void OS_TASK_Create(      OS_TASK*         pTask,
                    const char*            sName,
                          OS_PRIO          Priority,
                          OS_ROUTINE_VOID* pfRoutine,
                          void             OS_STACKPTR *pStack,
                          OS_UINT          StackSize,
                          OS_UINT          TimeSlice);
void OS_TASK_Suspend(OS_TASK* pTask);
void OS_SEMAPHORE_TakeBlocked(OS_SEMAPHORE* pSema);

Это может показаться кому-то непосильной работой написать даже просто враперы или дефайны для всех функций которые определены в заданной РТОС (наша РТОС несколько отличается, но для примера подойдет описание по ссылке:  смотри соответствующие подразделы API), к счастью не один С-проект не использует ВСЕ функции операционной системы, поэтому практическая задача намного проще, библиотека-врапер с которой будет компилироваться наш Эмбедед проект под Windows должна реализовать только те функции которые вызываются (упоминаются) в вашем проекте, более того компилятор выдаст вам список этих функций для реализации, при первой же попытке слинковать ваш Эмбедед С-проект на десктопе в десктопном окружении инструментов компиляции. Конечно, прежде чем дойти до этапа линковки вам будет необходимо успешно пройти этап компиляции, и этот этап тоже может приготовить вам сюрпризы, так как компиляция проекта, предназначенного для определенной платформы на другой платформе, для которой этот проект изначально не предназначен, не является какой-то тривиальной операцией. Вам, конечно, понадобится ваш опыт портирования проектов, или… или вам придется такой опыт приобрести каким-то образом.

Собственно, давайте посмотрим на функциональность модулей ПО, которые приведены на структурной схеме выше, и которые нам пришлось реализовать чтобы построить систему симуляции эмбедед проекта заданной структуры с С-кодом:

CustX Src — модуль (С или С++ или даже C# библиотека DLL) имитации-формирователь трафика данных соответствующего типа Х в соответствии с заданными физическими параметрами формирования трафика (параметрами являются в основном задержки-периоды, способ деления на пакеты и специально вносимые ошибки если нужны для тестирования)

CustX — модуль декодирования сырых данных соответствующего типа Х поступающих из источника (как будто из эфира)

rFW — модуль, который содержит весь код, который формирует так называемую прошивку устройства и работа которого подлежит тестированию, это тот самый код, который обращается к аппаратным регистрам ввода/вывода, к функциям РТОС.

HAL — модуль, который подменяет весь аппаратно-зависимый код, который выделяет и представляет области обычной хип-памяти в качестве регистровой памяти ввода/вывода для модулей rFW и РТОС, который содержит логику вызовов аппаратных прерываний, и реализацию этих прерываний, обеспечивает поступление данных, синхронизированное с симулируемой логикой прерываний, а также код начальной инициализации системы и функцию main () исходного эмбедед проекта. Модуль HAL (как ДЛЛ-ка) статически линкуется с модулями РТОС и rFW.

РТОС — модуль-врапер, библиотека функций или дефайнов к которым обращается пользовательский код проекта прошивки, по сути, это модуль, который производит преобразование сигнатур вызовов системных функций одной Операционной Системы в вызовы системных функций другой ОС, осуществляя подходящее преобразование параметров.

Test engine — модуль или в некоторых применениях интерфейсное приложение для запуска, управления, контроля текущих параметров во время симуляции. Это то, что можно очень коротко сформулировать по поводу этого модуля. 

Сроки запуска системы симуляции на десктопном ПК

Интересно что система изначально разрабатывалась как эксперимент, в который никто не верил. Она разрабатывалась одним единственным разработчиком в фоновом режиме, при некоторой ограниченной и достаточно скептической поддержке одного или двух коллег, и при пассивном противодействии остальных коллег. Срок, за который она превратилась из идеи в работающее приложение, можно оценить по разным критериям в период от одного до трех лет, при том, что эмбедед проект к тому времени существовал уже в течение не менее 10 лет, то есть система симуляции появилась примерно через 11–13 лет после вывода ембедед проекта на рынок. Еще 3–5 лет (в том числе, в зависимости от того сколько времени 3 или 1 год ушло на первый этап) ушло на то чтобы система стала применяться официально для тестирования кода.

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

Интересно узнать был ли у кого подобный опыт запуска С-кода предназначенного для микроконтроллеров на ПК. Какие проблемы вам приходилось решать в этом направлении?

© Habrahabr.ru