Analisis biblioteca esp idf para el manejo de GPIOs - nachocarballeda/embebidos_fiuba GitHub Wiki
En la biblioteca esp-idf (Utilizable con el modulo ESP32 Wrover) el manejo de los GPIOs se lleva a cabo en:
esp-idf->components->driver->include->driver->gpio.c
En su interior podemos identificar las funciones usadas para realizar todas las tareas relacionadas al uso de los GPIOs, inicializar, configurar, escribir y leer.
Algunos ejemplos básicos son:
// Setear direccion del GPIO
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
// Setear el nivel de salida de un GPIO de salida
esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level);
// Utilizado para obtener el nivel lógico de un dado GPIO
int gpio_get_level(gpio_num_t gpio_num);
Dentro de gpio_set_direction
podemos ver, que a su vez se llaman a otros métodos y definiciones:
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode)
{
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
if ((GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) != true) && (mode & GPIO_MODE_DEF_OUTPUT)) {
ESP_LOGE(GPIO_TAG, "io_num=%d can only be input", gpio_num);
return ESP_ERR_INVALID_ARG;
}
esp_err_t ret = ESP_OK;
if (mode & GPIO_MODE_DEF_INPUT) {
gpio_input_enable(gpio_num);
} else {
gpio_input_disable(gpio_num);
}
if (mode & GPIO_MODE_DEF_OUTPUT) {
gpio_output_enable(gpio_num);
} else {
gpio_output_disable(gpio_num);
}
if (mode & GPIO_MODE_DEF_OD) {
gpio_od_enable(gpio_num);
} else {
gpio_od_disable(gpio_num);
}
return ret;
}
En primer lugar veamos en donde están definidos gpio_num_t
y gpio_mode_t
:
Buscando, encontramos que gpio_num_t
se encuentra definida en components->soc->include->hal->gpio_types.h
:
typedef enum {
GPIO_NUM_NC = -1, /*!< Use to signal not connected to S/W */
GPIO_NUM_0 = 0, /*!< GPIO0, input and output */
GPIO_NUM_1 = 1, /*!< GPIO1, input and output */
GPIO_NUM_2 = 2, /*!< GPIO2, input and output */
GPIO_NUM_3 = 3, /*!< GPIO3, input and output */
GPIO_NUM_4 = 4, /*!< GPIO4, input and output */
GPIO_NUM_5 = 5, /*!< GPIO5, input and output */
GPIO_NUM_6 = 6, /*!< GPIO6, input and output */
GPIO_NUM_7 = 7, /*!< GPIO7, input and output */
GPIO_NUM_8 = 8, /*!< GPIO8, input and output */
GPIO_NUM_9 = 9, /*!< GPIO9, input and output */
GPIO_NUM_10 = 10, /*!< GPIO10, input and output */
GPIO_NUM_11 = 11, /*!< GPIO11, input and output */
GPIO_NUM_12 = 12, /*!< GPIO12, input and output */
GPIO_NUM_13 = 13, /*!< GPIO13, input and output */
GPIO_NUM_14 = 14, /*!< GPIO14, input and output */
GPIO_NUM_15 = 15, /*!< GPIO15, input and output */
GPIO_NUM_16 = 16, /*!< GPIO16, input and output */
GPIO_NUM_17 = 17, /*!< GPIO17, input and output */
GPIO_NUM_18 = 18, /*!< GPIO18, input and output */
GPIO_NUM_19 = 19, /*!< GPIO19, input and output */
GPIO_NUM_20 = 20, /*!< GPIO20, input and output */
GPIO_NUM_21 = 21, /*!< GPIO21, input and output */
#if CONFIG_IDF_TARGET_ESP32
GPIO_NUM_22 = 22, /*!< GPIO22, input and output */
GPIO_NUM_23 = 23, /*!< GPIO23, input and output */
GPIO_NUM_25 = 25, /*!< GPIO25, input and output */
#endif
/* Note: The missing IO is because it is used inside the chip. */
GPIO_NUM_26 = 26, /*!< GPIO26, input and output */
GPIO_NUM_27 = 27, /*!< GPIO27, input and output */
GPIO_NUM_28 = 28, /*!< GPIO28, input and output */
GPIO_NUM_29 = 29, /*!< GPIO29, input and output */
GPIO_NUM_30 = 30, /*!< GPIO30, input and output */
GPIO_NUM_31 = 31, /*!< GPIO31, input and output */
GPIO_NUM_32 = 32, /*!< GPIO32, input and output */
GPIO_NUM_33 = 33, /*!< GPIO33, input and output */
GPIO_NUM_34 = 34, /*!< GPIO34, input mode only(ESP32) / input and output(ESP32-S2) */
GPIO_NUM_35 = 35, /*!< GPIO35, input mode only(ESP32) / input and output(ESP32-S2) */
GPIO_NUM_36 = 36, /*!< GPIO36, input mode only(ESP32) / input and output(ESP32-S2) */
GPIO_NUM_37 = 37, /*!< GPIO37, input mode only(ESP32) / input and output(ESP32-S2) */
GPIO_NUM_38 = 38, /*!< GPIO38, input mode only(ESP32) / input and output(ESP32-S2) */
GPIO_NUM_39 = 39, /*!< GPIO39, input mode only(ESP32) / input and output(ESP32-S2) */
#if GPIO_PIN_COUNT > 40
GPIO_NUM_40 = 40, /*!< GPIO40, input and output */
GPIO_NUM_41 = 41, /*!< GPIO41, input and output */
GPIO_NUM_42 = 42, /*!< GPIO42, input and output */
GPIO_NUM_43 = 43, /*!< GPIO43, input and output */
GPIO_NUM_44 = 44, /*!< GPIO44, input and output */
GPIO_NUM_45 = 45, /*!< GPIO45, input and output */
GPIO_NUM_46 = 46, /*!< GPIO46, input mode only */
#endif
GPIO_NUM_MAX,
/** @endcond */
} gpio_num_t;
A su vez, gpio_mode_t
se encuentra en el mismo archivo:
typedef enum {
GPIO_MODE_DISABLE = GPIO_MODE_DEF_DISABLE, /*!< GPIO mode : disable input and output */
GPIO_MODE_INPUT = GPIO_MODE_DEF_INPUT, /*!< GPIO mode : input only */
GPIO_MODE_OUTPUT = GPIO_MODE_DEF_OUTPUT, /*!< GPIO mode : output only mode */
GPIO_MODE_OUTPUT_OD = ((GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD)), /*!< GPIO mode : output only with open-drain mode */
GPIO_MODE_INPUT_OUTPUT_OD = ((GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD)), /*!< GPIO mode : output and input with open-drain mode*/
GPIO_MODE_INPUT_OUTPUT = ((GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT)), /*!< GPIO mode : output and input mode */
} gpio_mode_t;
Dentro de gpio_set_direction
se puede ver que se hace una llamada a gpio_input_enable
, esta función esta definida en el mismo archivo:
static esp_err_t gpio_input_enable(gpio_num_t gpio_num)
{
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
gpio_hal_input_enable(gpio_context.gpio_hal, gpio_num);
return ESP_OK;
}
Como se puede ver, esta función llama a su vez a una función de mas bajo nivel gpio_hal_input_enable
, buscando podemos encontrar su definición en components->soc->include->hal->gpio_hal.h
:
#define gpio_hal_input_enable(hal, gpio_num) gpio_ll_input_enable((hal)->dev, gpio_num)
Como vemos es simplemente un MACRO hacia otra función llamada gpio_ll_input_enable
, buscando llegamos a su definición ubicada en components->soc->src->esp32->include->hal->gpio_ll.h
static inline void gpio_ll_input_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
{
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
}
Que a su vez llama a otra función PIN_INPUT_ENABLE
, que resulta ser una MACRO dentro de components->soc->soc->esp32->include->soc->io_mux_reg.h
#define PIN_INPUT_ENABLE(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME,FUN_IE)
SET_PERI_REG_MASK
en soc.h
es:
#define SET_PERI_REG_MASK(reg, mask) ({
ASSERT_IF_DPORT_REG((reg), SET_PERI_REG_MASK);
WRITE_PERI_REG((reg), (READ_PERI_REG(reg)|(mask)));
})
llamando a WRITE_PERI_REG
que finalmente escribe el valor en el registro
//write value to register
#define WRITE_PERI_REG(addr, val) ({
ASSERT_IF_DPORT_REG((addr), WRITE_PERI_REG);
(*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val);
})
#define ETS_UNCACHED_ADDR(addr) (addr)