PIC32MX – Microchip Tool Issues
Most recent edit: 30-August-2009
Initial Draft: 6-May-2009
Nadler & Associates developed a product which adds USB functionality to an earlier product, using Microchip's PIC32MX microcontroller and CodeSourcery's G++ v4.3-80 GNU-based toolchain. During development of this product, we encountered a number of issues with the Microchip-provided tools for PIC32MX.
To help Microchip, Microchip PIC32MX customers, and other vendors intending to support PIC32MX, this document lists problems and suggested solutions. To help Microchip more effectively work with 3rd party tool vendors, a number of tool-chain suggestions are provided as well. Without some of these changes, it is difficult or impossible for 3rd party vendors to support the PIC32MX using peripheral libraries and software stacks provided by Microchip.
Currently, despite advertisements to the contrary, no vendor supports C++ on PIC32MX. It is in all our interests to see broader support (C++ support in particular) for PIC32MX, and hopefully these suggestions will be received in the spirit they are intended !
Note: Issues 1.1 and 1.2 below are fixed in the v2.5 bundle release... Without the corrections below, Microchip's file-system code crashes or fails to operate properly in some circumstances. The bug-fixes below allow proper operation on PIC32MX, including FAT12 and FAT32 file system access.
FSIO.c sometimes crashes dereferencing a null pointer. Corrected source was provided to Microchip in October 2008 and was circulated by Microchip in the bootstrap loader example, but has been lost in the source distributed in the USB stack version 1.04 of December 2008. Here's the corrected source:
// Read the first char of the file name
// DRN: BUG: Dereferences null "dir" ptr: a = dir->DIR_Name[0];
// DRN: BUG: This crashed PIC32MX...
// Make sure there is a directory left
if(dir == (DIRENTRY)NULL || // DRN: Corrected
(a = dir->DIR_Name[0]) == DIR_EMPTY) ) // DRN: Corrected
{
status = NO_MORE;
}
FAT file structures must be defined as packed to operate correctly on MIPS/PIC32MX. Add __attribute__((packed)) to all FAT-related typedefs, including _BPB_FAT12, _BPB_FAT16, _BPB_FAT32, _PTE_MBR, _BootSec. Otherwise, FAT structures on disk will be incorrectly interpreted, leading to crashes, incorrect results, and/or corrupted file systems.
C-language include files should be referenced using include <abd>, not include “abc” (though this is not required by the C-language standard, it prevents problems with numerous toolchains). C-language includes should precede other includes. Otherwise we have compilation problems with some toolchains including G++ (also, please see note 4.1 below). Here's the corrected source:
#include <string.h> // DRN: include C-language headers using <> and before local headers
#include <stdlib.h> // DRN: include C-language headers using <> and before local headers
#include <ctype.h> // DRN: include C-language headers using <> and before local headers
#ifdef ALLOW_FSFPRINTF
#include <stdarg.h> // DRN: include C-language headers using <>
#endif
#include "MDD File System/FSIO.h"
#include "GenericTypeDefs.h"
#include "MDD File System/FSDefs.h"
Well-coded applications ensure there's adequate disk space prior writing a file, but the Microchip file system is missing the “how much space is available” function.
It has clearly been expensive for Microchip to create the MDD library. Still, customers need better quality, additional features, and FAT32 support. In these times of scarce resources, it might be better for all of us if Microchip either released the current code as open source and facilitated its maintenance, or abandoned it in favor of one of the existing open-source FAT implementations. Either choice would permit Microchip to focus its scarce resources on the PIC-specific software that adds real value to Microchip's offerings.
Per suggestion 1.5 above, Microchip is now circulating on the web site a copy of the FatFS file system. Unfortunately:
The version provided via the Microchip web site is no longer current and missing some bug fixes (please link, and do not copy), and
The required functions to bridge USB sector read/write as required by fatFS and USB sector read/write as provided by the Microchip USB-stack are missing.
This is creating a lot of additional work for Microchip customers.
Note: As of August 2009, the bundled PIC32MX software version 2.5 includes a more consistent set of software than the separately distributed earlier components... Note As of August 2009, Microchip's main PIC32 tools web page still links to version 1.04 of the USB stack, which was made obsolete by the USB-stack included in the version 2.5 bundle...
With the past several distributions of the USB stack, symptoms of version-control issues are evident, which is of great concern to customers trying to ensure the most recent and consistent software in our projects. A few examples:
Version 1.04 includes a version of “compiler.h” that is older than the prior release. The previous release included this comment in the header (now missing with associated changes):
* Howard Schlunder 11/07/2007 Reorganized and simplified
In struct_queue.h the macro StructQueueSpaceAvailable has disappeared but there is no change notice in the header.
Not all headers have change control comments or are up-to-date...
The version of the USB stack distributed with the bootloader example does not match any of the “official” numbered releases, and contains changes and fixes that may not be present in version 1.04.
The version of the MDD file system circulated with USB 1.04 is missing bug fixes circulated earlier (see above).
As 3rd party vendors may have to make source changes for correct operation with other tool-chains (for reasons detailed below), lack of consistent change notices in headers will cause difficulties.
Note as of August 2009,Microchip's main PIC32 tools web page still lists OTG as a future enhancement, however it seems to be present in the v2.5 bundle (and earlier releases)... OTG is advertised as a capability of PIC32MX but software support has not yet materialized. N&A is not using OTG, but other customers expect this advertised capability.
To use alternate toolchains, 3rd parties (either vendors or customers) will need to rebuild some or all of the Microchip libraries.
It is not possible to rebuild the PIC32MX libraries with the provided make file.
Some library sources are missing from the Microchip distributions, for example microchip-p32-1-04-proclib tree (creates processor-specific address definitions).
Items listed in this section present obstacles to successful support of PIC32MX by third parties. Any extension that Microchip makes to the C-language will be incompatible with any other toolchain, and create an obstacle for broader support of PIC32MX in the market. This could be mitigated if extensions are merged back into the open-source GCC development trunk, which to date has not happened.
In the current MPLAB distribution, the PIC32MX includes are co-mingled with C-language includes (dsplib_*.h, p32xxxx.h, cp0defs.h, plib.h, plus the peripheral, proc and sys subtrees). As other compilers (including later versions of GCC) have incompatible C-language headers, this creates compile-time confusion, and requires any 3rd party to manually segregate the PIC header files. Please create a separate single include-tree (for example PIC_INCLUDE), ideally at the user's option installed somewhere other than under “Program Files\Microchip” on Windows.
Use of directory names including spaces is Windows-specific and causes problems with GCC toolchains (for example, the VPATH directive in GCC make does not work properly with such names). Please use underscores instead, for example MDD_File_System. Currently, most but not all of Microchip's directory names use underscores... It will be much easier if they all do.
To ease use of components, it would be better to segregate “add-on” stacks such as DSP, USB, MDD. To ease source-control and customer mix-and-match, the include files for these components would be best kept in the same directory tree as the sources. Requiring users or 3rd party vendors to synchronize updates to include files located in a separate directory tree from the other sources for a package is error-prone, especially without good comments for all changes.
Microchip added #pragma config to ease setup
of PIC32MX configuration registers, but this solution:
- Is incompatible with any other toolchain, and
- Makes it difficult to find how exactly the chip is configured,
as these pragmas may be in different sources and/or combined with
unclear default values.
It is easier for developers in general (as
well as 3rd-party toolchains) to simply provide a single file
declaring the configuration register values. Here's a
suggested implementation:
http://www.nadler.com/embedded/pic32mx_cfg_init.c
Microchip added #pragma ipl to ease
implementation of ISRs in C, however this solution:
- Is incompatible with any other toolchain,
- Despite the name IPL, does not actually set the Interrupt Priority Level,
- Creates differing ISR prologue/epilogue using the IPL number as
an implied specification for shadow-register use
It would be helpful to be explicit about the generated prologue/epilogue, and ensure this extension is merged back into the open-source GCC development trunk.
To use Microchip's compiler with 3rd-party JTAG debuggers or other tools, it would be helpful to release GDB along with the other GCC tools provided by Microchip. While it is possible to rebuild GDB from the Microchip provided sources (as we did), this is a lot of effort that can be avoided.
Microchip provides an excellent low-cost tool with the hockey puck. Making public the interface to this device will allow 3rd-party tool vendors to support Microchip products with additional toolchains and on additional platforms.
Some of the Microchip headers are not valid C++. Consequently 3rd parties must change Microchip headers to support C++ on PIC32MX. Corrections were provided to Microchip in fall 2008 but have not been merged into released code.
For valid C++ code, use distinct names for all members of an enum; suggested correction:
// source pointer register
DMA_REG_IX_SPTR,
DMA_REG_IX_RESERVED_1, // DRN: use distinct names for all reserved...
DMA_REG_IX_RESERVED_2,
DMA_REG_IX_RESERVED_3,
// destination pointer register
DMA_REG_IX_DPTR,
DMA_REG_IX_RESERVED_4,
DMA_REG_IX_RESERVED_5,
DMA_REG_IX_RESERVED_6,
// cell size register
DMA_REG_IX_CSIZ,
DMA_REG_IX_CSIZ_CLR,
DMA_REG_IX_CSIZ_SET,
DMA_REG_IX_CSIZ_INV,
// cell pointer register
DMA_REG_IX_CPTR,
DMA_REG_IX_RESERVED_7,
DMA_REG_IX_RESERVED_8,
DMA_REG_IX_RESERVED_9,
// pattern data register
DMA_REG_IX_DAT,
DMA_REG_IX_DAT_CLR,
DMA_REG_IX_DAT_SET,
DMA_REG_IX_DAT_INV,
}DmaChnRegIx;
Casting from int to enum is not permitted in C++; suggested correction:
#ifdef __cplusplus // DRN - Wrap rtccRepeat type conversion
#define rtccRepeat_from_INT(_x) rtccRepeat(_x) // DRN: C++ cannot cast int to enum, but can construct enum from int...
#else
#define rtccRepeat_from_INT(_x) _x
#endif
and
extern __inline__ rtccRepeat __attribute__((always_inline)) RtccGetAlarmRpt(void) {
unsigned int r0, r1; // DRN: avoid C++ casting issues
do
{
r0=RTCALRM&_RTCALRM_AMASK_MASK;
r1=RTCALRM&_RTCALRM_AMASK_MASK;
} while(r0!=r1);
return rtccRepeat_from_INT( /*DRN: reqd for C++ to get enum type*/r0>>_RTCALRM_AMASK_POSITION );
}
Microchip circulated an USB-thumbdrive-to-flash bootloader as a Beta in late 2008, and it is now included in the v2.5 bundle as “production”. While it is extremely helpful (as many customers like us must incorporate a loader for in-the-field software updates), it has a number of problems as documented below. A patched version incorporating fixes for all of these problems (except 6.5) is available here: John Toebe's corrected bootloader
Microchip has not yet incorporated a bugfix to the
issue posted here in January 2009:
http://www.microchip.com/forums/tm.aspx?m=382076
(see excellent explanation of the bug and the fix, both provided by John Toebes).
There's an off-by-one error in boot_load_hex.c - it should read as follows:
if (address + length > MAX_FLASH_ADDRESS_PLUS1) // DRN: >, not >=
{
BLIO_ReportBootStatus(LOADER_ADDRESS_HIGH, "BL Load Hex: Address out of range, high\r\n");
The HEX files produced by vendors other than Microchip use logical addresses, and require masking to physical in boot_load_hex.c (this masking operation has no effect on MPlab-produced HEX files). It should read as follows:
case 0x04: // Extended Linear Address record
// set upper 16bits to value from record, lower 16bits are forced to 0 ** update to point to ULBA
baseAddress = (pRecord->data[0] << 8) | pRecord->data[1];
baseAddress = baseAddress << 16;
baseAddress = KVA_TO_PA(baseAddress ); // DRN: mask address to PIC32MX "physical" address
RecordInitialize(pRecord);
Typically a bootloader is built as a separate complete application, living in a distinct area of flash (this provides safety in the event of an interrupted field upgrade). The bootloader initially checks for a valid application signature, and branches to the application if this is found, but branches to the bootloader if its missing (or sometimes if another trigger is noticed; ie a button is depressed). This requires an set of facilities: application signature, startup code with test procedure, distinct memory location for the signature reflected in linker scripts for the application and bootloader, etc. None of these are provided with the example. See John Toebe's version for an example implementation.
Normally the application needs to be able to trigger a reload (in our particular example, the UI would notice a new HEX and ask the user). To support this, the bootloader needs a well-defined entry point where the application can branch to in order to start the load process. Many products will not have any buttons attached to the PIC32MX to trigger the bootload (the UI is on a different embedded device)...
Microchip, as numerous other vendors, early on created proprietary development tool chains for their parts. N&A has shipped products developed with MPLAB for small PICs, as well as similar tool chains from other vendors (Metrowerks, etc.). MPLAB is fine for PIC16C63 (4k 14-bit ROM, 192 bytes RAM) – small projects, typically single developer. We and our partners continue to use MPLAB happily for low-end parts. PIC32MX has 512kb flash, 32kb memory, much more complicated peripheral set (USB, DMA, etc.). Compared to PIC16C63, that’s 73x more code space, 166x more RAM. As the part capability grows exponentially, there’s corresponding growth in the tool capability required for cost-effective product development because of:
Code size and complexity
Language requirements (C++)
Complexity and number of required software stacks
Number of developers concurrently using the tools for concurrent development
Required integration with tools to support larger projects (source control, documentation, bug tracking, etc...)
The cost of providing support for new parts will continue to grow exponentially unless Moore's law is revoked. It has already made competitive proprietary IDEs prohibitively expensive (consider the cost of providing competitive C++ support in MPLAB). Other than for very small projects, Microchip is judged against customer expectations set by their experience with tools from Microsoft and Eclipse, as these are the tools used in the marketplace for larger projects. Microchip cannot cost-effectively compete with these IDEs, and MPLAB is not adequate for larger projects.
Microchip's goal of providing a seamless experience for customers migrating to PIC32MX is laudable ! However, the reality is that larger chips will be used for larger projects, and larger projects demand a much richer development platform for cost-effective development. Just as Microchip can no longer cost-effectively create a C-compiler and relies on the GCC toolchain, the time has come to shift focus (and precious resources) to supporting Eclipse.
Copyright © 2009 - Dave Nadler - All Rights Reserved
Contact Dave Nadler:
USA East Coast voice (978) 263-0097
Skype Dave.Nadler1
Dave.Nadler@Nadler.com