MATLAB Answers

Daryl
0

Add line to make file generated by simuliunk in external mode for raspberry pi

Asked by Daryl
on 15 Jan 2015
Latest activity Commented on by John Whittington on 15 Jun 2015
In am trying to run a simulink model on the raspberry pi.
The makefile generated by simulink has the following line in it:
LINKER_CODEGEN_ARGS := -lm -ldl -lpthread -lrt
I need to add the text -lwiringPi to this line.
LINKER_CODEGEN_ARGS := -lm -ldl -lpthread -lrt -lwiringPi
Does anyone know how i can add this line in the generated makefile?

  0 Comments

Sign in to comment.

3 Answers

Answer by John Whittington on 18 Mar 2015

Did you find a resolution for this? It's driving me mad! It seems to ignore the 'Simulation Target > Custom Code'. It's quite frustrating that the Raspberry Pi Support Package is not more documented. It's operation as the standard block library is limited and could be developed if the build process were more explained.

  3 Comments

After a day on this using 'grep' to find this line I found it uses the linux remote build templates in 'SupportPackages\R2014b\linux\toolbox\realtime\targets\linux\registry\defgmake_remotebuild.mkt'. Even using a brute force approach and changing this file I couldn't get them to reflect the generated Makefile?! It definitely uses the file as changing the name causes an error on the rtw_hook.
I finally found a solution using the (undocumented) command 'xmakefilesetup'. You can add compiler/linker flags and I was able to include -lwiringPi and compile remotely!!!!
Can you describe this method with xmakefilesetup clearly?
Yes, I've created a blog post: http://wp.me/p2C0Bi-bK
Scroll to the 'Remote Build Makefile Setup' section.

Sign in to comment.


Answer by Murat Belge on 18 Mar 2015

