В этом примере показано, как симулировать и сгенерировать код для асинхронных событий в многозадачной системе реального времени.
Откройте пример модели rtwdemo_async_mdlreftop
.
open_system('rtwdemo_async_mdlreftop');
Модель описывает источник прерывания и включает в себя Async Interrupt
блочная и ссылочная модель. The Async Interrupt
блок создает две служебные стандартные программы прерывания (ISR) Versa Module Eurocard (VME), которые передают сигналы прерывания в блоки Inport 1 и 2 ссылочных моделей.
Можно разместить Async Interrupt
блок между моделируемым источником прерывания и одним из следующих элементов модели:
Подсистема вызова функции
Task Sync
блок
Диаграмма Stateflow, сконфигурированная для входного события вызова функции
Ссылка на модель с Inport
блок, который соединяется с одним из предыдущих элементов модели
В этой модели примера Async Interrupt
блок передает асинхронные события (триггерные сигналы вызова функции), Interrupt1
и Interrupt2
, на ссылку модели через Inport
блоки 1 и 2.
Генератор кода производит код, адаптированный для операционной системы VxWorks. Перенастройте Async Interrupt
блок для генерации кода для альтернативного окружения во время выполнения приложения.
Откройте ссылочную модель. Ссылочная модель включает два Inport
блоки, которые получают прерывания, каждый соединяется с Asynchronous Task Specification
блок, подсистемы вызова функций счетчик и алгоритм, и Rate Transition
блоки. The Asynchronous Task Specification
блок, в комбинации с корневым уровнем Inport
блок, позволяет образцу модели принимать асинхронные входы вызова функции. Чтобы использовать блок:
Соедините Asynchronous Task Specification
блок к выходному порту корневого уровня Inport
блок, который выводит триггер вызова функции.
Выберите параметр выходная функция call для Inport
блок, чтобы указать, что он принимает сигналы вызова функции.
В диалоговом окне параметров для Asynchronous Task Specification
блок, установите приоритет задачи для асинхронной задачи, связанной со Inport
блок. Задайте целое число или []. Если вы задаете целое число, оно должно совпадать с приоритетом прерывания, инициируемого Async Interrupt
блок в родительской модели. Если вы задаете [], приоритеты не должны совпадать.
The Asynchronous Task Specification
блок для прерывания с более высоким приоритетом, interrupt1
, соединяйтесь с подсистемой вызова функций Count
. Count
представляет простую стандартную программу обработки прерывания (ISR). Вторая Asynchronous Task Specification
блочное соединение с подсистемой Algorithm
, который включает больше вещества. Он включает несколько блоков и создает два выходных значения. Обе подсистемы выполняются на уровне прерывания.
Для каждого уровня прерывания, заданного для Async Interrupt
блок в родительской модели, блок генерирует VME ISR, который выполняет подключенную подсистему, Task Sync
блок, или график.
В примере верхней модели Async Interrupt
блок сконфигурирован для прерываний 1 и 2 VME, с помощью смещений векторов прерывания 192 и 193. Прерывание 1 подключено для запуска подсистемы Count
. Прерывание 2 подключено для запуска подсистемы Algorithm
.
The Rate Transition
блоки обрабатывают передачу данных между портами, которые работают с различными скоростями. В двух образцах блоки защищают передачу данных (препятствуют их упреждению и повреждению). В другом образце специального поведения не происходит.
Передача данных происходит между одной задачей чтения и одной задачей записи.
Операция чтения или записи переменной размером в байт является атомарной.
Когда две задачи взаимодействуют, только одна может превентировать другую.
Для периодических задач задача с более высокой частотой имеет более высокий приоритет, чем задача с более низкой частотой. Задача с более высокой скоростью прерывает задачи с более медленными скоростями.
Задачи выполняются на одном процессоре. Квантование времени не разрешено.
Процессы не завершаются и не перезапускаются, особенно в то время как данные передаются между задачами.
Симулируйте модель. По умолчанию модель сконфигурирована так, чтобы показывать шаги расчета в разных цветах. Дискретные шаги расчета для входа и выхода выглядят красным и зеленым, соответственно. Константы пурпурные. Асинхронные прерывания фиолетовые. The Rate Transition
блоки, которые являются гибридными (вход и выход шагов расчета могут отличаться), выглядят желтыми.
Сгенерируйте код и отчет о генерации кода для модели. Async Interrupt
блок и Task Sync
Сгенерированный код блока предназначен для примера RTOS (VxWorks). Однако можно изменить блоки, чтобы сгенерировать код для другого окружения во время выполнения.
1. Создайте временную папку для процесса сборки и проверки.
currentDir = pwd; [~,cgDir] = rtwdemodir();
2. Создайте модель.
slbuild('rtwdemo_async_mdlreftop');
### Starting serial model reference code generation build
Warning: Simulink Coder: The tornado.tlc target will be removed in a future release.
### Successfully updated the model reference code generation target for: rtwdemo_async_mdlrefbot ### Starting build procedure for: rtwdemo_async_mdlreftop
Warning: Simulink Coder: The tornado.tlc target will be removed in a future release.
### Successful completion of code generation for: rtwdemo_async_mdlreftop Build Summary Code generation targets built: Model Action Rebuild Reason ==================================================================================== rtwdemo_async_mdlrefbot Code generated rtwdemo_async_mdlrefbot.c does not exist. Top model targets built: Model Action Rebuild Reason =========================================================================================== rtwdemo_async_mdlreftop Code generated Code generation information file does not exist. 2 of 2 models built (0 models already up to date) Build duration: 0h 0m 39.589s
Откройте сгенерированный исходный файл rtwdemo_async_mdlreftop.c
. Код инициализации соединяет и включает ISR isr_num1_vec192
для прерывания 1 и ISR isr_num2_vec193
для прерывания 2.
cfile = fullfile(cgDir, 'rtwdemo_async_mdlreftop_tornado_rtw', 'rtwdemo_async_mdlreftop.c'); rtwdemodbtype(cfile, ... 'static void rtwdemo_async_mdlreftop_initialize(void)', ... '/* Model terminate function */', ... 1, 0);
static void rtwdemo_async_mdlreftop_initialize(void) { /* Start for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Connect and enable ISR function: isr_num1_vec192 */ if (intConnect(INUM_TO_IVEC(192), isr_num1_vec192, 0) != OK) { printf("intConnect failed for ISR 1.\n"); } sysIntEnable(1); /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Connect and enable ISR function: isr_num2_vec193 */ if (intConnect(INUM_TO_IVEC(193), isr_num2_vec193, 0) != OK) { printf("intConnect failed for ISR 2.\n"); } sysIntEnable(2); /* End of Start for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* SystemInitialize for ModelReference: '<Root>/Model' incorporates: * Inport: '<Root>/In1_60hz' * Inport: '<Root>/In2_60_hz' * Inport: '<Root>/In3_60hz' * Outport: '<Root>/Out1' * Outport: '<Root>/Out2' * Outport: '<Root>/Out3' */ rtwdemo_async_mdlrefbot_Init(&rtwdemo_async_mdlreftop_Y.Out1); rtwdemo_async_mdlrefbot_Enable(); }
В сгенерированном исходном файле rtwdemo_async_mdlreftop.c
, проверьте код для ISRs isr_num1_vec192
и isr_num2_vec293
. Каждый ISR:
Отключает прерывания.
Сохраняет контекст с плавающей точкой.
Вызывает код, сгенерированный для подсистемы, подключенной к ссылочной модели Inport
блок, который получает прерывание.
Восстанавливает контекст с плавающей точкой.
Снова включает прерывания.
cfile = fullfile(cgDir, 'rtwdemo_async_mdlreftop_tornado_rtw', 'rtwdemo_async_mdlreftop.c'); rtwdemodbtype(cfile, ... 'void isr_num1_vec192(void)', ... 'time_T rt_SimUpdateDiscreteEvents', ... 1, 0);
void isr_num1_vec192(void) { int_T lock; FP_CONTEXT context; /* disable interrupts (system is configured as non-preemptive) */ lock = intLock(); /* save floating point context */ fppSave(&context); /* Call the system: '<Root>/Model' */ { /* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* ModelReference: '<Root>/Model' incorporates: * Inport: '<Root>/In1_60hz' * Inport: '<Root>/In2_60_hz' * Inport: '<Root>/In3_60hz' * Outport: '<Root>/Out1' * Outport: '<Root>/Out2' * Outport: '<Root>/Out3' */ rtwdemo_async_mdlrefbot_Interrupt1(&rtwdemo_async_mdlreftop_Y.Out1); /* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ } /* restore floating point context */ fppRestore(&context); /* re-enable interrupts */ intUnlock(lock); } /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ void isr_num2_vec193(void) { FP_CONTEXT context; /* save floating point context */ fppSave(&context); /* Call the system: '<Root>/Model' */ { /* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* ModelReference: '<Root>/Model' incorporates: * Inport: '<Root>/In1_60hz' * Inport: '<Root>/In2_60_hz' * Inport: '<Root>/In3_60hz' * Outport: '<Root>/Out1' * Outport: '<Root>/Out2' * Outport: '<Root>/Out3' */ rtwdemo_async_mdlrefbot_Interrupt2(); /* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ } /* restore floating point context */ fppRestore(&context); }
The Task Sync
блок генерирует следующий код завершения.
cfile = fullfile(cgDir, 'rtwdemo_async_mdlreftop_tornado_rtw', 'rtwdemo_async_mdlreftop.c'); rtwdemodbtype(cfile, ... 'static void rtwdemo_async_mdlreftop_terminate(void)', ... '/*========================================================================*', ... 1, 0);
static void rtwdemo_async_mdlreftop_terminate(void) { /* Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Disable interrupt for ISR system: isr_num1_vec192 */ sysIntDisable(1); /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Disable interrupt for ISR system: isr_num2_vec193 */ sysIntDisable(2); /* End of Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ }
bdclose('rtwdemo_async_mdlreftop');
rtwdemoclean;
cd(currentDir)