esp32-hal-gpio.c
1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 16 #include "stdint.h" 17 #include "esp32-hal-gpio.h" 18 #include "freertos/FreeRTOS.h" 19 #include "freertos/task.h" 20 #include "rom/ets_sys.h" 21 #include "esp_attr.h" 22 #include "esp_intr.h" 23 #include "rom/gpio.h" 24 #include "soc/gpio_reg.h" 25 #include "soc/io_mux_reg.h" 26 #include "soc/gpio_struct.h" 27 #include "soc/rtc_io_reg.h" 28 #include "esp_system.h" 29 30 #define ESP_REG(addr) *((volatile uint32_t *)(addr)) 31 32 const int8_t esp32_adc2gpio[20] = {36, 37, 38, 39, 32, 33, 34, 35, -1, -1, 4, 0, 2, 15, 13, 12, 14, 27, 25, 26}; 33 34 const DRAM_ATTR esp32_gpioMux_t esp32_gpioMux[GPIO_PIN_COUNT]={ 35 {0x44, 11, 11, 1}, 36 {0x88, -1, -1, -1}, 37 {0x40, 12, 12, 2}, 38 {0x84, -1, -1, -1}, 39 {0x48, 10, 10, 0}, 40 {0x6c, -1, -1, -1}, 41 {0x60, -1, -1, -1}, 42 {0x64, -1, -1, -1}, 43 {0x68, -1, -1, -1}, 44 {0x54, -1, -1, -1}, 45 {0x58, -1, -1, -1}, 46 {0x5c, -1, -1, -1}, 47 {0x34, 15, 15, 5}, 48 {0x38, 14, 14, 4}, 49 {0x30, 16, 16, 6}, 50 {0x3c, 13, 13, 3}, 51 {0x4c, -1, -1, -1}, 52 {0x50, -1, -1, -1}, 53 {0x70, -1, -1, -1}, 54 {0x74, -1, -1, -1}, 55 {0x78, -1, -1, -1}, 56 {0x7c, -1, -1, -1}, 57 {0x80, -1, -1, -1}, 58 {0x8c, -1, -1, -1}, 59 {0, -1, -1, -1}, 60 {0x24, 6, 18, -1}, //DAC1 61 {0x28, 7, 19, -1}, //DAC2 62 {0x2c, 17, 17, 7}, 63 {0, -1, -1, -1}, 64 {0, -1, -1, -1}, 65 {0, -1, -1, -1}, 66 {0, -1, -1, -1}, 67 {0x1c, 9, 4, 9}, 68 {0x20, 8, 5, 8}, 69 {0x14, 4, 6, -1}, 70 {0x18, 5, 7, -1}, 71 {0x04, 0, 0, -1}, 72 {0x08, 1, 1, -1}, 73 {0x0c, 2, 2, -1}, 74 {0x10, 3, 3, -1} 75 }; 76 77 typedef void (*voidFuncPtr)(void); 78 typedef void (*voidFuncPtrArg)(void*); 79 typedef struct { 80 voidFuncPtr fn; 81 void* arg; 82 bool functional; 83 } InterruptHandle_t; 84 static InterruptHandle_t __pinInterruptHandlers[GPIO_PIN_COUNT] = {0,}; 85 86 #include "driver/rtc_io.h" 87 88 extern void IRAM_ATTR __pinMode(uint8_t pin, uint8_t mode) 89 { 90 91 if(!digitalPinIsValid(pin)) { 92 return; 93 } 94 95 uint32_t rtc_reg = rtc_gpio_desc[pin].reg; 96 if(mode == ANALOG) { 97 if(!rtc_reg) { 98 return;//not rtc pin 99 } 100 //lock rtc 101 uint32_t reg_val = ESP_REG(rtc_reg); 102 if(reg_val & rtc_gpio_desc[pin].mux){ 103 return;//already in adc mode 104 } 105 reg_val &= ~( 106 (RTC_IO_TOUCH_PAD1_FUN_SEL_V << rtc_gpio_desc[pin].func) 107 |rtc_gpio_desc[pin].ie 108 |rtc_gpio_desc[pin].pullup 109 |rtc_gpio_desc[pin].pulldown); 110 ESP_REG(RTC_GPIO_ENABLE_W1TC_REG) = (1 << (rtc_gpio_desc[pin].rtc_num + RTC_GPIO_ENABLE_W1TC_S)); 111 ESP_REG(rtc_reg) = reg_val | rtc_gpio_desc[pin].mux; 112 //unlock rtc 113 ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = ((uint32_t)2 << MCU_SEL_S) | ((uint32_t)2 << FUN_DRV_S) | FUN_IE; 114 return; 115 } 116 117 //RTC pins PULL settings 118 if(rtc_reg) { 119 //lock rtc 120 ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux); 121 if(mode & PULLUP) { 122 ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pullup) & ~(rtc_gpio_desc[pin].pulldown); 123 } else if(mode & PULLDOWN) { 124 ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pulldown) & ~(rtc_gpio_desc[pin].pullup); 125 } else { 126 ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); 127 } 128 //unlock rtc 129 } 130 131 uint32_t pinFunction = 0, pinControl = 0; 132 133 //lock gpio 134 if(mode & INPUT) { 135 if(pin < 32) { 136 GPIO.enable_w1tc = ((uint32_t)1 << pin); 137 } else { 138 GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); 139 } 140 } else if(mode & OUTPUT) { 141 if(pin > 33){ 142 //unlock gpio 143 return;//pins above 33 can be only inputs 144 } else if(pin < 32) { 145 GPIO.enable_w1ts = ((uint32_t)1 << pin); 146 } else { 147 GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32)); 148 } 149 } 150 151 if(mode & PULLUP) { 152 pinFunction |= FUN_PU; 153 } else if(mode & PULLDOWN) { 154 pinFunction |= FUN_PD; 155 } 156 157 pinFunction |= ((uint32_t)2 << FUN_DRV_S);//what are the drivers? 158 pinFunction |= FUN_IE;//input enable but required for output as well? 159 160 if(mode & (INPUT | OUTPUT)) { 161 pinFunction |= ((uint32_t)2 << MCU_SEL_S); 162 } else if(mode == SPECIAL) { 163 pinFunction |= ((uint32_t)(((pin)==1||(pin)==3)?0:1) << MCU_SEL_S); 164 } else { 165 pinFunction |= ((uint32_t)(mode >> 5) << MCU_SEL_S); 166 } 167 168 ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction; 169 170 if(mode & OPEN_DRAIN) { 171 pinControl = (1 << GPIO_PIN0_PAD_DRIVER_S); 172 } 173 174 GPIO.pin[pin].val = pinControl; 175 //unlock gpio 176 } 177 178 extern void IRAM_ATTR __digitalWrite(uint8_t pin, uint8_t val) 179 { 180 if(val) { 181 if(pin < 32) { 182 GPIO.out_w1ts = ((uint32_t)1 << pin); 183 } else if(pin < 34) { 184 GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); 185 } 186 } else { 187 if(pin < 32) { 188 GPIO.out_w1tc = ((uint32_t)1 << pin); 189 } else if(pin < 34) { 190 GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); 191 } 192 } 193 } 194 195 extern int IRAM_ATTR __digitalRead(uint8_t pin) 196 { 197 if(pin < 32) { 198 return (GPIO.in >> pin) & 0x1; 199 } else if(pin < 40) { 200 return (GPIO.in1.val >> (pin - 32)) & 0x1; 201 } 202 return 0; 203 } 204 205 static intr_handle_t gpio_intr_handle = NULL; 206 207 static void IRAM_ATTR __onPinInterrupt() 208 { 209 uint32_t gpio_intr_status_l=0; 210 uint32_t gpio_intr_status_h=0; 211 212 gpio_intr_status_l = GPIO.status; 213 gpio_intr_status_h = GPIO.status1.val; 214 GPIO.status_w1tc = gpio_intr_status_l;//Clear intr for gpio0-gpio31 215 GPIO.status1_w1tc.val = gpio_intr_status_h;//Clear intr for gpio32-39 216 217 uint8_t pin=0; 218 if(gpio_intr_status_l) { 219 do { 220 if(gpio_intr_status_l & ((uint32_t)1 << pin)) { 221 if(__pinInterruptHandlers[pin].fn) { 222 if(__pinInterruptHandlers[pin].arg){ 223 ((voidFuncPtrArg)__pinInterruptHandlers[pin].fn)(__pinInterruptHandlers[pin].arg); 224 } else { 225 __pinInterruptHandlers[pin].fn(); 226 } 227 } 228 } 229 } while(++pin<32); 230 } 231 if(gpio_intr_status_h) { 232 pin=32; 233 do { 234 if(gpio_intr_status_h & ((uint32_t)1 << (pin - 32))) { 235 if(__pinInterruptHandlers[pin].fn) { 236 if(__pinInterruptHandlers[pin].arg){ 237 ((voidFuncPtrArg)__pinInterruptHandlers[pin].fn)(__pinInterruptHandlers[pin].arg); 238 } else { 239 __pinInterruptHandlers[pin].fn(); 240 } 241 } 242 } 243 } while(++pin<GPIO_PIN_COUNT); 244 } 245 } 246 247 extern void cleanupFunctional(void* arg); 248 249 extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional) 250 { 251 static bool interrupt_initialized = false; 252 253 if(!interrupt_initialized) { 254 interrupt_initialized = true; 255 esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, __onPinInterrupt, NULL, &gpio_intr_handle); 256 } 257 258 // if new attach without detach remove old info 259 if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg) 260 { 261 cleanupFunctional(__pinInterruptHandlers[pin].arg); 262 } 263 __pinInterruptHandlers[pin].fn = (voidFuncPtr)userFunc; 264 __pinInterruptHandlers[pin].arg = arg; 265 __pinInterruptHandlers[pin].functional = functional; 266 267 esp_intr_disable(gpio_intr_handle); 268 if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU 269 GPIO.pin[pin].int_ena = 1; 270 } else { //PRO_CPU 271 GPIO.pin[pin].int_ena = 4; 272 } 273 GPIO.pin[pin].int_type = intr_type; 274 esp_intr_enable(gpio_intr_handle); 275 } 276 277 extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type) 278 { 279 __attachInterruptFunctionalArg(pin, userFunc, arg, intr_type, false); 280 } 281 282 extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int intr_type) { 283 __attachInterruptFunctionalArg(pin, (voidFuncPtrArg)userFunc, NULL, intr_type, false); 284 } 285 286 extern void __detachInterrupt(uint8_t pin) 287 { 288 esp_intr_disable(gpio_intr_handle); 289 if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg) 290 { 291 cleanupFunctional(__pinInterruptHandlers[pin].arg); 292 } 293 __pinInterruptHandlers[pin].fn = NULL; 294 __pinInterruptHandlers[pin].arg = NULL; 295 __pinInterruptHandlers[pin].arg = false; 296 297 GPIO.pin[pin].int_ena = 0; 298 GPIO.pin[pin].int_type = 0; 299 esp_intr_enable(gpio_intr_handle); 300 } 301 302 303 extern void pinMode(uint8_t pin, uint8_t mode) __attribute__ ((weak, alias("__pinMode"))); 304 extern void digitalWrite(uint8_t pin, uint8_t val) __attribute__ ((weak, alias("__digitalWrite"))); 305 extern int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead"))); 306 extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterrupt"))); 307 extern void attachInterruptArg(uint8_t pin, voidFuncPtrArg handler, void * arg, int mode) __attribute__ ((weak, alias("__attachInterruptArg"))); 308 extern void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt"))); 309