# Squidly’s Progress

I am very happy to announce that Teuthida Technologies has been accepted into the  prestigious Microchip Authorized Design Partner program!

Teuthida Technologies specializes in designing with Microchip products.

This program grants greater access to the expertise, knowledge  and capabilities of Microchip’s world class engineering teams, tools, software, and manufacturing might! These many benefits, in turn, will allow  this web site and it’s associated consultancy, to be even better at presenting leading edge embedded systems development information, ideas and solutions!

I would personally like to thank Microchip staffers: Donna Mason, Andre Nemat, and Bret Walters for helping me and Teuthida Technologies so much in making this possible.

Again, Thank You!

Peter Camilleri (aka Squidly Jones)

PS: The Early Bird Discount for this years Microchip Masters conference ends TODAY!!! (April 27, 2012) Don’t miss out!!!

# Spiro Graphic Memories

[Update] If you are looking for information on the Spirograph toy, click here.

In examining the PIC 32 C compiler in C32 Impressions, there was a pressing need for several programs to stand in as benchmarks. One of those programs was a graphics applet that drew images inspired by the old Spirograph toy. As requested by a reader, this posting takes a look at the story behind the pretty picture.

When I was a kid, one of my favorite toys was my  Super Spirograph. This toy consisted of a number of gear toothed wheels, disks and inter-lockable shapes that when meshed together and driven by hand with a pen, would draw really cool pictures on paper. It was prone to having the little teeth slip, or the gears wobbling and ruining the picture, but I loved the toy all the same.

Years later in High School Math class, I was introduced to graphing trigonometric functions using polar coordinates. As difficult as it was to create those plots by hand (back then, fire was still a novelty so this was way before computers in the classroom) I still noted the similarity to the images created by my Spirograph.

A few years later in college, I was working as a research assistant at York University for Dr Keith Aldridge. I was given the task of writing device control software for a Calcomp pen plotter connected to an old Interdata 5/16 mini-computer. The purpose of this software was to help produce camera ready artwork for the graphs in the various papers and thesis of the post graduate students. The scaling, data manipulation, and string processing were all done in FORTRAN. To test my routines, sample data was needed. Thinking back to my childhood toy, I wrote a program to generate data sets based on a simple model of the Spirograph. The results were quite striking and beautiful. Regrettably, those prints are long lost.

It turns out that my code was not really simulating a Spirograph toy, but instead was producing a set of plots closely related to a family of curves called Rose plots. The basic formula for a Rose plot is:

$\text{For } \phi \text{ in } 0 \dots 2D\pi: r = cos( \frac{N}{D} \phi)$

Rose plots for various values of N and D, are pictured to the left.

While Rose plots are pretty close, they are not quite what I came up with. Rose plots all pass through the center point. In a pen plotter that is not a good thing as the center of the page would become saturated with ink and tear. I needed a way to simulate the wider radius of the Spirograph drawing wheel. I did this by adding a unit circle to my polar plot data like this:

$\text{For } \phi \text{ in } 0 \dots 2D\pi: r = 1 + A cos( \frac{N}{D} \phi)$

where A is typically 0.7. and N and D are relatively prime whole numbers.

So we come to the end. Just for the record, the benchmark sample used A=0.8, N=31 and D=30 to produce the figure on the left. Pretty, isn’t it?

Peter Camilleri (aka Squidly Jones)

# Some Gnarly Bits

Given recent posts on Abstraction and its application in making devices (like the M25P80) easier to deal with, the reader might be under the impression that the workings of the system underneath the covers are not a real concern; A sort of “Out of sight, out of mind” attitude. Well the reality is much more like “What you don’t know can hurt you!”

A very common example of this sort of thing in embedded systems is the attachment of various devices to General Purpose Input/Output (GPIO) pins. In the MMB32 development system for example, the LCD CS pin is connected to Port F, bit number 12. Conveniently, the PIC32 “C” Peripheral Libraries define an easy-to-use variable for this called _LATF12. It is very easy to use a macro to give this bit a more meaningful name:

#define LCD_CS_LAT_BIT      _LATF12

Then in my code, to deselect the LCD I simply write:

LCD_CS_LAT_BIT = 1;

And that would appear to be the end of that! Of course, it is not; the above code is a “time-bomb” that could go off with serious consequences. A very nice feature of MPLAB-X is a dis-assembly view of the generated code with source code interspersed at appropriate points. Below is the above code and its implementation in MIPS assembly language:

