Имитация нескольких экземпляров встроенного процессора - PullRequest
2 голосов
/ 10 января 2012

Я работаю над проектом, который предполагает подключение нескольких устройств, каждое из которых имеет встроенный (ARM) процессор.Одним из подходов к разработке, который я нашел полезным в прошлом для проектов, в которых использовался только один встроенный процессор, была разработка кода с использованием Visual Studio, разделенного на три части:

  1. Основной код приложения (в неуправляемом C /C ++ [см. Примечание])
  2. Код, имитирующий ввод / вывод (C / C ++), который выполняется в Visual Studio
  3. Встроенный код ввода / вывода (C), который Visual Studio не должен создавать, выполняется на целисистема.Ранее этот код был для PIC;для большинства будущих проектов я перехожу на ARM.

Подача встроенного компилятора / компоновщика кода из частей 1 и 3 приводит к получению шестнадцатеричного файла, который может работать в целевой системе.Совместное выполнение частей 1 и 2 дает код, который может выполняться на ПК, с преимуществами более совершенных средств отладки и более точного контроля за поведением ввода-вывода (например, я могу сделать так, чтобы код моделирования вводил некоторые типы случайных отклонений более легко, чем я могу)вызывать управляемые икоты на реальном оборудовании).

Целевой код написан на C, но среда моделирования использует C ++ для моделирования регистров ввода-вывода.Например, у меня есть структура данных PortArray;файл заголовка для встроенного компилятора содержит строку типа unsigned char LATA @ 0xF89;, а мой файл заголовка для моделирования включает #define LATA _IOBIT(f89,1), который, в свою очередь, вызывает макрос, который обращается к подходящему свойству объекта ввода / вывода, поэтому такой оператор, как LATA |= 4;, будетпрочитайте смоделированную защелку "или" прочитанное значение с помощью 4 и запишите новое значение.Чтобы это работало, целевой код должен компилироваться как в C ++, так и в C, но в большинстве случаев это не проблема.Наибольшее раздражение, вероятно, вызывают типы enum (которые ведут себя как целые числа в C, но для этого их необходимо уговорить в C ++).

Ранее я использовал два подхода для создания интерактивной симуляции:

  1. Скомпилируйте и свяжите DLL с целевым приложением и кодом моделирования, и получите VB-код в том же проекте, который взаимодействует с ним.
  2. Скомпилируйте код целевого приложения и некоторый код моделирования в EXE-файл с экземпляром Visual Studio и используйте второй экземпляр Visual Studio для пользовательского интерфейса моделирования.Пусть две программы обмениваются данными через TCP, так что почти вся «реальная» логика ввода / вывода находится в программе симуляции.Например, вышеупомянутая `LATA | = 4;` будет отправлять команду «read port 0xF89» на порт TCP, получать ответ, обрабатывать полученное значение и отправлять команду «write port 0xF89» с результатом.

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

Сложность состоит в том, чтобы выяснить, как заставить каждый моделируемый экземпляр получать свой собственный набор глобальных переменных.Если бы я должен был скомпилировать в EXE и запустить один экземпляр EXE для каждого имитируемого целевого устройства, это работало бы, но я не знаю практического способа поддерживать поддержку отладчика при этом.Другой подход заключается в том, чтобы расположить целевой код так, чтобы все компилировалось как один модуль, объединенный через #include.В целях моделирования все можно затем обернуть в один класс C ++, в котором глобальные переменные превращаются в переменные экземпляра класса.Это было бы немного более объектно-ориентированным, но мне действительно не нравится идея заставить весь код приложения жить в одном скомпилированном и связанном модуле.

Возможно, было бы идеально, если бы код мог загружать несколько экземпляров DLL, каждый со своим собственным набором глобальных переменных.Однако я не знаю, как это сделать, и не знаю, как заставить вещи взаимодействовать с отладчиком.Я не думаю, что действительно необходимо, чтобы все моделируемые целевые устройства выполняли код одновременно;было бы вполне приемлемо для примеров моделирования использовать совместную многозадачность.Если бы был какой-то способ выяснить, в каком диапазоне памяти хранятся глобальные переменные, можно было бы сделать так, чтобы метод 'task-switch' выменял все глобальные переменные, использованные ранее запущенным экземпляром, и менял содержимое, которое применимо.к включаемому экземпляру. Хотя я бы знал, как это сделать во встроенном контексте, я бы не знал, как это сделать на ПК.

