diff --git a/components/driver/dedic_gpio.c b/components/driver/dedic_gpio.c index 0ba96f643e..98109f51bd 100644 --- a/components/driver/dedic_gpio.c +++ b/components/driver/dedic_gpio.c @@ -3,7 +3,9 @@ * * SPDX-License-Identifier: Apache-2.0 */ + // #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG + #include #include #include @@ -12,6 +14,7 @@ #include "esp_heap_caps.h" #include "esp_intr_alloc.h" #include "esp_log.h" +#include "esp_check.h" #include "soc/soc_caps.h" #include "soc/gpio_periph.h" #include "soc/io_mux_reg.h" @@ -31,15 +34,6 @@ static const char *TAG = "dedic_gpio"; -#define DEDIC_CHECK(a, msg, tag, ret, ...) \ - do { \ - if (unlikely(!(a))) { \ - ESP_LOGE(TAG, "%s(%d): " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret_code = ret; \ - goto tag; \ - } \ - } while (0) - typedef struct dedic_gpio_platform_t dedic_gpio_platform_t; typedef struct dedic_gpio_bundle_t dedic_gpio_bundle_t; @@ -70,12 +64,12 @@ struct dedic_gpio_bundle_t { uint32_t out_offset; // offset in the bank (seen from output channel) uint32_t in_offset; // offset in the bank (seen from input channel) size_t nr_gpio; // number of GPIOs in the gpio_array - int gpio_array[0]; // array of GPIO numbers (configured by user) + int gpio_array[]; // array of GPIO numbers (configured by user) }; static esp_err_t dedic_gpio_build_platform(uint32_t core_id) { - esp_err_t ret_code = ESP_OK; + esp_err_t ret = ESP_OK; if (!s_platform[core_id]) { // prevent building platform concurrently _lock_acquire(&s_platform_mutexlock[core_id]); @@ -92,12 +86,12 @@ static esp_err_t dedic_gpio_build_platform(uint32_t core_id) } _lock_release(&s_platform_mutexlock[core_id]); - DEDIC_CHECK(s_platform[core_id], "no mem for s_platform[%d]", err, ESP_ERR_NO_MEM, core_id); + ESP_GOTO_ON_FALSE(s_platform[core_id], ESP_ERR_NO_MEM, err, TAG, "no mem for s_platform[%d]", core_id); ESP_LOGD(TAG, "build platform on core[%d] at %p", core_id, s_platform); } err: - return ret_code; + return ret; } static void dedic_gpio_break_platform(uint32_t core_id) @@ -144,23 +138,23 @@ static void dedic_gpio_default_isr(void *arg) static esp_err_t dedic_gpio_install_interrupt(uint32_t core_id) { - esp_err_t ret_code = ESP_OK; + esp_err_t ret = ESP_OK; if (!s_platform[core_id]->intr_hdl) { // prevent install interrupt concurrently _lock_acquire(&s_platform_mutexlock[core_id]); if (!s_platform[core_id]->intr_hdl) { int isr_flags = 0; - ret_code = esp_intr_alloc(dedic_gpio_periph_signals.irq, isr_flags, dedic_gpio_default_isr, s_platform[core_id], &s_platform[core_id]->intr_hdl); + ret = esp_intr_alloc(dedic_gpio_periph_signals.irq, isr_flags, dedic_gpio_default_isr, s_platform[core_id], &s_platform[core_id]->intr_hdl); // clear pending interrupt uint32_t status = dedic_gpio_ll_get_interrupt_status(s_platform[core_id]->dev); dedic_gpio_ll_clear_interrupt_status(s_platform[core_id]->dev, status); } _lock_release(&s_platform_mutexlock[core_id]); - DEDIC_CHECK(ret_code == ESP_OK, "alloc interrupt failed", err, ret_code); + ESP_GOTO_ON_ERROR(ret, err, TAG, "alloc interrupt failed"); } err: - return ret_code; + return ret; } static void dedic_gpio_uninstall_interrupt(uint32_t core_id) @@ -191,29 +185,29 @@ static void dedic_gpio_set_interrupt(uint32_t core_id, uint32_t channel, dedic_g esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_gpio_bundle_handle_t *ret_bundle) { - esp_err_t ret_code = ESP_OK; + esp_err_t ret = ESP_OK; dedic_gpio_bundle_t *bundle = NULL; uint32_t out_mask = 0; uint32_t in_mask = 0; uint32_t core_id = cpu_hal_get_core_id(); // dedicated GPIO will be binded to the CPU who invokes this API - DEDIC_CHECK(config && ret_bundle, "invalid argument", err, ESP_ERR_INVALID_ARG); - DEDIC_CHECK(config->gpio_array && config->array_size > 0, "invalid GPIO array or size", err, ESP_ERR_INVALID_ARG); - DEDIC_CHECK(config->flags.in_en || config->flags.out_en, "no input/output mode specified", err, ESP_ERR_INVALID_ARG); + ESP_GOTO_ON_FALSE(config && ret_bundle, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + ESP_GOTO_ON_FALSE(config->gpio_array && config->array_size > 0, ESP_ERR_INVALID_ARG, err, TAG, "invalid GPIO array or size"); + ESP_GOTO_ON_FALSE(config->flags.in_en || config->flags.out_en, ESP_ERR_INVALID_ARG, err, TAG, "no input/output mode specified"); // lazy install s_platform[core_id] - DEDIC_CHECK(dedic_gpio_build_platform(core_id) == ESP_OK, "build platform %d failed", err, ESP_FAIL, core_id); + ESP_GOTO_ON_ERROR(dedic_gpio_build_platform(core_id), err, TAG, "build platform %d failed", core_id); size_t bundle_size = sizeof(dedic_gpio_bundle_t) + config->array_size * sizeof(config->gpio_array[0]); bundle = calloc(1, bundle_size); - DEDIC_CHECK(bundle, "no mem for bundle", err, ESP_ERR_NO_MEM); + ESP_GOTO_ON_FALSE(bundle, ESP_ERR_NO_MEM, err, TAG, "no mem for bundle"); // for performance reasons, we only search for continuous channels uint32_t pattern = (1 << config->array_size) - 1; // configure outwards channels uint32_t out_offset = 0; if (config->flags.out_en) { - DEDIC_CHECK(SOC_DEDIC_GPIO_OUT_CHANNELS_NUM >= config->array_size, "array size(%d) exceeds maximum supported out channels(%d)", - err, ESP_ERR_INVALID_ARG, config->array_size, SOC_DEDIC_GPIO_OUT_CHANNELS_NUM); + ESP_GOTO_ON_FALSE(config->array_size <= SOC_DEDIC_GPIO_OUT_CHANNELS_NUM, ESP_ERR_INVALID_ARG, err, TAG, + "array size(%d) exceeds maximum supported out channels(%d)", config->array_size, SOC_DEDIC_GPIO_OUT_CHANNELS_NUM); // prevent install bundle concurrently portENTER_CRITICAL(&s_platform[core_id]->spinlock); for (size_t i = 0; i <= SOC_DEDIC_GPIO_OUT_CHANNELS_NUM - config->array_size; i++) { @@ -231,15 +225,15 @@ esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_ #endif } portEXIT_CRITICAL(&s_platform[core_id]->spinlock); - DEDIC_CHECK(out_mask, "no free outward channels on core[%d]", err, ESP_ERR_NOT_FOUND, core_id); + ESP_GOTO_ON_FALSE(out_mask, ESP_ERR_NOT_FOUND, err, TAG, "no free outward channels on core[%d]", core_id); ESP_LOGD(TAG, "new outward bundle(%p) on core[%d], offset=%d, mask(%x)", bundle, core_id, out_offset, out_mask); } // configure inwards channels uint32_t in_offset = 0; if (config->flags.in_en) { - DEDIC_CHECK(SOC_DEDIC_GPIO_IN_CHANNELS_NUM >= config->array_size, "array size(%d) exceeds maximum supported in channels(%d)", - err, ESP_ERR_INVALID_ARG, config->array_size, SOC_DEDIC_GPIO_IN_CHANNELS_NUM); + ESP_GOTO_ON_FALSE(config->array_size <= SOC_DEDIC_GPIO_IN_CHANNELS_NUM, ESP_ERR_INVALID_ARG, err, TAG, + "array size(%d) exceeds maximum supported in channels(%d)", config->array_size, SOC_DEDIC_GPIO_IN_CHANNELS_NUM); // prevent install bundle concurrently portENTER_CRITICAL(&s_platform[core_id]->spinlock); for (size_t i = 0; i <= SOC_DEDIC_GPIO_IN_CHANNELS_NUM - config->array_size; i++) { @@ -253,7 +247,7 @@ esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_ s_platform[core_id]->in_occupied_mask |= in_mask; } portEXIT_CRITICAL(&s_platform[core_id]->spinlock); - DEDIC_CHECK(in_mask, "no free inward channels on core[%d]", err, ESP_ERR_NOT_FOUND, core_id); + ESP_GOTO_ON_FALSE(in_mask, ESP_ERR_NOT_FOUND, err, TAG, "no free inward channels on core[%d]", core_id); ESP_LOGD(TAG, "new inward bundle(%p) on core[%d], offset=%d, mask(%x)", bundle, core_id, in_offset, in_mask); } @@ -293,17 +287,17 @@ err: if (bundle) { free(bundle); } - return ret_code; + return ret; } esp_err_t dedic_gpio_del_bundle(dedic_gpio_bundle_handle_t bundle) { - esp_err_t ret_code = ESP_OK; + esp_err_t ret = ESP_OK; bool recycle_all = false; - DEDIC_CHECK(bundle, "invalid argument", err, ESP_ERR_INVALID_ARG); + ESP_GOTO_ON_FALSE(bundle, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); uint32_t core_id = cpu_hal_get_core_id(); - DEDIC_CHECK(core_id == bundle->core_id, "del bundle on wrong CPU", err, ESP_FAIL); + ESP_GOTO_ON_FALSE(core_id == bundle->core_id, ESP_FAIL, err, TAG, "del bundle on wrong CPU"); portENTER_CRITICAL(&s_platform[core_id]->spinlock); s_platform[core_id]->out_occupied_mask &= ~(bundle->out_mask); @@ -323,25 +317,25 @@ esp_err_t dedic_gpio_del_bundle(dedic_gpio_bundle_handle_t bundle) } err: - return ret_code; + return ret; } esp_err_t dedic_gpio_get_out_mask(dedic_gpio_bundle_handle_t bundle, uint32_t *mask) { - esp_err_t ret_code = ESP_OK; - DEDIC_CHECK(bundle && mask, "invalid argument", err, ESP_ERR_INVALID_ARG); + esp_err_t ret = ESP_OK; + ESP_GOTO_ON_FALSE(bundle && mask, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); *mask = bundle->out_mask; err: - return ret_code; + return ret; } esp_err_t dedic_gpio_get_in_mask(dedic_gpio_bundle_handle_t bundle, uint32_t *mask) { - esp_err_t ret_code = ESP_OK; - DEDIC_CHECK(bundle && mask, "invalid argument", err, ESP_ERR_INVALID_ARG); + esp_err_t ret = ESP_OK; + ESP_GOTO_ON_FALSE(bundle && mask, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); *mask = bundle->in_mask; err: - return ret_code; + return ret; } void dedic_gpio_bundle_write(dedic_gpio_bundle_handle_t bundle, uint32_t mask, uint32_t value) @@ -370,11 +364,11 @@ uint32_t dedic_gpio_bundle_read_in(dedic_gpio_bundle_handle_t bundle) #if SOC_DEDIC_GPIO_HAS_INTERRUPT esp_err_t dedic_gpio_bundle_set_interrupt_and_callback(dedic_gpio_bundle_handle_t bundle, uint32_t mask, dedic_gpio_intr_type_t intr_type, dedic_gpio_isr_callback_t cb_isr, void *cb_args) { - esp_err_t ret_code = ESP_OK; - DEDIC_CHECK(bundle, "invalid argument", err, ESP_ERR_INVALID_ARG); + esp_err_t ret = ESP_OK; + ESP_GOTO_ON_FALSE(bundle, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); uint32_t core_id = cpu_hal_get_core_id(); // lazy alloc interrupt - DEDIC_CHECK(dedic_gpio_install_interrupt(core_id) == ESP_OK, "allocate interrupt on core %d failed", err, ESP_FAIL, core_id); + ESP_GOTO_ON_ERROR(dedic_gpio_install_interrupt(core_id), err, TAG, "allocate interrupt on core %d failed", core_id); uint32_t channel_mask = bundle->in_mask & (mask << bundle->in_offset); uint32_t channel = 0; @@ -391,6 +385,6 @@ esp_err_t dedic_gpio_bundle_set_interrupt_and_callback(dedic_gpio_bundle_handle_ } err: - return ret_code; + return ret; } #endif // SOC_DEDIC_GPIO_HAS_INTERRUPT diff --git a/components/driver/include/driver/dedic_gpio.h b/components/driver/include/driver/dedic_gpio.h index 0a40c179b8..238a270b47 100644 --- a/components/driver/include/driver/dedic_gpio.h +++ b/components/driver/include/driver/dedic_gpio.h @@ -30,10 +30,10 @@ typedef struct { const int *gpio_array; /*!< Array of GPIO numbers, gpio_array[0] ~ gpio_array[size-1] <=> low_dedic_channel_num ~ high_dedic_channel_num */ size_t array_size; /*!< Number of GPIOs in gpio_array */ struct { - int in_en: 1; /*!< Enable input */ - int in_invert: 1; /*!< Invert input signal */ - int out_en: 1; /*!< Enable output */ - int out_invert: 1; /*!< Invert output signal */ + unsigned int in_en: 1; /*!< Enable input */ + unsigned int in_invert: 1; /*!< Invert input signal */ + unsigned int out_en: 1; /*!< Enable output */ + unsigned int out_invert: 1; /*!< Invert output signal */ } flags; /*!< Flags to control specific behaviour of GPIO bundle */ } dedic_gpio_bundle_config_t; diff --git a/components/driver/test/test_dedicated_gpio.c b/components/driver/test/test_dedicated_gpio.c index 206819d1d7..7ba69abe4d 100644 --- a/components/driver/test/test_dedicated_gpio.c +++ b/components/driver/test/test_dedicated_gpio.c @@ -58,8 +58,6 @@ TEST_CASE("Dedicated GPIO bundle install/uninstall", "[dedic_gpio]") #define TEST_GPIO_GROUP_SIZE (4) -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) -// TODO ESP32-S3 IDF-3387 typedef struct { SemaphoreHandle_t sem; const int gpios[TEST_GPIO_GROUP_SIZE]; @@ -161,8 +159,6 @@ TEST_CASE("Dedicated GPIO run on multiple CPU core", "[dedic_gpio]") vSemaphoreDelete(sem); } -#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) - IRAM_ATTR static void test_dedic_gpio_isr_callback(void *args) { SemaphoreHandle_t sem = (SemaphoreHandle_t)args; diff --git a/components/hal/esp32s3/include/hal/cpu_ll.h b/components/hal/esp32s3/include/hal/cpu_ll.h index a8094c118c..284e86757d 100644 --- a/components/hal/esp32s3/include/hal/cpu_ll.h +++ b/components/hal/esp32s3/include/hal/cpu_ll.h @@ -203,12 +203,7 @@ static inline void cpu_ll_write_dedic_gpio_all(uint32_t value) static inline void cpu_ll_write_dedic_gpio_mask(uint32_t mask, uint32_t value) { - // ToDo: check if ESP32-S3 supports mask write instruction - uint32_t orig = 0; - asm volatile("rur.gpio_out %0" : "=r"(orig) : :); - orig &= ~mask; - orig |= value & mask; - asm volatile("wur.gpio_out %0"::"r"(orig):); + asm volatile("ee.wr_mask_gpio_out %0, %1" : : "r"(value), "r"(mask):); } #ifdef __cplusplus diff --git a/components/soc/esp32s3/dedic_gpio_periph.c b/components/soc/esp32s3/dedic_gpio_periph.c index 20d807496d..929cc7000e 100644 --- a/components/soc/esp32s3/dedic_gpio_periph.c +++ b/components/soc/esp32s3/dedic_gpio_periph.c @@ -25,26 +25,42 @@ const dedic_gpio_signal_conn_t dedic_gpio_periph_signals = { [1] = PRO_ALONEGPIO_IN1_IDX, [2] = PRO_ALONEGPIO_IN2_IDX, [3] = PRO_ALONEGPIO_IN3_IDX, + [4] = PRO_ALONEGPIO_IN4_IDX, + [5] = PRO_ALONEGPIO_IN5_IDX, + [6] = PRO_ALONEGPIO_IN6_IDX, + [7] = PRO_ALONEGPIO_IN7_IDX, }, .out_sig_per_channel = { [0] = PRO_ALONEGPIO_OUT0_IDX, [1] = PRO_ALONEGPIO_OUT1_IDX, [2] = PRO_ALONEGPIO_OUT2_IDX, [3] = PRO_ALONEGPIO_OUT3_IDX, + [4] = PRO_ALONEGPIO_OUT4_IDX, + [5] = PRO_ALONEGPIO_OUT5_IDX, + [6] = PRO_ALONEGPIO_OUT6_IDX, + [7] = PRO_ALONEGPIO_OUT7_IDX, } }, [1] = { .in_sig_per_channel = { - [0] = PRO_ALONEGPIO_IN4_IDX, - [1] = PRO_ALONEGPIO_IN5_IDX, - [2] = PRO_ALONEGPIO_IN6_IDX, - [3] = PRO_ALONEGPIO_IN7_IDX, + [0] = CORE1_GPIO_IN0_IDX, + [1] = CORE1_GPIO_IN1_IDX, + [2] = CORE1_GPIO_IN2_IDX, + [3] = CORE1_GPIO_IN3_IDX, + [4] = CORE1_GPIO_IN4_IDX, + [5] = CORE1_GPIO_IN5_IDX, + [6] = CORE1_GPIO_IN6_IDX, + [7] = CORE1_GPIO_IN7_IDX, }, .out_sig_per_channel = { - [0] = PRO_ALONEGPIO_OUT4_IDX, - [1] = PRO_ALONEGPIO_OUT5_IDX, - [2] = PRO_ALONEGPIO_OUT6_IDX, - [3] = PRO_ALONEGPIO_OUT7_IDX, + [0] = CORE1_GPIO_OUT0_IDX, + [1] = CORE1_GPIO_OUT1_IDX, + [2] = CORE1_GPIO_OUT2_IDX, + [3] = CORE1_GPIO_OUT3_IDX, + [4] = CORE1_GPIO_OUT4_IDX, + [5] = CORE1_GPIO_OUT5_IDX, + [6] = CORE1_GPIO_OUT6_IDX, + [7] = CORE1_GPIO_OUT7_IDX, } }, }, diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 68367d7223..05e11a847e 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -44,8 +44,8 @@ #include "gpio_caps.h" /*-------------------------- Dedicated GPIO CAPS -----------------------------*/ -#define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (4) /*!< 4 outward channels on each CPU core */ -#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (4) /*!< 4 inward channels on each CPU core */ +#define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */ +#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ /*-------------------------- I2C CAPS ----------------------------------------*/ #include "i2c_caps.h"