Testbench for FastIO

Dependencies:   FastIO mbed

Fork of FastIO by Igor Skochinsky

Files at this revision

API Documentation at this revision

Comitter:
Sissors
Date:
Tue Jul 01 17:21:29 2014 +0000
Parent:
4:b8e40f2a0aac
Child:
6:8ad8f8acd0a5
Commit message:
v1.0

Changed in this revision

FastIO.h Show diff for this revision Revisions of this file
FastIO.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- a/FastIO.h	Tue May 25 08:35:39 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-#ifndef __FAST_IO_H
-#define __FAST_IO_H
-
-#include "mbed.h"
-
-// Super-fast DigitalOut-like class for mbed
-//   by Igor Skochinsky
-
-// includes FastOut, FastPortOut and MaskedPortOut classes
-// usage:
-//   FastOut<LED2> led2;
-//   FastPortOut<Port0, LED_MASK> ledport2;
-//   MaskedPortOut<Port0, LED_MASK> ledport3;
-//   led2 = 1;
-//   ledport2 = LED_MASK;
-//   ledport3 = LED_MASK;
-// MaskedPortOut works the same way as FastPortOut, but it pre-sets the pin mask so that write can be done in one operation
-// this makes things faster but you can't control other pins of the port, even with other classes
-
-
-// pin definitions in PinNames.h start from LPC_GPIO0_BASE for P0_0 and there are 32 pins to a port (0 to 31)
-// Thus:
-// pin = LPC_GPIO0_BASE + port * 32 + bit
-// port = (pin - LPC_GPIO0_BASE) / 32
-// bit  = (pin - LPC_GPIO0_BASE) % 32
-
-#define PORTNO(pin) (((pin) - P0_0)/32)
-#define BITNO(pin)  (((pin) - P0_0)%32)
-
-// calculate the GPIO port definition for the pin
-// we rely on the fact that port structs are 0x20 bytes apart
-#define PORTDEF(pin) ((LPC_GPIO_TypeDef*)(LPC_GPIO0_BASE + PORTNO(pin)*0x20))
-
-#define PORTDEFPORT(port) ((LPC_GPIO_TypeDef*)(LPC_GPIO0_BASE + port*0x20))
-
-// calculate the mask for the pin's bit in the port
-#define PINMASK(pin) (1UL << BITNO(pin))
-
-// each port takes two PINSEL registers (8 bytes or 64 bits)
-// so there are 16 pins per PINSEL
-#define PINSELREG(pin)  (*(volatile uint32_t*)(LPC_PINCON_BASE + 4*(((pin) - P0_0)/16)))
-#define PINSELMASK(pin, v) (v << (((pin - P0_0)%16)*2) )
-
-// usage: FastOut<LED2> led2;
-// then use the same assignment operators as with DigitalOut
-template <PinName pin> class FastOut
-{
-public:
-    FastOut()
-    {
-        // set PINSEL bits to 0b00 (GPIO)
-        PINSELREG(pin) &= ~PINSELMASK(pin, 3);
-        // set FIODIR bit to 1 (output)
-        PORTDEF(pin)->FIODIR |= PINMASK(pin);
-    }
-    void write(int value)
-    { 
-        if ( value )
-            PORTDEF(pin)->FIOSET = PINMASK(pin);
-        else
-            PORTDEF(pin)->FIOCLR = PINMASK(pin);
-    } 
-    int read()
-    {
-        return PORTDEF(pin)->FIOPIN & PINMASK(pin) != 0;
-    }
-    FastOut& operator= (int value) { write(value); return *this; };
-    FastOut& operator= (FastOut& rhs) { return write(rhs.read()); };
-    operator int() { return read(); };
-};
-
-#define PINSELREG(pin)  (*(volatile uint32_t*)(LPC_PINCON_BASE + 4*(((pin) - P0_0)/16)))
-#define PINSELMASK(pin, v) (v << (((pin - P0_0)%16)*2) )
-
-// usage: FastPortOut<Port0, mask> led2;
-// then use the same assignment operators as with DigitalOut
-template <enum PortName port, uint32_t mask = 0xFFFFFFFF> class FastPortOut
-{
-public:
-    FastPortOut()
-    {
-        // init pins selected by the mask
-        uint32_t pin = LPC_GPIO0_BASE + port * 32;
-        for ( uint32_t pinmask = mask; pinmask !=0; pinmask >>= 1 )
-        {
-            if ( pinmask & 1 )
-            {
-                // set PINSEL bits to 0b00 (GPIO)
-                PINSELREG(pin) &= ~PINSELMASK(pin, 3);
-                // set FIODIR bit to 1 (output)
-                PORTDEF(pin)->FIODIR |= PINMASK(pin);
-            }
-            pin++;
-        }
-    }
-    void write(int value)
-    {
-        PORTDEFPORT(port)->FIOSET = value & mask;
-        PORTDEFPORT(port)->FIOCLR = ~value & mask;
-    } 
-    int read()
-    {
-        return PORTDEFPORT(port)->FIOPIN & mask;
-    }
-    FastPortOut& operator= (int value) { write(value); return *this; };
-    FastPortOut& operator= (FastPortOut& rhs) { return write(rhs.read()); };
-    operator int() { return read(); };
-};
-
-// usage: MaskedPortOut<Port0, mask> led2;
-// then use the same assignment operators as with DigitalOut
-template <enum PortName port, uint32_t mask = 0xFFFFFFFF> class MaskedPortOut
-{
-public:
-    MaskedPortOut()
-    {
-        // init pins selected by the mask
-        uint32_t pin = LPC_GPIO0_BASE + port * 32;
-        for ( uint32_t pinmask = mask; pinmask !=0; pinmask >>= 1 )
-        {
-            if ( pinmask & 1 )
-            {
-                // set PINSEL bits to 0b00 (GPIO)
-                PINSELREG(pin) &= ~PINSELMASK(pin, 3);
-                // set FIODIR bit to 1 (output)
-                PORTDEF(pin)->FIODIR |= PINMASK(pin);
-            }
-            pin++;
-        }
-        // set mask
-        PORTDEFPORT(port)->FIOMASK = mask;
-    }
-    void write(int value)
-    {
-        PORTDEFPORT(port)->FIOPIN = value;
-    } 
-    int read()
-    {
-        return PORTDEFPORT(port)->FIOPIN;
-    }
-    MaskedPortOut& operator= (int value) { write(value); return *this; };
-    MaskedPortOut& operator= (MaskedPortOut& rhs) { return write(rhs.read()); };
-    operator int() { return read(); };
-};
-
-#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FastIO.lib	Tue Jul 01 17:21:29 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/Sissors/code/FastIO/#d394ebd01052
--- a/main.cpp	Tue May 25 08:35:39 2010 +0000
+++ b/main.cpp	Tue Jul 01 17:21:29 2014 +0000
@@ -1,73 +1,344 @@
 #include "mbed.h"
