exponenta event banner

Создание целевого канала связи для моделирования процессора в петле (PIL)

Реализация канала связи для моделирования процессора в контуре (PIL).

Канал связи обеспечивает обмен данными между различными процессами. Канал связи поддерживает возможности, требующие обмена данными между программной средой Simulink ®, работающей на компьютере разработки (хосте), и развернутым кодом, работающим на целевом оборудовании. Например, моделирование PIL.

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

Два объекта, станция A и станция B, используют интерфейс rtiostream для настройки канала связи и обмена данными. В этом примере станция A и станция B настраиваются в одном и том же процессе на настольном компьютере.

Целевые драйверы подключения поддерживают моделирование PIL на цели. При моделировании станция A и станция B представляют целевой и хост-компьютеры, которые обмениваются данными через канал связи. На стороне хоста целевой драйвер подключения реализован как общая библиотека, которая загружается и вызывается из продукта MATLAB ®. На стороне назначения драйвер представляет собой исходный код или библиотеку, связанную с приложением, которое выполняется на цели.

Кроме того, можно:

  • Настройте собственный драйвер на стороне назначения для TCP/IP для работы с драйвером TCP/IP на стороне хоста по умолчанию.

  • Настройте предоставленный драйвер на стороне хоста для последовательной связи.

  • Реализуйте пользовательские драйверы целевого подключения, например, используя CAN или USB для главной и целевой сторон канала связи.

См. также раздел Тестирование сгенерированного кода с моделированием SIL и PIL и конфигурирование процессора в цикле (PIL) для пользовательского целевого объекта.

Просмотр исходного кода для реализации TCP/IP по умолчанию

Файловая rtiostream_tcpip.c реализует связь TCP/IP на стороне клиента и сервера. Параметр запуска настраивает драйвер для работы в режиме клиента или сервера. Этот исходный файл можно использовать в качестве отправной точки для пользовательской реализации. Для каждой стороны канала связи требуется только одна или другая из реализаций сервера или клиента. Если драйверы клиента и сервера работают на различных архитектурах, рекомендуется поместить код драйвера для каждой архитектуры в отдельный исходный файл.