420:                    LCD_CS_LAT_BIT = 1;
9D008958 3C03BF88   LUI V1, -16504
9D00895C 8C626160   LW V0, 24928(V1)
9D008960 24040001   ADDIU A0, ZERO, 1
9D008964 7C826304   INS V0, A0, 12, 1
9D008968 AC626160   SW V0, 24928(V1)

It’s not necessary to be an expert in MIPS assembler, the key points here are that the value of Port F is read using an LW instruction, modified in the next two instructions, and the modified value is written back to Port F using an SW instruction. How can this code be harmful? The fault is that it is not an  “Atomic Operation“!

Consider that Port F, having many bits, might be connected to more than one device besides the LCD. Further consider that this other device might be controlled by code in another task or perhaps an interrupt service routine. So now, contemplate the following scenario with an LCD and a Grunge Master 6000 (The 6000 is less costly than the 9000 but has more features than the 3000) both on Port F:

1. The LW instruction reads the current value of Port F.
2. The code modifies this value, setting bit number 12.
3. An interrupt occurs. While the interrupt is being processed, some other part of Port F is modified to send a command to the Grunge Master 6000.
4. The interrupt completes and normal execution resumes.
5. The SW instruction writes it’s modified value to Port F without the changes made during the interrupt! A BUG!

This nasty little bug would take the form of the Grunge Master 6000 command being “randomly” truncated. The odds of catching it with a break-point are extremely low. This is the sort of bug that has people saying things like “HELP! My Grunge Master 6000 code works perfectly until I add my LCD driver code.”

So how can this problem be circumvented? The answer is that the operations on Port F need to be indivisible or atomic. There cannot be a middle part where an interrupt could cause trouble. Some common answers include:

• Disable all interrupts while modifying the Port bits. This way the sensitive area of code is protected. The downside is that means turning interrupts off a lot and adding complexity to the code and increases interrupt latency. Further, it is easy to miss a spot and leave a vulnerability in the code.
• The CPU could have built in, atomic, instructions for setting, clearing and toggling bits. This is actually the case of 8 and 16 bit PICs. By performing the bit manipulation in a single, uninterruptable instruction, there is not a middle section that needs to be protected. Alas, the 32 bit PICs do not have these instructions.
• Microchip gave the 32 the PICs something else. Most peripheral registers have 3 “shadow” registers called the CLR, SET and INV registers. Writes to these registers perform Boolean operations on the register that they shadow. These are shown below:
CLR:  Register = Register & ~(Value)
SET:  Register = Register | Value
INV:  Register = Register ^ Value

These Boolean operations are atomic making them safe for use on shared resources without disabling interrupts.

To the left is a snippet from the PIC32 datasheet regarding these shadow registers. Note that reads from the shadow registers yield undefined values. Further note that the atomic nature of the operations applies to all three operations, not just INV or toggle as seems to be implied in the datasheet.

So, how does using these registers change the code? For starters, we must stop using the pre-packaged bit definition and switch to a new model. This means new definitions:

// Definitions for the LCD Chip Selct pin.
#define LCD_CS_TRIS_SET   TRISFSET
#define LCD_CS_TRIS_CLR   TRISFCLR
#define LCD_CS_LAT_SET    LATFSET
#define LCD_CS_LAT_CLR    LATFCLR

And the code changes as well:

419:                    // Disable LCD
9D008958 3C02BF88    LUI V0, -16504
9D00895C 24031000    ADDIU V1, ZERO, 4096
9D008960 AC436168    SW V1, 24936(V0)

The code is now safe. The update to Port F is accomplished atomically by the SW instruction and the sequence is eight bytes shorter than before as a bonus. The real benefit here though is that Port F is now safe to use for other devices without fear of mind busting interaction bugs ruining your day!

Sometimes, it really does pay to check carefully under the covers. It’s what good engineers do!

As always, comments and suggestions are welcomed and invited.

Peter Camilleri (aka Squidly Jones)

PS: Astute readers will have recognized the Grunge Master 6000 as being somewhat similar to the Grunt Master 6000 introduced in Scott Adams’ Dilbert universe. While similar in a lot of respects, only the Grunge Master is suitable for microprocessor interfacing.

# MMB-32 I/O Workseheets

