Этот пример показывает, как использовать Simulink Code Inspector, чтобы проверить, что код, сгенерированный из моделей, удовлетворяет цели исходного кода от DO - 178C, Факторы программного обеспечения в Бортовых Системах и Сертификации оборудования. Во-первых, код для иерархии модели автоматически сгенерирован Embedded Coder. Затем, сгенерированный код независимо проверяется Simulink Code Inspector. Наконец, ошибка намеренно введена в сгенерированный код и затем осмотрена для отказа.
Создайте временную папку (во временной папке вашей системы) для сборки и инспекционного процесса. Локально скопируйте модель slcidemo_roll_orig в sldemo_roll так, чтобы можно было изменить его.
currentDir = pwd; [tempDir, cgDir] = slcidemodir(); load_system('slcidemo_roll_orig') save_system('slcidemo_roll_orig', 'slcidemo_roll');
Эта модель представляет основной автопилот продольной оси с двумя рабочими режимами: прокрутитесь отношение содержат, и заголовок содержат. Логика режима для этих режимов является внешней к этой модели. Архитектура модели представляет заголовок, содержат режим и основную функцию отношения списка как модели, на которые ссылаются.
Функция управления ориентацией списком является ПИД-регулятором, который использует отношение списка и обратную связь уровня списка, чтобы произвести команду элерона. Вход контроллеру будет или основной ссылкой угла вращения или командой списка, чтобы отследить желаемый заголовок.
Рисунок 1 показывает верхний уровень модели Simulink.
open_system('slcidemo_roll');
Рисунок 1: схема верхнего уровня для модели автопилота продольной оси
Рисунок 2 показывает основное вычисление ссылки угла вращения, реализованное как виртуальную подсистему RollAngleReference. Embedded Coder встроит это вычисление непосредственно в основную функцию для slcidemo_roll.
open_system('slcidemo_roll/RollAngleReference');
Рисунок 2: Виртуальная подсистема RollAngleReference, реализующий ссылку угла вращения
Рисунок 3 показывает содержимое модели HeadingMode, которая вычисляет команду списка, чтобы отследить желаемый заголовок. Это - отдельная модель, на которую ссылается slcidemo_roll.
close_system('slcidemo_roll/RollAngleReference'); open_system('slcidemo_heading');
Рисунок 3: HeadingMode Модели, который вычисляет команду списка, чтобы отследить желаемый заголовок.
Рисунок 4 показывает содержимое модели BasicRollMode, которая вычисляет функцию управления ориентацией списком. Это - отдельная модель, на которую ссылается slcidemo_roll.
close_system('slcidemo_heading'); open_system('slcidemo_attitude');
Рисунок 4: Модель BasicRollMode, реализующий функцию управления ориентацией списком (ПИД)
Simulink Code Inspector поддерживает ограниченный набор моделирования семантики и оптимизации кода. Можно использовать его программу контроля совместимости, чтобы определить, выполняет ли модель тот ограниченный набор. Проверка совместимости и инспекция кода могут быть вызваны в интерактивном режиме от основного графического интерфейса пользователя Simulink Code Inspector. Этот пример иллюстрирует, как программно автоматизировать полный процесс генерации кода и контроль.
Чтобы включить инспекцию кода, параметр модели, AdvancedOptControl
должен быть установлен в значение '-SLCI'
на модели верхнего уровня, slcidemo_roll, который ограничивает набор оптимизации, которую использует Embedded Coder.
set_param('slcidemo_roll','AdvancedOptControl','-SLCI'); fprintf('\nInvoking compatibility checker ...\n'); config = slci.Configuration('slcidemo_roll'); result = config.checkCompatibility('DisplayResults','None'); for i = 1:numel(result) fprintf('\nModel ''%s'' passed %d checks with %d issues.',... result{i}.system,... result{i}.numPass, result{i}.numWarn + result{i}.numFail) end
Invoking compatibility checker ... Model 'slcidemo_roll' passed 46 checks with 0 issues.
Модель предварительно сконфигурирована, чтобы сгенерировать код с помощью Embedded Coder. Можно сгенерировать код неявно как часть инспекции кода, однако этот пример иллюстрирует, как разделить генерацию кода и инспекцию кода в отдельные шаги. Используйте метод setGenerateCode
, чтобы указать, что Simulink Code Inspector генерирует код до контроля.
rtwbuild('slcidemo_roll');
### Model reference code generation target (slcidemo_attitude.c) for model slcidemo_attitude is out of date because slcidemo_attitude.c does not exist. ### Starting build procedure for model: slcidemo_attitude ### Successful completion of code generation for model: slcidemo_attitude ### Model reference code generation target (slcidemo_heading.c) for model slcidemo_heading is out of date because slcidemo_heading.c does not exist. ### Starting build procedure for model: slcidemo_heading ### Successful completion of code generation for model: slcidemo_heading ### Starting build procedure for model: slcidemo_roll ### Successful completion of code generation for model: slcidemo_roll
Просмотрите сгенерированный код в подробном отчете HTML с двусторонней отслеживаемостью между моделью и кодом.
web(fullfile(cgDir,'slcidemo_roll_ert_rtw','html','slcidemo_roll_codegen_rpt.html'))
Инспекция кода независима от генерации кода. Теперь, сконфигурируйте модель, чтобы не регенерировать код для эталонных моделей.
set_param('slcidemo_roll','UpdateModelReferenceTargets','AssumeUpToDate'); save_system('slcidemo_roll')
Осмотрите сгенерированный код. По умолчанию Simulink Code Inspector принимает, что код был предварительно сгенерирован в папки по умолчанию, где Embedded Coder записывает свои файлы. Если вы хотите задать альтернативное местоположение, используйте методы setCodePlacement
и setCodeFolder
.
В этом примере используйте метод setReportFolder
, чтобы поместить отчеты инспекции кода в локальную папку отчета. setShowReport
метода задает, запускается ли отчет автоматически. Кроме того, укажите, что slcidemo_roll является моделью верхнего уровня.
config.setTopModel(true); config.setReportFolder(fullfile('.','report')); result = config.inspect('DisplayResults','None'); fprintf('Model %s status: %s\n',result.ModelName, result.Status);
recording macro in il recording macro in il Model slcidemo_roll status: PASSED
Этот пример приводит к переданному результату, как ожидалось, который разрабатывается в подробном отчете верификации.
web(fullfile('.', 'report','slcidemo_roll_report.html'));
Чтобы показать не пройдено результат, введите намеренную ошибку в сгенерированном коде. В этом примере измените блок Logical Operator в подсистеме RollAngleReference, рисунке 5, в сгенерированном коде от операции OR () к операции И (&&). Используйте функцию slcidemo_modifycode.
% Highlight the block for which the code will be modified hilite_system('slcidemo_roll/RollAngleReference/Or'); % Modify the generated code using a helper function (change || to &&) cfile = fullfile(cgDir,'slcidemo_roll_ert_rtw','slcidemo_roll.c'); slcidemo_modifycode(cfile,'<S1>/Or','||','&&')
Modified line 52 of file /tmp/slcidemo/slcidemo_roll_ert_rtw/slcidemo_roll.c. Before: if ((rtU_Phi >= 6.0F) || (rtU_Phi <= -6.0F)) { After : if ((rtU_Phi >= 6.0F) && (rtU_Phi <= -6.0F)) {
Рисунок 5: Блокируйтесь, для которого код изменяется, чтобы произвести ожидаемую погрешность
Инспекции кода не удается проверить, потому что код больше не совпадает с моделью.
result = config.inspect('DisplayResults','None'); fprintf('Model %s status: %s\n',result.ModelName, result.Status);
recording macro in il recording macro in il Model slcidemo_roll status: FAILED
Отказ ожидается. См. подробный отчет верификации.
[~,h,~]=web(fullfile('.','report','slcidemo_roll_report.html'));
Попробуйте подобное осуществление путем изменения модели или других аспектов сгенерированного кода.
Закройте модели и удалите временные директории и файлы.
close_system('slcidemo_roll_orig',0) close_system('slcidemo_roll',0) close_system('slcidemo_attitude',0) close_system('slcidemo_heading',0) close(h) cd(currentDir); rmdir(tempDir,'s');