主要内容

设备驱动 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 使用 setupImplstepImplreleaseImpl 方法来定义设备驱动模块的代码初始化、引脚输出行为和代码终止。通过 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

另请参阅

|