Magnus Errata Part 3

This article is the fourth in a two part series about some serious errata published regarding the Microchip PIC32 famility of embedded microcontrollers. Previous articles have been Magnus Errata Part 1,  Magnus Errata Part 2, and Magnus Errata Update. There has been a significant passage of time and with the arrival of new errata data, a new chapter in the story is called for. At the same time, a goal for this article is to clarify the application of errata data beyond the PIC32 designation. This is to reflect the fact that the PIC32 family is implemented in multiple varieties, each with unique characteristics.

The PIC32 family can be broadly divided into three main branches:

  1. Smaller parts: PIC32MX1xx/2xx
  2. Mid sized parts: PC32MX3xx/4xx
  3. Larger parts: PIC32MC5xx/6xx/7xx

The first condition was an issue with spurious Data Bus Exceptions when data constants were read from flash memory with interrupts turned on. The respective, current errata notes for this issue are:

1xx/2xx 3xx/4xx 5xx/6xx/7xx
Not applicable to these parts.

It is noteworthy that corrected silicon exists for the 5xx/6xx/7xx family but not the 3xx/4xx and that this issue does not apply to the 1xx/2xx family. I had hoped the errata would say more, but it does not. At the 2012 Master’s Conference I learned that this issue has never been observed when the cache and prefetch are set up normally. This explains why I have never seen this issue and why the vast majority never see it. If you are really paranoid, then implement the work-around, but for the majority of cases, I don’t see the point (PS: That’s my opinion, NOT engineering advice!)

The second condition was an issue with a double data write with interrupts turned on. This was indicated as mostly harmless except when the write target changed it’s state based on a write, like a UART, SPI port etc. The errata were:

1xx/2xx 3xx/4xx 5xx/6xx/7xx

Again, only the 5xx/6xx/7xxx family of parts has a note regarding a corrected revision, so this fix must still be forthcoming in the other two families. Also note that turning off interrupts during the write is now feature in addition to using DMA. And a correction to the errata is that the I/O port Toggle registers where left out as potential trouble spot. Double writing the Toggle register would create a very short spike rather than toggling the desired data bits.

One final word is that this article can never be the final word. I urge everyone working with a microcontroller to go to that chip’s web page and download and carefully study the published errata on that chip. As always; it’s what you don’t know that can hurt you.

Don’t forget that your comments and suggestions are most welcomed.

Peter Camilleri (aka Squidly Jones)

The Multimedia for PIC32MX7

One of the development boards purchased (at a considerable discount) at the recent Microchip Master’s Conference was the MikroEletronika Multimedia for PIC32MX7 pictured to the left. This is the larger cousin of the MMB32 board discussed in an early post with several enhancements. The MX7 is based on the more powerful PIC32MX795F512L part with CAN, Ethernet (100/10) and 128K of RAM vs 32K in the MMB32. Other enhancements over the smaller board include:

  • A switching power supply with a 9..32VDC or 7..23VAC input.
  • A full ICD3 RJ-11 connector.
  • A MCP9700A temperature sensor.
  • A 24AA01 high endurance EEPROM with a 128 byte capacity.
  • A mini, center push, switch joystick.
  • Three utility LED indicators.
  • A full RS-232 port with DB-9 connector.
  • A 100/10 Ethernet interface with a LAN8720A PHY and RJ connector.
  • A ADXL345 3D Accelerometer.
  • A full sized SC card slot vs a micro-SD card slot. I’m not sure this is a plus, but there it is all the same.

Like the V1.0 MMB32 board, the MX7 board uses a Wolfsen Microelectronics WM8731 Codec for sound instead of a VLSI Solutions VS1053 Audio Decoder chip used in the V1.10 MMB32.

This board packs a lot of power into a very small space. Is there a downside? It seems so. Unfortunately,  with so much functionality in a single chip, the two CAN devices and alternate pin outs, are not accessible. So this board is not suitable for CAN development, unless an external CAN peripheral is attached to an SPI bus.

Like the MMB32 there are a lot of resources to deal with. To help with this a Port Worksheet is provided (on a strictly as-is basis). Port Usage Map RevB is the updated spreadsheet with all three (MMB32 V1.0, MMB32 V1.1 and MM for PIC32MX7). Overall I very much look forward to testing my code on this new platform and reporting my results on this site as I make progress.

As always, your comments and suggestions are invited and welcomed. This is especially true if you find an error in the worksheet.

Peter Camilleri (aka Squidly Jones)

A Character Reference [Updated]

In an earlier posting, portable integer data types were examined in It takes all types… This posting continues this thought with an examination of the character data in realm of embedded systems programming.

