Tuesday, March 29, 2016

Autoincrementing build number in Atmel Studio 7 (and Visual Studio too).

This approach uses Windows batch file which reads current version from major_version.txt and current build number from build_number.txt, then increments the latter and composes header file build_number.h with different representations of version numbers. It's used as pre-built event in Atmel Studio 7 (which uses Visual Studio 2015 engine).

First thing you need is to manually create build_number.txt with the number 1 and major_version.txt with any number, for example, "1.0" (no quotation marks) in it before calling the batch. So both files are just one-liners with numbers.

Visual Studio pre- and post-build events are independent for Debug and Release configurations. You can choose to use different version numbers for each one. In this case you put separate files used for version numbers (including the batch file) in corresponding Debug and Release folders and edit my examples so the Studio finds this files not in project folder but in Debug or Release ones.

I chose to use one copy of version and build number for both Debug and Release configurations, that's why I place the batch file and both major_version.txt and build_number.txt in project directory, not Debug or Release ones. Also, that's why there's "..\\" before filenames in batch - otherwise pre-build event will try to find files in Debug or Release directory and complain there's no such files.

Here's my batch file:

set /p version=<..\\major_version.txt
@echo %version%
set /p old=<..\\build_number.txt
set /a new=%old%+1
@echo New build number: %new%
@echo Version: %version%.%new%
@echo %new% > ..\\build_number.txt
(
  echo #ifndef BUILD_NUMBER
  echo #define BUILD_NUMBER %new%U
  echo #endif
  echo #ifndef BUILD_NUMBER_STR
  echo #define BUILD_NUMBER_STR "%new%"
  echo #endif
  echo #ifndef VERSION_FULL_STR
  echo #define VERSION_FULL_STR "%version%.%new%"
  echo #endif
) > ..\\build_number.h

And in Pre-Build event command line you add  "$(MSBuildProjectDirectory)\make_buildnum.bat" (no quotation marks).



On each build there's the output in Studio showing new build number and full version:


Here's the resulting header file in project folder after calling the exact BAT file I showed earlier:
#ifndef BUILD_NUMBER
#define BUILD_NUMBER 24U
#endif
#ifndef BUILD_NUMBER_STR
#define BUILD_NUMBER_STR "24"
#endif
#ifndef VERSION_FULL_STR
#define VERSION_FULL_STR "0.9.24"
#endif


Hope this helps anyone.

Tuesday, April 14, 2015

Configuring PC-Lint to use with Atmel Studio and GCC Toolchain.

Generation of macro definition headers, --i options and size options for Lint when using Atmel GCC toolchain.

In theory this is done by using co-gcc.mak file provided with PC-Lint intallation (see C:/lint/lnt folder). I guess this works with standalone GCC installation. But when GCC is provided as part of Atmel Studio, invoking GNU make from C:\Program Files (x86)\Atmel\Atmel Studio 6.2\shellUtils folder doesn't work.
Instead, I just did manually all that makefile does.
Here's step-by-step instructions.

1) Makefile must provide a lot of options to Make utility to get correct output. These options are:
- GCC_BIN='name of gcc binary'
- GXX_BIN='name of g++ binary'
- CFLAGS='[usual C compile switches here]'
- CXXFLAGS='[usual C++ compile switches here]'
- CPPFLAGS='[usual common preprocessor switches here]'
- COMMON_FLAGS='[usual C & C++ compile switches here]'
In case of only C program we don't need all these C++ options, so we'll get only what we need.

2) Get COMMON_FLAGS options from Atmel Studio.
Open Project Properties (press Alt+F7), then get your options from Toolchain->ARM/GNU Common tab:

In our case it's -mthumb -D__SAMD21J17A__.

