The Arduino™ Blink Sketch on chipKIT DP32

Overview:

In this tutorial, the standard “Hello World” program (blinking LED) is used to help familiarize you with the chipKIT DP32 board and how it will interface with  the Multi-Platform Integrated Development Environment (MPIDE) and basic language functions.  

Reference:

During the course of this tutorial, various terms will be referenced including:
  • Sketch
  • Function
  • Variable
  • HIGH and LOW
  • INPUT and OUTPUT
We recommend that you read the following sections on the Arduino™ homepage to get a better understanding of these terms:

Hardware Used:

The hardware used in this tutorial will be the chipKIT DP32 manufactured by Digilent Inc. The reference guide for this board, schematics and other resources are available on the chipKIT DP32 homepage at: http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,892,1174&Prod=CHIPKIT-DP32  

Software Used:

In this tutorial, the chipKIT MPIDE will be used. If you haven’t already, follow the instructions at the links below to download MPIDE for your operating system:

Hardware Setup:

The DP32 can be powered in a number of ways including from the USB connection (J2) or over the screw terminal (J6). The user needs to select which method will be used to power the board by configuring the jumpers immediately next to the screw terminal as shown below:  

 jumper config

   

Procedure:

  1. Open MPIDE, by navigating to the extracted files in the folder you selected when you downloaded the source files. Locate the MPIDE executable (Windows® folder shown): openMPIDEopenMPIDE Double click the executable to open the MPIDE  Hint: At this point it is a good idea to create a shortcut to the mpide.exe and place on your desktop.
  2. The first time you open MPIDE, you will be notified that a “sketchbook folder” will be created. In Windows, this folder will be located in the “My Documents” directory. scketchbookFolder Click OK to continue.
  3. The MPIDE Window should appear. Note the following main areas of the IDE Window.MPIDE Workspace button overview
  4. The chipKIT MPIDE comes with a variety of examples that can be used to help explore some of the various features of both the MPIDE and the chipKIT Platform. To access these examples, select File>Examples.EXAMPLES Note that there are all kinds of examples from lighting an LED on the chipKIT Board to different types of displays.Under File>Examples>Basic, there is an example called Blink. This example blinks an LED on the chipKIT Board ON/OFF in 1 second intervals. This little program is what is known as the “Hello World” program as it is usually the first application new users create who are using a Microcontroller for the first time.This example could easily be opened and run as is. However, in order to highlight some of the features of the MPIDE, this example will be recreated from scratch.
  5. Click on the “New” button to open a new sketch window and then click “Save” button. Name the sketch something meaningful like DP32_Blink.  The default directory will be the mpide folder created when the MPIDE was first started. Note: If you navigate to the mpide folder, there will now be a new folder with the name of the sketch you just saved.
  6. In this part of the tutorial, you will create a simple routine that will blink LED 3 on the DP32.dp32 Add the following code into the MPIDE editor:
    int ledPin = 43;                 // LED connected to digital pin 26
    void setup()
    {
      pinMode(ledPin, OUTPUT);      // sets the digital pin as output
    }
    void loop()
    {
      digitalWrite(ledPin, HIGH);   // sets the LED on
      delay(1000);                  // waits for a second
      digitalWrite(ledPin, LOW);    // sets the LED off
      delay(1000);                  // waits for a second
    }
  7. There are quite a few things going on with this sketch. Under the “References” section at the top of the page, links are provided that will explain much of the content.Next, we will upload our code to the DP32.
  8. Make sure that the chipKIT DP32 is connected via the mini-B connector on the board to an availableUSB port on the computer.
  9. In MPIDE, select Tools>Board>chipKIT>chipKIT DP32 to identify the DP32 Board as a target select boardselectboard

    Next, you will need to place the DP32 into “Programming” or “Bootloader” mode; otherwise, the sketch will not be able to be uploaded to the board. To enter into this mode, hold down the RESET button followed by the PGM button, then release the RESET button first, followed by the PGM button. You will know you’ve done this correctly if LED1 begins to flash repeatedly. dp32_BUTTONS

    When the DP32 is in Bootloader mode, LED1 on the board will begin to flash on/off.

  10. Next, select Tools>Serial Port>COMxx. This will depend on which port was assigned to the chipKIT DP32 Board when first connected.selectserialport
  11. To load your sketch onto the chipKIT DP32 board’s Microcontroller, press the upload button. This will compile your sketch (check for errors) and then send to the Microcontroller.
 

