Archive for the Warnings Category

Updating Chapter 5

A lot of work has been done in MPLAB C30 rev 3.02 to perfect the management of interrupts and it affects the examples presented in the book in a number of ways.

A) Let’s start with the simplest change, the processor interrupt level (represented by 3 bits in the status register) and defined as a bit-field in the “p24fj128ga010.h” include file, has changed name, it is now spelled “_IPL” rather than just “_IP”. I am not sure where, but they tell me it was causing a possible name conflict. The fix is quick and does not require further explanation.

B) More worrisome, but not as critical as you might think, is a new warning that is generated now for every new interrupt service routine defined in the code examples:
Interrupts.c: xx: warning:  PSV model not specified for ‘_xxInterrupt’;
This is due to some changes implemented in the compiler to facilitate the implementation of the CodeGuard(tm) technology. Nothing special, really, all that happens is that the compiler does NOT assume that the “PSV window” (unfortunately this is a feature we learn about only in the next Chapter 6)  is under his control. It actually assumes the opposite now (that our application is managing it ), and therefore it takes preventive actions to make sure it is not corrupted during the ISR execution (saving the PSV value on the stack before the ISR and restoring its value after it).  And it tells us about it:
assuming ‘auto_psv’ this may affect latency

as it warns us that this “precautionary” push and pop require a few extra instructions, that affect the overall interrupt latency.
The fact is that none of the examples in the book makes any attempt at modifying the PSV and the default value (assigned by the compiler) is used throughout.

Unfortunately there is no global switch (compiler option) that can change the compiler assumptions and we have to either accept the (redundant)  warning and the increased latency (just a couple of cycles) or remember to add an attribute to each and every interrupt routine we define:
__attribute__((no_auto_psv)) 

Did I ever mention before how I  don’t care for the quadruple underscore and double parenthesis required by all GNU compilers to extend the C syntax?

For example:

void _ISR  __attribute__((no_auto_psv))  _T1Interrupt( void)
{
A less distracting option would be to define a new macro:

#define _NOPSV  __attribute__((no_auto_psv))

and use it as in the following example:

void _ISR  _NOPSV  _T1Interrupt( void)
{
We could be tempted to modify directly the definition of the _ISR macro to include the additional no_auto_psv attribute. But the _ISR macro is defined inside the device “p24fj128ga010.h” include file, and it is not considered a safe practice to modify standard include files, actually that is a VERY bad idea…

For now, since this is the first chapter were we learn to declare and use interrupt service routines, I will propose we use the _NOPSV macro explicitly.

Here are the three source codes used alternatively in the interrupt.mcp project:

1- Interrupts.c

2- Interrupts 32kHz

3- Interrupts RTCC

About main() and Advanced Warnings

The main() function is … a function and as such it is expected to either have a return value of a declared type (int, char …) or no return value at all in which case it should be declared using the keyword void. But from all the examples in the book you will notice that I do not use either of the two options. This is because, as part of my personal programming style, I like to use a “shortcut” that is part of the C language since the beginning of times (K&R). In fact, by default, declaring the main() function without specifying a type, I am telling the C compiler to assume it will be int.

Further, since we are not using an operating system, it does not matter if the main() function ever returns any value and therefore, in all the examples, you will notice that there is no return statement at the end of main() (by the way, we never return at all, as we typically stay in the main loop forever…

This is all nice and dandy, and can go completely unnoticed, until you enable the “advanced warnings” in the project configuration dialog box (Projects>Build Options for project”).

Project Build Options Dialog box

Enabling the Advanced Warnings is, in principle, a very good idea (and is now a default setting when you create a new project with MPLAB) since you can potentially expose a larger number of errors in your code, but it also creates a large number of “false alarms” as most of the “default” behaviors of the C compiler are now seen with a more critical eye…

So, if the advanced warnings are enabled, you will get a couple of extra error warnings:

  1. The compiler will demand that you give main() a type
  2. Depending if you choose to comply and declare main as
    a) int main( void)
    { …
    }
    or
    b) void main( void)
    { …
    }
    you are bound to get more warnings

If you chose option a), you will be asked to provide at least one return statement within the main function…

If you chose option b), you will receive another warning reminding you that main() was truly meant to return an integer …

In other words, you cannot win, because even if you chose a) and then add a useless return statement at the end of the main() function, you will be reminded later that the code is “unreachable” … which is profoundly true, since the application will typically remain in the main loop … forever.

My recommendation?

  1. Decide what is going to work best for your programming style.
  2. Tolerate the warnings, they are just that: warnings! They are not going to prevent your program from running correctly and they do not mean that there is necessarily anything wrong with your code,
  3. (and/or) Disable the advanced warnings immediately or just once you have convinced yourself that there is nothing ELSE wrong with your code.

The experts among you will learn/know how to disable individual warnings and will bypass all of the above…

|