Description: Fast GPIO using C++ templates. Now with port I/O.
Revision 1:8064f8b8cf82, committed 22 May 2010
- Comitter:
- Date:
- Sat May 22 22:58:38 2010 +0000
- Parent:
- 0:f1e54c45ccaf
- Child:
- 2:9c4a8c01862c
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FastIO.h Sat May 22 22:58:38 2010 +0000
@@ -0,0 +1,100 @@
+#ifndef __FAST_IO_H
+#define __FAST_IO_H
+
+#include "mbed.h"
+
+// Super-fast DigitalOut-like class for mbed
+// by Igor Skochinsky
+
+// 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<0> 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)
+ {
+ if ( value & mask )
+ PORTDEFPORT(port)->FIOSET = value & mask;
+ if ( 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(); };
+};
+
+#endif
\ No newline at end of file
--- a/main.cpp Fri Mar 12 10:12:32 2010 +0000
+++ b/main.cpp Sat May 22 22:58:38 2010 +0000
@@ -1,46 +1,13 @@
#include "mbed.h"
-// Super-fast DigitalOut-like class for mbed
-// by Igor Skochinsky
-// usage: FastOut<LED2> led2;
-// then use the same assignment operators as with DigitalOut
-template <PinName pin> class FastOut
-{
-// pin = LPC_GPIO0_BASE + port * 32 + bit
-// port = (pin - LPC_GPIO0_BASE) / 32
-// bit = (pin - LPC_GPIO0_BASE) % 32
-
- // helper function to calculate the GPIO port definition for the pin
- // we rely on the fact that port structs are 0x20 bytes apart
- inline LPC_GPIO_TypeDef* portdef() { return (LPC_GPIO_TypeDef*)(LPC_GPIO0_BASE + ((pin - P0_0)/32)*0x20); };
+#include "FastIO.h"
- // helper function to calculate the mask for the pin's bit in the port
- inline uint32_t mask() { return 1UL<<((pin - LPC_GPIO0_BASE) % 32); };
-
-public:
- FastOut()
- {
- // set FIODIR bit to 1 (output)
- portdef()->FIODIR |= mask();
- }
- void write(int value)
- {
- if ( value )
- portdef()->FIOSET = mask();
- else
- portdef()->FIOCLR = mask();
- }
- int read()
- {
- return (portdef()->FIOPIN) & mask() != 0;
- }
- FastOut& operator= (int value) { write(value); return *this; };
- FastOut& operator= (FastOut& rhs) { return write(rhs.read()); };
- operator int() { return read(); };
-};
+#define LED_MASK 0x07800000
DigitalOut led1(LED1);
FastOut<LED2> led2;
+PortOut ledport(Port0, LED_MASK);
+FastPortOut<Port0, LED_MASK> ledport2;
Timer t;
#define LOOPS 100000000
@@ -55,6 +22,7 @@
}
t.stop();
printf("DigitalOut: %f seconds (%d ns per iteration).\n", t.read(), t.read_us()/(LOOPS/1000));
+
count = LOOPS;
t.reset();
t.start();
@@ -65,4 +33,28 @@
}
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));
+
+ count = LOOPS;
+ t.reset();
+ t.start();
+ value = LED_MASK;
+ while ( count -- )
+ {
+ ledport2 = value;
+ value ^= LED_MASK;
+ }
+ t.stop();
+ printf("FastPortOut: %f seconds (%d ns per iteration).\n", t.read(), t.read_us()/(LOOPS/1000));
}
--- a/mbed.bld Fri Mar 12 10:12:32 2010 +0000 +++ b/mbed.bld Sat May 22 22:58:38 2010 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0 +http://mbed.org/users/mbed_official/code/mbed/builds/e6be4cd80aad

