GPIO descriptor fixes (#578)

This commit is contained in:
Ken Van Hoeylandt
2026-07-22 22:43:34 +02:00
committed by GitHub
parent a3fda9ad8f
commit 8b92aa8e5a
116 changed files with 376 additions and 541 deletions
@@ -22,12 +22,18 @@ struct Esp32GpioInternal {
extern "C" {
static error_t set_level(GpioDescriptor* descriptor, bool high) {
auto esp_error = gpio_set_level(static_cast<gpio_num_t>(descriptor->pin), high);
// ESP32 GPIO has no hardware output-invert for plain digital I/O: active-low is a
// software-only concept, tracked in descriptor->flags rather than any hw register.
bool level_to_set = (descriptor->flags & GPIO_FLAG_ACTIVE_LOW) != 0 ? !high : high;
auto esp_error = gpio_set_level(static_cast<gpio_num_t>(descriptor->pin), level_to_set);
return esp_err_to_error(esp_error);
}
static error_t get_level(GpioDescriptor* descriptor, bool* high) {
*high = gpio_get_level(static_cast<gpio_num_t>(descriptor->pin)) != 0;
bool physical_level = gpio_get_level(static_cast<gpio_num_t>(descriptor->pin)) != 0;
*high = (descriptor->flags & GPIO_FLAG_ACTIVE_LOW) != 0 ? !physical_level : physical_level;
return ERROR_NONE;
}
@@ -88,9 +94,9 @@ static error_t get_flags(GpioDescriptor* descriptor, gpio_flags_t* flags) {
output |= GPIO_FLAG_DIRECTION_OUTPUT;
}
if (esp_config.oe_inv) {
output |= GPIO_FLAG_ACTIVE_LOW;
}
// oe_inv is the output-enable-signal invert bit (GPIO-matrix routing), unrelated to
// active-low data level; that's a software-only concept tracked in descriptor->flags.
output |= (descriptor->flags & GPIO_FLAG_ACTIVE_LOW);
*flags = output;
return ERROR_NONE;
@@ -1,7 +1,7 @@
#include <tactility/drivers/esp32_gpio_helpers.h>
#include <tactility/drivers/gpio_controller.h>
#define TAG "gpio"
constexpr auto* TAG = "gpio";
void release_pin(GpioDescriptor** gpio_descriptor) {
if (*gpio_descriptor == nullptr) return;
@@ -9,12 +9,13 @@ void release_pin(GpioDescriptor** gpio_descriptor) {
*gpio_descriptor = nullptr;
}
bool acquire_pin_or_set_null(const GpioPinSpec& pin_spec, GpioDescriptor** gpio_descriptor) {
bool acquire_pin_or_set_null(const GpioPinSpec& pin_spec, gpio_flags_t direction_flags, GpioDescriptor** gpio_descriptor) {
if (pin_spec.gpio_controller == nullptr) {
*gpio_descriptor = nullptr;
return true;
}
*gpio_descriptor = gpio_descriptor_acquire(pin_spec.gpio_controller, pin_spec.pin, GPIO_OWNER_GPIO);
*gpio_descriptor = gpio_descriptor_acquire(pin_spec.gpio_controller, pin_spec.pin, pin_spec.flags | direction_flags, GPIO_OWNER_GPIO);
if (*gpio_descriptor == nullptr) {
LOG_E(TAG, "Failed to acquire pin %u from %s", pin_spec.pin, pin_spec.gpio_controller->name);
}
@@ -157,14 +157,14 @@ static error_t start(Device* device) {
auto dts_config = GET_CONFIG(device);
auto& sda_spec = dts_config->pinSda;
auto& scl_spec = dts_config->pinScl;
auto* sda_descriptor = gpio_descriptor_acquire(sda_spec.gpio_controller, sda_spec.pin, GPIO_OWNER_GPIO);
auto* sda_descriptor = gpio_descriptor_acquire(sda_spec.gpio_controller, sda_spec.pin, sda_spec.flags | GPIO_FLAG_DIRECTION_INPUT_OUTPUT, GPIO_OWNER_GPIO);
if (!sda_descriptor) {
LOG_E(TAG, "Failed to acquire pin %u", sda_spec.pin);
return ERROR_RESOURCE;
}
auto* scl_descriptor = gpio_descriptor_acquire(scl_spec.gpio_controller, scl_spec.pin, GPIO_OWNER_GPIO);
auto& scl_spec = dts_config->pinScl;
auto* scl_descriptor = gpio_descriptor_acquire(scl_spec.gpio_controller, scl_spec.pin, scl_spec.flags | GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (!scl_descriptor) {
LOG_E(TAG, "Failed to acquire pin %u", scl_spec.pin);
gpio_descriptor_release(sda_descriptor);
@@ -184,14 +184,14 @@ static error_t start(Device* device) {
auto dts_config = GET_CONFIG(device);
auto& sda_spec = dts_config->pinSda;
auto& scl_spec = dts_config->pinScl;
auto* sda_descriptor = gpio_descriptor_acquire(sda_spec.gpio_controller, sda_spec.pin, GPIO_OWNER_GPIO);
auto* sda_descriptor = gpio_descriptor_acquire(sda_spec.gpio_controller, sda_spec.pin, sda_spec.flags | GPIO_FLAG_DIRECTION_INPUT_OUTPUT, GPIO_OWNER_GPIO);
if (!sda_descriptor) {
LOG_E(TAG, "Failed to acquire pin %u", sda_spec.pin);
return ERROR_RESOURCE;
}
auto* scl_descriptor = gpio_descriptor_acquire(scl_spec.gpio_controller, scl_spec.pin, GPIO_OWNER_GPIO);
auto& scl_spec = dts_config->pinScl;
auto* scl_descriptor = gpio_descriptor_acquire(scl_spec.gpio_controller, scl_spec.pin, scl_spec.flags | GPIO_FLAG_DIRECTION_OUTPUT, GPIO_OWNER_GPIO);
if (!scl_descriptor) {
LOG_E(TAG, "Failed to acquire pin %u", scl_spec.pin);
gpio_descriptor_release(sda_descriptor);
@@ -65,11 +65,11 @@ struct Esp32I2sInternal {
auto& data_out_spec = dts_config->pin_data_out;
auto& mclk_spec = dts_config->pin_mclk;
bool success = acquire_pin_or_set_null(ws_spec, &ws_descriptor) &&
acquire_pin_or_set_null(bclk_spec, &bclk_descriptor) &&
acquire_pin_or_set_null(data_in_spec, &data_in_descriptor) &&
acquire_pin_or_set_null(data_out_spec, &data_out_descriptor) &&
acquire_pin_or_set_null(mclk_spec, &mclk_descriptor);
bool success = acquire_pin_or_set_null(ws_spec, GPIO_FLAG_DIRECTION_OUTPUT, &ws_descriptor) &&
acquire_pin_or_set_null(bclk_spec, GPIO_FLAG_DIRECTION_OUTPUT, &bclk_descriptor) &&
acquire_pin_or_set_null(data_in_spec, GPIO_FLAG_DIRECTION_INPUT, &data_in_descriptor) &&
acquire_pin_or_set_null(data_out_spec, GPIO_FLAG_DIRECTION_OUTPUT, &data_out_descriptor) &&
acquire_pin_or_set_null(mclk_spec, GPIO_FLAG_DIRECTION_OUTPUT, &mclk_descriptor);
if (!success) {
cleanup_pins();
@@ -68,17 +68,17 @@ static error_t start(Device* device) {
const auto* config = GET_CONFIG(device);
bool pins_ok =
acquire_pin_or_set_null(config->pin_dc, &data->dc_descriptor) &&
acquire_pin_or_set_null(config->pin_wr, &data->wr_descriptor) &&
acquire_pin_or_set_null(config->pin_rd, &data->rd_descriptor) &&
acquire_pin_or_set_null(config->pin_d0, &data->d0_descriptor) &&
acquire_pin_or_set_null(config->pin_d1, &data->d1_descriptor) &&
acquire_pin_or_set_null(config->pin_d2, &data->d2_descriptor) &&
acquire_pin_or_set_null(config->pin_d3, &data->d3_descriptor) &&
acquire_pin_or_set_null(config->pin_d4, &data->d4_descriptor) &&
acquire_pin_or_set_null(config->pin_d5, &data->d5_descriptor) &&
acquire_pin_or_set_null(config->pin_d6, &data->d6_descriptor) &&
acquire_pin_or_set_null(config->pin_d7, &data->d7_descriptor);
acquire_pin_or_set_null(config->pin_dc, GPIO_FLAG_DIRECTION_OUTPUT, &data->dc_descriptor) &&
acquire_pin_or_set_null(config->pin_wr, GPIO_FLAG_DIRECTION_OUTPUT, &data->wr_descriptor) &&
acquire_pin_or_set_null(config->pin_rd, GPIO_FLAG_DIRECTION_OUTPUT, &data->rd_descriptor) &&
acquire_pin_or_set_null(config->pin_d0, GPIO_FLAG_DIRECTION_OUTPUT, &data->d0_descriptor) &&
acquire_pin_or_set_null(config->pin_d1, GPIO_FLAG_DIRECTION_OUTPUT, &data->d1_descriptor) &&
acquire_pin_or_set_null(config->pin_d2, GPIO_FLAG_DIRECTION_OUTPUT, &data->d2_descriptor) &&
acquire_pin_or_set_null(config->pin_d3, GPIO_FLAG_DIRECTION_OUTPUT, &data->d3_descriptor) &&
acquire_pin_or_set_null(config->pin_d4, GPIO_FLAG_DIRECTION_OUTPUT, &data->d4_descriptor) &&
acquire_pin_or_set_null(config->pin_d5, GPIO_FLAG_DIRECTION_OUTPUT, &data->d5_descriptor) &&
acquire_pin_or_set_null(config->pin_d6, GPIO_FLAG_DIRECTION_OUTPUT, &data->d6_descriptor) &&
acquire_pin_or_set_null(config->pin_d7, GPIO_FLAG_DIRECTION_OUTPUT, &data->d7_descriptor);
if (!pins_ok) {
LOG_E(TAG, "Failed to acquire required i8080 pins");
@@ -91,7 +91,6 @@ static error_t start(Device* device) {
// RD is never toggled by the i80 LCD peripheral (write-only bus); drive it high once so the
// panel doesn't see spurious read strobes.
if (data->rd_descriptor != nullptr) {
gpio_descriptor_set_flags(data->rd_descriptor, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_level(data->rd_descriptor, true);
}
@@ -124,14 +123,13 @@ static error_t start(Device* device) {
return ERROR_RESOURCE;
}
// Acquire and deselect all CS pins (drive high)
// Acquire and deselect all CS pins
for (uint8_t i = 0; i < config->cs_gpios_count; i++) {
const GpioPinSpec* cs = &config->cs_gpios[i];
if (cs->gpio_controller == nullptr) continue;
GpioDescriptor* desc = gpio_descriptor_acquire(cs->gpio_controller, cs->pin, GPIO_OWNER_GPIO);
GpioDescriptor* desc = gpio_descriptor_acquire(cs->gpio_controller, cs->pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_GPIO);
if (desc != nullptr) {
gpio_descriptor_set_flags(desc, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_level(desc, true);
gpio_descriptor_set_level(desc, false); // logical low = physical high
data->cs_descriptors.push_back(desc);
} else {
LOG_E(TAG, "Failed to acquire CS pin %u", i);
@@ -14,7 +14,7 @@
#include <tactility/filesystem/file_system.h>
#include <tactility/log.h>
#define TAG "esp32_sdmmc"
constexpr auto* TAG = "esp32_sdmmc";
#define GET_CONFIG(device) ((const struct Esp32SdmmcConfig*)device->config)
#define GET_DATA(device) ((struct Esp32SdmmcInternal*)device_get_driver_data(device))
@@ -84,18 +84,18 @@ static error_t start(Device* device) {
// Acquire pins from the specified GPIO pin specs. Optional pins are allowed.
bool pins_ok =
acquire_pin_or_set_null(sdmmc_config->pin_clk, &data->pin_clk_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_cmd, &data->pin_cmd_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d0, &data->pin_d0_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d1, &data->pin_d1_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d2, &data->pin_d2_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d3, &data->pin_d3_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d4, &data->pin_d4_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d5, &data->pin_d5_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d6, &data->pin_d6_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d7, &data->pin_d7_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_cd, &data->pin_cd_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_wp, &data->pin_wp_descriptor);
acquire_pin_or_set_null(sdmmc_config->pin_clk, GPIO_FLAG_DIRECTION_OUTPUT, &data->pin_clk_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_cmd, GPIO_FLAG_DIRECTION_INPUT_OUTPUT, &data->pin_cmd_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d0, GPIO_FLAG_DIRECTION_INPUT_OUTPUT, &data->pin_d0_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d1, GPIO_FLAG_DIRECTION_INPUT_OUTPUT, &data->pin_d1_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d2, GPIO_FLAG_DIRECTION_INPUT_OUTPUT, &data->pin_d2_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d3, GPIO_FLAG_DIRECTION_INPUT_OUTPUT, &data->pin_d3_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d4, GPIO_FLAG_DIRECTION_INPUT_OUTPUT, &data->pin_d4_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d5, GPIO_FLAG_DIRECTION_INPUT_OUTPUT, &data->pin_d5_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d6, GPIO_FLAG_DIRECTION_INPUT_OUTPUT, &data->pin_d6_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_d7, GPIO_FLAG_DIRECTION_INPUT_OUTPUT, &data->pin_d7_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_cd, GPIO_FLAG_DIRECTION_INPUT, &data->pin_cd_descriptor) &&
acquire_pin_or_set_null(sdmmc_config->pin_wp, GPIO_FLAG_DIRECTION_INPUT, &data->pin_wp_descriptor);
if (!pins_ok) {
LOG_E(TAG, "Failed to acquire required one or more pins");
@@ -67,9 +67,9 @@ static error_t start(Device* device) {
auto* config = GET_CONFIG(device);
bool pins_ok =
acquire_pin_or_set_null(config->pin_cd, &data->pin_cd_descriptor) &&
acquire_pin_or_set_null(config->pin_wp, &data->pin_wp_descriptor) &&
acquire_pin_or_set_null(config->pin_int, &data->pin_int_descriptor);
acquire_pin_or_set_null(config->pin_cd, GPIO_FLAG_DIRECTION_INPUT, &data->pin_cd_descriptor) &&
acquire_pin_or_set_null(config->pin_wp, GPIO_FLAG_DIRECTION_INPUT, &data->pin_wp_descriptor) &&
acquire_pin_or_set_null(config->pin_int, GPIO_FLAG_DIRECTION_OUTPUT, &data->pin_int_descriptor);
if (!pins_ok) {
LOG_E(TAG, "Failed to acquire one or more pins");
@@ -86,11 +86,11 @@ static error_t start(Device* device) {
// Acquire pins from the specified GPIO pin specs. Optional pins are allowed.
bool pins_ok =
acquire_pin_or_set_null(dts_config->pin_sclk, &data->sclk_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_mosi, &data->mosi_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_miso, &data->miso_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_wp, &data->wp_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_hd, &data->hd_descriptor);
acquire_pin_or_set_null(dts_config->pin_sclk, GPIO_FLAG_DIRECTION_OUTPUT, &data->sclk_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_mosi, GPIO_FLAG_DIRECTION_OUTPUT, &data->mosi_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_miso, GPIO_FLAG_DIRECTION_INPUT, &data->miso_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_wp, GPIO_FLAG_DIRECTION_INPUT, &data->wp_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_hd, GPIO_FLAG_DIRECTION_INPUT, &data->hd_descriptor);
if (!pins_ok) {
LOG_E(TAG, "Failed to acquire required SPI pins");
@@ -135,18 +135,18 @@ static error_t start(Device* device) {
gpio_descriptor_set_flags(data->miso_descriptor, GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_PULL_UP);
}
// Acquire and deselect all CS pins (drive high)
// Acquire CS pins
for (uint8_t i = 0; i < dts_config->cs_gpios_count; i++) {
const GpioPinSpec* cs = &dts_config->cs_gpios[i];
if (cs->gpio_controller == nullptr) continue;
GpioDescriptor* desc = gpio_descriptor_acquire(cs->gpio_controller, cs->pin, GPIO_OWNER_SPI);
GpioDescriptor* desc = gpio_descriptor_acquire(cs->gpio_controller, cs->pin, GPIO_FLAG_DIRECTION_OUTPUT | GPIO_FLAG_ACTIVE_LOW, GPIO_OWNER_SPI);
if (desc != nullptr) {
gpio_descriptor_set_flags(desc, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_level(desc, true);
data->cs_descriptors.push_back(desc);
}
}
esp32_spi_deselect_all_cs(device);
data->initialized = true;
return ERROR_NONE;
}
@@ -155,7 +155,7 @@ void esp32_spi_deselect_all_cs(Device* device) {
auto* data = GET_DATA(device);
if (data == nullptr) return;
for (auto* desc : data->cs_descriptors) {
gpio_descriptor_set_level(desc, true);
gpio_descriptor_set_level(desc, false);
}
}
@@ -284,10 +284,10 @@ static error_t open(Device* device) {
// Acquire pins from the specified GPIO pin specs. Optional pins are allowed.
bool pins_ok =
acquire_pin_or_set_null(dts_config->pin_tx, &driver_data->tx_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_rx, &driver_data->rx_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_cts, &driver_data->cts_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_rts, &driver_data->rts_descriptor);
acquire_pin_or_set_null(dts_config->pin_tx, GPIO_FLAG_DIRECTION_OUTPUT, &driver_data->tx_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_rx, GPIO_FLAG_DIRECTION_INPUT, &driver_data->rx_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_cts, GPIO_FLAG_DIRECTION_INPUT, &driver_data->cts_descriptor) &&
acquire_pin_or_set_null(dts_config->pin_rts, GPIO_FLAG_DIRECTION_OUTPUT, &driver_data->rts_descriptor);
if (!pins_ok) {
LOG_E(TAG, "%s failed to acquire UART pins", device->name);