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

Эта тема описывает, как реализовать асинхронные блоки для использования с вашим целевым RTOS, с помощью Асинхронных блоков Синхронизации Прерывания и Задачи в качестве отправной точки. Блоки Перехода уровня независимы от цели, таким образом, вы не должны разрабатывать настроенные блоки перехода уровня.

Примечание

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

О реализации асинхронных блоков

Можно настроить асинхронные блоки библиотеки путем изменения реализации блока. Эти файлы

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

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

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

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

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

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

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

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

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

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

C реализация блока MEX

Большая часть кода в 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.

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

Следующая выборка кода показывает вызов 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, не принимайте, что сигналы порта являются инвариантными. Для получения дополнительной информации ​ видят Встроенные Инвариантные Сигналы (Simulink Coder). Если блок не является инвариантным, ​ генератор кода производит код только в инициализировать функции точки входа. Если блок является инвариантным, ​ генератор кода не производит код для блока.

Реализация 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/devices. Они

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

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

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

C реализация блока MEX

Как блок Async Interrupt, блок Task Sync настраивает таймер, в этом случае с фиксированным разрешением. Приоритет задачи, сопоставленной с блоком, получен из параметра Simulink task priority. Настройки 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) задача, которая ожидает семафора. Когда это получает семафор, это обновляет таймер метки деления блока и вызывает нисходящий код подсистемы, как описано в Икре, и Синхронизируйте Выполнение Задачи RTOS. 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

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

Похожие темы