/ MCUME_esp32 / espboot / components / Wire / esp32-hal-gpio.c
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