3) Get CFLAGS from Toolchain->ARM/GNU C Compiler tab. It's a huge list of options:
Here's full list: 
-x c -mthumb -D__SAMD21J17A__ -DDEBUG -DBOARD=SAMD21_XPLAINED_PRO -D__SAMD21J18A__ -DARM_MATH_CM0=true -DSPI_CALLBACK_MODE=false -DEXTINT_CALLBACK_MODE=true -DEVENTS_INTERRUPT_HOOKS_MODE=true  -I"../sam0/drivers/sercom/spi/quick_start_master/samd21_xplained_pro" -I"../src/ASF/sam0/utils/header_files" -I"../src/ASF/sam0/drivers/system/power/power_sam_d_r" -I"../src/ASF/common/utils" -I"../src/ASF/sam0/drivers/system/pinmux" -I"../src/ASF/sam0/drivers/system/power" -I"../src/ASF/sam0/drivers/system/reset/reset_sam_d_r" -I"../src/ASF/common/boards" -I"../src/ASF/sam0/drivers/sercom/spi" -I"../src/ASF/sam0/drivers/port" -I"../src/ASF/sam0/drivers/system/clock/clock_samd21_r21" -I"../src/ASF/sam0/boards" -I"../src/ASF/sam0/utils" -I"../src/ASF/thirdparty/CMSIS/Include" -I"../src/config" -I"../src/ASF/thirdparty/CMSIS/Lib/GCC" -I"../src/ASF/sam0/drivers/system/reset" -I"../src/ASF/sam0/drivers/system/interrupt/system_interrupt_samd21" -I"../src/ASF/sam0/boards/samd21_xplained_pro" -I"../src" -I"../src/ASF/sam0/drivers/sercom" -I"../src/ASF/sam0/utils/preprocessor" -I"../src/ASF/sam0/utils/cmsis/samd21/include" -I"../src/ASF/sam0/drivers/system" -I"../src/ASF/sam0/utils/cmsis/samd21/source" -I"../src/ASF/sam0/drivers/system/clock" -I"../src/ASF/sam0/drivers/system/interrupt" -I"../inc" -I"../src/ASF/common2/services/delay" -I"../src/ASF/common2/services/delay/sam0" -I"../src/ASF/sam0/drivers/extint" -I"../src/ASF/sam0/drivers/extint/extint_sam_d_r" -I"../src/ASF/common/services/ioport" -I"../src/ASF/sam0/drivers/events/events_sam_d_r" -I"../src/ASF/sam0/drivers/events"  -O3 -fdata-sections -ffunction-sections -g3 -Wall -mcpu=cortex-m0plus -c -pipe -fno-strict-aliasing -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror-implicit-function-declaration -Wpointer-arith -std=gnu99 -ffunction-sections -fdata-sections -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int -Wmain -Wparentheses -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef -Wshadow -Wbad-function-cast -Wwrite-strings -Wsign-compare -Waggregate-return  -Wmissing-declarations -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wredundant-decls -Wnested-externs -Wunreachable-code -Wcast-align --param max-inline-insns-single=500  -Wno-long-long -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"

Notice, that CFLAGS does contain both COMMON_FLAGS options. There's no need to use them twice, so we can drop COMMON_FLAGS and stick with CFLAGS only.

4) This is optional, but it lets to run GCC executable by only printing it's name without the full (and very long) path to it every time.
Add path to GCC binaries to PATH system variable. The path is "C:\Program Files (x86)\Atmel\Atmel Toolchain\ARM GCC\Native\4.8.1429\arm-gnu-toolchain\bin".

5) Create empty C file, for example D:\empty.c.
Get  macro definitions and redirect them to file by running GCC command with all that CFLAGS as arguments plus "-E -dM empty.c >lint_cmac.h" assuming you run command line from drive D:.

