How to port an Arduino library to ChipKit MPIDE

Post Reply
Posts: 27
Joined: Tue Nov 05, 2013 6:27 am

How to port an Arduino library to ChipKit MPIDE

Post by thinkpeace » Sun Jan 19, 2014 5:56 am

Porting a library from Arduino to ChipKit MPIDE

The following are things I learned when porting the RFM12B library to run on a ChipKit WF32. The RFM12B library I ported I got from ... o-library/

When porting a library from Arduino AVR to ChipKit MPIDE you should try to use Arduino library calls whenever possible rather than PIC32 or AVR specific code. Using PIC32 specific calls for efficiency is not typically needed because the PIC32 processor runs so much faster than the Arduino AVR. Also by using Arduino library calls, the code is easier to maintain and port to other boards.

I found it very useful to test everything on an Arduino while incrementally eliminating all the AVR specific code. Once it is working on the Arduino, compile and run the library on the ChipKit board. If it fails to compile, correct the incompatible code, and test again on the Arduino. Once it compiles on successfully for both the ChipKit, and for the Arduino, and runs succfully on the Arduino, it is time to test and debug the library on the ChipKit board.

The following are some of the changes that will need to be made to port Arduino code to the ChipKit.


To quickly find the AVR specific code while testing on an Arduino, remove #include <avr/io.h>, #include <avr/eeprom.h> and #include <avr/sleep.h>. Then compile to see all the missing references to AVR code.

Replace references to DDRB, PORTB and other AVR registers with pinMode() and digitalRead() and digitalWrite() calls.

Replace references to SPCR and SPDR to SPI library calls:

Code: Select all

			#include <SPI.h>
			SPI.setClockDivider( SPI_CLOCK_DIV4);
                        digitalWrite( spi_cs, LOW );
			in = SPI.transfer(out);
                        digitalWrite( spi_cs, HIGH );
Refer to the documentation for the ChipKit board to see what pins each external interrupt uses.

Any interrupt routines that use level LOW need to be changed to FALLING, and in in the interrupt routine, a test for the IRQ pin being low needs to be added.

Code: Select all

        attachInterrupt( 0, InterruptHandler, LOW );

void InterruptHandler() {
// Interrupt code here
Would be replaced with

Code: Select all

        attachInterrupt( 0, InterruptHandler, FALLING );

void InterruptHandler() {
    do   {
          // Interrupt codehere
    } while( digitalRead( IRQ_PIN ) == 0 );
Replace references to EIMSK, EICRA and EICRB with attachInterrupt(), noInterrupts() and interrupts().


In the RFM12B example from, LED_Control_Gateway, there was a variable declared as follows:

Code: Select all

char * sendBuf="x:y"; //format is MODE:SPEED
For it to work on the ChipKit, I had to change it to the following

Code: Select all

char sendBuf[4]
This is because on the ChipKit it was put into program space rather than in RAM.

The PROGMEM keyword is not needed. Constant variables will be put in flash without this keyword. It can be removed or defined as follows
#define PROGMEM
On the ChipKit boards, constant variables are located in flash and can be read directly. No special functions like pgm_read_word() are needed.


if _crc16_update() is called, an equivalent function needs to be added. Currently the MPIDE port of the Arduino library doesn't have this function. Below is a replacement written in C which I found here: ... __crc.html.

Code: Select all

			crc16update(uint16_t crc, uint8_t a)
				int i;

				crc ^= a;
				for (i = 0; i < 8; ++i)
					if (crc & 1)
					crc = (crc >> 1) ^ 0xA001;
					crc = (crc >> 1);

				return crc;

if sleep_mode() is used, instead of sleeping, use a while loop which loops until a varible set by an interrupt routine indicates that processing can continue. Example:

Code: Select all

If you are running from battery, and really need to put the processor to sleep, an equivalent function would need to be written.


Use conditional compilation to include code specific to different board types.

Code: Select all

#ifdef defined(__AVR__)
#include	<avr/io.h>

#if defined(__PIC32MX__)
#include	<something>

#if defined(_BOARD_WF32_)
#define IRQ_PIN 3
#elif defined(_BOARD_UNO_)
#define IRQ_PIN 38
My next project will be to port the LowPowerLab RFM69 library. It should take a fraction of the time with what I've learned so far.

Post Reply