Archive for January 2008

More on Chapter 5 Tips and Tricks and builtin functions

If after yesterday’s posting you though things were getting ugly (I agree), you will be pleased to learn that since the introduction of MPLAB C30 v3.02 things have improved considerably. After all, performing the unlock sequences should not be an “impossible” task in C requiring super advanced inline assembly programming skills!

Four new builtin functions of the compiler come to our rescue:

  • __builtin_write_RTCWEN( void)
  • __builtin_write_NVM( void);
  • __builtin_write_OSCCONL( unsigned char value);
  • __builtin_write_OSCCONH( unsigned char value);

[Note: a double underscore preceeds each function name]
They give us complete access to the RCFGCAL, NVM and OSCCON control registers by performing the proper unlock sequences.

You will find a complete (long) list of builtin functions well documented in Appendix B of the MPLAB C30 compiler.

Chapter 5 Tips and Tricks

It is in Chapter 5 that we present for the first time the use of inline assembly. As a general rule in the book, this is a compromise accepted only in cases where we need to perform a task otherwise “impossible” if using only the C language, in this case: the unlock sequences of the OSCCON register and the RTCC register.

Both unlock sequences require the use of inline assembly because they must be performed in a very strict order, something we cannot “count” on the compiler to respect. Compilers are somewhat rebellious, they like to be in control of things and to be free to accomplish their tasks in the way THEY judge to be the most appropriate!

The inline assembly codes presented in the Tips and Tricks section works, but as I learned recently they are not optimal, especially when using the latest version of the MPLAB C30 compiler. A better way to do things is to still use inline assembly but, thanks to a special notation, let the compiler choose at least the registers to be used.

Here is an example showing the RTCC unlock sequence (and RTCWREN bit set) as recommended to me by the true MPLAB C30 gurus:

