Протокол связи XCP для моделирования внешнего режима Simulink ® является протоколом связи ведущий-ведомый. По умолчанию программное обеспечение поддерживает моделирование внешнего режима XCP:
На компьютере-разработчике для кода, который генерируется с помощью ERT (ert.tlc) и GRT (grt.tlc) системные целевые файлы.
Если системный целевой файл для пользовательского целевого оборудования получен из системных целевых файлов ERT или GRT, можно использовать поставляемые API для обеспечения целевого подключения XCP. Применяются ограничения внешнего режима XCP.
Программное обеспечение целевого соединения внешнего режима содержит:
Уровень абстракции внешнего режима
Уровень подчиненного протокола XCP
Уровень ведомого транспорта XCP
Уровень абстракции платформы XCP

Для взаимодействия с Simulink во время моделирования внешнего режима целевое приложение должно вызывать функции из уровня абстракции внешнего режима.
Родительская папка для файлов исходного кода:
matlabroot\toolbox\coder\xcp\src\target\ext_mode
API-интерфейсы уровня объявлены в include\ext_mode.h и реализовано в src\xcp_ext_mode.c.
Для связи с Simulink целевое приложение использует службы, предоставляемые уровнем абстракции внешнего режима. Эта блок-схема показывает необходимые целевые шаги приложения для установления связи с Simulink.