As I mentioned in my article About the MMB-32 development project I am working with the mikromedia for PIC32 development board for various tutorials, exercises and projects. One slight issue with this board is that there a lot of resources to keep track of and further the boards changed quite a bit from version 1.0 to version 1.1.

Keeping track of all the I/O resources can be daunting and creating projects for a mixed population of 1.0 and 1.1 boards means I need to find common ground. Rather than the error prone process of pouring over tiny, hard-to-read schematics, I created I/O worksheets for each of the types of MMB-32 boards available.

Since they may be of use to other as well, here they are in PDF format:

or if you prefer, both worksheets in the form of a XLSX format spreadsheet:

Port Usage Map

I hope you find them as useful and time saving as I do. As always, your comments and suggestions are invited and welcomed.

Peter Camilleri (aka Squidly Jones)

# The M25P80 Serial Memory Device

This posting will bring together two threads; Non-Volatile Options for parameter storage and the Abstraction of hardware through the use of modular “C” programming techniques.

At the conclusion of the non-volatile options posting, all proposals save one had been rejected. The sole remaining avenue was to store parameter data the the M25P80 SPI Flash Memory device installed in the MMB32 development board. As stated in the that posting, this device is not at all ideal for the task. So let’s take this opportunity to take a closer look at the requirements compared to the device and determine what makes it problematic.

# Capacity

The capacity requirements for parameter storage are very modest. Typically a few hundred or at most a few thousand bytes is more than enough for most applications.

(+) The M25P80 exceeds this need by a large margin with a capacity of 1,048,576 bytes, commonly referred to as one mega-byte. This capacity is so large that it opens up the possibility of other potential uses for the device.

The device should allow arbitrary bytes to be read from the media.

(+) The M25P80 meets this requirement.

# Writing

The device should allow arbitrary bytes to be written to the media.

(–) The M25P80 does not allow the writing of data! Instead data must be written using a two step process in which the media is erased to the value 0xFF and then data is “laid down” using the bit-wise AND of the current media value and the new data. If data is written without an erase, the result is the bit-wise AND of the old and new data.

# Granularity

The device should allow operations to take place on arbitrary locations without concern for alignment or other requirements.

(–) The M25P80 does not allow arbitrary locations. Instead:

• Erase commands operate on either sectors of 65.535 bytes or the entire device.
• The bit-wise AND operation may start on any byte, but a sequence of these bytes may not cross a page (256 byte) boundary.

# Speed

The device should perform all commands at a reasonable speed compared with the expected data update rate and general user interface requirements (< 100 milliseconds).

(–) The M25P80 execution times may be summarized as:

• Read: quick; as fast as the SPI interface. (< 1 microsecond per byte)
• Bit-wise AND: modest; as slow as 5 milliseconds, 0.8 milliseconds typical.
• Erase: very very slow!; up to 20 seconds and only 0.6 seconds typical.

# Endurance

The device should allow 100,000 write cycles.

(+) The M25P80 is rated for at least an endurance of 100,000 erase/write cycles and a data retention specification of 20 years at 55°C.

# Bridging the Gap

At this point, the next step is to use modular programming and abstraction to bridge the gap between the requirements and the actual device. While the gap is rather larger large, potential “deal breakers” of inadequate capacity or endurance are not issues. Instead, the major areas needing attention are the bit-wise AND “writing” of data, erase granularity, slow erase cycles, and write page boundaries.

Figure 1

The semantic gap between the application and the hardware is large enough that it cannot be easily bridged by a single abstraction. That’s why this design uses two: A low level, device driver abstraction and a high level but very simple, file system that presents applications with an easy to use interface to the the storage device. This is illustrated in figure 1.

The low level driver is a fairly simple piece of code that abstracts out the SPI interface, the M25P80 command set and reworks them into a small set of callable “C” functions. This layer does deal with one issue though; the function that writes a data block automatically handles the cases where the block crosses page boundaries and performs the correct sequence of device commands. Thus at least that gap is closed. The function prototypes are listed below:

The balance of the gap is left to higher layers of software to deal with. These will be examined in an upcoming post on the Trivial File System.

As always, comments are invited and welcome!

Peter Camilleri (aka Squidly Jones)

# Magnus Errata Update

I am glad to report that Microchip has updated its PIC32 errata to add a little more clarity to the situation. These issues were discussed in previous posts Magnus Errata 1 and Magnus Errata 2. The specific clarifications are:

