chipKIT® Development Platform

Inspired by Arduino™

Comparison of Pin switching methods in MPIDE and MPLABX

Created Sat, 29 Oct 2011 21:29:01 +0000 by drBart


drBart

Sat, 29 Oct 2011 21:29:01 +0000

I was interested in what sort of performance difference you get using various methods to toggle an LED, and get a general idea of how long it takes to repeat the code.

For this test, I had a DSO 082 O-Scope (CHEAP!) hooked up on pin 13 and ground.

The first method, I keep a state variable that indicates if the LED should be on or off. I negate the var and write it to pin 13. I observed a square wave with a period of about 1.6uS.

//state var to indicate LED state
int state = 0;

void setup()
{                
  //Set pin13 as output
  pinMode(13, OUTPUT);     
}

void loop()
{
  //negate the state variable
  state = !state;
  //write state to LED
  digitalWrite(13, state);
}

This next method, I read the pin state, negated it, and wrote to the pin. I observed a square wave with a period of about 3.5uS

void setup() {                
  //Set pin13 as output
  pinMode(13, OUTPUT);     
}

void loop()
{
  digitalWrite(13, !digitalRead(13));   //toggle LED
}

This last program was also written in MPIDE. It's nice that we have access to the peripheral library :) I observed a square wave with a period of about .2uS, though it's at the limit of what I can observe on the DSO 082.

void setup()
{                
  pinMode(13, OUTPUT);     
}

void loop()
{
  mPORTAToggleBits(BIT_3);   //toggle LED
}

With this program, I set and clear in one loop. I observed sharp pulses every .1uS, but again, I am at the limit of what I can see on my scope.

void setup()
{                
  pinMode(13, OUTPUT);     
}

void loop()
{
  mPORTASetBits(BIT_3);
  mPORTAClearBits(BIT_3);
}

I put an infinite loop inside of the loop function. I observed a signal that had a period of less than .02uS, but this is beyond my scopes ability to accurately display.

void setup()
{                
  pinMode(13, OUTPUT);     
}

void loop()
{
  while(1){
    mPORTASetBits(BIT_3);
    mPORTAClearBits(BIT_3);
  }
}

This last one I switched out the set and clear lines for a single toggle line. I observed little more than noise on my scope. Clearly, there is some unseen overhead outside of the loop() function.

Edit: I have a better scope, now. I measured a wave with a period of 50nS or 20Mhz. That would imply that there are four instructions per wave (80 MIPS / 20MHz = 4 instructions/wave): we do the boolean check twice and the toggle twice.

void setup()
{                
  pinMode(13, OUTPUT);     
}

void loop()
{
  while(1){
    mPORTAToggleBits(BIT_3);
  }
}

Lastly, I used MPLABX to program the PIC32 with this code through the picKit3. observed a square wave with a period of 20uS

#include <plib.h>
#include <p32xxxx.h>
int main(void)
{
  mPORTAClearBits(BIT_3);
  mPORTASetPinsDigitalOut(BIT_3);
  while(1)
    mPORTAToggleBits(BIT_3);
}

I won't lie, I was expecting the code compiled by MPLABX to run much faster. Does anyone have any ideas on why I'm seeing such poor performance in MPLABX?


WestfW

Sun, 30 Oct 2011 02:35:20 +0000

what does the machine code look like?

As a guess, perhaps you haven't done the clock system initialization that sets the PIC to run at 80 MHz instead of the unmultiplied 8MHz of the external crystal. From init.c:

void init()
{
#ifdef _ENABLE_PIC_RTC_
	// Configure the device for maximum performance but do not change the PBDIV
	// Given the options, this function will change the flash wait states, RAM
	// wait state and enable prefetch cache but will not change the PBDIV.
	// The PBDIV value is already set via the pragma FPBDIV option above..
	__PIC32_pbClk	=	SYSTEMConfig(F_CPU, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
#else
	__PIC32_pbClk	=	SYSTEMConfigPerformance(F_CPU);
#endif

Darth Maker

Sun, 30 Oct 2011 05:31:02 +0000

Loop() is slower than a while() because of function call overhead. Main looks like this:

#include "WProgram.h"

int main()
{
init();

Setup();

for(;;)
{
Loop();
}
return 0;
}

You could probably get the same performance if you make Loop an inline function, which would make more sense anyway.