{int *nvmkey = &NVMKEY;
int v1 = 0×55;
asm volatile(”mov %0,[%1]\n\t”
“com %0,%0\n\t”
“mov %0,[%1]\n\t”
“bset RCFGCAL,#13″ : “+r”(v1) : “r”(nvmkey));
}

First of all notice how two parameters (%0 and %1) are replacing what before was the explicit use of processor registers. Now the choice is left to the compiler so that there is no interference/limitation whatsoever with the compiler register optimization algorithms.

Notice how the four assembly statements are passed inside a single inline assembly statement using a special escape sequence to terminate each line (\n\t) and concatenate with the next one.

Finally notice how the statement contains two additional parameters separated by “:”. They inform the compiler of what kind of registers will be required and what kind of use we will make of them.

You will find more details on this special notation inside the MPLAB C30 compiler User Guide chapter 8. Some pretty advanced stuff!

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

Flying along the Salt River

Probably most of you will think of Arizona as one flat desert place, but that is quite a mistake. Actually 70% or Arizona surface is covered by mountainous terrain. It is true though that 90% of the population do live in the arid and flat part of the state and a large portion of that population is specifically concentrated in the Phoenix metropolitan area.

From Chandler, one of the suburbs south of Phoenix where I keep my airplane hangared, it takes less than 10 min. of flying time to get to 8,000 ft peaks, canyons and lakes of breathtaking beauty.

This Sunday I had a special mission. Dick, my neighbor, was planning one of his fishing expeditions along the Salt River. He typically adventures in such remote areas with his jeep relying on his GPS and the available topo maps, but this time he had asked me to help him prospect the area by the air before adventuring further in where his maps were showing no access.

The air was extremely smooth on a freezing, but sunny, morning like only Arizona can offer in January. We transitioned over Falcon Field and then climbed to 6,000 feet to reach lake Roosvelt and proceed on to follow the Salt River.

six pack

My mistake was not to bring the digital camera with me this time so, I apologize in advance, you will have to rely only on the few low-res pictures we took with my cell phone camera…

Salt River Crossing

After approx. 30min. we passed the gorge, where the only bridge that crosses the river takes the highway 60 north toward Showlow, and we continued East along the steeper part of the river canyons.

There was still snow on the canyon walls covered partially by forest and exposed to the North.

snow

We followed several faint tracks and marked the points on the plane’s GPS where we believed they could be usable to reach the river.

white river

Flying slowly and following the river twists and turns, after about an hour, we reached the point where the Black river and White river merge. A few miles further up, we landed at WhiteRiver(E24), deep inside the Apache Indian reservation, for a little rest.

For our return, we picked a lazy and panoramic route west, passing over the huge mines of Miami (AZ)
Miami

overflying Superior and then reaching Chandler back from the south east, just skimming the San Tan mountains and the busy Williams airport airspace.

2.8 hours of cross country flying in smooth clear air, pure bliss!

Updating Chapter 4

There are no changes required to the code in chapter 4 after the upgrade to MPLAB C30 v.3.02. But there are some changes in MPLAB 8.00 behavior that will have you puzzled when looking for the subroutines (library modules) used by the compiler for the long long (64-bit) integer multiplications.

In fact, the listing in the Disassembly window will not show anymore the long long multiplication routine muldi3.c as MPLAB 7.40 and older versions did. In a way the Disassembly listing has been cleaned up a bit, but don’t despair. If you follow the next few steps you’ll be able to find the missing routine anyway:

  1. Take note of the subroutine address, the number after the rcall mnemonic:
    (00280 in my case)
    long long mul
  2. Open the Program Memory Window and make sure to select the Symbolic view
    (use the tabs at the bottom left corner of the window)
  3. Press CTRL+F to open the search dialog box and type the address (00280) or simply scroll down the window until you reach the address.
    00280
  4. There you will recognize the label __muldi3 marking the entry point of the 64-bit multiplication routine used by the compiler. (That’s pretty dry reading, isn’t it?)

Looking at the exercises proposed in Chapter 4:

  1. Using Timer2 to self time the number of cycles used by each arithmetic operation is just a good idea. Exercise 4-1
    Most/all operations will fall withing the 16-bit resolution of the timer (within 65,536 cycles) so that it is easy to obtain all the cycle counts in a single watch window shot:
    multiplications
    Notice how some of the values changed a little bit since version 1.30 of the MPLAB C30 compiler?
  2. Checking all the divisions at once is just as simple now: Excercise 4-2
    Here are the results:
    divisions
    Do you notice anything interesting? Who said float math has to be always slower than integer?
  3. Trigonometric operations (sin()) is performed using polynomial approximations and therefore multiple additions and multiplications. This has to be “hard”… Excercise 4-3
    trig
    Looking at these numbers you can almost guess the order of the polynomials…
  4. Complex math as well is composed of multiple operations of the fundamental type (integer/float): Excercise 4-4
    complex

Updating Chapter 3

Chapter 3 does not require any special consideration after the upgrade to MPLAB C30 v.3.02. So we will take the opportunity to work on the examples proposed:

  1. Sensing a button before starting the sequence is a step in the right direction to help the visual synchronization as long as the operator has good motion coordination skills. Here is the simple enough code that assumes the leftmost button on the Explorer 16 demonstration board (connected to PORTD pin 6 -RD6) is used: Exercise 3-1
  2. Things can be improved further if a little electro-mechanical ingenuity is used. Adding a pendulum and a second contact to detect the beginning of the hand sweep and the counter hand sweep to produce a reversed sequence (a good opportunity to show a for loop counting down). The following code will assume that the second switch is connected in parallel to the rightmost button on the Explorer16 (PORTD pin 13 -RD13): Exercise 3-2

As I am writing this, I feel the urge to explore other more sophisticated options. For example, how about checking the two switches for a few sweeps timing the hand motion and later starting the display after scaling/optimizing the delay intervals  to obtain a single message in both directions and possibly perfectly “centered”?  The algorithm could also constantly adjust the timing at each subsequent hand movement… oh how sweet!?

Updating Chapter 2

Continuing with the review of the code examples for the latest revision of the MPLAB C30 compiler (3.02) it is time to look at Chapter 2.

There is a single example used in this chapter and the code needs no massaging beside remembering to disable the advanced warnings or otherwise ignore the obvious complaint about main() type (see previous post).

Here is the code: Loop.c

Notice that the definition of DELAY can be shortened to just 16 to speed up considerably (1000 x) the simulation when using only MPLAB SIM and the Logic Analyzer window.

We can also take the opportunity to complete the exercises proposed at the end of the chapter:

  1. The first exercise required us to replace the simple on/off sequence with a count.
    Declaring an 8-bit integer called count (this might require some of you to peek into chapter 4 already) we get the mission accomplished quickly: Exercise 2-1.
  2. The second exercise required us to replace the on/off sequence with a rotating pattern. To make things more interesting we will choose a 16-bit variable that we will call pattern. The exercise is actually quite valuable because it forces us to recognize the fact that in C language there is no concept of rotation, but there are only shift operators. So unless we make use of inline assembly, we are forced to take things in our hands and perform a three steps sequence: Exercise 2-2. Commenting and un-commenting different sections you will see examples of right and left rotations.
    Adding all PORTA pins to the channels of the Logic Analizer will help get the full picture:
    shift right

The C programming experts among you will not fail to recognize the opportunity to use special “shortcuts” using advanced operators such as +=, >>=, <<= and some conditional expressions trickery.

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…

Setting the configuration bits

Speaking of configuration bits, in the book I have made clear from the beginning that I would expect the reader to set them always in a specific configuration chosen for debugging with the Explorer16 board. In fact the checklists titled “Device Configuration for Explorer16 demonstration board” guides the reader through a few steps accessing the “Configure” menu and opening the Configuration Bits dialog box. This dialog box in particular has been enhanced in the latest versions of MPLAB to include one new checkbox at the top titled: “Configuration Bits set in Code“. In order to select the configuration manually, as suggested in the book, this checkbox must be unchecked!

On the other side, with the checkbox checked, we can take advantage of this new feature and make our configuration part of the source code. Before we delve into the details of the syntax to be used, we must consider the pros and cons that come with it, let’s start with the pros:

  1. Documentation: when publishing the code, the configuration is automatically included
  2. Permanent association: code and configuration are now permanently joined

On the other side the cons include:

  1. Device dependence: the configuration is strictly related to the device chosen
  2. Cryptic: the syntax as we well see shortly is far from readable or self explanatory
  3. Repetitive: we would need to include the same lines of code at the top of each project in the book or hide them in an include file ad hoc (hence voiding the number 1 pro: documentation)

My preference would be for the first chapters to maintain the use of the manual configuration, which is persistent in MPLAB as we create new projects and more readable. I ‘d suggest a transition to the configuration in code for the later chapters and the more advanced projects.

PIC24 Device Configuration in Code

The MPLAB C30 compiler does not offer any special extension to take care of the device configuration bits, but rather leaves the job to the linker. After all, it is a matter of setting a few bits (initializing) a couple of special locations in FLASH memory, a task easily accomplished by a few pre-processor macros (and the linker).

You will find them inside the device include file “p24fj128ga010.h” almost at the very end of the long long file, including examples of their use and some useful hints on where to place them:

/*
** Only one invocation of CONFIG1 should appear in a project,
** at the top of a C source file (outside of any function).
**
** The following constants can be used to set CONFIG1.
** Multiple options may be combined, as shown:
**
** _CONFIG1( OPT1_ON & OPT2_OFF & OPT3_PLL )

*/

To match the device configuration proposed in the book’s checklists, place the following two lines of code at the top of the main source code of each project (but after the #include <p24…> statement):

_CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & ICS_PGx2 & FWDTEN_OFF)

_CONFIG2( FNOSC_PRIPLL & FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_HS)

Now you understand what I meant above when I mentioned the code to be a bit cryptic…

MPLAB C30 v 3.02

Part of the challenge of writing a book based on new tools and products is to make sure that the content remains valid and relevant as they tend to evolve quickly in the months and years after the book release. In our case, both the PIC24 product line and most of the tools surrounding it have changed considerably since the book release in March. This is without even considering the fact that most of the actual book content was written on average another 12 months before publication. Think of all the new PIC24 models introduced in 2007 (40+), the new peripherals introduced (think of the Peripheral Pin Select) and the changes in the MPLAB IDE , the MPLAB SIM simulator stimulus interface etc… The recent release of version 3.02 of the MPLAB C30 compiler represents a tipping point for the projects in the book…

We need to go back chapter by chapter and re-check all the projects to provide the new readers a better cleaner experience. In fact we can do this together…

Let’s start. Here are my notes for Chapter 1: The First Flight

1- I had to re-build the workspace. The latest version of MPLAB uses a different window manager. The docking mechanism has changed in particular… so close all the windows (Including the Project and the Output window) and then re-open them again. Reposition the windows as you prefer.

2- Some readers have asked for separate files to be offered for each phase of experimentation in the project. So I have now saved 4 separate files:

  1. Hello1. ccontains the very first experiment with PORTA.
  2. Hello2.c contains the fix to make PORTA output pins work.
  3. Hello3.c contains the test of PORTB.
  4. Hello4.c contains the fix required to re-gain control of the analog pins on PORTB.

NOTE: A common problem reported by many readers (who did not use the checklists) is the lack of control of 4 pins of PORTA. They are in particular pin RA0, RA1, RA4 and RA5 and they seem to misbehave no matter what they do to the TRISA and PORTA registers. It is the JTAG port that takes control of those pins when enabled. Since we don’t use it, at least none of the Microchip development tools does, disable it setting the appropriate configuration bit.

Configuration Bits