To have fully prepared command at hand, I created file D:\gcc_get_lint_cmac.txt with such contents:
arm-none-eabi-gcc -x c -mthumb -D__SAMD21J17A__ -DDEBUG -DBOARD=SAMD21_XPLAINED_PRO -D__SAMD21J18A__ -DARM_MATH_CM0=true -DSPI_CALLBACK_MODE=false -DEXTINT_CALLBACK_MODE=true -DEVENTS_INTERRUPT_HOOKS_MODE=true  -I"../sam0/drivers/sercom/spi/quick_start_master/samd21_xplained_pro" -I"../src/ASF/sam0/utils/header_files" -I"../src/ASF/sam0/drivers/system/power/power_sam_d_r" -I"../src/ASF/common/utils" -I"../src/ASF/sam0/drivers/system/pinmux" -I"../src/ASF/sam0/drivers/system/power" -I"../src/ASF/sam0/drivers/system/reset/reset_sam_d_r" -I"../src/ASF/common/boards" -I"../src/ASF/sam0/drivers/sercom/spi" -I"../src/ASF/sam0/drivers/port" -I"../src/ASF/sam0/drivers/system/clock/clock_samd21_r21" -I"../src/ASF/sam0/boards" -I"../src/ASF/sam0/utils" -I"../src/ASF/thirdparty/CMSIS/Include" -I"../src/config" -I"../src/ASF/thirdparty/CMSIS/Lib/GCC" -I"../src/ASF/sam0/drivers/system/reset" -I"../src/ASF/sam0/drivers/system/interrupt/system_interrupt_samd21" -I"../src/ASF/sam0/boards/samd21_xplained_pro" -I"../src" -I"../src/ASF/sam0/drivers/sercom" -I"../src/ASF/sam0/utils/preprocessor" -I"../src/ASF/sam0/utils/cmsis/samd21/include" -I"../src/ASF/sam0/drivers/system" -I"../src/ASF/sam0/utils/cmsis/samd21/source" -I"../src/ASF/sam0/drivers/system/clock" -I"../src/ASF/sam0/drivers/system/interrupt" -I"../inc" -I"../src/ASF/common2/services/delay" -I"../src/ASF/common2/services/delay/sam0" -I"../src/ASF/sam0/drivers/extint" -I"../src/ASF/sam0/drivers/extint/extint_sam_d_r" -I"../src/ASF/common/services/ioport" -I"../src/ASF/sam0/drivers/events/events_sam_d_r" -I"../src/ASF/sam0/drivers/events"  -O3 -fdata-sections -ffunction-sections -g3 -Wall -mcpu=cortex-m0plus -c -pipe -fno-strict-aliasing -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror-implicit-function-declaration -Wpointer-arith -std=gnu99 -ffunction-sections -fdata-sections -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int -Wmain -Wparentheses -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef -Wshadow -Wbad-function-cast -Wwrite-strings -Wsign-compare -Waggregate-return  -Wmissing-declarations -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wredundant-decls -Wnested-externs -Wunreachable-code -Wcast-align --param max-inline-insns-single=500  -Wno-long-long -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -E -dM empty.c >lint_cmac.h

If you followed stage 4 and added path to system variable, you can copy it in command line nad run it as it is. If not, instead of just arm-none-eabi-gcc provide full path to .exe
As a result of running this command we now have file D:\lint_cmac.h with all the macros from compiler set to our project build options. The list is pretty long, so here's only part of it, so you could understand how does it look like:
#define __DBL_MIN_EXP__ (-1021)
#define __HQ_FBIT__ 15
#define __UINT_LEAST16_MAX__ 65535
#define __ARM_SIZEOF_WCHAR_T 32
#define __ATOMIC_ACQUIRE 2
#define __SFRACT_IBIT__ 0
#define __FLT_MIN__ 1.1754943508222875e-38F
#define BOARD SAMD21_XPLAINED_PRO
......................................

6) Now we need to specify the list of directories with system headers, so Lint would know where to get them.
Run arm-none-eabi-gcc -c -v empty.c. You get a lot of output. Find the section which starts with "#include "..." search starts here" and ends with "End of search list". Copy that paths to a file named gcc-include-path.lnt (create that file first, of course).
There's more simple way to do this. Just go to Project options in Atmel Studio and copy these paths from ARM/GNU Common->General->Default Include Paths.
gcc-include-path.lnt file provides this paths to PC-Lint as parameters, so it must include paths in form of --i parameter as follows:
--i"c:\program files (x86)\atmel\atmel toolchain\arm gcc\native\4.8.1429\arm-gnu-toolchain\bin\../lib/gcc/arm-none-eabi/4.8.3/include"
Each path should be on a separate line.

7) Copy files lint_cmac.h and gcc-include-path.lnt to PC-Lint folder C:\lint.

Running PC-Lint for GCC compiled projects.

Use provided with install co-gcc.lnt as your Lint configuration file or as a template for your own such file.
You will invoke Lint in form of
lint std.lnt source-files-to-be-linted
That std.lnt file could include that macro and directories files we got earlier. It also can include a list of source files, so you'll be able to lint your project with just 
lint std.lnt

