Erik -
/
FastIO_TestBench
Testbench for FastIO
Fork of FastIO by
Revision 5:8a7a7df0a9c7, committed 2014-07-01
- 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
--- 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