-
 #include "FastIO.h"
+ 
+DigitalInOut led1(LED1);
+FastInOut<LED2> led2;
+ 
+Timer t;
+#define LOOPS 10000
 
-#define LED_MASK 0x07800000
+void basic_test();
+void fixed_write();
+void variable_write();
+void read();
+void operator_toggle();
+void input_output();
+
+void print_results(int digicount, int fastcount);
+
+int main() {
+    printf("\r\nAll numbers are the number of core clock cycles per IO operation\r\n");
+    
+    basic_test();
+    fixed_write();
+    variable_write();
+    read();
+    operator_toggle();
+    input_output();
+    
+    while(1);
+}
 
-DigitalOut led1(LED1);
-FastOut<LED2> led2;
-PortOut ledport(Port0, LED_MASK);
-FastPortOut<Port0, LED_MASK> ledport2;
-MaskedPortOut<Port0, LED_MASK> ledport3;
+void print_results(int digicount, int fastcount) {
+    float digicycles = (float)digicount / LOOPS * (float)SystemCoreClock / 1000000.0f;
+    float fastcycles = (float)fastcount / LOOPS * (float)SystemCoreClock / 1000000.0f;
+    printf("Standard took %.1f cycles, FastIO took %.1f cycles, which is %d%%\r\n", digicycles, fastcycles,(int)(100.0f*fastcycles/digicycles + 0.5));
+}
+ 
+void basic_test() {
+printf("Verifying basic behavior\r\n");
+    int error = 0;
+    led1.output();
+    led2.output();
+    led1 = 1;
+    led2 = 1;
+    error += (led1.read() != 1);
+    error += (led2.read() != 1);
+    led1 = 0;
+    led2 = 0;
+    error += (led1.read() != 0);
+    error += (led2.read() != 0);
+    
+    if (error == 0) 
+        printf("Basic behavior verified\r\n");
+    else {
+        printf("Error in basic behavior\r\n");
+        while(1);
+    }
+}
 
