Sunday, June 10, 2018

Improving Code Quality with Microchips MPALB-X IDE and XC32 Compiler

Authors Michael Barr [1], Les Hatton [2], Robert Martin [3] and a host of others basically plead with programmers to use more formal code analysis techniques, such as: “Static Analysis” during the design phase of all embedded projects.

Addition of these steps is not time consuming or even expensive in most cases, the payback is usually justified by preventing even a single problem in shipped code.

Recently I have moved all my Microchip PIC development to their MPLAB-X and XC32 compiler. This saved a nominal sum per year in compiler updates, because this Microchip tool chain is free and it makes my clients also happy to be able to get the development tool chain for really the cost of a very simple programmer / debugger.

The XC32 compiler is a version of the venerable GNU GCC compiler geared especially for the MIPS based PIC32 product line. This tool chain also includes their rather all encompassing ‘Harmony’ software framework that handles all the driver and peripheral initialization and provides a consistent Hardware Abstraction Layer when programming any of the PIC32 devices.

Note: This article applies to MPALB-X version 4.15 and greater and XC32 Version 2.05 and later, the current versions as of June 2018.

Improved Static Analysis for Free:

The first step to better code is to turn all the GCC warnings, this is accomplished by supplying the ‘-Wall’ switch to the compiler options window [4], as shown below.



   Add All Warnings to the XC32 compiler options

‘Wall’ or ‘Warnings All’ will enable all the possible compiler warnings, but it doesn’t go out of its way to mark every library function as a problem. I find that it only adds three or four warnings from a previously cleanly compiled project. The errors it finds are mostly relevant and easy to deal with. You will find unused variables, bad definitions and improperly initialized variables.

I’m not sure what level of warnings are enabled as default in XC32, but you should definitely not compile without ‘all warnings’ turned on. It’s absolutely free, so use it.

GCC supplies a push/pop mechanism to disable specific warnings at various places in the code.

For example the function,

void foo(void)
{
    int32_t unused = 0;
}


will produce a warning: “warning: unused variable 'unused' [-Wunused-variable]”

This warning (or other warnings) can be disabled at the ‘function scope’ like this,

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
void foo(void)
{
    int32_t unused = 0;
}
#pragma GCC diagnostic pop


The above works to disable this specific warning at the ‘function level’


Trying to disable this warning inside a function will not always work and may be ignored.

void foo(void)
{
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wunused-variable"

    int32_t unused = 0;

    #pragma GCC diagnostic pop
}

The above does NOT work to disable this specific warning inside a function.


If you think about the above example, this makes sense. How could the compiler know that the variable is unused until it hits the final closing brace ‘}’ ? So by extension this example does work,

void foo(void)
{
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wunused-variable"

    int32_t unused = 0;
}
#pragma GCC diagnostic pop


The above does work to disable a specific warning inside a function, but not for a single variable. This will disable the ‘unused variable’ warnings for all variables between the ‘ignored’ and the ‘pop’.


For more information in the GCC diagnostic pragmas see Reference 5. Also note that Microchip makes no mention of this functionality in their documentation so it should be considered: ‘Undocumented’.


Improved Static Analysis for very little cost:

The next level of static analysis is to use a ‘Lint’ program [6]. First developed for UNIX in the mid 1970’s, but not widely used with regularity much of anywhere else because of the lack of suitable executables.

In the mid 1980’s when I first started writing C code, there was a program advertised called PC-Lint [7] and it sold for probably $300 then. That was a lot of money. Today the same program, but updated for 30+ years sells for $400. That’s not so much money when you consider the cost of giving one bug to your customers. In fact now, it’s downright cheap and will pay for itself if it finds a single problem! There are a few open source version of something like Lint, but nothing that compares to a reasonably priced, finished commercial product like PC-Lint.

MPLAB-X contains an optional plug-in to enable PC-Lint functionality inside the MPLAB-X environment. It is fairly easy to get going, but it took me probably 3 hours to get it working inside MPLAB-X the first time. I might be able to save you some time with the following instructions.

Installing the MPALB-X Plug-In:

Start MPLAB-X and install the PC-Lint Plug-In
    Tools - > Plugins - > Available Plugins
    Select: “PC-Lint Plugin”, and finally select: “Install”.


Installing PC-Lint:

With the advent of User Account Controls (UAC) in Windows 7 and later it is much harder to get software to play properly, because many programs need elevated privileges to have access to certain directories, etc.

The default install location for PC-Lint is in “C:\Program Files(x86)\PC-Lint”, this is a problematic directory when running with UAC enabled, and I wasted an hour trying to get configuration files properly written until I gave up and re-installed PC-Lint off the root directory here: “C:\PL-Lint\”, then no problems at all. Just do this and save yourself time!

Even with the very latest PC-Lint version you won’t get the latest XC32 compiler initialization files or ‘.Int’ files. You will need to go to the Gimple website (www.gimpel.com/html/pub90/co-xc32.lnt ) and get this file,

    co-xc32.Int

Save the file in this directory,

    C:\PC-Lint\Int\

Don’t run the PC-Lint supplied configuration file builder (CONFIG.exe) it won’t know about the latest co-xc32.Int file anyway and it will just need to be manually modified anyway.

