C++ on PIC32MX using CodeSourcery's G++ GCC-Based Tools

Most recent edit: 26-September-2009
Initial Draft: 6-May-2009

Background

Nadler & Associates developed a product which adds USB functionality to an earlier product, using Microchip's PIC32MX USB-equipped microcontroller. The code for this add-on includes many thousands of lines of C++ previously running on a PC. Unfortunately, Microchip-provided tools do not support C++, so we used CodeSourcery's G++ v4.3-80 GNU-based toolchain.

CodeSourcery's G++ for MIPS ELF targets the Malta 24k. The package includes little-endian code generation and software floating point as required for PIC32MX. G++ also includes the complete C++ library (formerly known as the C++ standard library), which is missing from a number of commercial offerings claiming “C++ support”. Exceptions, collections, and so forth can be used with this package (carefully, PIC32MX only has 32kb of RAM).

To use CodeSourcery's MIPS ELF G++ on PIC32MX required the adaptations described below. A minimal example program (just blinks the LEDs) for the Microchip USB Starter Board contains these adaptations and is available here: 20090926_CPP_demo.zip. See ReadMe.txt in the ZIP for instructions on loading and running this example.

Microchip's chip programming and debugging tools use proprietary interfaces, and are consequently not supported by 3rd party tools. We used the PIC32MX JTAG port for programming via the low-cost USBJTAG-NT JTAG adapter.

PIC32MX configuration register initialization

On startup out of reset, PIC32MX sets many of the hardware control parameters from a set of reserved locations in flash. For example, this is required to start the chip in a configuration that matches the hardware-provided clock. Microchip added a proprietary set of #pragma config's to their C compiler, but these are not supported by any other toolchain, and make it easy to scatter initialization information around the code (and hard to find the actual configuration used). We replaced the Microchip #pragma config's with a simple initialized array loaded into the reserved locations.

See pic32mx_cfg_init.c

Reset Startup Code

We created startup code that does the minimal required low-level initialization run by the chip when it is reset. This startup code puts the PIC32MX into vectored interrupt mode, performs some very basic hardware initialization, saves the reason-code for the the reset, then calls the CodeSourcery “CS3” initialization layer. CS3 brings up the C/C++ environment (initializing memory, calling constructors for static objects, etc), then calls the application main().
See PIC32MX-reset.S

ISR Wrapper

Microchip added additional attributes for declaring an ISR, neither supported by CodeSourcery nor generally by GCC. To replace these Microchip-proprietary attributes, we created a simple assembly wrapper that calls a C-language ISR. The wrapper creates both the MIPS interrupt vector branch entry and the ISR prologue/epilogue (saves/restores the processor state).
SeeISRwrapper.inc and the example invocation in ISRwrapper.S

ISR routines in Microchip-provided libraries will compile as coded, but the unsupported attributes will be ignored. For each required ISR, add an entry in ISRwrapper.S
For example, for the USB ISR declaration coded as:

#pragma interrupt _USB1Interrupt ipl4 vector 45
void _USB1Interrupt( void )

add a line to ISRwrapper.S:

ISR_wrapper 45,_USB1Interrupt # USB vector 45 routes to C-language ISR “_USB1Interrupt”

Linker Script

Directed by the linker script, the linker places code and data in specific memory regions available in PIC32MX, creates a copy of initialized data in ROM for use during initialization, fills in the interrupt vectors, allocates stack and heap (and checks for adequate space), etc. It does not translate “logical” or “virtual” memory addresses to the “physical” addresses required for programming the PIC32MX; this must be performed by the device programmer (or some other post-processing of the linker output).
See csGCC_PIC32MX_flash.ld

Bare Metal Platform Adaptations

CodeSourcery G++ is based on the newlib version of the C libraries. In addition to the standard C library (memory management for example), newlib provides a simple method of filling in primitives normally provided by an OS.

File IO

Implementing read() and write() redirects IO; in the example program stdin/stdout/stderr are redirected to UART1. Similarly file IO can be redirected to a non-OS implementation (for example a file system implemented on top of Microchip's USB stack).
See DRN_PIC32MX_CS_glue.c

Console IO - UART

The example program includes an ISR-based implementation of character IO to UART1, including work-arounds for a couple of PIC32MX UART hardware 'features'.
See DRN_PIC32MX_UART1.h/.c

Time

Implementing time() provides clock information to the runtime library. The example includes an implementation of time() using a PIC32MX timer.
See PIC32MX_time.h/.cpp

PIC32MX Header Files

The Microchip 1.04 compiler distribution includes header files for PIC32MX hardware and libraries, but unfortunately some of these files are co-mingled with the base C-language headers. A different toolchain with differing C-language headers (such as any later GCC) will conflict, and compilation will fail. It is necessary to segregate the PIC32MX headers from the base C language headers for succesful compilation. Also, some of the headers are not valid C++ and minor corrections are required; details can be found here: work-arounds for Microchip tool issues. Contact Dave Nadler if a copy of the segregated and C++-compatible headers is required.

USB Demonstration Program

We implemented an example program which demonstrates basic file operations with a USB memory stick, using UART1 as the console. As currently implemented it requires N&A hardware and does not run on Microchip evaluation boards. Contact Dave Nadler if this is required.

Not Implemented

Not yet implemented are:



Copyright © 2009 - Dave Nadler - All Rights Reserved

Contact Dave Nadler:
USA East Coast voice (978) 263-0097
Skype Dave.Nadler1
Dave.Nadler@Nadler.com

Valid HTML 4.0 Transitional