-Timer t;
-#define LOOPS 100000000
-int main() {
-    int value = 0;
-    int count = LOOPS;
+
+void fixed_write() {
+    int overhead;
+    int digitalinout;
+    int fastinout;
+    int count;
+    
+    printf("\nMeasuring fixed write pattern speed\r\n");
+    led1.output();
+    led2.output();
+    
+    //Calculate loop overhead
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- ) {
+        led1.write(1);
+        led1.write(0);
+    }
+    t.stop();
+    overhead = t.read_us();
+    
+    count = LOOPS / 2;
+    t.reset();
     t.start();
     while ( count -- )
     {
-        led1.write(value);
-        value = 1-value;
+        led1.write(1);
+        led1.write(0);
+        led1.write(1);
+        led1.write(0);
+    }
+    t.stop();
+    digitalinout = t.read_us() - overhead;
+    
+    //Calculate loop overhead
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- ) {
+        led2.write(1);
+        led2.write(0);
+    }
+    t.stop();
+    overhead = t.read_us();
+    
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- )
+    {
+        led2.write(1);
+        led2.write(0);
+        led2.write(1);
+        led2.write(0);
     }
     t.stop();
-    printf("DigitalOut: %f seconds (%d ns per iteration).\n", t.read(), t.read_us()/(LOOPS/1000));
+    fastinout = t.read_us() - overhead;
+    
+    print_results(digitalinout, fastinout);
+}
+
+void variable_write() {
+    int overhead;
+    int digitalinout;
+    int fastinout;
+    int count;
+    
+    printf("\nMeasuring variable write pattern speed\r\n");
+    led1.output();
+    led2.output();
+    
+    //Calculate loop overhead
+    int value = 1;
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- ) {
+        value = value - 1; led1.write(value);
+        value = value - 1; 
+        value = value - 1;
+        value = value - 1; led1.write(value);
+    }
+    
+    t.stop();
+    overhead = t.read_us();
+
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- )
+    {
+        value = value - 1; led1.write(value);
+        value = value - 1; led1.write(value);
+        value = value - 1; led1.write(value);
+        value = value - 1; led1.write(value);
+    }
+    t.stop();
+    digitalinout = t.read_us() - overhead;
     
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- ) {
+        value = value - 1; led2.write(value);
+        value = value - 1; 
+        value = value - 1;
+        value = value - 1; led2.write(value);
+    }
+    
+    t.stop();
+    overhead = t.read_us();
+
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- )
+    {
+        value = value - 1; led2.write(value);
+        value = value - 1; led2.write(value);
+        value = value - 1; led2.write(value);
+        value = value - 1; led2.write(value);
+    }
+    t.stop();
+    fastinout = t.read_us() - overhead;
+    print_results(digitalinout, fastinout);
+}
+
+void read() {
+    int overhead;
+    int digitalinout;
+    int fastinout;
+    int count;
+    
+    printf("\nMeasuring read speed\r\n");
+    led1.input(); led1.mode(PullUp);
+    led2.input(); led2.mode(PullUp);
+    
+    //Calculate loop overhead
+    count = LOOPS;
+    t.reset();
+    t.start();
+    while ( count -- ) {
+    }
+    t.stop();
+    overhead = t.read_us();
+
     count = LOOPS;
     t.reset();
     t.start();
     while ( count -- )
     {
-        led2 = value;
-        value = 1-value;
+        if (led1.read() == 2)       //This shouldn't happen due to pull-up, if you get weird results, it is happening
+            break;   
     }
     t.stop();
-    printf("FastOut: %f seconds (%d ns per iteration).\n", t.read(), t.read_us()/(LOOPS/1000));
-
-    count = LOOPS;
-    t.reset();
-    t.start();
-    value = LED_MASK;
-    while ( count -- )
-    {
-        ledport.write(value);
-        value ^= LED_MASK;
-    }
-    t.stop();
-    printf("PortOut: %f seconds (%d ns per iteration).\n", t.read(), t.read_us()/(LOOPS/1000));
+    digitalinout = t.read_us() - overhead;
 
     count = LOOPS;
     t.reset();
     t.start();
-    value = LED_MASK;
     while ( count -- )
     {
-        ledport2 = value;
-        value ^= LED_MASK;
+        if (led2.read() == 2)       //This shouldn't happen due to pull-up, if you get weird results, it is happening
+            break;       
+    }
+    t.stop();
+    fastinout = t.read_us() - overhead;
+ 
+    print_results(digitalinout, fastinout);
+}
+
+void operator_toggle() {
+    int overhead;
+    int digitalinout;
+    int fastinout;
+    int count;
+    
+    printf("\nMeasuring toggling using operators speed\r\n");
+    led1.output();
+    led2.output();
+    
+    //Calculate loop overhead
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- ) {
+        led1 = !led1;      
+        led1 = !led1;
+    }
+    t.stop();
+    overhead = t.read_us();
+
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- ) {
+        led1 = !led1;      
+        led1 = !led1;
+        led1 = !led1;      
+        led1 = !led1;
+    }
+    t.stop();
+    digitalinout = t.read_us() - overhead;
+    
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- ) {
+        led2 = !led2;
+        led2 = !led2;
     }
     t.stop();