Instead just make a file named: ‘XC32-std.Int’ in the directory: “C:\PC-Lint\”

Place these lines in the file,

//  Microchip MPLAB XC32 C, -si4 -sp4,
//  Custom lint options file for XC2 V2.x

co-xc32.lnt

C:\PC-Lint\options.lnt  -si4 -sp4
-i"C:\Program Files (x86)\Microchip\xc32\v2.05\pic32mx\include\lega-c"


You may need to modify the exact path and name depending on your circumstances. Here you can see that I am using Harmony Version 2.05 and I use the ‘Lega-c” library and include files.

If you are in doubt as to the exact path to use, just open up your projects ‘stdio.h’ or some other well known system header file and see what the path is by hovering on the file name tab in the GUI, then use that.

Make sure that there is a file called: “Options.Int” in this directory also: “C:\PC-Lint\”. Right now this file can just have a single empty line in it.

Now setup the PC-Lint interface in MPLAB-X. Select: Tools - > Options → Embedded and then select the PCLint tab at the right hand side as shown below. Then click: OK.



Set these options as above on the PC-Lint configuration screen.


Right click on your main projects name, then select: “Generate PCLint Dependency Files” You should see this in the PC-Lint output window.

If the directory is not writable these files will not be written correctly and you will waste another hour trying to figure out why. To be safe, re-generate these files every time you switch and start working on another XC32 project. Just think of it as “Getting Latest” from your source control.


Let’s go Linting:

This step will seem daunting and you will wonder why you did all this in the first place. Why? Because your first ‘Lint’ will produce about 20 pages of warnings.

Let’s try it – Select a small ‘c’ file from your project, like “App.c” for example, right click on its name and select: “Lint this file”.

Have no fear – 99% of those warnings will be the same complaint about some name probem or some header file, etc. These warnings that can be easily suppressed.

Just open the file: “C:\PC-Lint\options.Int” file and start adding errors to suppress the spurious warnings. In 30 minutes, by checking half a dozen of my code modules, I was easily able to get rid of all the ‘chaff’ and get down to those few simple things that should be checked or fixed.

Here is the “Options.Int” file that I ended up with,

// Please note -- this is a representative set of error suppression
//                options.  Please adjust to suit your own policies
//                See  manual (chapter LIVING WITH LINT)
//                for further details.

-w3     // Overall warning level (3=default) Settings 2 and 3 are OK.

-e586   // function 'printf' is deprecated.
-e793   // suppress message about extern identifiers being more than 31 chars long
-e9045  // non-hidden definition of type 'struct
-e9058  // unused outside of typedefs
-e970   // Use of modifier or type '_Bool' outside of a typedef
-e9071  // defined macro '_APP_H' is reserved to the compiler
-e537   // repeated include
-e950   // Note 950: Non-ANSI reserved word or construct: like: '_nop()'

-passes(2) // Make 2 passes on the code


Now that wasn’t so bad after-all – Now I can just Lint my files one by one and see the warnings / errors that really show up. I had a number of iffy initialized variables, some missing ‘defaults’ in Switch statements and a few of the dreaded,

    If(test)
        foo();


instead of,

    If(test)
  {
        foo();
  }

Constructs.

Most importantly I found a few real problems (like copy and paste errors) that would have prevented proper program operation and would have cost me debugging time to fix.


Gimpel offers this sage advice for first time “Linters”,

“If you've never linted your code before, you may want to modify the warning level initially.  Try running with -w1 to report only errors.  After you've fixed the resulting errors (or suppressed those that you don't want reported), run with -w2, and so forth. “


Further Reading:
Hopefully this tutorial will get you at least 80% of the way to where you want to be, in a very short period of time. For more information, the Gimpel website has a FAQ list that provides helpful hints and the PC-Lint manual is full of further in depth information.

You may also want to consider "Breadboarding" your C code on your PC before placing it on your target Embedded System, these two posts show how I accomplish this,

* Breadboarding Embedded Code
* Breadboarding Embedded Code - Part II


References:

[1] Micheal Barr The Barr group. Prolific writer about best ‘C’ practices,
    https://barrgroup.com/content/barr-group-embedded-c-coding-standard-now-available-free-embedded-systems-designers

[2] Les Hatton, Author of: “Safer C”, McGraw-Hill, 1994

[3] Robert Martin is a frequent speaker at programming conferences. Many of his talks can be viewed on Youtube.

[4] There are a number of other compiler options available, I find that this one is the best for catching stupid mistakes without marking every single library function as non-compliant. For other possible options see the XC32 Compiler Users Guide – Yes there is actually a manual and as near as I can tell Microchip keeps it up to date.

[5] GCC Diagnostic Pragmas manual page,
    https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html

[6] LINT    https://en.wikipedia.org/wiki/Lint_(software)

[7] Gimple Software PC-Lint, Version 9.00L is the current version.
    http://www.gimpel.com/html/pcl.htm

PC-Lint has been called the longest continuously available software product in the history of mankind, since it has been available from the 1980’s until now.


Article By: Steve Hageman www.AnalogHome.com

We design custom: Analog, RF and Embedded systems for a wide variety of industrial and commercial clients. Please feel free to contact us if we can help on your next project.


Note: This Blog does not use cookies (other than the edible ones).