The “C” programming language has supported the character data type since in infancy of the language in 1972. Well sort of a supported data type. In a fashion typical of the extreme minimalism of early “C”, development the “char” data type was made to serve three distinct and often incompatible uses. Char is (was) used for:

  • The coding of a single character of data. A pointer to characters became synonymous with a pointer to an array of characters terminated with a null character. This is what passed for strings in”C”.
  • The smallest integer data type supported by the processor. This small data type was attractive when the range of values was known to be very limited and space was tight (as it always was)!
  • The smallest unit of addressable storage. As such pointers to “char” were treated as interchangeable with pointer of any type. This usage of “char” has been obsolete for quite some time now with pointers to “void” fulfilling this role.

There are two main issues with this state of affairs.

The first is that in “C”, by default all integer data types are signed. For integers this makes sense as this matches the traditional view of integer variables as a subset of integers in mathematics. Thus the integer usage of “char” mandates that it too must default to being signed. This is in direct conflict with “char” for character data. Textual data does not posses a sign and while the meaning of the words may be negative, the text of those words cannot be negative!

Despite common sense, “C” defines “char” as signed. Over the years, many compilers have given the programmer the option to default it to be unsigned instead, but this is hardly universal.

The second issue that is encountered is the mapping of character glyphs, like ‘C’ to a code like 67. Early in the history of computers, mapping were in chaos. Then the ANSI  committee came up with the ASCII code (pictured to the left, labeled in octal) in 1965 and order was restored, briefly!

ASCII is a seven bit code that handles text in English, Numbers plus some punctuation. Soon the demand arose for accented characters, new punctuation and much more. Most processors use eight bit bytes, so most characters had 128 unused codes available for other uses (assuming you got around the signed nonsense) The big problem was that while 128 free codes was enough for a few languages, it was not enough for all of them. Thus was born the Codepage. The Codepage was a number that allowed the selection of one character mapping from many. Now, in embedded systems, Codepages were not generally used. The application hardwired the mapping of code to glyphs. As applications become more sophisticated, this option becomes less attractive.

And then there is the problem of Asian character sets. Here 128 extra codes is quite inadequate. Many thousands of codes are required. Over the years, many strange and bizarre coding schemes have been created to handle Japanese, Chinese, Korean and other Asian languages. I am glad to say that I won’t waste time discussing them as they are all obsolete. They have been swept aside by Unicode!

Unicode defines a huge 1 million code character space and a smaller 65536 subset. These characters may be encoded through a number of schemes; some of these are:

  1. UTF-32: this massive four byte format can encode the full 1 million character set. It is seldom used due to it’s space inefficiency and the fact that codes greater than 65535 are seldom required. There are two flavors of UTF-32: Big Endian and Little Endian (see below).
  2. UTF-16: this format based on two byte format uses 2 bytes for most glyphs and 4 for seldom used (or supported) ones. There are two flavors of UTF-16: Big Endian and Little Endian (see below).
  3. UTF-8: this variable length encoding includes traditional seven bit ASCII. That is, any valid seven bit ASCII string is also a UTF-8 string. In addition, the coding is such that data may be processed one byte at a time. This means that UTF-8 strings can work with most standard “C” library routines. This compatibility is a huge advantage! Further, UTF-8 is the most compact encoding with glyphs ranging from 1 to 4 bytes long or 1 to 3 bytes long for the 65535 code subset. The downside is that the encoding is variable. To find the N’th character in a string, it is necessary to scan the string. It also complicates the allocation of buffers and such.

So what is to be done in an embedded system? I think it is foolish to imagine that one designer can select one coding scheme in advance for all others. It is for that reason that the emSystem software library provides the choice of four possible encodings:

//**********************************************************
// Advanced character support configuration
//**********************************************************
#define CHAR_ASCII_7    0   // Standard 7 bit ASCII.
#define CHAR_ASCII_8    1   // The 8 bit extension to ASCII.
#define CHAR_UTF_8      2   // The var len extension to ASCII.
#define CHAR_UTF_16     3   // The 16 bit extension to ASCII.

// What sorts of characters are to be supported?
#define CHAR_SUPPORT    CHAR_ASCII_7

How support for these four options are implemented is the topic of a future posting. For more information on ASCII and Unicode Encoding please visit the ASCII Table. As always, your comments and suggestions are most welcomed.

Peter Camilleri (aka Squidly Jones)

