Set Up PIL Connectivity by Using Target Framework
Before you can run processor-in-the-loop (PIL) simulations, you must set up connectivity between Simulink® and your target hardware. The connectivity enables the PIL simulation to:
Build the target application.
Download, start, and stop the application on the target hardware.
Support communication between Simulink and the target hardware.
Note
For Polyspace® Test™ C/C++ testing on target hardware, the same steps are required to set up a connection between Polyspace Test and the target hardware.
Use one of these workflows.
Workflow | When to use |
---|---|
target namespace with
rtiostream API | Use this workflow if your target application has large I/O requirements that need high-bandwidth communication. See Use rtiostream API for PIL Target Connectivity. You can specify a debugger. See Support PIL Debugging and DebugExecutionTool Template. |
target namespace with debugger | Use this workflow if:
See Use Debugger for PIL Target Connectivity and DebugIOTool Template. |
Use rtiostream
API for PIL Target Connectivity
To provide PIL connectivity between Simulink and the target hardware, you can use the target
Package
with the rtiostream API. In this example, your
development computer is the target hardware.
Create a
target.Board
object that provides MATLAB® with a description of your target hardware.hostTarget = target.create('Board', ... 'Name', 'Example Intel Board');
To support code generation and data I/O in PIL simulations, associate the object with processor, connection, and communication descriptions.
Associate the board with a processor
To support code generation, associate the board with a
target.Processor
object that contains a language implementation. For this example, create atarget.Processor
object and reuse an existingtarget.LanguageImplementation
object. For information about setting up a customtarget.LanguageImplementation
object, see Register New Hardware Devices.processor = target.create('Processor', 'Name', 'ExampleProcessor'); processor.LanguageImplementations = target.get('LanguageImplementation', ... 'Intel-x86-64 (Windows64)');
Associate the
target.Board
object with the newtarget.Processor
object by using theProcessors
propertyhostTarget.Processors = processor;
Specify execution information for the target hardware
Create an object that contains details about executing the target application. The object describes the tool that is required to run the target application on the target hardware. To capture system commands for starting and stopping the target application, you can use the
HostProcessExecutionTool
orSystemCommandExecutionTool
class.applicationExecution = target.create('HostProcessExecutionTool'); applicationExecution.Name = 'Windows Application';
Create a
Command
object for downloading and running the target application. Assign the string variable'$(EXE)'
to theString
property as a place holder for the target application name, which is not known until execution.runCommand = target.create('Command'); runCommand.String = '$(EXE)'; applicationExecution.StartCommand = runCommand; hostTarget.Tools.ExecutionTools = applicationExecution;
Create the communication interface for the target hardware
Create a
CommunicationInterface
object that provides the target hardware with details of the communication channel and the rtiostream API implementation.Use:
The shipped TCP/IP
rtiostream
implementation source file.A
BuildDependencies
object to specify, for thertiostream
API, the source files that are compiled with the target application.A
MainFunction
object to pass arguments to the target application
comms = target.create('CommunicationInterface'); comms.Name = 'Windows TCP Interface'; comms.Channel = 'TCPChannel'; comms.APIImplementations = target.create('APIImplementation', ... 'Name', 'x86 RTIOStream Implementation'); comms.APIImplementations.API = target.create('API', 'Name', 'RTIO Stream'); comms.APIImplementations.BuildDependencies = target.create('BuildDependencies'); comms.APIImplementations.BuildDependencies.SourceFiles = ... {fullfile('$(MATLAB_ROOT)', ... 'toolbox', ... 'coder', ... 'rtiostream', ... 'src', ... 'rtiostreamtcpip', ... 'rtiostream_tcpip.c')}; comms.APIImplementations.MainFunction = target.create('MainFunction', ... 'Name', 'TCP RtIOStream Main'); comms.APIImplementations.MainFunction.Arguments = {'-blocking', '1', '-port', '0'}; hostTarget.CommunicationInterfaces = comms;
Specify PIL protocol information
This step is optional. A PIL simulation uses a communication protocol for the transfer of data between Simulink and the target hardware. The
target.PILProtocol
class describes the parameters of the protocol. For this example, you can improve target run-time performance by increasing the I/O buffer size that the protocol uses.Create a
target.PILProtocol
object and specify I/O buffer size.pilProtocol = target.create('PILProtocol'); pilProtocol.Name = 'Windows PIL Protocol'; pilProtocol.SendBufferSize = 50000; pilProtocol.ReceiveBufferSize = 50000; hostTarget.CommunicationProtocolStacks = pilProtocol;
If you do not perform this step, default
target.PILProtocol
values are used.You can configure a PIL simulation to produce execution-time profiles for the generated code. To support code execution profiling, you must create a timer object that describes the retrieval of current time from generated code running on the target hardware. The timer object description must include a description of the function that retrieves time and its implementation.
This example uses a C function,
timestamp_x86
, which returns the current time as auint64
data type.timerSignature = target.create('Function'); timerSignature.Name = 'timestamp_x86'; timerSignature.ReturnType = 'uint64';
Capture the function in an API object.
timerApi = target.create('API'); timerApi.Functions = timerSignature; timerApi.Language = target.Language.C; timerApi.Name = 'Windows Timer API';
Capture the dependencies of the function, that is, the source and header files that are required to run the function.
timerDependencies = target.create('BuildDependencies'); timerDependencies.IncludeFiles = {'host_timer_x86.h'}; timerDependencies.IncludePaths = {'$(MATLAB_ROOT)/toolbox/coder/profile/src'}; timerDependencies.SourceFiles = {'host_timer_x86.c'};
Create an object that combines the API and dependencies.
timerImplementation = target.create('APIImplementation'); timerImplementation.API = timerApi; timerImplementation.BuildDependencies = timerDependencies; timerImplementation.Name = 'Windows Timer Implementation';
Create the timer object and associate it with the timer information.
timer = target.create('Timer'); timer.APIImplementation = timerImplementation; timer.Name = 'Windows Timer';
Assign the timer to the processor object.
processor.Timers = timer;
Specify connection between development computer and target hardware
The previous steps created target hardware support for communications and running the target application. Now, set up a connection between your development computer and the target hardware by creating a
TargetConnection
object. Specify:The communication channel, which is the same channel specified in the target hardware communication interface –– see step 4.
The connection properties.
The target, which is the board description specified in previous steps.
connection = target.create('TargetConnection'); connection.Name = 'Host Process Connection'; connection.Target = hostTarget; connection.CommunicationChannel = target.create('TCPChannel'); connection.CommunicationChannel.Name = 'External Process TCPCommunicationChannel'; connection.CommunicationChannel.IPAddress = 'localhost'; connection.CommunicationChannel.Port = '0';
Make board and connection objects persist across MATLAB sessions
To register the connectivity in MATLAB, add the target hardware and connection information to an internal database by using the
target.add
function. By default, the information is only available for the current MATLAB session. To make the registration persist across MATLAB sessions, specify the name-value pair'UserInstall', true
.target.add([hostTarget connection], 'UserInstall', true);
You can now specify your development computer as the target hardware for PIL simulations. Before you run a PIL simulation, in the Configuration Parameters dialog box, set Hardware board to
Example Intel Board
.
Support PIL Debugging
The workflow in Use rtiostream API for PIL Target Connectivity provides PIL connectivity between Simulink and the target hardware. To also support PIL debugging, implement the following steps after or instead of step 3 (Specify execution information for the target hardware):
Describe the debugger execution service implementation
Create a
target.ExecutionService
object that references the debugger abstraction interface.debugExecutionTool = target.create('ExecutionService', ... 'Name', 'GDB Launch'); debugExecutionTool.APIImplementation = ... target.create('APIImplementation', ... 'Name', 'myServiceImplementation'); debugExecutionTool.APIImplementation.BuildDependencies = ... target.create('MATLABDependencies'); debugExecutionTool.APIImplementation.BuildDependencies.Classes = ... {'myImplementationClass'}; debugExecutionTool.APIImplementation.API = ... target.get('API', ... 'DebugExecutionTool');
Associate the debugger execution service with the board
Associate the
target.ExecutionService
object with thetarget.Board
object.hostTarget.Tools.DebugTools = debugExecutionTool;
DebugExecutionTool
Template
This section provides a pseudocode example of
target.DebugExecutionTool
debugger abstraction. Use a
target.DebugExecutionTool
object to:
Control the lifetime of an application running in the debugger.
Automate applying breakpoints.
For interactions with the debugger, you can use MATLAB external language interfaces to APIs, which the debugger vendor supplies.
Section Descriptions for target.DebugExecutionTool
Debugger Abstraction Example
target.DebugExecutionTool Object | Comments |
---|---|
classdef DebugExecutionToolTemplate < target.DebugExecutionTool | Example implementation of
|
properties (Access=private)
DebuggerHandle;
end
| Optional. Add
any state required to interact
with the debugger or application being run in the debugger
as a property of |
methods | Method implementations that perform debugger
interactions. Each method returns a
|
function this = DebugExecutionToolTemplate() end | Optional. Constructor for the
Perform
basic initialization here. For example, setting state for
calls to |
function errFlag = open(this) this.DebuggerHandle = this.callExternalDebugger('open'); errFlag = false; end | Optional. Add logic here to open the debugger. Typically, use system commands or the external API provided by the debugger. If you cannot open the
debugger without also loading the application into the
debugger, do not implement this method. Use the
If you cannot open the debugger
without also starting execution of the application, do not
implement this method. Use the
|
function errFlag = loadApplication(this) this.callExternalDebugger('load application', ... this.Application, .... this.ApplicationCommandLineArguments); this.callExternalDebugger('set breakpoints', this.Breakpoints); errFlag = false; end | Optional. Load the application into the debugger. Add logic here to load the application into the debugger. For example, load a project into an IDE debugger or load the application executable file into the debugger harness. Also add logic to set breakpoints in the debugger to break execution. The path to the application file is
stored in the Additional
command line arguments for the application are stored in
Breakpoints
to set are stored in
If you
cannot load the application without also starting execution
of the application, do not implement this method. Implement
the logic in the |
function errFlag = startApplication(this) this.callExternalDebugger('start application'); errFlag = false; end | Required. Start the application execution in the debugger. Add logic here to start the application execution in the debugger. The path
to the application to load is stored in the
Additional
command line arguments to pass to the application are stored
in
Breakpoints
to set are stored in
|
function errFlag = stopApplication(this) this.callExternalDebugger('stop application'); errFlag = false; end | Optional. Stop the application execution in the debugger. Add logic here to stop the application execution in the debugger. If your
If your
|
function errFlag = unloadApplication(this) this.callExternalDebugger('unload application'); errFlag = false; end | Optional. Unloads the application from the debugger. If you implemented the
If your
|
function errFlag = close(this) this.callExternalDebugger('close'); errFlag = false; end | Optional. Closes the debugger. Add logic here to close the debugger.
If you implemented the |
end |
|
methods (Access=private) function output = callExternalDebugger(~, varargin) output = []; fprintf("\nInstructed the debugger to '%s'\n", varargin{1}); if nargin > 2 disp('Using arguments:'); disp(varargin(2:end)); end end end | Private methods. |
end |
|
Pseudocode for target.DebugExecutionTool
Debugger
Abstraction Example
classdef DebugExecutionToolTemplate < target.DebugExecutionTool % DEBUGEXECUTIONTOOLTEMPLATE Example implementation of target.DebugExecutionTool % debugger abstraction. % Copyright 2023 The MathWorks, Inc. properties (Access=private) % Optional % Add any state required to interact with the debugger or % application being run in the debugger as a property of % DebugExecutionTool. Apply private access so that only this file % can access the state. % % For example, the state could be a handle to the debugger % application provided by the debugger external API. DebuggerHandle; end % Method implementations that perform debugger interactions. % Each method will return a 'errFlag' logical flag. If the method % executes, 'errFlag' is set to false. % Consider also using the MATLAB error method to report custom % error information. methods % Constructor for the target.DebugExecutionToolTemplate. The constructor % creates an instance of the tool allowing its methods to be called % on that instance. Optional. function this = DebugExecutionToolTemplate() % Basic initialization can be performed here. For example % setting state ready for calls to open end % Open the debugger. Optional. function errFlag = open(this) % Add logic here to open the debugger. Typically, use system % commands or the external API provided by the debugger. % % If you cannot open the debugger without also loading the % application into the debugger, this method should not be % implemented and the logic should be performed in the % 'loadApplication' method. % % If you cannot open the debugger without also starting % execution of the application, this method should not be % implemented and the logic should be performed in the % 'startApplication' method. this.DebuggerHandle = this.callExternalDebugger('open'); errFlag = false; end % Load the application into the debugger. Optional. function errFlag = loadApplication(this) % Add logic here to load the application into the debugger. % This could be loading a project into an IDE debugger or % loading the application executable into the debugger harness. % % Additionally add logic to set breakpoints in the debugger to % break execution. % % The path to the application to load is stored in the % Application property of this class which can be accessed % using this.Application in this method. % % Additional command line arguments to pass to the % application are stored in % this.ApplicationCommandLineArguments. % % Breakpoints to set are stored in this.Breakpoints % % If you cannot load the application without also starting % execution of the application, this method should not be % implemented and the logic should be performed in the % 'startApplication' method. this.callExternalDebugger('load application', ... this.Application, .... this.ApplicationCommandLineArguments); this.callExternalDebugger('set breakpoints', this.Breakpoints); errFlag = false; end % Start the application execution in the debugger. Required. function errFlag = startApplication(this) % Add logic here to start the application execution in the % debugger. % % The path to the application to load is stored in the % Application property of this class which can be accessed % using this.Application in this method. % % Additional command line arguments to pass to the % application are stored in % this.ApplicationCommandLineArguments. % % Breakpoints to set are stored in this.Breakpoints this.callExternalDebugger('start application'); errFlag = false; end % Stop the application execution in the debugger. Optional. function errFlag = stopApplication(this) % Add logic here to stop the application execution in the % debugger. % If your 'startApplication' method opened the debugger, % perform the opposite action here, i.e. close the % debugger. % % If your 'startApplication' method loaded the application, % perform the opposite action here, i.e. unload the % application from the debugger. this.callExternalDebugger('stop application'); errFlag = false; end % Unloads the application from the debugger. Optional. function errFlag = unloadApplication(this) % If you implemented the 'loadApplication' method, % then add logic here to unload the application from % the debugger. % If your 'loadApplication' method opened the debugger, % perform the opposite action here, i.e. close the % debugger. this.callExternalDebugger('unload application'); errFlag = false; end % Closes the debugger. Optional. function errFlag = close(this) % Add logic here to close the debugger. If you implemented the % 'open' method, you should implement this method. this.callExternalDebugger('close'); errFlag = false; end end methods (Access=private) function output = callExternalDebugger(~, varargin) output = []; fprintf("\nInstructed the debugger to '%s'\n", varargin{1}); if nargin > 2 disp('Using arguments:'); disp(varargin(2:end)); end end end end
Use Debugger for PIL Target Connectivity
To provide PIL connectivity between Simulink and the target hardware, you can use the target
Package
with a debugger, for example, the GNU® Debugger.
Implement the
target.DebugIOTool
debugger abstraction interfaceImplement the interface in a class called
myImplementationClass
. For an example pseudocode implementation, see DebugIOTool Template.classdef myImplementationClass < target.DebugIOTool properties (Access=private) … end methods … end methods (Access=private) … end end
Create
target.Board
object that provides MATLAB with a description of your target hardware.hostTarget = target.create('Board', ... 'Name', 'GDB Debug PIL IO');
Associate the board with a processor
To support code generation, associate the board with a
target.Processor
object that contains a language implementation. For this example, create atarget.Processor
object and reuse an existingtarget.LanguageImplementation
object. For information about setting up a customtarget.LanguageImplementation
object, see Register New Hardware Devices.hostTarget.Processors = target.get('Processor', ... 'Intel-x86-64 (Linux 64)');
Describe the debugger execution service implementation
Create a
target.ExecutionService
object that references the debugger abstraction interface.matlabExecution = target.create('ExecutionService', ... 'Name', 'GDB Launch'); matlabExecution.APIImplementation = ... target.create('APIImplementation', ... 'Name', 'myServiceImplementation'); matlabExecution.APIImplementation.BuildDependencies = ... target.create('MATLABDependencies'); matlabExecution.APIImplementation.BuildDependencies.Classes = ... {'myImplementationClass'}; matlabExecution.APIImplementation.API = ... target.get('API', ... 'DebugIOTool');
Associate debugger execution service with the board
Associate the
target.ExecutionService
object with thetarget.Board
object.hostTarget.Tools.DebugTools = matlabExecution;
Make board object persist across MATLAB sessions
Add the board object to an internal database and make the object persist across MATLAB sessions.
target.add(hostTarget, 'UserInstall', true);
Before you run a PIL simulation, in the Configuration Parameters dialog box, set Hardware board to
GDB Debug PIL IO
.
DebugIOTool
Template
This section provides a pseudocode example of
target.DebugIOTool
debugger abstraction. Use a
target.DebugIOTool
object to:
Control the lifetime of an application running in the debugger.
Automate common debugger actions. For example, applying breakpoints and continuing execution from a paused state.
Read and write to memory that the application uses.
For interactions with the debugger, you can use MATLAB external language interfaces to APIs, which the debugger vendor supplies.
Section Descriptions for target.DebugIOTool
Debugger
Abstraction Example
target.DebugIOTool Object | Comments |
---|---|
classdef DebugIOToolTemplate < target.DebugIOTool | Example implementation of
|
properties (Access=private)
DebuggerHandle;
end
| Optional. Add
any state required to interact
with the debugger or application being run in the debugger
as a property of |
methods | Method implementations that perform debugger
interactions. Each method returns a
|
function this = DebugIOToolTemplate() end | Optional. Constructor for the
Perform basic
initialization here. For example, setting state for calls to
|
function errFlag = open(this) this.DebuggerHandle = this.callExternalDebugger('open'); errFlag = false; end | Optional. Add logic here to open the debugger. Typically, use system commands or the external API provided by the debugger. If you cannot open the
debugger without also loading the application into the
debugger, do not implement this method. Use the
If you cannot open the debugger
without also starting execution of the application, do not
implement this method. Use the
|
function errFlag = loadApplication(this) this.callExternalDebugger('load application', ... this.Application, .... this.ApplicationCommandLineArguments); this.callExternalDebugger('set breakpoints', this.Breakpoints); errFlag = false; end | Optional. Load the application into the debugger. Add logic here to load the application into the debugger. For example, load a project into an IDE debugger or load the application executable file into the debugger harness. Also add logic to set breakpoints in the debugger to break execution. The path to the application file is
stored in the Additional
command line arguments for the application are stored in
Breakpoints
to set are stored in
If you
cannot load the application without also starting execution
of the application, do not implement this method. Implement
the logic in the |
function errFlag = startApplication(this) this.callExternalDebugger('start application'); errFlag = false; end | Required. Start the application execution in the debugger. Add logic here to start the application execution in the debugger. The path
to the application to load is stored in the
Additional
command line arguments to pass to the application are stored
in
Breakpoints
to set are stored in
|
function errFlag = stopApplication(this) this.callExternalDebugger('stop application'); errFlag = false; end | Optional. Stop the application execution in the debugger. Add logic here to stop the application execution in the debugger. If your
If your
|
function errFlag = unloadApplication(this) this.callExternalDebugger('unload application'); errFlag = false; end | Optional. Unloads the application from the debugger. If you implemented the
If your
|
function errFlag = close(this) this.callExternalDebugger('close'); errFlag = false; end | Optional. Closes the debugger. Add logic here to close the debugger.
If you implemented the |
function [atBreakpoint, errFlag] = ... stoppedAtBreakpoint(this, breakpoint) result = this.callExternalDebugger('determine breakpoint hit', ... breakpoint.File, ... breakpoint.Line, ... breakpoint.Function); atBreakpoint = ~isempty(result); errFlag = false; end | Required. Asks if the debugger is currently
stopped at the specified breakpoint. Returns
Add logic to determine if the debugger has broken execution at the breakpoint passed into the function. The
Set the
|
function errFlag = continueExecution(this) this.callExternalDebugger('continue execution'); errFlag = false; end | Required. Continues execution if application is paused in the debugger. |
function errFlag = write(this, variableName, memoryStream) sizeOfMemoryVariable = uint64(numel(memoryStream)); arrayFormat = repmat('%d,', [1 sizeOfMemoryVariable]); arrayFormat(end) = []; this.callExternalDebugger(sprintf(['execute (void*)memcpy(%s,' ... '(unsigned char [%d]){%s}, %d)'], ... variableName, ... sizeOfMemoryVariable, ... sprintf(arrayFormat, memoryStream), ... sizeOfMemoryVariable)); errFlag = false; end | Write the memory stream to target platform memory specified by the variable name. Add logic to
write
The variable represents a pointer to the
smallest addressable integer type. For example, write
operations on a target platform where
(void*)memcpy(<variableName>, (unsigned char[<sizeOfMemoryStream>]) {<memoryStream(1)>,<memoryStream(2)>}, <sizeOfMemoryStream>); memcpy
approach to write data to the variable. |
function [memoryStream, errFlag] = read(this, ... variableName, ... sizeToRead) memoryStream = this.callExternalDebugger(... sprintf("read (unsigned char [%d])*%s", ... sizeToRead, variableName)); memoryStream = uint64(memoryStream); errFlag = false; end | Read the memory stream from target platform memory specified by variable name. Add logic to read
from the The The variable represents a pointer to the smallest addressable integer type. Read operations are equivalent to this C code: (unsigned char [<sizeToRead>])*<variableName> |
end |
|
methods (Access=private) function output = callExternalDebugger(~, varargin) output = []; fprintf("\nInstructed the debugger to '%s'\n", varargin{1}); if nargin > 2 disp('Using arguments:'); disp(varargin(2:end)); end end end | Private methods. |
end |
|
Pseudocode for target.DebugIOTool
Debugger Abstraction
Example
classdef DebugIOToolTemplate < target.DebugIOTool % DEBUGIOTOOLTEMPLATE Example implementation of target.DebugIOTool % debugger abstraction. % Copyright 2020 The MathWorks, Inc. properties (Access=private) % Optional % Add any state required to interact with the debugger or % application being run in the debugger as a property of % DebugIOTool. Apply private access so that only this file % can access the state. % % For example, the state could be a handle to the debugger % application provided by the debugger external API. DebuggerHandle; end % Method implementations that perform debugger interactions. % Each method will return a 'errFlag' logical flag. If the method % executes, 'errFlag' is set to false. % Consider also using the MATLAB error method to report custom % error information. methods % Constructor for the target.DebugIOTool. The constructor % creates an instance of the tool allowing its methods to be called % on that instance. Optional. function this = DebugIOToolTemplate() % Basic initialization can be performed here. For example % setting state ready for calls to open end % Open the debugger. Optional. function errFlag = open(this) % Add logic here to open the debugger. Typically, use system % commands or the external API provided by the debugger. % % If you cannot open the debugger without also loading the % application into the debugger, this method should not be % implemented and the logic should be performed in the % 'loadApplication' method. % % If you cannot open the debugger without also starting % execution of the application, this method should not be % implemented and the logic should be performed in the % 'startApplication' method. this.DebuggerHandle = this.callExternalDebugger('open'); errFlag = false; end % Load the application into the debugger. Optional. function errFlag = loadApplication(this) % Add logic here to load the application into the debugger. % This could be loading a project into an IDE debugger or % loading the application executable into the debugger harness. % % Additionally add logic to set breakpoints in the debugger to % break execution. % % The path to the application to load is stored in the % Application property of this class which can be accessed % using this.Application in this method. % % Additional command line arguments to pass to the % application are stored in % this.ApplicationCommandLineArguments. % % Breakpoints to set are stored in this.Breakpoints % % If you cannot load the application without also starting % execution of the application, this method should not be % implemented and the logic should be performed in the % 'startApplication' method. this.callExternalDebugger('load application', ... this.Application, .... this.ApplicationCommandLineArguments); this.callExternalDebugger('set breakpoints', this.Breakpoints); errFlag = false; end % Start the application execution in the debugger. Required. function errFlag = startApplication(this) % Add logic here to start the application execution in the % debugger. % % The path to the application to load is stored in the % Application property of this class which can be accessed % using this.Application in this method. % % Additional command line arguments to pass to the % application are stored in % this.ApplicationCommandLineArguments. % % Breakpoints to set are stored in this.Breakpoints this.callExternalDebugger('start application'); errFlag = false; end % Stop the application execution in the debugger. Optional. function errFlag = stopApplication(this) % Add logic here to stop the application execution in the % debugger. % If your 'startApplication' method opened the debugger, % perform the opposite action here, i.e. close the % debugger. % % If your 'startApplication' method loaded the application, % perform the opposite action here, i.e. unload the % application from the debugger. this.callExternalDebugger('stop application'); errFlag = false; end % Unloads the application from the debugger. Optional. function errFlag = unloadApplication(this) % If you implemented the 'loadApplication' method, % then add logic here to unload the application from % the debugger. % If your 'loadApplication' method opened the debugger, % perform the opposite action here, i.e. close the % debugger. this.callExternalDebugger('unload application'); errFlag = false; end % Closes the debugger. Optional. function errFlag = close(this) % Add logic here to close the debugger. If you implemented the % 'open' method you should implement this method. this.callExternalDebugger('close'); errFlag = false; end % Asks if the debugger is currently stopped at the specified % breakpoint. Returns true if at the specified breakpoint, false % otherwise. Required. function [atBreakpoint, errFlag] = ... stoppedAtBreakpoint(this, breakpoint) % Add logic to determine if the debugger has broken execution % at the breakpoint passed into the function. % % The 'breakpoint' input variable is of type target.Breakpoint % which provides the description of the breakpoint. It contains % properties Function, File and Line which describes the % location of the breakpoint. % % Set the atBreakpoint return value to true if the debugger is % stopped at the breakpoint, or false if not. result = this.callExternalDebugger('determine breakpoint hit', ... breakpoint.File, ... breakpoint.Line, ... breakpoint.Function); atBreakpoint = ~isempty(result); errFlag = false; end % Continues execution if application execution is paused in the % debugger. Required. function errFlag = continueExecution(this) this.callExternalDebugger('continue execution'); errFlag = false; end % Write the specified memory stream to the target platform memory % specified by the given variable name. function errFlag = write(this, variableName, memoryStream) % Add logic to write the memoryStream data to the variableName % variable in the target. This function should assume that the % appropriate breakpoint has been hit to perform such an % action. % % memoryStream is a vector of uint64 values to be written to % the target platform. The unit64 values act as a container for % the smallest addressable integer on the target platform. In % most cases this will be a container for the size of char on % the target platform, which will commonly be 8-bit. % % The specified variable will represent a pointer to the % smallest addressable integer type. % As an example write operations on a target platform where % char represents the smallest addressable integer should be % equivalent to the following memcpy call in C code: % % (void*)memcpy(<variableName>, % (unsigned char[<sizeOfMemoryStream>]) % {<memoryStream(1)>,<memoryStream(2)>, ...}, % <sizeOfMemoryStream>); % % A lot of debuggers allow for immediate execution of code when % execution is broken, if so, attempt to use the above command % to write data to the variable like the below example: sizeOfMemoryVariable = uint64(numel(memoryStream)); arrayFormat = repmat('%d,', [1 sizeOfMemoryVariable]); arrayFormat(end) = []; this.callExternalDebugger(sprintf(['execute (void*)memcpy(%s,' ... '(unsigned char [%d]){%s}, %d)'], ... variableName, ... sizeOfMemoryVariable, ... sprintf(arrayFormat, memoryStream), ... sizeOfMemoryVariable)); errFlag = false; end % read the memory stream from the target platform memory specified % by the given variable name. function [memoryStream, errFlag] = read(this, ... variableName, ... sizeToRead) % Add logic to read from the variableName variable on the % target. This function should assume that the appropriate % breakpoint has been hit to perform such an action. % % The memoryStream return value should be a vector of uint64 % values. The unit64 values act as a container for the smallest % addressable integer on the target platform. In most cases % this will be a container for the size of char on the target % platform, which will commonly be 8-bit. % % The specified variable will represent a pointer to the % smallest addressable integer type. % Read operations should be equivilant to inspecting the result % of the following C code: % (unsigned char [<sizeToRead>])*<variableName> % % A lot of debuggers allow for immediate execution of code when % execution is broken, if so, attempt to use the above command % to inspect the value of the buffer and return it to MATLAB. memoryStream = this.callExternalDebugger(... sprintf("read (unsigned char [%d])*%s", ... sizeToRead, variableName)); % The memory stream must be returned as a vector of uint64 % values memoryStream = uint64(memoryStream); errFlag = false; end end methods (Access=private) function output = callExternalDebugger(~, varargin) output = []; fprintf("\nInstructed the debugger to '%s'\n", varargin{1}); if nargin > 2 disp('Using arguments:'); disp(varargin(2:end)); end end end end
See Also
Related Topics
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list:
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)