В этих таблицах перечислены функции, которые целевое приложение должно вызывать на каждом этапе.
| Стадия | Функция | Цель |
|---|---|---|
| Извлеките аргументы командной строки внешнего режима. | |
| Инициализация созданного кода модели Simulink. | |
| Инициализация целевого подключения внешнего режима. | ||
| Дождитесь запроса на запуск с компьютера разработки, который будет создан при нажатии кнопки Выполнить. | |
|
| Выполните один шаг созданного кода модели Simulink. |
Для идентификатора времени выборки модели сигналы выборки, сгенерированные функцией шага модели, передают содержимое пакета на транспортный уровень протокола связи для передачи на компьютер разработки. | ||
Передача и прием пакета от физического интерфейса связи и обработка содержимого пакета в соответствии с выбранным протоколом связи. | ||
HOST STOP REQUEST OR SIMULATION COMPLETE | Проверьте, получен ли запрос на остановку моделирования внешнего режима от модели на компьютере разработчика. Запрос создается при нажатии кнопки «Остановить». | |
| Проверьте, завершено ли выполнение сгенерированного кода модели. | ||
RESET |
| Завершить созданный код модели Simulink. |
| Сброс целевого подключения внешнего режима в исходное состояние. |
В этом примере псевдокода показано, как можно реализовать различные этапы блок-схемы в целевом приложении. Во время RUN среда выполнения внешнего режима требует, по меньшей мере, двух потоков:
Периодический поток, ответственный за выполнение созданного кода модели.
Фоновый поток, который отвечает за запуск стека связи внешнего режима и передачу и прием пакетов.
Псевдокод имитирует многопоточность, выполняя periodicThread и extmodeBackgroundRun последовательно в пределах одного и того же while() цикл.
/*------------- Pseudo-Code Example -------------*/
/* Define periodic thread */
void periodicThread(void)
{
/* Run model step function */
modelName_step();
/* Notify external mode abstraction layer about periodic event */
extmodeEvent(PERIODIC_EVENT_ID, currentSimulationTime);
}
/* Main function for target application */
main(int argc, char *argv[])
{
/*------------- INITIALIZE -------------*/
/* Parse external mode command line arguments */
extmodeParseArgs(argc, argv);
/* Initialize model */
modelName_initialize();
/* Initialize external mode target connectivity */
extmodeInit(extModeInfo, finalSimulationTime);
/*------------- HOST START REQUEST -------------*/
/* Wait until a start request is received from development computer */
extmodeWaitForHostRequest(EXTMODE_WAIT_FOREVER);
/*------- HOST STOP REQUEST OR SIMULATION COMPLETE -------*/
/* While simulation is not complete and stop request is not received */
while (!extmodeSimulationComplete() && !extmodeStopRequested()) {
/*------------- RUN -------------*/
periodicThread();
extmodeBackgroundRun();
}
/*------------- RESET -------------*/
/* Terminate model */
modelName_terminate();
/* Reset external mode target connectivity */
extmodeReset();
return 0;
}
Для просмотра кода, вызывающего функции, выполните пример моделирования во внешнем режиме с помощью функции XCP Communication with System target file, для которой установлено значение ert.tlc. Затем из папки создания кода откройте ert_main.c.
Уровень подчиненного протокола XCP интерпретирует команды и данные XCP в соответствии со стандартом ASAM (ASAM) Ассоциации стандартизации систем автоматизации и измерений (Association for Standardization of Automation and Measuring Systems, ASAM MCD-1 XCP).
Папка исходного кода:
matlabroot\toolbox\coder\xcp\src\target\slave\protocol\src
Ведомый транспортный уровень XCP передает и принимает сообщения от среды связи в соответствии со спецификациями ASAM.
Исходная папка:
matlabroot\toolbox\coder\xcp\src\target\slave\transport\src
Уровень абстракции платформы XCP обеспечивает:
Драйвер XCP для передачи и приема необработанных данных через физический интерфейс связи.
Реализация статического распределителя памяти.
Другие целевые аппаратные функции.
Пример адаптации см. в разделе Создание пользовательского слоя абстракции.
Драйвер XCP посылает и принимает сообщения XCP по каналу связи. При моделировании во внешнем режиме процесс построения автоматически добавляет файлы драйверов в информационный объект построения.
Драйвер XCP основан на rtiostream API. Например, при моделировании внешнего режима на основе хоста используются следующие параметры: rtiostream файлы:
matlabroot\toolbox\coder\rtiostream\src\rtiostreamtcpip.c
matlabroot\toolbox\coder\rtiostream\src\rtiostream_serial.c
Для получения подробной информации о внедрении и тестировании rtiostream канал связи, см.:
Коммуникационный rtiostream API (встроенный кодер)
Для пользовательского уровня абстракции платформы необходимо добавить rtiostream файлы в информационный объект построения. Пример см. в разделе Создание пользовательского слоя абстракции.
Подчиненное программное обеспечение XCP требует динамического выделения блоков памяти переменного размера для хранения внутренних структур данных.
При моделировании во внешнем режиме процесс построения автоматически добавляет файлы распределителя памяти в информационный объект построения.
xcpMemBlockSizes и xcpMemBlockCounts макросы препроцессора определяют распределение памяти.
Распределитель памяти по умолчанию может выделять и освобождать до 16 различных наборов блоков памяти. Для каждого набора можно переопределить назначения по умолчанию во время компиляции. Можно указать:
Размер блока через XCP_MEM_BLOCK_ макрос препроцессора.N_SIZE
Количество блоков в каждом наборе через XCP_MEM_BLOCK_ макрос препроцессора.N_NUMBER
Например, эти макросы препроцессора создают четыре блока по 64 байта и восемь блоков по 256 байтов.
#define XCP_MEM_BLOCK_1_SIZE 64 #define XCP_MEM_BLOCK_1_NUMBER 4 #define XCP_MEM_BLOCK_2_SIZE 256 #define XCP_MEM_BLOCK_2_NUMBER 8
Настройте размеры блоков различных наборов в порядке возрастания:
XCP_MEM_BLOCK_ < N_SIZEXCP_MEM_BLOCK_N+1_SIZE
Наименьший размер блока, XCP_MEM_BLOCK_1_SIZE, должен быть достаточно большим, чтобы удерживать указатель.
Сконфигурируйте выравнивание для распределителя памяти через XCP_MEM_ALIGNMENT макрос препроцессора. Например:
#define XCP_MEM_ALIGNMENT 8
Этот файл определяет интерфейс уровня абстракции платформы:
matlabroot\toolbox\coder\xcp\src\target\slave\platform\include\xcp_platform.h
XCP_CUSTOM_PLATFORM макрос препроцессора в информационный объект построения. Предоставление реализации пользовательских функций в файле с именем xcp_platform_custom.h. Если не определено XCP_CUSTOM_PLATFORM, в процессе сборки используются файлы по умолчанию, поддерживающие системы Linux ® и Windows ®.В этой таблице описываются функциональные возможности, которые необходимо обеспечить для программного обеспечения подчиненного сервера XCP, развертываемого на целевом оборудовании.
| Функциональность | Подробнее |
|---|---|
Взаимное исключение | Для доступа к структурам системных данных с поддержкой взаимного исключения драйвер XCP зависит от базовых API для определения, инициализации, блокировки и разблокировки. Для поддержки взаимного исключения для целевого оборудования предоставьте пользовательскую реализацию. Реализация по умолчанию для Linux и Windows поддерживает взаимное исключение. #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) ... #define XCP_MUTEX_DEFINE(lock) HANDLE lock #define XCP_MUTEX_INIT(lock) lock = CreateMutex(0, FALSE, 0) #define XCP_MUTEX_LOCK(lock) WaitForSingleObject((lock), INFINITE) #define XCP_MUTEX_UNLOCK(lock) ReleaseMutex(lock) #else ... #include <pthread.h> #define XCP_MUTEX_DEFINE(lock) pthread_mutex_t lock #define XCP_MUTEX_INIT(lock) pthread_mutex_init(&(lock), NULL) #define XCP_MUTEX_LOCK(lock) pthread_mutex_lock(&(lock)) #define XCP_MUTEX_UNLOCK(lock) pthread_mutex_unlock(&(lock)) ... #endif |
| Сон | Предоставьте API ожидания, который переводит вызывающий поток в спящий режим до истечения указанного времени. По умолчанию для систем Linux и Windows используется следующая реализация: #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
...
#define XCP_SLEEP(seconds,microseconds) Sleep((seconds) * 1000 \
+ (((microseconds) + 1000 - 1) / 1000))
#else
...
#if _POSIX_C_SOURCE >= 199309L
#define XCP_SLEEP(seconds,microseconds) do {struct timespec t;\
t.tv_sec = seconds; t.tv_nsec = microseconds * 1000; nanosleep(&t, NULL);} while(0)
#else
/* nanosleep is not available. Use select instead. */
#define XCP_SLEEP(seconds,microseconds) do {struct timeval t; t.tv_sec = seconds;\
t.tv_usec = microseconds; select(0, NULL, NULL, NULL, &t);} while(0)
#endif /* _POSIX_C_SOURCE >= 199309L */
...
#endif |
Регистрация | Для генерации диагностических сообщений ведомому программному обеспечению XCP требуется пользовательский API печати, поддерживающий службы регистрации, предоставляемые целевым оборудованием. Если не определить |
Преобразование адреса | Стандарт XCP выражает адрес переменной в памяти как 32-битный адрес с 8-битным расширением. Мастер XCP извлекает адреса сигналов и параметры модели путем анализа отладочной информации, создаваемой процессом построения. Отладочная информация имеет формат DWF или PDB. Мастер XCP запрашивает доступ к параметрам и сигналам, посылая команду XCP, содержащую аргументы. Когда Используйте #if defined(__MINGW32__) || defined(__MINGW64__) #define XCP_ADDRESS_GET(addressExtension, address) \ (uint8_T*) ((uintptr_t) address) #else #define XCP_ADDRESS_GET(addressExtension, address) \ (uint8_T*) ((address) + (uint8_T*)&__ImageBase) #endif addressExtension равно 0. |
Установка и копирование памяти | Можно указать оптимизированную версию памяти копирования и задать операции с памятью. Если не определить #ifndef XCP_MEMCPY #define XCP_MEMCPY memcpy #endif #ifndef XCP_MEMSET #define XCP_MEMSET memset #endif |
Анализ аргументов командной строки | Если оконечное оборудование не поддерживает синтаксический анализ аргументов командной строки, определите макрос препроцессора Для замены set_param(modelName, 'OnTargetWaitForStart', 'on'); -DON_TARGET_WAIT_FOR_START=1) компилятору. |
Для процесса построения можно определить команду посткодового создания, создающую пользовательский уровень абстракции платформы.
Укажите файл заголовка xcp_platform_custom.h. Этот пример Linux определяет требуемые функции.
#ifndef XCP_PLATFORM_CUSTOM_H
#define XCP_PLATFORM_CUSTOM_H
/* XCP_ADDRESS_GET */
#include <stdint.h>
#define XCP_ADDRESS_GET(addressExtension, address) (uint8_T*) ((uintptr_t) address)
/* XCP_MUTEX */
#include <pthread.h>
#define XCP_MUTEX_DEFINE(lock) pthread_mutex_t lock
#define XCP_MUTEX_INIT(lock) pthread_mutex_init(&(lock), NULL)
#define XCP_MUTEX_LOCK(lock) pthread_mutex_lock(&(lock))
#define XCP_MUTEX_UNLOCK(lock) pthread_mutex_unlock(&(lock))
/* XCP_SLEEP */
#include <sys/time.h> /* gettimeofday */
#if _POSIX_C_SOURCE >= 199309L
#include <time.h> /* for nanosleep */
#else
#include <stddef.h>
#include <sys/select.h> /* for select */
#endif
/* _POSIX_C_SOURCE >= 199309L */
#if _POSIX_C_SOURCE >= 199309L
#define XCP_SLEEP(seconds,microseconds) do {struct timespec t;\
t.tv_sec = seconds; t.tv_nsec = microseconds * 1000; nanosleep(&t, NULL);} while(0)
#else
/* nanosleep is not available. Use select instead. */
#define XCP_SLEEP(seconds,microseconds) do {struct timeval t; t.tv_sec = seconds;\
t.tv_usec = microseconds; select(0, NULL, NULL, NULL, &t);} while(0)
#endif /* _POSIX_C_SOURCE >= 199309L */
#endif
Определите команду создания посткодов.
function myXCPTargetPostCodeGenCommand(buildInfo) buildInfo.addDefines('-DXCP_CUSTOM_PLATFORM', 'OPTS'); % Configure the default memory allocator buildInfo.addDefines('-DXCP_MEM_BLOCK_1_SIZE=64', 'OPTS'); buildInfo.addDefines('-DXCP_MEM_BLOCK_1_NUMBER=46', 'OPTS'); buildInfo.addDefines('-DXCP_MEM_BLOCK_2_SIZE=256', 'OPTS'); buildInfo.addDefines('-DXCP_MEM_BLOCK_2_NUMBER=10', 'OPTS'); % Add my rtiostream buildInfo.addSourceFiles(customRtIOStreamFileName, ... customRtIOStreamSrcPath); % If the target hardware does not support parsing of command % line arguments buildInfo.addDefines('-DEXTMODE_DISABLE_ARGS_PROCESSING', 'OPTS'); end
extmodeBackgroundRun | extmodeEvent | extmodeGetFinalSimulationTime | extmodeInit | extmodeParseArgs | extmodeReset | extmodeSetFinalSimulationTime | extmodeSimulationComplete | extmodeStopRequested | extmodeWaitForHostRequest