Файл заголовка rtiostream.h содержит прототипы для функций rtIOStreamOpen/Send/Recv/Close. Включите его (используя # include) для пользовательских реализаций.

Извлеките расположение исходного кода драйвера TCP/IP.

rtiostreamtcpip_dir=fullfile(matlabroot,'toolbox','coder','rtiostream','src',...
                              'rtiostreamtcpip');

Просмотреть rtiostream_tcpip.c.

edit(fullfile(rtiostreamtcpip_dir,'rtiostream_tcpip.c'));

Просмотреть файл rtiostream.h.

edit(fullfile(matlabroot,'rtw','c','src','rtiostream.h'));

Расположение файлов общей библиотеки

Чтобы получить доступ к целевым драйверам подключения из продукта MATLAB, необходимо скомпилировать их в общую библиотеку. Общая библиотека должна находиться в системном пути. Общая библиотека для драйверов TCP/IP по умолчанию находится в matlabroot/bin/$ ARCH ($ ARCH - архитектура системы, например win64).

Расширение и расположение файла общей библиотеки зависит от операционной системы.

[~, ~, sharedLibExt] = coder.BuildConfig.getStdLibInfo;

Определите общую библиотеку для станции A и станции B.

libTcpip = ['libmwrtiostreamtcpip' sharedLibExt];
disp(libTcpip)
libmwrtiostreamtcpip.dll

Тестирование драйверов целевого подключения

При реализации пользовательского целевого драйвера подключения рекомендуется тестировать его из продукта MATLAB. В следующем примере показано, как загрузить драйверы целевого подключения TCP/IP по умолчанию и использовать их для обмена данными между станцией A и станцией B.

Для доступа к драйверам можно использовать rtiostream_wrapper MEX-файла. С помощью этого MEX-файла можно загрузить общую библиотеку и получить доступ к функциям rtiostream, чтобы открыть и закрыть канал rtiostream, а также отправить и получить данные.

Станции A и B выполняются на хост-компьютере. Станция A сконфигурирована как сервер TCP/IP, а станция B - как клиент TCP/IP. Как правило, для связи между хостами и целевыми узлами хост конфигурируется как клиент TCP/IP, а целевой сервер - как сервер TCP/IP.

Выберите номер порта для TCP.

if usejava('jvm')
    % Find a free port
    tempSocket = java.net.ServerSocket(0);
    port = num2str(tempSocket.getLocalPort);
    tempSocket.close;
else
    % Use a hard-coded port
    port = '14646';
end

Откройте rtiostream Station A в качестве сервера TCP/IP.

stationA = rtiostream_wrapper(libTcpip,'open',...
                                 '-client', '0',...
                                 '-blocking', '0',...
                                 '-port',port);

Если канал связи открывается, то возвращаемое значение является дескриптором соединения. Возвращаемое значение -1 указывает на ошибку.

Проверьте возвращаемое значение.

assert(stationA~=(-1))

Откройте rtiostream Station B в качестве клиента TCP/IP.

stationB = rtiostream_wrapper(libTcpip,'open',...
                                 '-client','1',...
                                 '-blocking', '0',...
                                 '-port',port,...
                                 '-hostname','localhost');

Если канал связи открывается, то возвращаемое значение является дескриптором соединения. Возвращаемое значение -1 указывает на ошибку.

Проверьте возвращаемое значение.

assert(stationB~=(-1))

Передача данных со станции B на станцию A

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

Передача данных сообщения со станции B на станцию A.

msgOut = uint8('Station A, this is Station B. Are you there? OVER');

[retVal, sizeSent] = rtiostream_wrapper(libTcpip,...
                                       'send',...
                                       stationB,...
                                       msgOut,...
                                       length(msgOut));

Возвращаемое значение, равное нулю, указывает на успех.

assert(retVal==0);

Убедитесь, что байты в сообщении отправлены.

assert(sizeSent==length(msgOut));

Время завершения передачи данных.

pause(0.2)

Прием данных на станции A.

[retVal, msgRecvd, sizeRecvd] = rtiostream_wrapper(libTcpip,...
                                                 'recv',...
                                                 stationA,...
                                                 100);

Возвращаемое значение, равное нулю, указывает на успех.

assert(retVal==0);

Убедитесь, что байты в сообщении получены.

assert(sizeRecvd==sizeSent);

Просмотрите полученные данные.

disp(char(msgRecvd))
Station A, this is Station B. Are you there? OVER                                                   

Отправка ответа со станции A на станцию B

Передача данных ответа со станции A на станцию B.

msgOut = uint8('Station B, this is Station A. Yes, I''m here! OVER.');
[~, sizeSent] = rtiostream_wrapper(libTcpip,... %#ok
                                       'send',...
                                       stationA,...
                                       msgOut,...
                                       length(msgOut));

Время завершения передачи данных.

pause(0.2)

Прием данных на станции B.

[~, msgRecvd, sizeRecvd] = rtiostream_wrapper(libTcpip,... %#ok
                                                 'recv',...
                                                 stationB,...
                                                 100);

Просмотрите полученные данные.

disp(char(msgRecvd))
Station B, this is Station A. Yes, I'm here! OVER.                                                  

Закрытие соединения и выгрузка общих библиотек

Закрыть ртиострим на станции B.

retVal = rtiostream_wrapper(libTcpip,'close',stationB);

Возвращаемое значение, равное нулю, указывает на успех.

assert(retVal==0);

Закрыть ртиострим на станции А.

retVal = rtiostream_wrapper(libTcpip,'close',stationA);

Возвращаемое значение, равное нулю, указывает на успех.

assert(retVal==0)

Выгрузите общую библиотеку.

rtiostream_wrapper(libTcpip, 'unloadlibrary');

Драйвер на стороне хоста для последовательной связи

Предоставленный драйвер на стороне хоста можно использовать для последовательной связи в качестве альтернативы драйверам для TCP/IP. Сведения о настройке последовательного драйвера см. в разделе rtiostream_wrapper в справочной документации Embedded Coder ®.

Настройка собственного драйвера на стороне назначения

Если конечный объект имеет Ethernet-соединение и доступен стек TCP/IP, выполните следующие действия:

  1. Напишите обертку для стека TCP/IP, которая делает его доступным через интерфейс rtiostream, определенный в файле rtiostream.h.

  2. Напишите тестовое приложение для цели, которое отправляет и получает некоторые данные.

  3. Используйте rtiostream_wrapper MEX-файл и драйвер TCP/IP на стороне хоста для тестирования программного обеспечения драйвера, работающего на конечном объекте.

  4. При наличии рабочего драйвера на целевой стороне включите исходные файлы драйверов в сборку для автоматически создаваемого кода.

Драйвер на стороне назначения можно настроить на работу только как сервер TCP/IP, поскольку драйвер на стороне хоста по умолчанию для PIL настроен как клиент TCP/IP.

Если необходимо использовать канал связи, который еще не поддерживается на стороне хоста, запишите драйверы для хоста и цели. В этом случае вы по-прежнему можете использовать файл rtiostream_wrapper MEX для тестирования драйверов rtiostream.

Настройка собственного драйвера на стороне хоста

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

На стороне хоста можно протестировать драйверы с помощью файла rtiostream_wrapper MEX. Если драйвер включает диагностические выходные данные операторов printf и rtiostream_wrapper загружает общую библиотеку, необходимо заменить операторы printf операторами mexPrintf.

При наличии работающего драйвера устройства на стороне хоста его необходимо сделать доступным в программной среде Simulink. Для моделирования PIL зарегистрируйте общую библиотеку на стороне хоста через sl_customization.

Связанные темы