设备驱动 System object 的结构
设备驱动模块是一种专用形式的 MATLAB System 模块,当部署到基于 ARM® Cortex®-A 的硬件板时,它会生成自定义 C/C++ 代码。创建设备驱动模块使用户能够轻松访问硬件板的功能(如通信协议或硬件库),而这些功能在支持包中没有提供。
根据端口类型,Simulink® 设备驱动模块可以归属于两组之一:
源模块只有输出端口。在仿真中,源模块输出预先确定的信号。此信号可以从随机数生成器、存储数组或常量值创建。在代码生成后,源模块输出从该模块所表示的 I/O 设备捕获的数据。例如,Digital Read 模块的生成代码输出数字 I/O 引脚的逻辑状态。

信宿模块只有输入端口。在仿真中,信宿模块充当 Terminator 模块。在代码生成后,信宿模块根据输入端口信号设置和更新 I/O 设备。例如,Digital Write 模块的生成代码将数字 I/O 引脚的逻辑状态设置和更新为等于输入端口信号。

要定义设备驱动模块的行为,您需要使用 System object™。然后使用 MATLAB System 模块来引用该对象并将其包含在模型中。每个 System object 使用 setupImpl、stepImpl 和 releaseImpl 方法来定义设备驱动模块的代码初始化、引脚输出行为和代码终止。通过 stepImpl 中的条件语句,设备驱动模块在仿真模式下运行。此模式支持整个模型在主机上运行,无论是在测试时还是当您无法访问硬件板时。System object 还提供用于添加编译工件的服务。这些工件包括源文件、包含路径、共享库和预处理器定义,它们将被添加到 Simulink 生成的代码。这些工件自动定义模块的端口属性并生成模块封装。
类定义
在 System object 代码的顶部,定义您的 System object 的名称以及它从其继承的类。
classdef classname < matlab.System & coder.ExternalDependency & matlab.system.mixin.Propagates ... end
所有 System object 都必须继承自 matlab.System。此外,设备驱动 System object 继承自 coder.ExternalDependency,后者提供 API 以将编译工件添加到生成的代码。matlab.system.mixin.Propagates 类提供 API 以定义 System object 的输出大小、数据类型和复/实性。您可以从其他类继承,例如 matlab.system.mixin.CustomIcon。使用此类指定 MATLAB System 模块上显示的名称和图标。
构造函数方法
模板 System object 类(在创建 Digital Write 模块和创建 Digital Read 模块指南中使用)使用标准构造函数方法:
methods % Constructor function obj = classname(varargin) coder.allowpcode('plain'); setProperties(obj,nargin,varargin); end ... end
初始化方法、输出方法和终止方法
这些方法定义在初始化、输出和终止时发生的情况。使用 setupImpl 初始化硬件外设。使用 stepImpl 对硬件外设进行读取或写入。使用 releaseImpl 释放所使用的硬件资源。这三个方法是定义设备驱动模块行为的基础方法。
methods (Access=protected) function setupImpl(obj) % Implement tasks that need to be performed only once end function stepImpl(obj,u) % Device driver output end function releaseImpl(obj) % Termination code end end
输入和输出信号属性
以下代码节定义模块的输入或输出数目以及数据类型和大小。例如,信宿模块中的 getNumInputsImpl 方法设置输入端口数量。同样,源模块中的 getNumOutputsImpl 方法设置输出端口数量。
methods (Access=protected) % Simulink functions function isInputSizeMutableImpl(~,~) flag = false; end ... function num = getNumInputsImpl(~) num = 1; end function num = getNumOutputsImpl(~) num = 0; end end
编译工件
编译工件定义编译设备驱动代码所需的源文件位置、包含路径、共享库、库搜索路径和预处理器定义。使用 getDescriptiveName 方法定义 System object 的标识字符串。代码生成引擎使用此字符串来报告错误。使用 isSupportedContext 方法指定代码生成上下文。在设备驱动模块中,仅 Real-Time Workshop (rtw) 代码生成上下文适用,因此此函数始终指定 'rtw'。使用 updateBuildInfo 方法指定编译 System object 所需的源文件和头文件、包含路径、库和定义。
methods (Static)
function name = getDescriptiveName()
name = 'decriptive name';
end
function tf = isSupportedContext(context)
tf = context.isCodeGenTarget('rtw');
end
function updateBuildInfo(buildInfo, context)
if context.isCodeGenTarget('rtw')
% Update buildinfo
srcDir = fullfile(fileparts(mfilename('fullpath')),'src'); %#ok<NASU>
includeDir = fullfile(fileparts(mfilename('fullpath')),'include');
addIncludePaths(buildInfo,includeDir);
% Use the following API's to add include files, sources and
% linker flags
%addIncludeFiles(buildInfo,'source.h',includeDir);
%addSourceFiles(buildInfo,'source.c',srcDir);
%addLinkFlags(buildInfo,{'-lSource'});
%addLinkObjects(buildInfo,'sourcelib.a',srcDir);
%addCompileFlags(buildInfo,{'-D_DEBUG=1'});
%addDefines(buildInfo,'MY_DEFINE_1')
end
end