I use PC-Lint with Visual Lint embedded in Atmel Studio and Visual Lint invokes Lint with custom std.lnt file. This file includes following:

// Author recommendations and checks recommended by industry bodies
au-barr10.lnt                   //
au-misra3.lnt                   //

// Compiler configuration
co-gcc.lnt                   // AVR/ARM GCC compiler

// PC-lint warning level (0 through 4). Recommended levels are -w1 (Basic), -w2 (Thorough), -w1 -w3 (Aggressive), or -w3 (Very Aggressive)
-w1 -w3                             // Aggressive

Here we turn on Michael Barr's 10 rules check and MISRA-2012 checks, set warning level to Aggressive and use co-gcc.lnt as compiler configuration.

co-gcc.lnt is used as it was provided with PC-Lint installation and it contains the calls to our gcc-include-path.lnt and lint_cmac.h files (see the contents of your co-gcc.lnt and how it calls this files and other options useful for GCC).

So now any time we run PC-Lint it takes in consideration all the include files paths and all macros that are actually used in our GCC project compilation.


Monday, April 13, 2015

Static inline functions in embedded C.

To declare and define inline static function:

1) Do not declare it in header file! Any other source files must be unable to know about this function's existence.
2) Instead, declare it in function prototypes section in source file after variables section and before functions section.
Example: static inline void dmx_flush_idx(void);
3) Place definition of a function in the source file where you define all your functions.
Example:
static inline void dmx_flush_idx(void)
{
    g_rx_cnt = 0;
    g_rx_idx = 0;
    g_tx_cnt = 0;
    g_tx_idx = 0;  
}

When static inline function is declared and defined as described, it passes MISRA 2012 checking in PC-Lint and Atmel Studio's Clang-based Naggy isn't naggy about it ;)

Friday, April 10, 2015

Pointer Allocation Strategies

Disclaimer: this text is fully copied from Eskimo.com. All credits are to original authors. I just like to have it here than browsing my bookmarks or search for it again and again every time I need to take a look. BTW, there's a whole lot of useful articles on C by Steve Summit at Eskimo.com.

Pointer Allocation Strategies

    Pointers are viewed by many as the bane of C programming, because out-of-control pointers can do a lot of damage, and can be hard to track down. But real programs tend to make heavy use of pointers. How can we keep pointers under control?

    The big problem with pointers, of course, is that they can point anywhere, including to places they're not supposed to. When a pointer points to the wrong place (perhaps because it was never initialized properly, such that it essentially points to a random place), a fetch of the data it "points" to will result in garbage (or may cause the program to crash with a memory access violation), and a write of some new data to the location it "points" to will damage some other part of your program, or of some other program, or of the operating system (or may cause the program to crash). Crashes, in fact, though they're frustrating and annoying, may be preferable to the alternatives, namely performing quiet but meaningless computations or damaging other code, both of which can be even more annoying and even harder to track down.

    Our goal, then, is to make sure that our pointers are always valid, or when they are not, to make sure that we can know that they are not. First, then, let's discuss what we mean by a "valid pointer."

     A valid pointer (more precisely, a valid pointer value) is one that does in fact point to an object of the type that the pointer is declared to point to. Furthermore, if the pointer will be used to store new values, the old value must be sitting in writable memory (that is, it must not be a variable that was declared const, or a string that results from a string literal). In contrast to valid pointers, we may distinguish among several kinds of invalid pointers: null pointers, uninitialized pointers, pointers to memory that used to exist but has disappeared, pointers to memory that once came from malloc but has since been freed.

     The tricky thing about valid and invalid pointers is that there's no simple way in C to ask "is this pointer valid?" or "is this pointer invalid?". The only questions we can ask about pointers are "is this pointer equal to this other pointer?", "is this pointer unequal to this other pointer?", and, for pointers into the same array, "is this pointer greater or less than this other pointer?".

     Part one of our strategy for managing pointers, then, will be to arrange that all or most invalid pointers are null pointers. Whenever we do anything which would cause a pointer to be invalid, that is, whenever we declare one (such that it would otherwise have a garbage initial value), or whenever we do something that causes the memory which one of our pointers used to point to to disappear, we'll set the pointer to NULL. Having done so, we can test whether the pointer is currently valid by checking if it's not equal to the null pointer, or contrariwise, we can test whether it's invalid by checking if it's equal to the null pointer.

     Remember that C doesn't generally do any of this automatically. It does not guarantee that all newly-allocated pointers are initialized to null pointers, and it does not insert automatic validity checks before you try to use a pointer. If you want to be sure that a pointer is initialized to a null pointer, you must generally set it to NULL. If you have a pointer which you're thinking of using but which might or might not be valid (and if it's a pointer which you believe you'd have set to NULL if it was invalid), you must precede your use of the pointer with a test of the form

