Developing for PIC32 Using the Imagination Technologies Codescape Toolchain

This guide is for those who don't want to use XC32 or would like unrestricted optimisation options without paying out for the non-free Microchip compiler.

Since the PIC32 has a MIPS core, the Imagination Technologies (Who own MIPS) toolchain can be used to generate object code. Most programs should be able to be ported with a little effort.

If you just want to get something working fast, there are a couple of demo projects with everything collected together at the bottom of the page.

What You Will Need

Installing The Toolchain

Download the file from the link above. On Linux you will need to make the file executable and run it as root for a multi user install. On Windows I assume you can just download and run the executable.

You will be asked where to install the SDK, the default place is probably fine if you don't know better. The second choice to make is whether to install the Linux development components, you don't need them for any PIC32 work so just choose the "Bare Metal Applications" option here.

Choose device types

The PIC32 series consists of devices from the microAptiv, M4K and M-class families, if you don't know which category you device falls under, it should be on the datasheet. If you're lazy or planning on developing for multiple types of PIC32 you can select all three.

Choose device types

PIC32 Part Support

This can be used as a library of register locations for PIC32s distributed very kindly by Jason Kajita.

It is up to you if you want to use this or not, it's not technically necessary, but it makes things easier not having to look up the locations of registers, and if you don't like you code filled with magic numbers then you would probably end up building a subset of this anyway.

You will need to include 2 files from this package:



If the header includes another for backwards compatibility you will need to either find that file in the pic32 part support download and include it in your project or remove the lines that include the file if you do not intend to use any of the legacy functionality it provides.

/* include generic header file for backwards compatibility with old C32 v1.xx code */
/* WARNING: Macros from this file are deprecated and should not be used in new     */
/*          source code.                                                           */
#include "ppic32mx.h"

Linker Script and Reset Code

Pick the appropriate linker script (MX or MZ) and include it in your project. It may be the case that you need to change the location of the config bits to match your device, these locations can be found in the datasheet and can be modified in the linker scripts as below.

 . = __base + 0x0bf0; /* Config bits */

These linker scripts and the reset code was written by my colleague Neil Jones, so thanks to him and Imagination for allowing me to post them here.

The following is a makefile fragment that shows the inclusion of the MX linker script and the setting of parameters. more information on these parameters can be found in section 15.3 of the toolchain documentation found at imgtec/Documentation/Toolchain/MIPS_Toolchain_Codescape_GNU_Tools_for_MIPS_Programmers_Guide_X.X.X.pdf (the imgtec directory i in /opt by default for a multi user install).

MIPS_MTI_ELF_ROOT ?= /opt/imgtec/Toolchains/mips-mti-elf/2016.05-03
# Overrides the system value that is set to the img-elf toolchain by default



ABI := 32
APP_START := 0x9d001000
LDSCRIPT := targets/fc1/pic32mx_uhi.ld
include ${MIPS_ELF_ROOT}/share/mips/rules/

CFLAGS += -march=m4k -EL -msoft-float
LDFLAGS += -march=m4k -EL -msoft-float -Wl,--defsym,__use_excpt_boot=0
LDFLAGS += -Wl,-Map,

Copying Data to RAM

There is a little code that is required to copy the data section from flash to RAM before main executes, this is done using one of the callback hooks provided by the HAL.

extern char _rom_data_copy __attribute__((section(".data")));
extern char _fdata __attribute__((section(".data")));
extern char _edata __attribute__((section(".data")));

void __attribute__((section(".boot"))) software_init_hook(void)
    // copy initialised data from its LMA to VMA
    memcpy(&_fdata, &_rom_data_copy, (unsigned long int)&_edata -
        (unsigned long int)&_fdata);

Config Bits

Config bits just require variables to be initialised with the required values as below. The section names can be found in the respective linker script, the MZ is significantly more complex than the MX, see the MZ LED flash projects for an example.

unsigned long int DEVCFG0_VAL __attribute__ ((section(".devcfg0"))) = 0xfffffffful;
unsigned long int DEVCFG1_VAL __attribute__ ((section(".devcfg1"))) = 0xfffffffful;
unsigned long int DEVCFG2_VAL __attribute__ ((section(".devcfg2"))) = 0xfffffffful;
unsigned long int DEVCFG3_VAL __attribute__((section(".devcfg3"))) = 0xfffffffful;

Flashing The Device

If you are using a PICkit or similar Microchip inspired tool to upload object code to your MCU, you will need to convert the virtual addresses specified in the elf generated by the Codescape toolchain to physical ones. This can be done using objcpy.

objcpy --change-section-lma .lowerbootflashalias-0xA0000000 \
       --change-section-lma .bootflash1-0xA0000000 \
       --change-section-lma .bootflash2-0xA0000000 \
       --change-section-lma .exception_vector-0x80000000 \
       --change-section-lma .text-0x80000000 \
       --change-section-lma .init-0x80000000 \
       --change-section-lma .fini-0x80000000 \
       --change-section-lma .eh_frame-0x80000000 \
       --change-section-lma .jcr-0x80000000 \
       --change-section-lma .ctors-0x80000000 \
       --change-section-lma .dtors-0x80000000 \
       --change-section-lma .rodata-0x80000000 \
       --change-section-lma .data-0x80000000 \
       --change-section-lma .bss-0x80000000 \
       --change-section-lma .startdata-0x80000000 \
       your.elf your_physical.elf

Flashing an LED

Below are some flashy projects to get you started, they all include a makefile, linker script, the required PIC32 part support files, separate files containing the config and the data copy to RAM, and a c "main" file.

PIC32MX250F128B (Dev board: digilent chipKIT DP32)

PIC32MZ2048EFG100 (Dev board: digilent chipKIT Wi-Fire)