Создайте пользовательскую асинхронную библиотеку

В этом разделе описывается, как реализовать асинхронные блоки для использования с целевой RTOS, используя блоки Async Interrupt и Task Sync в качестве начальной точки. Rate Transition блоки не зависят от цели, поэтому вам не нужно разрабатывать настраиваемые переходные блоки скорости.

Примечание

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

Сведения о реализации асинхронных блоков

Вы можете настроить асинхронные библиотечные блоки, изменив реализацию блока. Эти файлы являются

  • Базовая S-функция блока Файла MEX

  • Файлы TLC, которые код системы управления генерацию блока

В сложение необходимо изменить маски блоков, чтобы удалить ссылки, характерные для примера RTOS (VxWorks®) и включать параметры, требуемые вашей целевой RTOS.

Реализация пользовательских блоков является расширенной темой, требующей ознакомления с Simulink® Формат MEX S-функции и API, а также с Target Language Compiler (TLC). Эти темы рассматриваются в следующих документах:

В следующих разделах рассматриваются реализации C/C + + и TLC блоков асинхронной библиотеки, включая необходимые SimStruct макросы и функции в библиотеке асинхронной поддержки TLC (asynclib.tlc).

Реализация блока асинхронного прерывания

Исходные файлы для блока Async Interrupt расположены в matlabroot/ rtw/c/tornado/устройства (открыто):

  • vxinterrupt1.c: Файл MEX на C исходный код для использования в строение и симуляции

  • vxinterrupt1.tlc: Реализация TLC для использования в генерации кода

  • asynclib.tlc: библиотека функций поддержки TLC, вызываемая реализацией TLC блока. Вызовы библиотеки суммируются в библиотеке поддержки asynclib.tlc.

Реализация блоков MEX на C

Большая часть кода в vxinterrupt1.c выполняет обыкновенные функции, не связанные с асинхронной поддержкой (для примера, получения и валидации параметров из маски блока, маркировки параметров нетронутыми и передачи данных о параметре в model.rtw файл).

mdlInitializeSizes функция использует специальные SimStruct макросы и SS_OPTIONS настройки, которые требуются для асинхронных блоков, как описано ниже.

Обратите внимание, что следующие макросы нельзя вызвать раньше ssSetOutputPortWidth вызывается:

  • ssSetTimeSource

  • ssSetAsyncTimerAttributes

  • ssSetAsyncTimerResolutionEl

  • ssSetAsyncTimerDataType

  • ssSetAsyncTimerDataTypeEl

  • ssSetAsyncTaskPriorities

  • ssSetAsyncTaskPrioritiesEl

Если один из вышеуказанных макросов вызывается раньше ssSetOutputPortWidthпоявится следующее сообщение об ошибке:

SL_SfcnMustSpecifyPortWidthBfCallSomeMacro {  
S-function '%s' in '%<BLOCKFULLPATH>'
must set output port %d width using
ssSetOutputPortWidth before calling macro %s
 }

ssSetAsyncTimerAttributes.  ssSetAsyncTimerAttributes объявляет, что блок требует таймера, и устанавливает разрешение таймера, заданное для Timer resolution (seconds) параметров блоков.

Прототип функции

ssSetAsyncTimerAttributes(SimStruct *S, double res)

где

  • S является указателем Simstruct.

  • Значение Timer resolution (seconds) параметра устанавливается равным res.

Следующий фрагмент кода показывает вызов ssSetAsyncTimerAttributes.

/* Setup Async Timer attributes */
ssSetAsyncTimerAttributes(S,mxGetPr(TICK_RES)[0]);

ssSetAsyncTaskPriorities.  ssSetAsyncTaskPriorities устанавливает приоритет задачи Simulink для блоков, выполняемых на каждом уровне прерывания, как задано для параметров блоков Simulink task priority.

Прототип функции

ssSetAsyncTaskPriorities(SimStruct *S, int numISRs, 
                         int *priorityArray)

где

  • S является SimStruct указатель.

  • numISRs - количество прерываний, заданное для VME interrupt number(s) параметров блоков.

  • priorityarray - целочисленный массив, содержащий номера прерываний, заданные для параметров блоков VME interrupt number(s).

Следующий фрагмент кода показывает вызов на ssSetAsyncTaskPriorities:

/* Setup Async Task Priorities */
    priorityArray = malloc(numISRs*sizeof(int_T));
    for (i=0; i<numISRs; i++) {
        priorityArray[i] = (int_T)(mxGetPr(ISR_PRIORITIES)[i]);
    }
    ssSetAsyncTaskPriorities(S, numISRs, priorityArray); 
    free(priorityArray);
    priorityArray = NULL;
}

