Created Sat, 29 Oct 2011 21:29:01 +0000 by 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?
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
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.