├── README.md ├── test_A.jpg └── test_B.jpg /README.md: -------------------------------------------------------------------------------- 1 | # Faster GPIOs on ESP8266 2 | 3 | Do you use standard GPIO_OUTPUT_SET() macros for your bit-banging and do you want to make it faster? Well, then you're on the right place. Continue reading and you'll see how to get 6x faster GPIOs compared to standard GPIO_OUTPUT_SET() macros. 4 | 5 | The way I see it, GPIO_OUTPUT_SET() was/is intended to be just for first initialization. 6 | For controlling the output GPIOs in the code it's much better to skip all the unnecessary calling underlying the GPIO_OUTPUT_SET() and set output GPIO pins directly using GPIO_OUT_W1TS_ADDRESS / GPIO_OUT_W1TC_ADDRESS registers. The resulting code will be smaller and faster. 7 | 8 | ## Test A - using GPIO_OUTPUT_SET() 9 | 10 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15); 11 | GPIO_OUTPUT_SET(15, 1); 12 | // 13 | while(1){ 14 | uint8_t i; 15 | for(i=0;i<20;i++) GPIO_OUTPUT_SET(15, 1); 16 | GPIO_OUTPUT_SET(15, 0); 17 | // 18 | vTaskDelay(1); 19 | } 20 | 21 | ![Test A](https://raw.githubusercontent.com/wdim0/esp8266_direct_gpio/master/test_A.jpg) 22 | 23 | ## Test B - using GPIO_OUT_W1TS/C directly 24 | 25 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15); 26 | GPIO_OUTPUT_SET(15, 1); 27 | // 28 | while(1){ 29 | uint8_t i; 30 | for(i=0;i<20;i++) GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1<<15); 31 | GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1<<15); 32 | // 33 | vTaskDelay(1); 34 | } 35 | 36 | ![Test B](https://raw.githubusercontent.com/wdim0/esp8266_direct_gpio/master/test_B.jpg) 37 | 38 | The timebase of the scope is set to 2 us per div in both test cases.
39 | Test A - impulse length is around 12 us.
40 | Test B - impulse length is around 1.9 us
41 | => code B is around 6x faster than A 42 | 43 | Tests configuration: ESP8266 running at default 80 MHz, RTOS (SDK 1.4.0) 44 | 45 | ## GPIO_OUT_W1TS/C details 46 | 47 | Each register is for all GPIOs - every bit corresponds to one GPIO (GPIO 0 is bit0, GPIO 1 is bit1, ...). You don't need to mask anything. If you just want to set one GPIO H/L, set the proper bit to 1, leave other bits to 0. Easy, fancy, fast. 48 | 49 | GPIO_OUT_W1TS_ADDRESS - write 1 to set GPIO (high) 50 | 51 | GPIO_OUT_W1TC_ADDRESS - write 1 to clear GPIO (low) 52 | 53 | Reading these registers, will give you 0 - they are just for writing. 54 | 55 | ## Conclusion 56 | 57 | It's definitely better to use direct GPIO control of output pins by writing to GPIO_OUT_W1TS_ADDRESS / GPIO_OUT_W1TC_ADDRESS registers. I've briefly looked into Espressif's GPIO driver (gpio.c, gpio.h) but there are no macros dedicated to this exactly. But anyway, it's so easy that we can do our own macros. 58 | 59 | Also, if you're using standard GPIO_INPUT_GET(...) for reading of GPIO inputs, you can optimize for speed. Just simply read GPIO_IN_ADDRESS register directly like this:
60 | ((GPIO_REG_READ(GPIO_IN_ADDRESS)&(BIT(12)))!=0) 61 | 62 | To sum it up and give you some hints: 63 | 64 | ... macros: 65 | 66 | #define GPIO4 ((GPIO_REG_READ(GPIO_IN_ADDRESS)&(BIT(4)))!=0) //each bit is for corresponding GPIO 67 | 68 | #define GPIO2_H (GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1<<2)) 69 | #define GPIO2_L (GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1<<2)) 70 | #define GPIO2(x) ((x)?GPIO2_H:GPIO2_L) 71 | 72 | ... init: 73 | 74 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2); 75 | GPIO_OUTPUT_SET(2, 0); //GPIO2 as output low 76 | 77 | GPIO_DIS_OUTPUT(4); //GPIO4 as input 78 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4); 79 | 80 | ... work with GPIOs: 81 | 82 | GPIO2_H; //set GPIO2 high (as fast as possible) 83 | GPIO2_L; //set GPIO2 low (as fast as possible) 84 | GPIO2(1); //set GPIO2 high (slightly slower, because of decision in macro) 85 | GPIO2(GPIO4); //set on GPIO2 the same level as is on GPIO4 input 86 | -------------------------------------------------------------------------------- /test_A.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wdim0/esp8266_direct_gpio/41620587d4ec2152aa406d0d14923f84a512130b/test_A.jpg -------------------------------------------------------------------------------- /test_B.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wdim0/esp8266_direct_gpio/41620587d4ec2152aa406d0d14923f84a512130b/test_B.jpg --------------------------------------------------------------------------------