SS_OPTION настройки.  Выдержка из кода ниже показывает SS_OPTION настройки для vxinterrupt1.c. SS_OPTION_ASYNCHRONOUS_INTERRUPT должен использоваться, когда подсистема вызова функции присоединена к прерыванию. Для получения дополнительной информации см. документацию для SS_OPTION и SS_OPTION_ASYNCHRONOUS в matlabroot/ simulink/include/simstruc.h.

ssSetOptions( S, (SS_OPTION_EXCEPTION_FREE_CODE |
              SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME |
              SS_OPTION_ASYNCHRONOUS_INTERRUPT |

Если S-функция задает SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME опция и наследует шаг расчета Infгенератор кода определяет, как создать код для блока, исходя из того, является ли блок инвариантным. Блок инвариантен, если его портовые сигналы инвариантны. Сигнал инвариантен, если он имеет постоянное значение в течение всей симуляции. Если вы задаете Constant шаг расчета блока, не принимайте, что сигналы порта инвариантны. Для получения дополнительной информации см. «Входные инвариантные сигналы». Если блок не инвариантен, генератор кода производит код только в функции initialize entry-point. Если блок инвариантен, генератор кода не производит код для блока.

Реализация TLC

В этом разделе рассматриваются каждая функция vxinterrupt1.tlc, с акцентом на специфические для цели функции, которые вам нужно будет изменить, чтобы сгенерировать код для вашего целевого RTOS.

Сгенерируйте директивы # include . vxinterrupt1.tlc начинается с оператора

%include "vxlib.tlc"

vxlib.tlc является целевым файлом, который генерирует директивы для включения заголовочных файлов для примера RTOS (VxWorks). Вы должны заменить это файлом, который генерирует включает для вашего целевого RTOS.

Функция BlockInstanceSetup.  Для каждого подключенного выхода блока Async Interrupt, BlockInstanceSetup определяет имя функции для соответствующего ISR в сгенерированном коде. Имена функций имеют вид

isr_num_vec_offset

где num - номер ISR, заданный для параметров блоков VME interrupt number(s) и offset - смещение таблицы прерывания, заданные параметры блоков VME interrupt vector offset(s).

В пользовательской реализации это соглашение об именовании является необязательным.

Эти имена функции кэшируются для использования Outputs функция, которая генерирует фактический код ISR.

Выходы.  Outputs итерация по подключенным выходам блока Async Interrupt. ISR генерируется для каждого такого выхода.

Код ISR кэшируется в "Functions" раздел сгенерированного кода. Перед генерацией ISR, Outputs делает следующее:

  • Генерирует вызов нисходящего блока (кэшируется во временном буфере).

  • Определяет, должен ли ISR быть заблокирован или нет (как задано параметрами блоков Preemption Flag(s)).

  • Определяет, является ли блок, соединенный с блоком Async Interrupt, блоком Task Sync. (Эта информация получена при помощи asynclib вызовы LibGetFcnCallBlock и LibGetBlockAttribute.) Если да,

    • Флаг упреждения для ISR должен быть установлен на 1. Ошибка приводит к обратному.

    • Вызовы RTOS (VxWorks) для сохранения и восстановления контекста с плавающей точкой генерируются, если только пользователь не сконфигурировал модель только для генерации кода с целым числом.

При генерации кода ISR, Outputs вызывает asynclib функция LibNeedAsyncCounter для определения, требуется ли таймер для подключенной подсистемы. Если да, и если источник времени установлен в SS_TIMESOURCE_SELF около ssSetTimeSource, LibSetAsyncCounter вызывается для генерации RTOS (VxWorks) tickGet вызов функции и обновление счетчика. В вашей реализации необходимо сгенерировать либо эквивалентный вызов целевой RTOS, либо сгенерировать код для чтения регистра таймера на целевом компьютере.

Запуск функции.   Start функция генерирует необходимые вызовы RTOS (VxWorks) (int_connect и sysInt_Enable) для подключения и включения каждого ISR. Необходимо заменить это вызовами целевой RTOS.

Оконечная функция.   Terminate функция генерирует вызов sysIntDisable отключение каждого ISR. Необходимо заменить это вызовами целевой RTOS.

Реализация блока синхронизации задач

Исходные файлы для блока Task Sync расположены в matlabroot/ rtw/c/tornado/устройства (откройте). Они есть

  • vxtask1.cpp: Исходный код файла MEX, для использования в строении и симуляции.

  • vxtask1.tlc: Реализация TLC для использования в генерации кода.

  • asynclib.tlc: библиотека функций поддержки TLC, вызываемая реализацией TLC блока. Вызовы библиотеки суммируются в библиотеке поддержки asynclib.tlc.

Реализация блоков MEX на C

Как и блок Async Interrupt, блок Task Sync настраивает таймер, в этом случае с фиксированным разрешением. Приоритет задачи, связанной с блоком, получен из параметров блоков Simulink task priority. The SS_OPTION настройки те же, что и для блока Async Interrupt.

ssSetAsyncTimerAttributes(S, 0.01);

priority  = (int_T) (*(mxGetPr(PRIORITY)));
ssSetAsyncTaskPriorities(S,1,&priority);

ssSetOptions(S, (SS_OPTION_EXCEPTION_FREE_CODE |
                 SS_OPTION_ASYNCHRONOUS |
                 SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME |
}

Реализация TLC

Сгенерируйте директивы # include . vxtask1.tlc начинается с оператора

%include "vxlib.tlc"

vxlib.tlc является целевым файлом, который генерирует директивы для включения заголовочных файлов для примера RTOS (VxWorks). Вы должны заменить это файлом, который генерирует включает для вашего целевого RTOS.

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

Запуск функции.   Start функция генерирует необходимые вызовы RTOS (VxWorks), чтобы задать хранилище для семафора, которое используется в управлении задачей, порожденной блоком Task Sync. В зависимости от значения CodeFormat Генерируется переменная TLC целевого устройства либо статическое объявление памяти, либо динамический вызов выделения памяти. Эта функция также создает семафор (semBCreate) и порождает задачу RTOS (taskSpawn). Необходимо заменить их вызовами целевой RTOS.

Выходы.   Outputs функция генерирует пример задачи RTOS (VxWorks), которая ожидает семафор. Когда он получает семафор, он обновляет таймер такта блока и вызывает дочерний подсистемный код, как описано в Spawn и Synchronize Execution of RTOS Task. Outputs также генерирует код (вызываемый с уровня прерывания), который предоставляет семафор.

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

Обратите внимание также, что, если целевой RTOS динамически выделил память, связанную с задачей, Terminate функция должна отменить выделение памяти.

Библиотека поддержки asynclib.tlc

asynclib.tlc - библиотека функций TLC, поддерживающих реализацию асинхронных блоков. Некоторые функции специально разработаны для использования в асинхронных блоках. Для примера, LibSetAsyncCounter генерирует вызов для обновления таймера для асинхронного блока. Другими функциями являются утилиты, которые возвращают информацию, требуемую асинхронными блоками (для примера, информацию о связанных подсистемах вызова функции).

В следующей таблице приведены общие вызовы в библиотеке. Для получения дополнительной информации смотрите исходный код библиотеки и vxinterrupt1.tlc и vxtask1.tlc файлы, которые вызывают функции библиотеки.

Сводные данные функций библиотеки asynclib.tlc

Функция

Описание

LibBlockExecuteFcnCall

Для использования встроенными S-функциями с выходами вызова функции. Генерирует код для выполнения подсистемы вызова функции.

LibGetBlockAttribute

Возвращает значение поля из блочной записи.

LibGetFcnCallBlock

Учитывая блок S-Function и индекс вызова, возвращает запись блока для подсистемы вызова нисходящей функции.

LibGetCallerClockTickCounter

Предоставляет доступ к счетчику времени для асинхронной задачи в восходящем направлении.

LibGetCallerClockTickCounterHighWord

Предоставляет доступ к высокому слову счетчика времени восходящей асинхронной задачи.

LibManageAsyncCounter

Определяет, нужен ли асинхронной задаче счетчик, и управляет собственным таймером.

LibNeedAsyncCounter

Если вызывающий блок требует асинхронного счетчика, возвращается TLC_TRUE, в противном случае возвращается TLC_FALSE.

LibSetAsyncClockTicks

Возвращает код, который устанавливает clockTick счетчики, которые должны поддерживаться асинхронной задачей.

LibSetAsyncCounter

Генерирует код, чтобы задать значение деления для асинхронного счетчика блока.

LibSetAsyncCounterHighWord

Генерирует код, чтобы задать значение деления высокого слова асинхронного счетчика блока

Похожие темы