Note: Big Endian vs Little Endian refers to a holy war in computer science about how bytes in multibyte data should be ordered. The Big Endian camp favors the most significant byte being first (in the lowest address) while the Little Endian camp favors the least significant byte being first. To help avoid chaos, a byte order mark may be placed at the start of a text to indicate the byte ordering in use. The names given these byte orderings trace back over 200 years to the Jonathan Swift book Gulliver’s Travels.

[Update 1] A now for Unicode the Movie! Starring all 109,242 characters in the Unicode Version 6.0 specification (a cast of 0.1 millions) it is amazing how many forms of written/printed language exist on this planet!

[Update 2] I don’t know how I could have missed adding a link to the Unicode Consortium.

Modules: The A2D Manager

The examination of modular programming so far has included a look at module coupling, module event propagation, and the CallBack Manager mechanism. This posting delves into the operation of an actual data source module, the A2D Manager. First a little background:

In this space, a number of articles have dealt with getting the most from an embedded, resistive touch screen. In all of the articles that have examined the touch screen, the topic that has been omitted until now is “how are the touch screen voltages actually measured?” The answer lies with the PIC-32s capable Analog to Digital Converter (A2D or A/D Converter). A glance at the A2D reference manual gives some idea of the power of this peripheral. A common complication is the fact that the A2D is often required to operate multiple analog devices. In this case those devices are “unspecified” analog sensors.

A typical solution to the requirement to share a device is to use a mutual exclusion (or MUTEX) semaphore to enforce serial reuse of the resource. The only problem with this approach is that it has poor timing consistency. The rate of analog measurements would be subject to timing variation due the order of task execution. Instead the approach used is to place control of the A2D in the hands of an A2D manager. The A2D Manager handles the reading of analog data and serves up this data to client tasks. The goal of the A2D manager was to read all the analog data possible at a constant, predictable rate, make that data available to tasks that need it, and to use as few resources as possible.

The diagram to the left summarizes the operation of the A2D Manager. After initialization in the emInitA2DManager function, the A2D manager does not use a task. It does use a programmable timer and an interrupt service routine (ISR). All 16 analog input channels are scanned once per millisecond, under the control of the timer. At the end of the millisecond, the ISR is triggered by the A2D and copies the data from the A2D to a buffer with the following definition:

typedef struct
{
    uint16_t seq;      // A counter. 1 count per cycle.
    uint16_t analog;   // 0 == analog pin, 1 == digital pin.
    uint16_t data[16]; // A2D data.
} emA2DRESULTS;

To share data with client tasks, the ISR then calls a callback list to inform interested parties that data is available. The callback list itself is one of those rare instances of global data that is required. This is declared as:

extern emPCALLBACKLIST emA2DIsrCallBackList;

The “Isr” in the name reminds coders of client code that this callback occurs in the context of an interrupt service routine, so brevity is a requirement. The A2D Manager initializes the list with:

emA2DIsrCallBackList = 
  emCreateCallBackList(A2D_CALLBACK_LIST_ENTRIES);

Callback lists are managed by the Callback Manager; previously discussed. An example of a client adding a callback to the list is:

emAddCallBack(emA2DIsrCallBackList, &touchCB, emFront);

In which the function touchCB is added to the emA2DIsrCallBackList in the first free slot. When the A2D Manager is ready to signal an event, the code for this is simply:

// Execute the A2D callback list.
emExecuteCallBackPV(emA2DIsrCallBackList, 
                    &xHigherPriorityTaskWoken);

In which the first parameter is the callback list and the second is a pointer to a flag used by the FreeRTOS to indicate that a higher priority task is now ready to run and that a task switch is needed when the interrupt service routine concludes.

It goes without saying that the A2D manager is a compromise. It does however meet its goals of providing a constant 1 K Hz data rate; It does read all 16 possible channels; and it does not tie up a task or use a lot of resources. What resources are used then?

  1. Timer 3 is used to generate Start Conversion pulses at a rate of 16,000 Hz. This consumes no CPU bandwidth.
  2. The A2D module is used to read all 16 possible channels and buffer them.  This consumes no CPU bandwidth.
  3. An interrupt is triggered every 16th sample, or 1,000 Hz. At this point, the A2D buffers are full of data that are copied to a buffer.
  4. A Callback list is used to update clients of the A2D manager.
  5. 36 bytes of RAM for the shared data structure and the the callback list uses an additional 4+8*A2D_CALLBACK_LIST_ENTRIES bytes.

In review, the Callback Manager is a good mechanism for supporting the case where one data/event source needs to reach multiple data/event sinks. In the examination of the Message Queue or Message Pump the case of multiple data/event sources and a single data/event sink will be discussed.

As always, your comments and thoughts are encouraged and welcomed.

Peter Camilleri (aka Squidly Jones)