Peter Camilleri (aka Squidly Jones)

# Non-Volatile Options

Don’t worry. I am not about to branch into offering investment advice; Especially not the dubious world of the derivatives marketplace. I am instead looking at one of the unresolved issues in my Touch Screen Calibration series; Namely, where do the parameters go when we’ve gathered them? They need to be stored in some sort of non-volatile storage. What are the ideal characteristics of this storage and what do I have on hand in my Mikroe MMB32 development board? Ideally, the storage:

• is non-volatile so that data is not lost when power is removed.
• is permanently attached so that system parameters are always available.
• supports atomic update so that parameters cannot be half written.
• is simple to program so that a lot of program storage is not wasted.

# Plan A

Many microcontrollers have on chip non-volatile resources. A wide selection of PIC chips have on board EEPROM that is an excellent choice for this sort of parameter data. Regrettably the PIC32MX460F512L used in my development board has no on chip EEPROM storage, so this easy option is not available. Still, the part has flash memory that could be pressed into service as EEPROM emulation. I did not look into this option too deeply at this time due to the complexity of the software needed and some doubts as to how it would affect real-time performance by turning off interrupts for long periods of time. I may revisit this at a later time.

# Plan B

If your microcontroller lacks non-volatile storage, an easy, inexpensive option is to utilize a low cost serial EEPROM device. They are  is easy to use and come in I2C bus and SPI bus versions. This is a great idea, except that Mikroe didn’t put one on the development board I’m using. I could easily add an EEPROM but that would be cheating! A sub-variant of this plan are all the modern FRAM and MRAM non-volatile serial RAM devices that are on the market. These offer greater write speed and higher write endurance than EEPROM at a premium price but are still cheating! I wanted to only use resources already on board!

# Plan C

Another approach is to use a battery backed up calendar/clock with ram. Indeed the  PIC32MX460F512L chip has an RTCC module and a plethora of power savings modes. The spec sheet has over 60 line items detailing power consumption so this is not a simple matter. In fact getting the chip into a low power mode is very complex and difficult. Further the PIC32 is not a member of Microchip’s XLP family of low power chips designed for battery powered operation, so the low power modes are not that low. Finally the back-light control circuit for the MMB32 display consumes about 5ma of current even when the display is off. This would drain any battery dead in short order so this option won’t work either.

# Plan D

OK, if the RTCC in the PIC is no help to us, we can add an external RTCC/RAM module. There are many to choose from. Mikroe makes a very nice RTC PROTO Board that has it’s own battery, RTCC and 240 bytes of non-volatile RAM. Perfect, and since it is separate from the PIC32, life is a lot easier code wise since the switch-over to low power mode is handled by the RTCC boards hardware and I shouldn’t have to worry about power thief circuits. This too is cheating, but I purchased one of the Mikroe boards so I will be revisiting this option again at a later time.

# Plan E

OK, so enough of what the MMB32 does not have. What about some non-volatile resources that it does have? Well there are two. The first is an SD memory card slot. This allows access to up to 2 giga-bytes of storage, which is staggering. The downsides are that this is removable storage, so the user can easily remove the memory device with all the essential parameters in it. In order to utilize an SD card, a low level driver is required, and a FAT32 file system to organize the data on that card. That is a lot off complex code that will be difficult to use and will devour resources. Now if a large file system is already needed, the incremental expense is minor to store parameters there. However if you were not already planning in that direction, it is a huge waste of flash memory.

# Plan F

OK we are at the end, and still no closer to our answer. What’s left on our MMB32? Well there is a M25P80 SPI flash memory. It is NOT an EEPROM, it’s not all that flexible, and it’s not an easy chip to use well. Why do I say that? Yes, the full megabyte capacity is great and the SPI interface is simple and straight forward, but while data can be written (well it’s not a write so much as a bit-wise AND operation) one byte at a time, the device needs to be erased before any space can be overwritten. The bad news? The smallest unit that can be erased is an enormous 64K bytes and the erase time is up to 3 seconds! There is a command to erase the whole device but that can take up to 20 seconds! To use this device we need to create for it a file system that is small, simple and works well on this very primitive storage system. That file system is called the Trivial File System and is the subject of a my next posting on this topic.

Peter Camilleri (aka Squidly Jones)

# Abstraction in C

