The fun part of writing a book on a brand new product is that it is never finished. A new product is just like a living organism. It keeps moving, changing and growing under our eyes. Since I started writing the book in April 2007 many things have changed in the PIC32, its libraries and the tools that support it.
In the following I will try to keep track of the changes that affect the code examples and in general the content of the book so that you will be able to continue using the material presented even when using new versions of the MPLAB IDE, C compiler and tools.
MPLAB X Projects and XC32 Compiler Conversion
80 MHz operation!
The first shocking you will have when reading the new Microchip literature (and web site) is that the PIC32 is now rated for 80MHz operation. A 10%+ increase in performance over what was originally announced and above what I used as a reference in all examples in the book. You are free to modify the configuration bit settings to take advantage of the increased performance available, but remember that some exercises will require additional adjustments to the timings to keep things working.
Example of configuration bit settings for 80MHz operation:
#pragma config POSCMOD=XT, FNOSC=PRIPLL
#pragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_20, FPLLODIV=DIV_1
#pragma config FPBDIV=DIV_2, FWDTEN=OFF, CP=OFF, BWP=OFF
80MHz Peripheral BusThe second surprise will come when you will realize that now the peripheral bus is allowed to operate at 80MHz as well. This has a profound impact in on the performance of all peripherals. For example the UART modules can now operate at up to 20M baud, and toggling an I/O pin you could actually produce a 40MHz square wave (not that I would recommend it).
As a side effect though, the system.h library has changed behavior with regards to what is now considered the best performance setting! When you invoke the SYSTEMConfigPerformance( FCY) function passing a parameter >40MHz (as we do in the explore.c library used in many examples in the book) the Peripheral Bus divider is now set to 1:1 (whereas previously it was limited to 1:2) modifying the default setting provided by the Configuration Bit settings. In other words, all the peripherals will now be running at twice the speed we originally planned on!
There are several possible alternative fixes:
- Make sure to restore the OSC_PB_DIV setting immediately after the SYSTEMConfigPerformance() call:
- Use the new SYSTEMConfig( ) function that updates only the features you "approve" and specify in the second parameter:
- Create your own custom configuration function using any or all of the steps indicated in the examples of chapter 7. As a side benefit, you get to choose the name of the function! Please submit your ideas, I will publish the most entertaining ones...
- Modify the examples code to take advantage of the increased Peripheral Bus frequency.
For example, in the example code of chapter 7, you will need to modify the constant used to scale the timer results to consider the increased bus speed:
// read the timer count
t = ReadTimer45();
f = t/80E6;
PLIB libraries updatesSince version 1.03 of the MPLAB C32 compiler, the DMA library has changed a little to improve the interface consistency with the other libraries/modules.
Two modifications are required to keep the examples in the book (chapters 12 and following) working:
- The parameter DMA_OPEN_NORM, used in the DmaChnOpen() function is renamed DMA_OPEN_DEFAULT instead
- The function DmaChnWriteControlFlags() is renamed
- Macros "mPowerSaveSleep" and "mPowerSaveIdle" are now offered as functions:
use PowerSaveSleep() and PowerSaveIdle() instead
- Page 41, third paragraph, I state that the OpenTimer1() library function does not clear the TMR1 register.
This is not true anymore, the library has been updated to include this feature.
The more recent versions of the MPLAB C32 compiler (v1.6 and later) have changed the way interrupt nesting is defined by default by making it automatically Enabled!
The effect of this change is that of making part of the "nesting.c" example (pages 97-98) irrelevant if not misleading.
Since nesting is always automatically enabled upon entry in an ISR, using the asm( ei); command (or commenting it out) produces always the same result: the TMR3 interrupt preempts the TMR2 ISR (while(1) loop).
From this point though the simulation will not proceed as described at step 9 (page 97 and following) but the interrupt will keep occurring continuously preventing the execution to proceed through the next few instruction and up to the increment of the counter.
In fact the nested interrupt will fail to update the IPL register with the proper TMR3 interrupt priority level (IPL3), continuing to use the IPL1 value instead as defined in the __ISR macro.
This behavior could not be observed with original compiler setting (nesting disabled by default) because the "EI" instruction was delayed until after the entire interrupt ISR prologue giving the processor time to reach the breakpoint if only barely.
A new macro "__ISR_SINGLE()" has been introduced to handle properly such cases. At the cost of a slightly longer prologue, each ISR entry will now make sure to set the correct corresponding Interrupt Priority Level.