Main Content

Generate MISRA C:2012 Compliant Code and Verify with Polyspace

When generating C code for your MATLAB® code base, you can configure the code generator to produce code that is compliant with a large subset of the MISRA™ C:2012 guidelines. See MISRA C:2012 Coding Directives and Rules Supported for Code Generation (Embedded Coder).

This example consists of the following steps:

  • Create and run a MATLAB entry-point function that uses the fft and islocalmax functions to perform basic spectral analysis on an input time-domain signal.

  • Generate and run a MEX function for this MATLAB function to check for potential run-time issues in the generated code.

  • Generate standalone C source code that is compliant with a large subset of the MISRA C:2012 guidelines by using the coder.setupMISRAConfig (Embedded Coder) and codegen (MATLAB Coder) functions.

  • Perform static analysis by using Polyspace® Bug Finder™ to check the compliance of the generated code with the MISRA C:2012 guidelines.

Define MATLAB Entry-Point Function

Define an entry-point function powerSpectrumPeaks that calculates the Fourier transform of a time-domain signal sampled at frequency fs. The function then squares the absolute value of the Fourier transform to obtain the power spectrum of the signal in the frequency domain. Finally, it returns the frequencies at which the peaks of the power spectrum, which have a pre-specified minimum prominence, are located.

type powerSpectrumPeaks.m
function peaks = powerSpectrumPeaks(signal,fs,prominence)
n = length(signal);
signalIndices = 1:n;

y = fft(signal);
power = abs(y).^2/n;

peakIndices = signalIndices(islocalmax(power,MinProminence=prominence));
peaks = (peakIndices - 1)*fs/n;
end

Define a complex time-domain signal that has two frequency components at 50 Hz and 300 Hz.

fs = 1000;            % Sampling frequency                    
T = 1/fs;             % Sampling period       
L = 1500;             % Length of signal
t = (0:L-1)*T;        % Time vector
x = 0.7*exp(2*1i*pi*50*t) + 1.3*exp(2*1i*pi*300*t);  % Input signal

To filter out the noise from the power spectrum, define a minimum peak prominence that the islocalmax function uses.

prominence = 0.001;

Call the entry-point function powerSpectrumPeaks with these inputs. The function returns a 2-by-1 array that contains the two component frequencies of the input signal.

powerSpectrumPeaks(x,fs,prominence)
ans = 1×2

    50   300

Check for Run-Time Issues by Generating and Running MEX

Use the codegen command to generate a MEX function for the powerSpectrumPeaks function. Provide the example input values defined in the previous section to the -args argument.

codegen powerSpectrumPeaks -args {x,fs,prominence} -d mexcode
Code generation successful.

Run the generated MEX function with the same inputs. The output of the MEX function matches that of MATLAB execution.

powerSpectrumPeaks_mex(x,fs,prominence)
ans = 1×2

    50   300

Generate MISRA Compliant Standalone C Source Code

Create a coder.EmbeddedCodeConfig (MATLAB Coder) object for generating standalone C source code. For improved compliance of the generated code with the MISRA C:2012 guidelines, use the coder.setupMISRAConfig function to configure this object.

cfg = coder.config('lib','ecoder',true);
cfg.GenCodeOnly = true;
coder.setupMISRAConfig(cfg);

Generate standalone C source code for the powerSpectrumPeaks function. Specify the code generation folder as misracompliantcode.

codegen -config cfg powerSpectrumPeaks -args {x,0,0} -d misracompliantcode -report
Code generation successful: View report

Run Static Analysis on Generated Code at Command Line

Use Polyspace Bug Finder to statically check for compliance of the generated code with the subset of MISRA C:2012 rules and directives that are categorized as either mandatory or required. The MISRA C:2012 standard performs this categorization slightly differently for user-written code and automatically generated code. In this example, you use the categorization for automatically generated code.

Create a pslinkoptions object opts for static analysis with Polyspace Bug Finder.

opts = pslinkoptions('ec');
opts.VerificationMode = 'BugFinder';

To configure the static analysis, open the Polyspace user interface and create a new project file misrachecker.psprj. In the Project Browser, select the Configuration node of the module. In the Configuration pane, set these options:

  • In the Coding Standards and Code Metrics pane, select Check MISRA C:2012. From the adjacent drop-down list, select mandatory-required. Also, select Use generated code requrements.

  • Optionally, in the Bug Finder Analysis pane, clear Find defects to restrict your analysis to MISRA checks only.

  • Optionally, in the Advanced Settings pane, in the Other box, enter -quiet. This setting suppresses the printing of the log when you run the checks.

Finally, associate this project file with your options object opts.

opts.EnablePrjConfigFile = true;
opts.PrjConfigFile = fullfile(pwd,"misrachecker.psprj");

Use the pslinkrun function to run the analysis. Provide the location of the code generation folder and the options object opts to the pslinkrun function.

[polyspaceFolder, resultsFolder] = pslinkrun('-codegenfolder', 'misracompliantcode', opts);

Import the analysis results into a table by using the polyspace.BugFinderResults object and the getResults object function. Use the function groupsummary to display the number of violations for each rule or directive.

resObj = polyspace.BugFinderResults(resultsFolder);
resTable = getResults(resObj, 'readable');
groupsummary(resTable,'Check')
ans=5×2 table
                                                               Check                                                               GroupCount
    ___________________________________________________________________________________________________________________________    __________

    14.3 Controlling expressions shall not be invariant.                                                                                3    
    9.1 The value of an object with automatic storage duration shall not be read before it has been set.                                4    
    Dir 1.1 Any implementation-defined behaviour on which the output of the program depends shall be documented and understood.        18    
    Dir 4.14 The validity of values received from external sources shall be checked.                                                    7    
    Dir 4.15 Evaluation of floating-point expressions shall not lead to the undetected generation of infinities and NaNs.              28    

The generated code is compliant with the mandatory and required categories of the MISRA C:2012 guidelines except Directives 1.1, 4.14, and 4.15, and Rules 9.1 and 14.3. This behavior is consistent with the compliance information listed in the tables in MISRA C:2012 Coding Directives and Rules Supported for Code Generation (Embedded Coder).

See Also

(Embedded Coder) |

Related Topics