I am going to go out on a limb and state that in my view, the quest from greater Abstraction has been one of the key driving forces in the field of computer science.  Software engineers have long been envious of our electrical engineering cousins who have the luxury of using integrated circuits to contain and hide complexity. On many occasions, I have heard calls for the creation of “software ICs” that would be just as easy to use as hardware ICs.

The first step in this direction was the use of high level languages. Rather than messing about with loading registers, adding and storing results you could simply write A=B+C;  A tangle of branches, jumps and labels was replaced with far more manageable structured constructs; and the concept of assembly language subroutines became the high level language concept of functions. With algebraic notation and structured programming a function could wrap up a complex algorithm into a nice easy to use package. Mission Accomplished!

Except, it doesn’t really work though. The problem is that a function is too limiting. Just as a real IC often has multiple functions, to be useful, so will software ICs. Yes you can make a function do multiple things with an extra “command” parameter, but that is a rather slow, complex, and ugly approach often called “Swiss Army Knife” syndrome. We need to take a number of functions, plus supporting code and data,  and tie them together somehow into a larger unit. That unit was embodied in the concept of a module.

The fact that you are reading this article means that you probably already know the basics of Modular programming in “C”. Modular programming is so essential to “C” programming that even the super silly “Hello World!” program demonstrates it by utilizing the stdio module of the standard “C” library.

#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}

Note that the discipline to organize files along these lines is not enforced by the language and it is possible to create some really horrible messes, but it is not difficult to follow either, so most programmers do so. Now within the header file consider these three declarations:

/* 1 */ extern int FontCount;
/* 2 */ int CountFonts(FONT_ROOT fontRoot);
/* 3 */ extern int TestCode(int testType);

Line 1 is used to declare a variable being exported and line 2, a function prototype which also serves to export the function and finally line 3, declares that the coder does not understand that the “extern” keyword does not apply to function prototypes. Unfortunately, the error in line 3 is so common, that it is allowed, but the spurious “extern” serves no purpose.

More modern languages make modular programming an integral part of the language; the keep-it-simple “C” language provides just enough resources to make it possible. The header file plays the vital role as the Interface to the module. Sometimes, if the abstracted code is of a large scope, we call it a Library or a Framework and the interface gets the fancier title of Application Programming Interface or API.

In the world of computing, many themes often repeat with endless variation. Consider the simple serial port. Most embedded systems have them. The addresses and register details vary, but the basic capabilities are similar. Removing the fiddly distinctions and creating a reusable interface is a perfect example of abstraction in action. In the old days this sort of thing was called a BIOS, but today it goes by the fancier name of Hardware Abstraction Layer or HAL.

In the ideal world, there would be a standardized HAL interface and each vendor would code to that interface. While abstraction is not perfect, it would go a long way toward improving portability. The problem is, such a universal HAL spec does not exist, and even if it did, most vendors do not want it to lead to true portability as this would make it easier for their customers to switch away to other brands.

A most infamous case of this is from the PC programming world. Microsoft created an abstraction called MFC to encapsulate the Windows API and make it easier to write programs. The problem was that Microsoft was in competition with other vendors offering similar systems and did not desire to make it easy to write portable applications. By “coincidence”, the MFC library has so many places where raw Windows programming is required that one pundit stated that “The MFC framework is not so much an encapsulation as a leaky diaper!”

Another example of this sort of problem is the Cortex Microcontroller Software Interface Standard or CMSIS which is supposed to make it easier to move among ARM processors but is plagued with vendor specific deviations and non-standard definitions thus making the task of porting from one ARM core to another about as hard as porting from ARM to an unrelated core. Don’t get me wrong, I think CMSIS is a great idea, it’s just that there needs to be more oversight and compliance testing to make it work.

In the mean time, the best that can be done is to establish HAL standards at the project, team or corporate level and use these, non-vendor based models for creating a sensible, level playing field. With some luck, an open source project might even propagate such a fair model to the point that it becomes a defacto standard. It has happened before. Where would the world of networking be without the historic development of TCP/IP? We can only hope.

Abstraction and Modular programming are powerful tools in the armory of the embedded programmer. While not complete, “C” supports them well enough to create very sophisticated applications. In upcoming articles, I hope to examine some examples of modular abstraction in action!

As always, comments and input are welcome!

Peter Camilleri (aka Squidly Jones)