I am assuming you are developing a Simulink block that uses the wiringPi library. If you develop your block as a System object, you can specify shared libraries, sources, headers, etc. in a method called updateBuildInfo(). The System objet must inherit from coder.ExternalDependency. You can then import the System object to Simulink as a block. Here is an example System object that uses wiringPi library for digital write:
classdef DigitalWrite_raspi < matlab.System ... & coder.ExternalDependency ... & matlab.system.mixin.Propagates ... & matlab.system.mixin.CustomIcon % % Set the logical state of a digital output pin. %
% Copyright 2014 The MathWorks, Inc.
%#codegen
%#ok<*EMCA>
properties (Nontunable)
Pin = 14
end
properties (Constant, Hidden)
AvailablePin = [4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27];
OUTPUT = 1;
INPUT = 0;
end
methods
% Constructor
function obj = DigitalWrite_raspi(varargin)
coder.allowpcode('plain');
% Support name-value pair arguments when constructing the object.
setProperties(obj,nargin,varargin{:});
end
function set.Pin(obj,value)
coder.extrinsic('sprintf') % Do not generate code for sprintf
validateattributes(value,...
{'numeric'},...
{'real', 'positive', 'integer','scalar'},...
'', ...
'Pin');
assert(any(value == obj.AvailablePin), ...
'Invalid value for Pin. Pin must be one of the following: %s', ...
sprintf('%d ', obj.AvailablePin));
obj.Pin = value;
end
end
methods (Access=protected)
function setupImpl(obj)
if coder.target('Rtw')
coder.cinclude('digitalio_raspi.h');
coder.ceval('digitalIOSetup', obj.Pin, obj.OUTPUT);
end
end
function stepImpl(obj,u)
if coder.target('Rtw')
coder.ceval('writeDigitalPin', obj.Pin, u);
end
end
function releaseImpl(obj) %#ok<MANU>
end
end
methods (Access=protected)
%%Define input properties
function num = getNumInputsImpl(~)
num = 1;
end
function num = getNumOutputsImpl(~)
num = 0;
end
function flag = isInputSizeLockedImpl(~,~)
flag = true;
end
function varargout = isInputFixedSizeImpl(~,~)
varargout{1} = true;
end
function flag = isInputComplexityLockedImpl(~,~)
flag = true;
end
function varargout = isInputComplexImpl(~)
varargout{1} = false;
end
function validateInputsImpl(~, u)
if isempty(coder.target)
% Run this always in Simulation
validateattributes(u,{'logical','double'},{'scalar','binary'},'','u');
end
end
function icon = getIconImpl(~)
% Define a string as the icon for the System block in Simulink.
icon = 'Digital Write';
end
end
methods (Static, Access=protected)
function simMode = getSimulateUsingImpl(~)
simMode = 'Interpreted execution';
end
function isVisible = showSimulateUsingImpl
isVisible = false;
end
end
methods (Static)
function name = getDescriptiveName()
name = 'Digital Write';
end
function b = isSupportedContext(context)
b = context.isCodeGenTarget('rtw');
end
function updateBuildInfo(buildInfo, context)
if context.isCodeGenTarget('rtw')
% Update buildInfo
rootDir = fullfile(fileparts(mfilename('fullpath')),'src');
buildInfo.addIncludePaths(rootDir);
buildInfo.addIncludeFiles('digitalio_raspi.h');
buildInfo.addSourceFiles('digitalio_raspi.c',rootDir);
buildInfo.addLinkFlags({'-lwiringPi'});
end
end
end
end
And here are the associated source files:
digitalio_raspi.c:
#include <wiringPi.h>
#include "digitalio_raspi.h"
// Digital I/O initialization
void digitalIOSetup(uint8_T pin, boolean_T mode)
{
static int initialized = false;
// Perform one-time wiringPi initialization
if (!initialized) {
wiringPiSetupGpio();
initialized = 1;
}
// mode = 0: Input
// mode = 1: Output
if (mode) {
pinMode(pin, OUTPUT);
}
else {
pinMode(pin, INPUT);
}
}
// Read logical state of a digital pin
boolean_T readDigitalPin(uint8_T pin)
{
return ((boolean_T)digitalRead(pin));
}
// Write a logic value to pin
void writeDigitalPin(uint8_T pin, boolean_T val)
{
digitalWrite(pin, val);
}
// [EOF]
and digitalio_raspi.h:
#ifndef _DIGITAL_IO_RASPI_H_
#define _DIGITAL_IO_RASPI_H_
#include "rtwtypes.h"
void digitalIOSetup(uint8_T pin, boolean_T mode);
boolean_T readDigitalPin(uint8_T pin);
void writeDigitalPin(uint8_T pin, boolean_T val);
#endif //_DIGITAL_IO_RASPI_H_

  0 Comments

Sign in to comment.


Answer by Murat Belge on 18 Mar 2015

If you want to add a:
  • Source file
  • Header file
  • Linker flag
unconditionally in your Simulink model, you can add an InitFcn callback to your model and use one of the following functions in the callback:
realtime.addBuildInfoSrcFile(<source file>, <model name>)
realtime.addBuildInfoIncPath(<include path>, <model name>)
realtime.addBuildInfoLinkerFlag(<linker flag>, <model name>)
For example, to add '-lwiringPi' linker flag use the the following in the model InitFcn callback:
realtime.addBuildInfoLinkerFlag('-lwiringPi',gcs)
To additionally specify the location of the shared library use the following:
realtime.addBuildInfoLinkerFlag('-lwiringPi -L/usr/lib/',gcs)
In all three functions above, you can specify a cell array of source files, include paths or linker flags.

  2 Comments

Thanks for these replies Murat, they are useful. The 'realtime.addBuildInfo' doesn't seem to be unconditional however. I get the error:
'Attempt to reference field of non-structure array.'
Using 'xmakefilesetup' as I said in my reply is the only way I can get it working.
Hi John. Thank you so much for xmakefilesetup. It worked ! after struggling so long, I finally end up with your post. You saved my week.

Sign in to comment.