Редактировать

Мои вопросы будут такими:

  1. Есть ли более приятный способ сделать паузу и проверить логику симуляции в отладчике VS2010, сохраняя отзывчивый пользовательский интерфейс для внешнего интерфейса симулятора, чем запускать внешний интерфейс симулятора и логику симулятора в отдельных экземплярах VS2010, если логика моделирования должна быть записана на C, а внешний интерфейс симуляции в управляемом коде?Например, есть ли способ сообщить отладчику, что при достижении точки останова некоторым или всем другим потокам должно быть разрешено продолжать работу, пока поток, достигший точки останова, приостановлен?
  2. Если основная часть логики моделирования должна быть совместима с исходным кодом со встроенной системой, написанной на C (так, чтобы одни и те же исходные файлы могли быть скомпилированы и запущены для целей моделирования под VS2010, а затем скомпилированы компилятором встроенных системдля использования в реальном оборудовании), есть ли способ отладчика VS2010 взаимодействовать с несколькими имитированными экземплярами встроенного устройства?Предположим, что производительность вряд ли будет проблемой, но количество экземпляров будет достаточно большим, так что создание отдельного проекта для каждого экземпляра, вероятно, будет раздражать в отсутствие какого-либо способа автоматизации процесса.Я могу думать о трех несколько подходящих подходах, но не знаю, как заставить любой из них работать действительно хорошо.Есть также подход, который был бы лучше, если это возможно, но я не знаю, как заставить его работать.
    1. Оберните весь код моделирования в один класс C ++, чтобы члены класса стали глобальными переменными в целевой системе.Я склоняюсь к этому подходу, но, по-видимому, для его компиляции необходимо, чтобы все было скомпилировано как единый модуль, что раздражающе сказалось бы на разработке кода целевой системы.Есть ли хороший способ иметь члены экземпляра класса доступа к коду, как если бы они были глобальными, не требуя, чтобы все функции, использующие такие экземпляры, были членами одного и того же модуля?
    2. Скомпилируйте отдельную DLL для каждого имитируемого экземпляра (так что, например, если я хочу запустить до 16 экземпляров, я включу в проект 16 DLL, все из которых используют одни и те же исходные файлы).Это может сработать, но каждое изменение конфигурации проекта должно быть повторено 16 раз.Действительно некрасиво.
    3. Скомпилируйте логику симуляции в EXE и запустите соответствующее количество экземпляров этого EXE.Это может сработать, но я не знаю ни одного удобного способа сделать такие вещи, как установить точку останова, общую для всех экземпляров.Возможно ли иметь несколько запущенных экземпляров EXE, прикрепленных к одному экземпляру отладчика?
    4. Загружать несколько экземпляров DLL таким образом, чтобы каждый экземпляр получал свои собственные глобальные переменные, оставаясь при этом доступным в отладчике.Это было бы лучше, если бы это было возможно, но я не знаю, как это сделать.Является ли это возможным?Как?Я никогда не использовал AppDomains, но моя интуиция подсказала бы, что это может быть полезно здесь.
  3. Если я использую один экземпляр VS2010 для внешнего интерфейса, а другой - для логики симуляции, есть ли способ упорядочить вещи так, чтобы запуск кода в одном автоматически запускал код в другом?

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

Ответы [ 2 ]

1 голос
/ 11 января 2012

Я бы подумал, что вам все равно придется запустить 16 копий основного кода приложения, но что ваш имитатор ввода-вывода на основе TCP может сохранять различный набор регистров / состояний для каждого входящего соединения TCP. 1001 *

Вместо набора глобальных переменных поместите их в единую структуру, охватывающую состояние ввода-вывода одного устройства. Либо создайте новый поток для каждого сокета, либо просто сохраните список активных сокетов и выделите отдельный экземпляр структуры состояния для каждого сокета.

0 голосов
/ 10 января 2012

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

...