-    printf("FastPortOut: %f seconds (%d ns per iteration).\n", t.read(), t.read_us()/(LOOPS/1000));
+    overhead = t.read_us();
+    
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- )
+    {
+         led2 = !led2;
+         led2 = !led2;
+         led2 = !led2;
+         led2 = !led2;
+    }
+    t.stop();
+    fastinout = t.read_us() - overhead;
+    print_results(digitalinout, fastinout);
+}
 
-    count = LOOPS;
+void input_output() {
+    int overhead;
+    int digitalinout;
+    int fastinout;
+    int count;
+    
+    printf("\nMeasuring switching between input and output\r\n");
+    
+    //Calculate loop overhead
+    count = LOOPS / 2;
     t.reset();
     t.start();
-    value = LED_MASK;
+    while ( count -- ) {
+        led1.input();
+        led1.output();
+    }
+    t.stop();
+    overhead = t.read_us();
+
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- ) {
+        led1.input();
+        led1.output();
+        led1.input();
+        led1.output();
+    }
+    t.stop();
+    digitalinout = t.read_us() - overhead;
+    
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
+    while ( count -- ) {
+        led2.input();
+        led2.output();
+    }
+    t.stop();
+    overhead = t.read_us();
+    
+    count = LOOPS / 2;
+    t.reset();
+    t.start();
     while ( count -- )
     {
-        ledport3 = value;
-        value ^= LED_MASK;
+        led2.input();
+        led2.output();
+        led2.input();
+        led2.output();
     }
     t.stop();
-    printf("MaskedPortOut: %f seconds (%d ns per iteration).\n", t.read(), t.read_us()/(LOOPS/1000));
-}
+    fastinout = t.read_us() - overhead;
+    print_results(digitalinout, fastinout);
+}
\ No newline at end of file
--- a/mbed.bld	Tue May 25 08:35:39 2010 +0000
+++ b/mbed.bld	Tue Jul 01 17:21:29 2014 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/e6be4cd80aad
+http://mbed.org/users/mbed_official/code/mbed/builds/024bf7f99721
\ No newline at end of file