if(p != NULL)

    Furthermore, if you write the test if(p != NULL), it does not in the general case mean "is p valid?". The test if(p != NULL) can only be used to mean "is p valid?" if you have taken care to make sure that all non-valid pointers have been set to null.

    (There is one condition under which C does guarantee that a pointer variable will be initialized to a null pointer, and that is when the pointer variable is a global variable or a member of a global structure, or more precisely, when it is part of a variable, array, or structure which has static duration.)

     Remember, too, that the shorthand form

if(p)

is precisely equivalent to if(p != NULL). So you may be able to read if(p) as "if p is valid", but again, only if you've ensured that whenever p is not valid, it is set to null.

    The degree of care with which you have to implement a pointer management strategy may be different for different pointer variables you use. If a pointer variable is immediately set to a valid pointer value, and if nothing ever happens which could make it become invalid, then there's no need to check it before each time you use it. Similarly, if a pointer is set to point to different locations from time to time, but it can be shown that it will always be valid, there's again no reason to test it all the time. However, if a particular pointer is valid some of the time and invalid other of the time, or in particular, if it records some optional data which might or might not be present, then you'll want to be very careful to set the pointer to NULL whenever it's not valid (or whenever the optional data is not present), and to test the pointer before using it (that is, before fetching or writing to the location that it points to).

    Everything we've just said about "pointer variables" is equally true, and perhaps more important, for pointer fields within structures. When you define a structure, you will typically be allocating many instances of that structure, so you will have many instances of that pointer. You will typically have central pieces of code which operate on instances of that structure, meaning that each time the piece of code runs, it may be operating on a different instance of the structure, so if the pointer field is one that isn't always valid (that is, isn't valid in all instances of the structure), the code had better test it before using it. Similarly, the code had better set the pointer field to NULL if it ever invalidates it.

     For example, one of the first features we added to the adventure game was a long description for objects and rooms. But the long description is optional; not all objects and rooms have one. Suppose we chose to use a char * within struct object and struct room to point at a dynamically-allocated string containing the long description. (This choice would be preferable to a fixed-size array of char because it may be the case that some long descriptions will be elaborately long, and we'd neither want to limit the potential length of descriptions by having a too-small array nor waste space for objects with short or empty descriptions by always using a too-large array.) For each instance of an object or room structure, we'd initialize the description field to contain a null pointer. For each room or object with a long description, we'd set the description field to contain a pointer to the appropriate (and appropriately-allocated) string. Finally, when it came time to print the descrition, we'd use code like

if(objp->desc != NULL)
printf("%s\n", objp->desc);
else printf("You see nothing special about the %s.\n", objp->name);

    Particular care is needed when pointers point to dynamically-allocated memory, managed with the standard library functions malloc, free, and realloc. Somehow, it's easier to make mistakes here, and their consequences tend to be more damaging and harder to track down.

    First of all, of course, you must always ensure that the allocation functions malloc and realloc succeed. These functions return null pointers when they are unable to allocate the requested memory, so you must always check the return value to see that it is not a null pointer, before using it. (If the return value is a null pointer, you will generally print some kind of error message and abort at least the particular function that needed the allocated memory, or perhaps abort the entire program.)

    Don't get in the habit of assuming that a single, simple call to malloc will "always" succeed. Don't make excuses like "this program doesn't use much memory to begin with, and I'm only allocating 10 bytes here, so how can it possibly fail?" For one thing, there are more reasons for malloc to fail--and return a null pointer--than that there was no more memory. Typically, malloc will also return a null pointer if it is able to detect that you have misused some of the memory that you have previously allocated, perhaps by writing to more of it than you asked for. In this case, malloc is trying to tell you something, something you need to know, and although its voice is small (and although tracking down the problem that it's complaining about may be difficult), you will only have more problems, and more difficult to track down, if malloc returns a null pointer but you then use that pointer as if it were valid. (As an example of how it can be alarmingly easy to misuse the memory that malloc gives you, consider this hypothetical scrap of code for making a dynamically-allocated copy of a string:

char *copystring = malloc(strlen(originalstring)) /* Beware... */
if(copystring != NULL)
strcpy(copystring, originalstring);
Hint: what about the \0 that terminates the string?)

    In a program that allocates a lot of different pieces of memory for a lot of different things, it can be a real nuisance to have to check each pointer returned from each call to malloc to make sure it's not null. One popular shortcut is to define a "wrapper" function around malloc, which calls malloc and checks the return value in one central place. For example, the adventure game uses the function

#include <stdio.h>
#include <stdlib.h>
#include "chkmalloc.h"

void *chkmalloc(size_t sz)
{
    void *ret = malloc(sz);
    if(ret == NULL)
{
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
    return ret;
}

One way to think about chkmalloc is that it centralizes the test on malloc's return value. Another way of thinking about it is that it is a special, alternate version of malloc that never returns NULL. (The fact that it never returns NULL does not mean that it never fails, but just that if/when it does fail, it signifies this by calling exit instead of returning NULL.) Aborting the entire program when a call to malloc fails may seem draconian, and there are programs (e.g. text editors) for which it would be a completely unacceptable strategy, but it's fine for our purposes, especially if it doesn't happen very often. (In any case, aborting the program cleanly with a message like "Out of memory" is still vastly preferable to crashing horribly and mysteriously, which is what programs that don't check malloc's return value eventually do.)

    Another area of concern is that when you're calling free and realloc, there are more ways for pointers to become invalid. For example, consider the code

/* p is known to have come from malloc() */
free(p);

After calling free, is p valid or invalid? C uses pass-by-value, so p's value hasn't changed. (The free function couldn't change it if it tried.) But p is most definitely now invalid; it no longer points to memory which the program can use. However, it does still point just where it used to, so if the program accidentally uses it, there will still seem to be data there, except that the data will be sitting in memory which may now have been allocated to "someone else"! Therefore, if the variable p persists (that is, if it's something other than a local variable that's about to disappear when its function returns, or a pointer field within a structure which is all about to disappear), it would probably be a good idea to set p to NULL:

 free(p);
p = NULL;

(Of course, setting p to NULL only accomplishes something if later uses of p check it before using it.)

    Finally, let's think about realloc. realloc, remember, attempts to enlarge a chunk of memory which we originally obtained from malloc. (It lets us change our mind about how much memory we had asked for.) But realloc is not always able to enlarge a chunk of memory in-place; sometimes it must go elsewhere in memory to find a contiguous piece of memory big enough to satisfy the enlargement request. So what about this code?

newp = realloc(oldp, newsize);

Is oldp valid or invalid after this call? It depends on whether realloc returned the old pointer value or not (that is, on whether it was able to enlarge the memory block in-place or had to go elsewhere). 

Most of the time, you will use realloc something like this:

newp = realloc(p, newsize);
if(newp != NULL)
{
/* success; got newsize */
p = newp;
}
else 
{
/* failure; p still points to block of old size */
}

With a setup like this, p remains valid, and newp is a temporary variable which we don't use further after testing it and perhaps assigning it to p.

    A final issue concerns pointer aliases. If several pointers point into the same block of memory, and if that block of memory moves or disappears, all the old pointers become invalid. If you have a sequence of code which amounts to

p2 = p;
...
free(p);
p = NULL;

then setting p to NULL may not have been sufficient, because p2 just became invalid, too, and may also need setting to NULL. The situation is particularly tricky with realloc: suppose that you have a pointer to a chunk of memory:

char *p = malloc(10);

and another pointer which points within that chunk:

char *p2 = p + 5;

Now, if you reallocate p, and if realloc has to go elsewhere and so returns a different pointer value which you assign to p, you've also got to fix up p2, because it just had the rug yanked out from under it, and is now invalid. To keep p2 up-to-date, you might use code like this:

int p2offset = p2 - p;
newp = realloc(p, newsize);
if(newp != NULL)
{
/* success; got newsize */
p = newp;
p2 = p + p2offset;
}
else
{
/* failure; p and p2 still point to block of old size */
}

Before calling realloc, we record (in the int variable p2offset) how far beyond p the secondary pointer p2 used to point, so that we can generate a corresponding new value of p2 if p moves.

This page by Steve Summit // Copyright 1996-1999 //

Thursday, April 9, 2015

Integrating Cppcheck into Atmel Studio 6.2.

Introduction.

Static analysis tools are very useful. And it's a good idea to use them frequently.
Since I am mostly using Atmel Stuio as my IDE, it seems natural to try and integrate all possible static analysis tools right into it than use them in standalone manner.

Tools I've tried so far are Cppcheck and PC-Lint. The former is freeware and has GUI application where you can test the whole project folder.
The latter is not free, but it is a nightmare to use with GCC compiler - there's no any nice instructions on how to set it up for GCC. I did all the steps from readme files of PC-Lint, but in my case there were a lot of  errors after invoking GNU Make and I didn't really want to dig into it to make it work.

Instead, I downloaded Visual Lint, which has integration of PC-Lint into Atmel Studio 6.1 and 6.2, although even this way needs some manual Windows registry editing to make things work. More to say, Visual Lint still uses all PC-Lint configuration and option files, so even if it seems to work now, I'm still not sure it works how it should work. I'll take a more closer look on working with Visual Lint and post about it later. One more thing - Visual Lint is not freeware, it has Trial version which works for 30 days. Seems enough to decide whether you need it or not.

Now, let's get to integrating free Cppcheck into Atmel Studio.

Integration of Cppcheck into Atmel Studio.

This article is where I got the method and description.

First, get Cppcheck from their site and install it.

Then, you may see that there're integration plugins for popular IDEs, including Visual Studio.
And since Atmel Studio is based on VS, it seems appropriate to use VS plugin.
Unfortunately, it didn't work for me.

I also found somewhere VSIX plugin for Atmel Studio 6.0, but that didn't work either.

The solution is to use Cppcheck as External Tool. The procedure of integrating is usual for Visual Studio and the same with Atmel Studio.

In Atmel Studio, open Tools-->External Tools.
Click Add and fill in forms as seen on this screenshot:


You can change arguments as you wish to get different level of testing and reporting.

After that, Cppcheck appears in External Tools menu:


Using Cppcheck under Atmel Studio.

It can be used in following way. When source file opened in Atmel Studio, just click Cppcheck in External Tools and it will perform static analisys of this file. Any messages will be shown in Output window.
Here's an example of Error message from Cppcheck:

The example of arguments shown previously works for testing only current source file. To test all files in project folder, just change $(ItemPath) to $(ItemDir).

Then, you can experiment with different flags. Try and find what combination works better for you: maybe it's preferred to check only for critical errors in code, or maybe it's nice to have warnings about style or performance issues.

This is flags I found useful for me:
--force - forces checking of all possible #IFDEFs; could be slow, but is a must for big projects
--includes-file=$(EXTRA_INCLUDE_PATHS_ARM)" - in my case EXTRA_INCLUDE_PATHS_ARM is a system path variable showing path for text file with paths of all header files from GCC-ARM toolchain.
-q or --quiet - quiet mode, suppresses service messages from Cppcheck
-j 4 - to use all four cores of CPU for faster testing
--enable=warning,style,performance - enable more tests
--inconclusive - shows warnings even if Cppcheck is not sure if it's really and error. There may be false positives, each such warning should be closely investigated whether it really needs any correction.

Full list of checks performed by Cppcheck is here.

Why this blog exists.

Well, the idea is that there's a lot of useful stuff on the web, no matter if is it work related or something else.

And usually, when I need something, I just search for it. But sometimes old links became broken, or whole sites move, losing their content. And when this happens, just bookmarking the links doesn't work.

So here I am going to save what I think is useful in form of pure text and pictures. It may (and will) contain material from other blogs, articles etc. and if I take something from other people, I'll always provide the links in hope that it doesn't infringe anyone's rights.