Verifying Operation:

After the sketch is sent to the chipKIT DP32 board’s Microcontroller, LED 3 on the chipKIT DP32 should flash on and off in 1 second intervals.  
VN:F [1.9.22_1171]
Rating: 6.5/10 (6 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

This Page is Dedicated to You, the chipKIT Users and Developers

Here you can find:

  • Detailed ideas for embedded applications on chipKIT boards, both simple and complicated.
  • Post your projects here – boast about your innovations and unleash the techie in you.
  • Hot upcoming challenges and awards.
To see information specific to chipKIT users: Click Here To see information specific to chipKIT developers: Click Here

Featured Contest: chipKIT Design Challenge

Calling all North American academics and hackerspaces! Show Us Your chipKIT Embedded Platform Projects. Win up to $5,500 in development tools for your lab. The chipKIT team strives to create an embedded controller platform that facilitates the interests of budding engineers and hobbyists. If you are among the ones who would like to showcase your talents and be recognized, you are in the right place. Register now.

Register for the chipKIT Design Challenge

VN:F [1.9.22_1171]
Rating: 4.9/10 (11 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Programming Microchip starter kits from MPIDE

Running on Microchip Starter Kits

MPIDE has been expanded explicitly to support all of the Microchip starter kits such as:
  • PIC32 Starter Kit
  • PIC32 USB Starter Kit
  • PIC32 Ethernet Starter Kit
  • Explorer 16 Starter Kit
Currently for all of these boards you will need some sort of USB to serial adapter. For all but the Exp-16 I use an FTDI cable that breaks out to pins. I connect those to pins on the expansion board for uart1. The PIC32 USB Starter Kit and PIC32 Ethernet Starter Kits are also compatible with the USB PIC32 bootloader. The Explorer-16 has an on-board DB-9 RS-232 connector. This is connected to UART2. The bootloader is configured to use UART2 for the Explorer-16 and the Serial ports for Arduino are remapped so that Serial.print goes to uart2 and Serial1.print goes to uart1. This is all done automatically so the user does not have to worry about it at all. In order to install the bootloader on any of these boards, you have to have one of the Microchip compatible programmers such as the MPLAB ICD 3 or PICkit 3. Ideally you should download MPLAB X IDE from microchip (http://www.microchip.com/mplabx) and use that to compile and burn the bootloader. The bootloader source and pre-compiled hex files are all on github. (https://github.com/chipKIT32/pic32-Arduino-Bootloader)

Using other PIC32 boards

As far as using MPIDE with other boards, the answer is YES, it should work with ANY PIC32 there is. The only limit might be it won’t work on chips smaller than 32K, And that’s because it hasn’t been tried on anything smaller. To get it to work on other boards, a few things have be be done.
  • First, the bootloader has to be burned onto the target board. The source is on github and MPLAB is used to compile and burn the bootloader. The multi-platform MPLAB-X was used on a Mac, but other versions should work as well.
  • If you using a chip that has not already been added to avrdude.conf, that has to be done.
  • You need to add a new entry to boards.txt and then you will be able to program the board directly from MPIDE.
VN:F [1.9.22_1171]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Running StickOS BASIC on a chipKIT board

Have you ever wished you could examine and manipulate the pins and peripherals of your MCU *interactively*, while it was live and connected to your embedded circuit, rather than using just “reset and run” debugging? If so, StickOS BASIC may be for you! With StickOS BASIC, you can log in to your MCU using nothing but a terminal emulator, and then take full control of the MCU from a command-line, just as if you had an In-Circuit Emulator. StickOS can run either in “slave” mode, tethered to and controlled by a host computer as a glorified intelligent I/O port, or it can run in “master” mode, programmed in BASIC, interactively debugged, and even configured to autorun its BASIC program autonomously. In StickOS BASIC, it is trivial to examine and manipulate I/O pins. I/O pins can be configured for digital input or output, analog input or output, servo output, or frequency output. Once a pin is configured, it can be bound to a BASIC variable, and from then on, examining or manipulating the pin is as simple as examining or manipulating the bound variable. For example, to configure pin 3 for servo output, bind it to the variable “motor1”, and then set it up for a 1ms (1000us) PWM pulse width is as easy as (interactively, at the command-line, or in a program):
    > dim motor1 as pin 3 for servo output
    > let motor1=1000
    > _
In StickOS BASIC, it is equally trivial to use timers, UARTs, advanced I2C or SPI peripherals, as well as HD44780-compatible LCDs and simple scanned keypads. And most importantly, it can all be done interactively — no more guessing what your MCU is up to! The StickOS debugger supports command-line program interruption, breakpoints, assertions, watchpoints, live variable (and pin) manipulation and examination, execution tracing and single-stepping, sampling profiling, and even edit-and-continue! When you’re ready to move up, you can then port your BASIC program to C using the MPLAB X StickOS Skeleton project, and take advantage of all the same pin/peripheral configuration, flash manipulation, etc., used by StickOS BASIC. A detailed introduction to StickOS on the chipKIT boards is here: http://www.cpustick.com/chipkit.htm An overview of the StickOS BASIC language features is in the Quick Reference guide, here: http://www.cpustick.com/downloads/quickref.v1.82.pdf More information and downloads for the chipKIT boards are available here: http://www.cpustick.com/downloads.htm
VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Programming Hints

Use defines

At the abstraction layer, everything is the same, at least we hope so. At the low level you will have to re-write it. You should NEVER include anything from the avr libraries i.e. #include <avr/io.h> for any project that does not use an AVR chip. From now on, you should be doing this:
/* For AVR */
#if defined(__AVR__)
    #include <avr/io.h>
#endif

/* For PIC32 */
#if defined(__PIC32MX__)
    #include <p32xxxx.h>    /* this gives all the CPU/hardware definitions */
    #include <plib.h>       /* this gives the i/o definitions */
#endif
There are also a few predefined macros which may be useful as arguments to #ifdef:
/* For PIC32 */
#define __PIC32MX__ 1

/* For Uno32 */
#define __32MX320F128H__ 1

/* For Max32 */
#define __32MX795F512L__ 1

I/O: PIC32 vs AVR

The I/O port modules on the PIC32 microcontrollers and the AVR microcontrollers are implemented differently. The ports on PIC32 parts are organized as 16 bit ports. The ports on AVR parts are organized as 8 bit ports. Each I/O port on an AVR part has an associated data direction register (DDRx) used to control whether the pins in the port are inputs or outputs. For example, DDRD is the data direction register for PORTD. On an AVR microcontroller, setting a DDR register bit to ‘1’ makes the associated pin anoutput. Each I/O port on a PIC part has an associated tristate register (TRISx) used to control pin direction. For example, the equivalent register in a PIC part would be TRISD. On a PIC microcontroller, setting a TRIS bit to ‘1’ makes the corresponding pin an input. On an AVR part, writing to the PORT register writes to a latch. If the pin is configured as an output the value in the latch sets the state of the pin. If the pin is configured as an input, it controls turning on or off an internal pull-up resistor. On a PIC, writing to the PORT register actually writes to a register called LAT (latch). Writing to the PORT or the LAT register has the same effect. If the pin is configured as an output, it sets the state of the pin. If the pin is configured as an input, it doesn’t do anything but write to the latch. On an AVR part you read the pin state by reading the PIN register. On a PIC part, you read the pin state by reading the PORT register. On an AVR part if you read from the PORT register, you read the last value written. To read the last value written on a PIC part, you read the LAT register. AVR parts have a programmable internal pull-up resistor on every I/O pin. On pins that are configured as inputs, the pull-up resistor is enabled by writing a ‘1’ to the corresponding bit in the PORT register. The pull-up is disabled by writing a ‘0’ to the bit. PIC32 parts only have programmable pull-up resistors on the pins that are capable of generating a pin change interrupt (CNx pins). The pull-ups are enabled by setting the appropriate bits in the CNPUE register. PIC32 parts have the ability to make any pin an open drain output. Each port has an associated open drain control (ODC) register. A pin is made open drain by setting the corresponding ODC bit to ‘1’. Setting an ODC bit to ‘0’ makes the pin a normal digital output. PIC32 parts also have SET, CLR, and INV registers associated with the TRIS, LAT, and PORT registers for each each I/O port. The SET register is used to set one or more bits to ‘1’. The CLR register is used to clear one or more bits to ‘0’. The INV register is used to toggle the state of one or more bits. In each case a ‘1’ bit in the value written will cause the effect (SET, CLR, or INV) to occur to the corresponding bit in the register . Each bit written as ‘0’ has no effect on the bits in the register. For example, writing the value 0x0001 to TRISxSET will set bit 0 of the TRISx register to 1, leaving all other bits unchanged. Writing the value 0x0001 to the TRISxCLR register will clear bit 0 of the TRISx register to 0. Writing the value 0x0001 to the TRISxINV register will toggle the state of bit 0 in the TRISx register. When writing to a SET, CLR, or INV register, the hardware reads the associated register, modifies the value based on the ‘1’ bits in the value written, and writes the result back to the register. This is performed as an atomic (uninterruptible) operation, and is more efficient than the typical read-modify-write sequence used on most other processors. The output compares in the PIC32 aren’t associated with timers the way they are in the AVR. Each output compare can be set to trigger from timer 2 or timer 3. So, you can toggle up to 5 pins from the same timer.

Adding libraries

To add libraries, put them in a folder in your Arduino sketch folder called libraries. These are picked up as contributed libraries and will show up for both PIC and AVR environments. Libraries placed here are also preserved when you upgrade MPIDE.

Fastest way to toggle bits on a PIC32

The fastest way to toggle a pin on PIC32 is going to be something like
      while(1)
        {
          LATGINV = B01000000;
        }
For PIC32, usually the LAT registers are best for output and the PORT registers are best for input. The *INV (invert) registers are the fastest way to toggle an SFR bit. There are also *SET and *CLR registers that allow for quick bit sets and bit clears.

Interrupt handler setup

void setup() {
........
OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0xFFFF);
ConfigIntTimer2((T2_INT_ON | T2_INT_PRIOR_3));
........
}

#ifdef __cplusplus
extern "C" {
#endif

void __ISR(_TIMER_2_VECTOR,IPL3AUTO) comms_handler(void)
{
  mT2ClearIntFlag();  // Clear interrupt flag
digitalWrite(LED, HIGH);
}
#ifdef __cplusplus
}
#endif
Do not put INTEnableSystemMultiVectoredInt in your setup code or any place else, it is already called BEFORE your setup code gets called. Look at wiring.c for details.

Device configuration words and the bootloader

#pragma config will not work in an MPIDE sketch because, like the Arduino’s fuses, the PIC32’s configuration words are set in the bootloader code and the chipKIT application linker scripts are set to discard the configuration-word values. To change the configuration-word values, change them in the bootloader project (with the bootloader linker script). If for some reason, you need the configuration-word values in the application linker script, you can modify the linker script with regards to the config regions and .config_xxx sections. You can use the bootloader linker script as a guide.

Missing header files?

If the main sketch does not #include all needed header files then it will not compile and you will get missing file errors. This also includes any #include statements that your 3rd party libraries may have. So, check those libraries and make sure that all #include statements in them are also in your sketch.  

Using attachInterrupt() / detachInterrupt()

 /************************************************************************
  ** ExtIntTest - Sketch to Test External Interrupts
  *************************************************************************
  ** This sketch tests the attachInterrupt and detachInterrupt functions.
  ** It assumes that pin 3 has been looped back to the external interrupt
  ** pin to be tested. It generates edges on pin 3 to trigger interrupts.
  ** The interrupt service routine then blinks the LED to show that it
  ** has been entered.
  **
  ** Uno32 External Interrupt pins:
  ** INT0 = 38, INT1 = 2, INT2 = 7, INT3 = 8, INT4 = 35
  **
  ** Max32 External Interrupt pins:
  ** INT0 = 3, INT1 = 2, INT2 = 7, INT3 = 21, INT4 = 20
  **
  *************************************************************************
  ** History:
  **
  ** 08/08/2011(GeneA): created
  **
  ************************************************************************/

 /* ------------------------------------------------------------ */
 /* Local Symbol Definitions */
 /* ------------------------------------------------------------ */

 #if defined(_BOARD_UNO_)
 #define pinINT0 38
 #define pinINT1 2
 #define pinINT2 7
 #define pinINT3 8
 #define pinINT4 35
 #define pinSrc 3 // used as external interrupt source

 #elif defined(_BOARD_MEGA_)
 #define pinINT0 3
 #define pinINT1 2
 #define pinINT2 7
 #define pinINT3 21
 #define pinINT4 20
 #define pinSrc 4 // external interrupt source

 #else
 #error "No supported board specified.
 #endif

 #define INT0 0
 #define INT1 1
 #define INT2 2
 #define INT3 3
 #define INT4 4

 /* Since the Max32 doesn't have the second LED on pin 43,
 ** this test assumes that an external LED has been connected
 ** to pin 43 on that board.
 */

 #define pinLED1 13
 #define pinLED2 43

 #define intTest INT1

 /* ------------------------------------------------------------ */
 /* Local Variables */
 /* ------------------------------------------------------------ */

 volatile int intStat;

 /* ------------------------------------------------------------ */
 /* Forward Declarations */
 /* ------------------------------------------------------------ */

 void IsrTest();

 /* ------------------------------------------------------------ */
 /* Procedure Definitions */
 /* ------------------------------------------------------------ */
 /** setup
  **
  ** Parameters:
  ** none
  **
  ** Return Value:
  ** none
  **
  ** Errors:
  ** none
  **
  ** Description:
  ** Initialization function called at the beginning of execution.
  */

 void setup() {

 /* Use the LEDs to indicate activity
  */

 pinMode(pinLED1, OUTPUT); // indicates foreground task activity
 pinMode(pinLED2, OUTPUT); // indicates ISR activity
 digitalWrite(pinLED1, LOW);
 digitalWrite(pinLED2, LOW);

 /* Make all of the external interrupt pins be inputs.
  */

 pinMode(pinINT0, INPUT);
 pinMode(pinINT1, INPUT);
 pinMode(pinINT2, INPUT);
 pinMode(pinINT3, INPUT);
 pinMode(pinINT4, INPUT);

 /* Make the stimulus pin be an output.
  */

 pinMode(pinSrc, OUTPUT);
 digitalWrite(pinSrc, LOW);
 }

 /* ------------------------------------------------------------ */
 /** loop
  **
  ** Parameters:
  ** none
  **
  ** Return Value:
  ** none
  **
  ** Errors:
  ** none
  **
  ** Description:
  ** Application event loop
  */

 void loop() {
 int itrTest;

 /* Install the handler for the interrupt being tested.
 ** Test rising edge triggering first.
 */

 intStat = 0;
 attachInterrupt(intTest, IsrTest, RISING);

 /* For rising edge triggered interrupts, both LEDs
 ** should go on and off at the same time.
 */

 for (itrTest = 0; itrTest < 10; itrTest++) {
     digitalWrite(pinLED1, HIGH);
     digitalWrite(pinSrc, HIGH);
     delay(500);
     digitalWrite(pinSrc, LOW);
     digitalWrite(pinLED1, LOW);
     delay(500);
 }

 /* Uninstall the handler and test to make sure that
 ** we aren't getting interrupts any more.
 */

 detachInterrupt(intTest);
 digitalWrite(pinLED2, LOW);

 /* Only one LED should be blinking here.
 */

 for (itrTest = 0; itrTest < 5; itrTest++) {
     digitalWrite(pinLED1, HIGH);
     digitalWrite(pinSrc, HIGH);
     delay(500);
     digitalWrite(pinSrc, LOW);
     digitalWrite(pinLED1, LOW);
     delay(500);
 }

 intStat = 0;
 digitalWrite(pinLED1, HIGH);
 digitalWrite(pinSrc, HIGH);
 delay(1000);

 attachInterrupt(intTest, IsrTest, FALLING);

 /* For falling edge triggered interrupts, the LEDs
 ** should blink out of phase with each other.
 */

 for (itrTest = 0; itrTest < 10; itrTest++) {
     digitalWrite(pinLED1, LOW);
     digitalWrite(pinSrc, LOW);
     delay(500);
     digitalWrite(pinSrc, HIGH);
     digitalWrite(pinLED1, HIGH);
     delay(500);
 }

 /* Uninstall the handler and test to make sure that
 ** we aren't getting interrupts any more.
 */

 detachInterrupt(intTest);
 digitalWrite(pinLED2, LOW);

 /* Only one LED should be blinking here.
 */

 for (itrTest = 0; itrTest < 5; itrTest++) {
     digitalWrite(pinLED1, LOW);
     digitalWrite(pinSrc, LOW);
     delay(500);
     digitalWrite(pinSrc, HIGH);
     digitalWrite(pinLED1, HIGH);
     delay(500);
 }

 /* Show that this iteration of the test has completed
 */

 for (itrTest = 0; itrTest < 5; itrTest++) {
     digitalWrite(pinLED1, HIGH);
     delay(100);
     digitalWrite(pinLED1, LOW);
     delay(100);
 }

 delay(1000);

 }

 /* ------------------------------------------------------------ */
 /** IsrTest
  **
  ** Parameters:
  ** none
  **
  ** Return Value:
  ** none
  **
  ** Errors:
  ** none
  **
  ** Description:
  ** Interrupt handler routine.
  ** This toggles the state of LED2 each time it is entered.
  */

 void IsrTest() {

 intStat = 1 - intStat;
 if (intStat != 0) {
     digitalWrite(pinLED2, HIGH);
 }
 else {
     digitalWrite(pinLED2, LOW);
 }

 }

 /* ------------------------------------------------------------ */

 /***********************************************************************/

Notes on porting issues from one Novice’s perspective

There are several challenges in porting stuff from Arduino to Max32

Overloaded pins

Almost every pin on the MAX32 does many different things. This is, in part, due to the fact that the attached pins on the PIC32 do many different things. However, it can make it hard to find functional pins not in use to do what you want to do. Especially if your application wants to manipulate several bits at once (e.g. an 8 bit data path to an LCD display).

Crazy pin layouts

Not sure why they chose to do things this way, but many of the pin functions on the Max 32 are in very different places from the Mega 2560. Both platforms, for example, suffer from the fact that there is only one place where you can get 8 pins mapped to consecutive bits on a single register (at least if you want them all on the same connector). On the Mega 2560, these are 22-29 where 22 is bit0 and 29 is bit 7 of register D. On the Max32, pin 30 is bit 7 and pin 37 is bit 0 of register E. The I2C bus is still on 20-21. SPI is still on 50-53, but 53 can’t be used for SS if you are using the built-in Ethernet MAC. The Ethernet MAC<->Phy connection ties up a lot of pins. It would have been nice if they’d put the Phy on-board and moved the conflicting pins on to the pins 70-84 connector and made some of the Arduino-intersecting pins available for more Arduino-like purposes. Unfortunately, instead, they blocked off pins 7, 40-43, 45-49, and 53 and those pins are tied up for a stack-on Phy daughter card. Thankfully, they used the RMII and not the MII. It takes some digging in the documentation to find all the pin reservations and whatnot for the various peripherals. The most useful guide to resolving pin conflicts is the Max32 Reference Manual from the diligent web site, but, one must constantly go back and forth between the text describing each advanced peripheral and the pin-map at the end of the document in order to decipher all the conflicts. It would be nice if someone could produce a table which listed each of the built-in peripherals on one axis and each of the pins on the other axis with the squares filled in for each pin used by each peripheral. Another table that would be handy would be one with each peripheral on both axis and squares filled in showing which peripherals were mutually exclusive. For example, if you’re using CAN1, UART3 conflicts. If you’re using CAN2, I2C conflicts, etc.

Ethernet uses MANY pins all over the place (bad) and a software stack (maybe good)

The built-in Ethernet MAC uses a lot of pins to talk to the RMII Phy. Someone made a post on the forum asking why no MII. While it’s true that MII would allow faster communications with less processor overhead, the simple reality is that for a board with 83 pins, this board already has surprisingly few functionally available pins. Especially if you’re building something that you want to be a shield that can be used with both Mega2560 and Max32. (In fact, see crazy pin layouts for one reason this is near impossible). The Ethernet RMII interface is the worst offender in the pin conflict world. It ties up pins 7, 40-43, 45-49, and 53 for exclusive use. Of course there are different pins tied up by the W5100 interface which has a built-in phy and a built-in TCP/IP stack. The built-in phy means not as many pins tied up on the Mega 2560 using the W5100. Even with a software-stack based MAC chip with an external Phy, on the Mega 2560 platform this is usually implemented with the MAC and Phy on the same shield so that the MAC<->Phy interface doesn’t use any GPIO pins from the ATMega chip. However, this isn’t (entirely) Digilent/ChipKit’s fault. In this case, the PIC32MX975 implements the MAC requiring an external Phy. This means that the point where the MAC<->Phy pins are tied up is inside the MCU itself. The implementation of a simple MAC that isn’t overloaded with a built-in TCP-IP stack does make programs larger (add about 45k for the IPv4 stack, for example), but it allows you to implement whatever protocol you want on top of the MAC. (For example, I am hoping to take the IPv6 library contributed by someone else and combine it with the existing chipKITEthernet library to produce a dual-stack Max32. Well, actually, I’m hoping someone else will do that soon, but, if they don’t, I’ll end up tackling the project). OTOH, the W5100 chip commonly used on the Arduino platform requires only 1 dedicated SS pin and uses the SPI bus for everything else. It’s slower and can only do IPv4 (unless you use RAW packet IO mode to emit hand-crafted ethernet frames). Since IPv4 will likely be 99% obsolete in less than 5 years, that seems like a serious limitation to the platform. In my discussions with Wizard, they’ve pretty much blown off the idea of supporting IPv6 on their chips so far, so, I’m very glad the PIC32 has a raw MAC built-in and that Max32 went with this implementation.

Differing approaches to low-level IO

The AVR and the PIC have radically different low-level IO mechanisms. Unfortunately, the standard libraries for both the Arduino and the Max32 platforms give you two choices for dealing with this. This is more a natural result of the way MPIDE evolved than something the developers set out to do wrong, but, the end result is still a relatively high level of dysfunctionality. The Arduino developers didn’t conceive of the need to support anything but ATMEGA and wrote accordingly. The MPIDE developers had a lot of work to do just to add multiple-platform support to existing abstraction libraries, so, abstracting more direct chip-level interactions to provide new functionality that would require library surgery for both platforms was probably perceived as an unnecessary additional adventure at the time. However, to make for clean integrated portable development in the future, this kind of needs to happen. A highly abstracted (slow) compatible library (digitalRead/Write, analogRead/Write) for dealing with a single PIN at a time and essentially raw access to the hardware registers. What is needed is a standard abstraction layer at the lowest level possible that provides a standard mechanism for doing multiple-pin simultaneous register manipulation using the most efficient hardware method available while remaining just abstract enough to hide the hardware differences. It definitely doesn’t help that the PIC32 has 16 bit hardware registers while the ATMega uses 8-bit registers, but, this could still be handled: For example, having a library that provided an API such as assign()/set()/clear()/invert() each of which took the form set(RegisterC, 0xffc3) where RegisterC was a handle for hardware register C (PIC32) or C & D (ATMega) and 0xffc3 were the bits to set. On the PIC32, this would be implemented as LATC = 0xffc3. On the ATMega it would be implemented as PORTC |= (0xffc3 >> 8); PORTD |= (0xffc3 & 0x00ff);. assign() would simply assign the argument value to the appropriate register(s). set(), clear(), and invert() would function along the lines of the SET/CLR/INV register aliases on the PIC32. It might be better to implement 8-bit based arguments, however. This will make the code more ATMega native and slower on the PIC, but, wouldn’t require ATMega programmers to understand that PORTC means PORTC at 0xff00 and PORTD at 0x00ff in the arguments. I’m really not sure what the ideal solution is, which at the end of the day may be a hard question to answer and could be part of the reason this hasn’t happened yet.

Weird AVR-specific mechanisms like PROGMEM peppered throughout libraries

The best thing about the Arduino platform (arguably it’s only saving grace) is that there are a ton of libraries out there for supporting an incredibly wide variety of hardware. This is no small feat and is the only explanation I can find for Arduino’s extreme popularity, especially as a micro controller entry-level platform. (Though the IDE is helpful for beginners too, but, with MPIDE, that’s no longer an Arduino-exclusive advantage). Unfortunately, no effort whatsoever has been made in the Arduino world to make the libraries at all portable to other platforms and many libraries make use of non-abstracted low-level hardware functions that are AVR specific. In particular, it seems to be very popular in the Arduino to load static arrays into PROGMEM and then use special functions for accessing their contents. (see any graphical device library with built-in font(s) for an example). Beyond that, there’s the low-level IO stuff mentioned in the previous subtopic. Both of these things mean that I’ve had to perform surgery on almost every library I’ve used.

MPIDE is both ahead of and behind Arduino IDE

MPIDE development drove many of the changes/enhancements incorporated into Arduino IDE 1.00. Unfortunately, MPIDE did not keep up with the changes to Arduino IDE in 1.00 that it was not driving, so, MPIDE is trapped in this weird limbo between 0023 and 1.00 for now. (March 6, 2012) Work is ongoing to resolve this and I plan to make an effort to contribute to that work, but, this means even more libraries need surgery to back port them to the Max32 environment for the time being. One place where this is hideously obvious is in the Ethernet library(ies).

Both platforms suck at networking

On the Arduino, for example, the W5100 chip exports link state only through a single hardware pin. There is no way to read the value of this pin short of performing hardware surgery on the Arduino board. The pin goes from the W5100 chip through an LED (and possibly a resistor) to ground and that’s all she wrote. You’d have to intercept the trace before the first external component and tie that to a digital pin to be able to detect link state in your program. The W5100 chip, among its other faults does not export this value in a software-readable register. The situation is slightly better in the Max32. Because the RMII is external to the PIC32 MAC, the PIC32 has to make this information (from the Phy) available in a register so that software can correctly control the MAC<->Phy interface. The chipKITEthernet library has a function for reading this called MACIsLinked(). For some bizarre reason, this function is in the lower-level utility/… part of the library and is not exported as part of the public API. There seems to be an assumption that if you’re using the Ethernet Library, you don’t necessarily have any concerns about how long it takes for calls to return (sort of). The Chipkit library is actually written with these performance capabilities in mind at the lower level, but, for unknown reasons, they are only partially exported to the application. For example, you can set the timeout (in seconds) for a client.connect() call, but you can’t set the timeout for begin() with DHCP. The lower level library allows this to be done, but, does not export the capability. Worse, the Chipkit Ethernet.begin() returns void while the Arduino 1.00 returns int. With the Arduino, if int=0, something bad happened. With Chipkit, determining whether or not something bad happened is a bit of an adventure. Both have standard DHCP timeouts taken directly from desktop computer implementations (around 30 seconds). This is fine if networking is critical to your application and you don’t mind pending until the network works, but, if the network is a “nice to have” feature your application will take advantage of when it is working (as in my particular application), you want DHCP to be almost non-blocking (a 5 second timeout is tolerable in my application, but a 30-second hang is untenable). Ideally this should be controllable from the application. In the case of the Chipkit library, the needed functionality is almost there, but, tDHCPTimeout in the low level library is defined as a local (?!!) constant (?!) within the begin() function. Making this a global variable and exporting it to the API is all that is needed to provide the necessary functionality.

Miscellaneous additional rants

For an “Arduino Compatible” board, getting my hardware working on the Max32 has been an unexpected adventure. Don’t get me wrong, I LOVE that my frame rate has gone from 250ms+/frame to ~25ms/frame and that my buttons have become reasonably responsive. I LOVE that the TCP/IP is a library and not a chip-based mechanism (I want to dual-stack my Max32 eventually). I think I found an IPv6 library for it and there is already the IPv4 library that ships with the MPIDE, so, hopefully I can marry them. (additional note: Don’t use the Ethernet library that Chipkit ships with the MPIDE. Download the package that includes the chipKITEthernet library. It’s a much better starting point). Another example, however, is that the MPIDE Ethernet Library has functionality in 0023 beyond the Arduino 0023 Ethernet Library, but, falls short of the Ethernet Library in Arduino 1.0.

Concluding thought

I hope these notes on my experience are helpful to other developers. I also hope that the IDE developers at both Chipkit and Arduino will work on implementing these suggestions and merging the two IDEs into a single standardized environment for multiple-platform development.
VN:F [1.9.22_1171]
Rating: 10.0/10 (2 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 2 votes)