# Magnus Errata Part 2

In the first part of this series, Magnus Errata Part 1, we looked at the problems caused by reading data from flash memory while interrupts are in use. In this second part we examine the more serious issue of double writes to sensitive I/O registers. Here is the issue as presented in the errata:

Double Write Issue

In this scenario, a write operation is duplicated when it is interrupted at just the wrong moment. Now, in most cases, this poses no problem. A = 3; would simply assign 3 to A twice. However, some I/O registers are sensitive to multiple writes. The data registers for the SPI, UART, I2C, PMP, and GPIO Toggle will not perform correctly if double write occur.

The answer given, was to use the DMA controller to do the writing to these registers. This is a most draconian and unworkable “fix” for the problem. It replaces a simple write to a register with an enormous amount of code to set up the DMA to transfer the data byte. And further since DMA controllers don’t like to be shared, a whole extra layer of mutual exclusion logic is required.

To make matters worse, I just don’t trust this report! If this issue were as bad as the docs make it out to be, you would expect a lot of problems. I mean the issue is I/O and interrupts! Where is the out cry? Why does my own code work without any trace of error? Here’s what I saw in the forums; rpg7 wrote:

“I am running a project the has 4 SPIs clocking in framed mode at 2.048Mbit and a bitbashed uart (No USART pins left if all SPI in use) running at 57600 baud. The bitbashing runs interrupts at 172800 interrupts per second and the SPIs shift out 128 bytes at a time 8000 times persecond. The BB UART has highest priorty so it is interrupting the SPI interrupt continuously. Also have not had any errors so far.. Got my fingers crossed. “

Marc Coussement wrote

“Problem solved !!!

Confirmed by Microchip

First read the errata and look [at the] work around.

Conclusion: …………… stop using PIC32″

Mikael wrote:

“No, it’s a mayor issue, CPU double writes (by mistake) to peripheral, think about it.. uart, spi i2c….

And the workaround is really ugly.

bsder wrote:

“Do I have to disable *all* interrupts? Can they just be masked out? At peripheral level or global level? What about software interrupts? (always occur at a particular pipeline stage and may dodge the bullet) What about timer-based interrupts? (probably always occur relative to a clock edge and probably *don’t* dodge the bullet–they can float through different pipeline stages).

If I put on my microprocessor designer hat, it’s probably that the peripheral commits a pipeline stage before the MIPS32 actually commits. If that’s the case, simply masking off externally driven interrupts (either directly per unit or globally) should be sufficient and won’t require a massive draining of the pipeline.

This severe an errata needs a lot more *public* information and precision.”

and

“[snark] So … I can shut off interrupts for a cycle or two, or I can completely re-architect my application to use a poorly documented peripheral which has driven some quite competent people on this board absolutely mad. And that’s if I’m not actually using the DMA engine. Uh, yeah, I’ll get right on that Microchip… [/snark]”

“Microchip understands importance of having this issue fixed and is actively working on it. Please check with your local Microchip representative on availability dates and obtaining early samples (if desired). “

I know that Microchip will track down the cause of these silicon bugs and fix them. In spite of this, I know that we can’t just bury our heads in the sand and wait for the problem to go away. It won’t. Ever! For quite some time we will be living with a PIC32 population that includes a lot of defective chips. We need useful, feasible work-arounds, not wishful insanity, because these corrective fixes will be needed for some time.

That’s why I was pleased to see this from Stampede:

“Errata #44: This issue is very similar to errata #43, but in this case interrupt has to happen at exact time as you are writing to a peripheral. Depending on the application (how often peripheral is getting written and how often interrupts are occurring in the system), user may not see this issue very frequently. It also depends if their system can handle double write case, if it happens.

While workaround maybe an “overkill” for some applications, it is a valid workaround and it will prevent double write to a peripheral.

Disabling interrupts while performing write to peripheral is another valid workaround and we will update errata to state this.

So the errata seems not to be too severe as it might seem on the first sight…

Cheers Stefan”

Well, I’m not cheering yet, but controlling interrupts around writes to sensitive registers is a lot more feasible than hauling out the nastiest peripheral on the block to copy over  just one byte.

I was planning on waiting for Microchip to update its errata docs, but that has still not happened. So, I am publishing now and will update these postings as more information becomes available. As always, your comments and observations are welcomed!

Peter Camilleri (aka Squidly Jones)