This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 18718316dcddd93b0326da977acdabd9207f73b4 Author: Tiago Medicci Serrano <[email protected]> AuthorDate: Wed Oct 11 16:10:07 2023 -0300 esp32/ble: enable the BLE interrupt during a SPI flash operation This commit sets the BLE's interrupt as a IRAM-enabled interrupt, which enables it to run during a SPI flash operation. This enables us to create a cache to off-load semaphores and message queues operations and treat them when the SPI flash operation is finished. By doing that, we avoid packet losses during a SPI flash operation. --- arch/xtensa/src/esp32/Kconfig | 9 + arch/xtensa/src/esp32/esp32_ble_adapter.c | 151 +++++++-- arch/xtensa/src/esp32/esp32_spicache.c | 27 ++ arch/xtensa/src/esp32/esp32_spicache.h | 13 + arch/xtensa/src/esp32/esp32_user.c | 12 + arch/xtensa/src/esp32/esp32_wireless.c | 338 ++++++++++++++++++++- arch/xtensa/src/esp32/esp32_wireless.h | 138 +++++++++ .../xtensa/esp32/common/scripts/legacy_sections.ld | 18 +- .../esp32/esp32-devkitc/configs/ble/defconfig | 6 +- 9 files changed, 672 insertions(+), 40 deletions(-) diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig index 996ac5f50f..9794746ce1 100644 --- a/arch/xtensa/src/esp32/Kconfig +++ b/arch/xtensa/src/esp32/Kconfig @@ -198,6 +198,15 @@ config ESP32_RUN_IRAM This loads all of NuttX inside IRAM. Used to test somewhat small images that can fit entirely in IRAM. +config ESP32_EXCEPTION_ENABLE_CACHE + bool + default y + depends on ESP32_SPIFLASH + ---help--- + When an exception triggers, the panic function reenables the SPI Flash + cache to allow functions that are located in SPI Flash to run. + Disable this option to save IRAM space. + menu "ESP32 Peripheral Selection" config ESP32_UART diff --git a/arch/xtensa/src/esp32/esp32_ble_adapter.c b/arch/xtensa/src/esp32/esp32_ble_adapter.c index c7050db08e..818411fb4a 100644 --- a/arch/xtensa/src/esp32/esp32_ble_adapter.c +++ b/arch/xtensa/src/esp32/esp32_ble_adapter.c @@ -50,12 +50,15 @@ #include <irq/irq.h> #include "hardware/esp32_dport.h" +#include "hardware/wdev_reg.h" #include "espidf_wifi.h" #include "xtensa.h" #include "xtensa_attr.h" #include "esp32_rt_timer.h" #include "esp32_ble_adapter.h" #include "esp32_wireless.h" +#include "esp32_irq.h" +#include "esp32_spicache.h" #ifdef CONFIG_ESP32_WIFI_BT_COEXIST # include "esp_coexist_internal.h" @@ -104,6 +107,11 @@ do {\ #define ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL 0x20200622 +#ifdef CONFIG_ESP32_SPIFLASH +# define BLE_TASK_EVENT_QUEUE_ITEM_SIZE 8 +# define BLE_TASK_EVENT_QUEUE_LEN 8 +#endif + #ifdef CONFIG_ESP32_BLE_INTERRUPT_SAVE_STATUS # define NR_IRQSTATE_FLAGS CONFIG_ESP32_BLE_INTERRUPT_SAVE_STATUS #else @@ -176,6 +184,16 @@ typedef enum } btdm_wakeup_src_t; #endif +/* Superseded semaphore definition */ + +struct bt_sem_s +{ + sem_t sem; +#ifdef CONFIG_ESP32_SPIFLASH + struct esp_semcache_s sc; +#endif +}; + typedef enum { PERIPH_LEDC_MODULE = 0, @@ -521,6 +539,13 @@ static sq_queue_t g_int_flags_used; static struct irqstate_list_s g_int_flags[NR_IRQSTATE_FLAGS]; +/* Cached queue control variables */ + +#ifdef CONFIG_ESP32_SPIFLASH +static struct esp_queuecache_s g_esp_queuecache[BLE_TASK_EVENT_QUEUE_LEN]; +static uint8_t g_esp_queuecache_buffer[BLE_TASK_EVENT_QUEUE_ITEM_SIZE]; +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -860,7 +885,7 @@ static xt_handler esp_ble_set_isr(int n, xt_handler f, void *arg) int ret; uint32_t tmp; struct irq_adpt_s *adapter; - int irq = n + XTENSA_IRQ_FIRSTPERIPH; + int irq = esp32_getirq(0, n); wlinfo("n=%d f=%p arg=%p irq=%d\n", n, f, arg, irq); @@ -877,7 +902,7 @@ static xt_handler esp_ble_set_isr(int n, xt_handler f, void *arg) if (!adapter) { wlerr("Failed to alloc %d memory\n", tmp); - assert(0); + DEBUGPANIC(); return NULL; } @@ -888,7 +913,7 @@ static xt_handler esp_ble_set_isr(int n, xt_handler f, void *arg) if (ret) { wlerr("Failed to attach IRQ %d\n", irq); - assert(0); + DEBUGPANIC(); return NULL; } @@ -912,17 +937,21 @@ static xt_handler esp_ble_set_isr(int n, xt_handler f, void *arg) static void esp32_ints_on(uint32_t mask) { uint32_t bit; + int irq; for (int i = 0; i < 32; i++) { bit = 1 << i; if (bit & mask) { - int irq = i + XTENSA_IRQ_FIRSTPERIPH; - wlinfo("Enabled bit %d\n", irq); + irq = esp32_getirq(0, i); + DEBUGVERIFY(esp32_irq_set_iram_isr(irq)); up_enable_irq(irq); + wlinfo("Enabled bit %d\n", irq); } } + + UNUSED(irq); } /**************************************************************************** @@ -1081,7 +1110,7 @@ static void bt_periph_module_enable(periph_module_e periph) * ****************************************************************************/ -static int esp_int_adpt_cb(int irq, void *context, void *arg) +static int IRAM_ATTR esp_int_adpt_cb(int irq, void *context, void *arg) { struct irq_adpt_s *adapter = (struct irq_adpt_s *)arg; @@ -1182,26 +1211,32 @@ static void IRAM_ATTR task_yield_from_isr(void) static void *semphr_create_wrapper(uint32_t max, uint32_t init) { int ret; - sem_t *sem; + struct bt_sem_s *bt_sem; int tmp; - tmp = sizeof(sem_t); - sem = kmm_malloc(tmp); - if (!sem) + tmp = sizeof(struct bt_sem_s); + bt_sem = kmm_malloc(tmp); + DEBUGASSERT(bt_sem); + if (!bt_sem) { wlerr("ERROR: Failed to alloc %d memory\n", tmp); return NULL; } - ret = nxsem_init(sem, 0, init); + ret = nxsem_init(&bt_sem->sem, 0, init); + DEBUGASSERT(ret == OK); if (ret) { wlerr("ERROR: Failed to initialize sem error=%d\n", ret); - kmm_free(sem); + kmm_free(bt_sem); return NULL; } - return sem; +#ifdef CONFIG_ESP32_SPIFLASH + esp_init_semcache(&bt_sem->sc, &bt_sem->sem); +#endif + + return bt_sem; } /**************************************************************************** @@ -1220,9 +1255,9 @@ static void *semphr_create_wrapper(uint32_t max, uint32_t init) static void semphr_delete_wrapper(void *semphr) { - sem_t *sem = (sem_t *)semphr; - nxsem_destroy(sem); - kmm_free(sem); + struct bt_sem_s *bt_sem = (struct bt_sem_s *)semphr; + sem_destroy(&bt_sem->sem); + kmm_free(bt_sem); } /**************************************************************************** @@ -1244,7 +1279,8 @@ static int IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw) { *(int *)hptw = 0; - return esp_errno_trans(nxsem_trywait(semphr)); + DEBUGPANIC(); + return 0; } /**************************************************************************** @@ -1263,7 +1299,24 @@ static int IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw) static int IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw) { - return semphr_give_wrapper(semphr); + int ret; + struct bt_sem_s *bt_sem = (struct bt_sem_s *)semphr; + +#ifdef CONFIG_ESP32_SPIFLASH + if (spi_flash_cache_enabled()) + { + ret = semphr_give_wrapper(bt_sem); + } + else + { + esp_post_semcache(&bt_sem->sc); + ret = 0; + } +#else + ret = semphr_give_wrapper(bt_sem); +#endif + + return esp_errno_trans(ret); } /**************************************************************************** @@ -1314,21 +1367,21 @@ static void esp_update_time(struct timespec *timespec, uint32_t ticks) static int semphr_take_wrapper(void *semphr, uint32_t block_time_ms) { int ret; - sem_t *sem = (sem_t *)semphr; + struct bt_sem_s *bt_sem = (struct bt_sem_s *)semphr; if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) { - ret = nxsem_wait(sem); + ret = nxsem_wait(&bt_sem->sem); } else { if (block_time_ms > 0) { - ret = nxsem_tickwait(sem, MSEC2TICK(block_time_ms)); + ret = nxsem_tickwait(&bt_sem->sem, MSEC2TICK(block_time_ms)); } else { - ret = nxsem_trywait(sem); + ret = nxsem_trywait(&bt_sem->sem); } } @@ -1358,9 +1411,9 @@ static int semphr_take_wrapper(void *semphr, uint32_t block_time_ms) static int semphr_give_wrapper(void *semphr) { int ret; - sem_t *sem = (sem_t *)semphr; + struct bt_sem_s *bt_sem = (struct bt_sem_s *)semphr; - ret = nxsem_post(sem); + ret = nxsem_post(&bt_sem->sem); if (ret) { wlerr("Failed to post sem error=%d\n", ret); @@ -1495,13 +1548,21 @@ static int mutex_unlock_wrapper(void *mutex) * ****************************************************************************/ -static int32_t esp_queue_send_generic(void *queue, void *item, - uint32_t ticks, int prio) +static IRAM_ATTR int32_t esp_queue_send_generic(void *queue, void *item, + uint32_t ticks, int prio) { int ret; struct timespec timeout; struct mq_adpt_s *mq_adpt = (struct mq_adpt_s *)queue; +#ifdef CONFIG_ESP32_SPIFLASH + if (!spi_flash_cache_enabled()) + { + esp_send_queuecache(queue, item, mq_adpt->msgsize); + return esp_errno_trans(OK); + } +#endif + if (ticks == OSI_FUNCS_TIME_BLOCKING || ticks == 0) { /** @@ -1587,6 +1648,7 @@ static int IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item, void *hptw) { + DEBUGPANIC(); return 0; } @@ -1803,7 +1865,7 @@ static void IRAM_ATTR srand_wrapper(unsigned int seed) static int IRAM_ATTR rand_wrapper(void) { - return random(); + return getreg32(WDEV_RND_REG); } /**************************************************************************** @@ -2234,6 +2296,26 @@ static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size) } mq_adpt->msgsize = item_size; + +#ifdef CONFIG_ESP32_SPIFLASH + if (queue_len <= BLE_TASK_EVENT_QUEUE_LEN && + item_size == BLE_TASK_EVENT_QUEUE_ITEM_SIZE) + { + esp_init_queuecache(g_esp_queuecache, + &mq_adpt->mq, + g_esp_queuecache_buffer, + BLE_TASK_EVENT_QUEUE_LEN, + BLE_TASK_EVENT_QUEUE_ITEM_SIZE); + } + else + { + wlerr("Failed to create queue cache." + " Please incresase BLE_TASK_EVENT_QUEUE_LEN to, at least, %d", + queue_len); + return NULL; + } +#endif + return (void *)mq_adpt; } @@ -2420,6 +2502,13 @@ int esp32_bt_controller_init(void) return ERROR; } +#ifdef CONFIG_ESP32_SPIFLASH + if (esp_wireless_init() != OK) + { + return -EIO; + } +#endif + if (btdm_osi_funcs_register(&g_osi_funcs) != 0) { wlerr("Error, probably invalid OSI Functions\n"); @@ -2915,7 +3004,7 @@ int esp32_vhci_register_callback(const esp_vhci_host_callback_t *callback) return ret; } -int coex_bt_request_wrapper(uint32_t event, +int IRAM_ATTR coex_bt_request_wrapper(uint32_t event, uint32_t latency, uint32_t duration) { @@ -2926,7 +3015,7 @@ int coex_bt_request_wrapper(uint32_t event, #endif } -int coex_bt_release_wrapper(uint32_t event) +int IRAM_ATTR coex_bt_release_wrapper(uint32_t event) { #if defined(CONFIG_ESP32_WIFI_BT_COEXIST) return coex_bt_release(event); @@ -2935,7 +3024,7 @@ int coex_bt_release_wrapper(uint32_t event) #endif } -uint32_t coex_bb_reset_lock_wrapper(void) +uint32_t IRAM_ATTR coex_bb_reset_lock_wrapper(void) { #if defined(CONFIG_ESP32_WIFI_BT_COEXIST) return coex_bb_reset_lock(); @@ -2944,7 +3033,7 @@ uint32_t coex_bb_reset_lock_wrapper(void) #endif } -void coex_bb_reset_unlock_wrapper(uint32_t restore) +void IRAM_ATTR coex_bb_reset_unlock_wrapper(uint32_t restore) { #if defined(CONFIG_ESP32_WIFI_BT_COEXIST) coex_bb_reset_unlock(restore); diff --git a/arch/xtensa/src/esp32/esp32_spicache.c b/arch/xtensa/src/esp32/esp32_spicache.c index fe43cb6260..292ff23370 100644 --- a/arch/xtensa/src/esp32/esp32_spicache.c +++ b/arch/xtensa/src/esp32/esp32_spicache.c @@ -147,4 +147,31 @@ void IRAM_ATTR spi_enable_cache(int cpu) putreg32(regval, ctrl1reg); } +/**************************************************************************** + * Name: spi_flash_cache_enabled + * + * Description: + * Check at runtime if flash cache is enabled on both CPUs. + * + * Returned Value: + * True if both CPUs have flash cache enabled, false otherwise. + * + ****************************************************************************/ + +bool spi_flash_cache_enabled(void) +{ + bool result = false; + + if (((getreg32(DPORT_PRO_CACHE_CTRL_REG) & DPORT_PRO_CACHE_ENABLE) != 0) +#ifdef CONFIG_SMP + && ((getreg32(DPORT_APP_CACHE_CTRL_REG) & DPORT_APP_CACHE_ENABLE) != 0) +#endif + ) + { + result = true; + } + + return result; +} + #endif /* CONFIG_ESP32_SPICACHE */ diff --git a/arch/xtensa/src/esp32/esp32_spicache.h b/arch/xtensa/src/esp32/esp32_spicache.h index 25ba86d390..54c6c33e51 100644 --- a/arch/xtensa/src/esp32/esp32_spicache.h +++ b/arch/xtensa/src/esp32/esp32_spicache.h @@ -81,6 +81,19 @@ void spi_disable_cache(int cpu); void spi_enable_cache(int cpu); +/**************************************************************************** + * Name: spi_flash_cache_enabled + * + * Description: + * Check at runtime if flash cache is enabled on both CPUs. + * + * Returned Value: + * True if both CPUs have flash cache enabled, false otherwise. + * + ****************************************************************************/ + +bool spi_flash_cache_enabled(void); + #ifdef __cplusplus } #endif diff --git a/arch/xtensa/src/esp32/esp32_user.c b/arch/xtensa/src/esp32/esp32_user.c index 9b405c8070..051dcfdbcf 100644 --- a/arch/xtensa/src/esp32/esp32_user.c +++ b/arch/xtensa/src/esp32/esp32_user.c @@ -33,6 +33,7 @@ #include <debug.h> #include "xtensa.h" +#include "esp32_spicache.h" /**************************************************************************** * Public Data @@ -323,6 +324,17 @@ static void advance_pc(uint32_t *regs, int diff) uint32_t *xtensa_user(int exccause, uint32_t *regs) { +#ifdef CONFIG_ESP32_EXCEPTION_ENABLE_CACHE + if (!spi_flash_cache_enabled()) + { + spi_enable_cache(0); +#ifdef CONFIG_SMP + spi_enable_cache(1); +#endif + _err("\nERROR: Cache was disabled and re-enabled\n"); + } +#endif + #ifdef CONFIG_ARCH_USE_TEXT_HEAP /* Emulate byte access for module text. * diff --git a/arch/xtensa/src/esp32/esp32_wireless.c b/arch/xtensa/src/esp32/esp32_wireless.c index 92f25758d9..109e61aa9a 100644 --- a/arch/xtensa/src/esp32/esp32_wireless.c +++ b/arch/xtensa/src/esp32/esp32_wireless.c @@ -24,20 +24,25 @@ #include <nuttx/config.h> #include <nuttx/kmalloc.h> +#include <nuttx/mqueue.h> + #include <netinet/in.h> #include <sys/param.h> #include <debug.h> #include <assert.h> #include "xtensa.h" -#include "hardware/esp32_soc.h" #include "hardware/esp32_dport.h" #include "hardware/esp32_emac.h" -#include "esp32_wireless.h" +#include "hardware/esp32_soc.h" +#include "esp32_irq.h" #include "esp32_partition.h" + #include "esp_phy_init.h" #include "phy_init_data.h" +#include "esp32_wireless.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -48,6 +53,28 @@ # define MAC_ADDR_UNIVERSE_BT_OFFSET 1 #endif +/* Software Interrupt */ + +#define SWI_IRQ ESP32_IRQ_CPU_CPU2 +#define SWI_PERIPH ESP32_PERIPH_CPU_CPU2 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Wireless Private Data */ + +struct esp_wireless_priv_s +{ + volatile int ref; /* Reference count */ + + int cpuint; /* CPU interrupt assigned to SWI */ + + struct list_node sc_list; /* Semaphore cache list */ + struct list_node qc_list; /* Queue cache list */ + struct list_node qc_freelist; /* List of free queue cache structures */ +}; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -165,6 +192,10 @@ static phy_country_to_bin_type_t g_country_code_map_type_table[] = #endif +/* Private data of the wireless common interface */ + +static struct esp_wireless_priv_s g_esp_wireless_priv; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -206,6 +237,68 @@ static inline void phy_digital_regs_load(void) } } +/**************************************************************************** + * Name: esp_swi_irq + * + * Description: + * Wireless software interrupt callback function. + * + * Parameters: + * cpuint - CPU interrupt index + * context - Context data from the ISR + * arg - NULL + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +static int esp_swi_irq(int irq, void *context, void *arg) +{ + int i; + int ret; + struct esp_semcache_s *sc; + struct esp_semcache_s *sc_tmp; + struct esp_queuecache_s *qc_entry; + struct esp_queuecache_s *qc_tmp; + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + + modifyreg32(DPORT_CPU_INTR_FROM_CPU_2_REG, DPORT_CPU_INTR_FROM_CPU_2, 0); + + list_for_every_entry_safe(&priv->sc_list, sc, sc_tmp, + struct esp_semcache_s, node) + { + for (i = 0; i < sc->count; i++) + { + ret = nxsem_post(sc->sem); + if (ret < 0) + { + wlerr("ERROR: Failed to post sem ret=%d\n", ret); + } + } + + sc->count = 0; + list_delete(&sc->node); + } + + list_for_every_entry_safe(&priv->qc_list, qc_entry, qc_tmp, + struct esp_queuecache_s, node) + { + ret = file_mq_send(qc_entry->mq_ptr, (const char *)qc_entry->buffer, + qc_entry->size, 0); + if (ret < 0) + { + wlerr("ERROR: Failed to send queue ret=%d\n", ret); + } + + list_delete(&qc_entry->node); + list_add_tail(&priv->qc_freelist, &qc_entry->node); + } + + return OK; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -754,7 +847,7 @@ const esp_phy_init_data_t *esp_phy_get_init_data(void) kmm_free(init_data_store); return NULL; } -#else /* CONFIG_ESP32_PHY_DEFAULT_INIT_IF_INVALID */ +#else /* CONFIG_ESP32_PHY_DEFAULT_INIT_IF_INVALID */ wlerr("ERROR: Failed to validate PHY data partition\n"); kmm_free(init_data_store); return NULL; @@ -797,7 +890,7 @@ void esp_phy_release_init_data(const esp_phy_init_data_t *init_data) kmm_free((uint8_t *)init_data - sizeof(phy_init_magic_pre)); } -#else /* CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION */ +#else /* CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION */ /**************************************************************************** * Name: esp_phy_get_init_data @@ -1067,3 +1160,240 @@ void esp32_phy_enable(void) leave_critical_section(flags); kmm_free(cal_data); } + +/**************************************************************************** + * Name: esp_init_semcache + * + * Description: + * Initialize semaphore cache. + * + * Parameters: + * sc - Semaphore cache data pointer + * sem - Semaphore data pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_init_semcache(struct esp_semcache_s *sc, sem_t *sem) +{ + sc->sem = sem; + sc->count = 0; + list_initialize(&sc->node); +} + +/**************************************************************************** + * Name: esp_post_semcache + * + * Description: + * Store posting semaphore action into semaphore cache. + * + * Parameters: + * sc - Semaphore cache data pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +IRAM_ATTR void esp_post_semcache(struct esp_semcache_s *sc) +{ + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + + if (!sc->count) + { + list_add_tail(&priv->sc_list, &sc->node); + } + + sc->count++; + + /* Enable CPU 2 interrupt. This will generate an IRQ as soon as non-IRAM + * are (re)enabled. + */ + + modifyreg32(DPORT_CPU_INTR_FROM_CPU_2_REG, 0, DPORT_CPU_INTR_FROM_CPU_2); +} + +/**************************************************************************** + * Name: esp_init_queuecache + * + * Description: + * Initialize queue cache. + * + * Parameters: + * qc - Queue cache data pointer + * mq_ptr - Queue data pointer + * buffer - Queue cache buffer pointer + * len - Queue cache max length + * size - Queue cache buffer size + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_init_queuecache(struct esp_queuecache_s *qc, + struct file *mq_ptr, + uint8_t *buffer, + size_t len, + size_t size) +{ + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + int i; + + for (i = 0; i < len; i++) + { + qc[i].mq_ptr = mq_ptr; + qc[i].size = size; + qc[i].buffer = buffer; + list_initialize(&qc[i].node); + + list_add_tail(&priv->qc_freelist, &qc[i].node); + } +} + +/**************************************************************************** + * Name: esp_send_queuecache + * + * Description: + * Store posting queue action and data into queue cache. + * + * Parameters: + * qc - Queue cache data pointer + * buffer - Data buffer + * size - Buffer size + * + * Returned Value: + * None. + * + ****************************************************************************/ + +IRAM_ATTR void esp_send_queuecache(void *queue, uint8_t *buffer, int size) +{ + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + struct esp_queuecache_s *msg; + irqstate_t flags; + + flags = enter_critical_section(); + + msg = (struct esp_queuecache_s *)list_remove_head(&priv->qc_freelist); + DEBUGASSERT(msg != NULL); + + DEBUGASSERT(msg->size == size); + DEBUGASSERT(msg->mq_ptr == queue); + + memcpy(msg->buffer, buffer, size); + + list_add_tail(&priv->qc_list, &msg->node); + + leave_critical_section(flags); + + /* Enable CPU 2 interrupt. This will generate an IRQ as soon as non-IRAM + * are (re)enabled. + */ + + modifyreg32(DPORT_CPU_INTR_FROM_CPU_2_REG, 0, DPORT_CPU_INTR_FROM_CPU_2); +} + +/**************************************************************************** + * Name: esp_wireless_init + * + * Description: + * Initialize ESP32 wireless common components for both BT and Wi-Fi. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int esp_wireless_init(void) +{ + int ret; + irqstate_t flags; + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + + flags = enter_critical_section(); + if (priv->ref != 0) + { + priv->ref++; + leave_critical_section(flags); + return OK; + } + + priv->cpuint = esp32_setup_irq(0, SWI_PERIPH, 1, ESP32_CPUINT_LEVEL); + if (priv->cpuint < 0) + { + /* Failed to allocate a CPU interrupt of this type. */ + + wlerr("ERROR: Failed to attach IRQ ret=%d\n", ret); + ret = priv->cpuint; + leave_critical_section(flags); + + return ret; + } + + ret = irq_attach(SWI_IRQ, esp_swi_irq, NULL); + if (ret < 0) + { + esp32_teardown_irq(0, SWI_PERIPH, priv->cpuint); + leave_critical_section(flags); + wlerr("ERROR: Failed to attach IRQ ret=%d\n", ret); + + return ret; + } + + list_initialize(&priv->sc_list); + list_initialize(&priv->qc_list); + list_initialize(&priv->qc_freelist); + + up_enable_irq(SWI_IRQ); + + priv->ref++; + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: esp_wireless_deinit + * + * Description: + * De-initialize ESP32 wireless common components. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int esp_wireless_deinit(void) +{ + irqstate_t flags; + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + + flags = enter_critical_section(); + + if (priv->ref > 0) + { + priv->ref--; + if (priv->ref == 0) + { + up_disable_irq(SWI_IRQ); + irq_detach(SWI_IRQ); + esp32_teardown_irq(0, SWI_PERIPH, priv->cpuint); + } + } + + leave_critical_section(flags); + + return OK; +} diff --git a/arch/xtensa/src/esp32/esp32_wireless.h b/arch/xtensa/src/esp32/esp32_wireless.h index 27e52aa8df..6b7e328cfa 100644 --- a/arch/xtensa/src/esp32/esp32_wireless.h +++ b/arch/xtensa/src/esp32/esp32_wireless.h @@ -24,8 +24,12 @@ /**************************************************************************** * Included Files ****************************************************************************/ +#include <semaphore.h> +#include <stdbool.h> +#include <stdint.h> #include <nuttx/config.h> +#include <nuttx/list.h> #include "xtensa_attr.h" @@ -48,6 +52,31 @@ #define MAC_LEN (6) +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Semaphore Cache Data */ + +struct esp_semcache_s +{ + struct list_node node; + + sem_t *sem; + uint32_t count; +}; + +/* Queue Cache Data */ + +struct esp_queuecache_s +{ + struct list_node node; + + struct file *mq_ptr; + size_t size; + uint8_t *buffer; +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -217,4 +246,113 @@ int phy_printf(const char *format, ...) printf_like(1, 2); int esp32_phy_update_country_info(const char *country); +/**************************************************************************** + * Name: esp_init_semcache + * + * Description: + * Initialize semaphore cache. + * + * Parameters: + * sc - Semaphore cache data pointer + * sem - Semaphore data pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_init_semcache(struct esp_semcache_s *sc, sem_t *sem); + +/**************************************************************************** + * Name: esp_post_semcache + * + * Description: + * Store posting semaphore action into semaphore cache. + * + * Parameters: + * sc - Semaphore cache data pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_post_semcache(struct esp_semcache_s *sc); + +/**************************************************************************** + * Name: esp_init_queuecache + * + * Description: + * Initialize queue cache. + * + * Parameters: + * qc - Queue cache data pointer + * mq_ptr - Queue data pointer + * buffer - Queue cache buffer pointer + * len - Queue cache max length + * size - Queue cache buffer size + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_init_queuecache(struct esp_queuecache_s *qc, + struct file *mq_ptr, + uint8_t *buffer, + size_t len, + size_t size); + +/**************************************************************************** + * Name: esp32_wl_send_queuecache + * + * Description: + * Store posting queue action and data into queue cache. + * + * Parameters: + * queue - Pointer to the queue + * buffer - Data buffer + * size - Buffer size + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_send_queuecache(void *queue, uint8_t *buffer, int size); + +/**************************************************************************** + * Name: esp_wireless_init + * + * Description: + * Initialize ESP32 wireless common components for both BT and Wi-Fi. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int esp_wireless_init(void); + +/**************************************************************************** + * Name: esp_wireless_deinit + * + * Description: + * De-initialize ESP32 wireless common components. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int esp_wireless_deinit(void); + #endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_WIRELESS_H */ diff --git a/boards/xtensa/esp32/common/scripts/legacy_sections.ld b/boards/xtensa/esp32/common/scripts/legacy_sections.ld index dab3308376..705b02fbbd 100644 --- a/boards/xtensa/esp32/common/scripts/legacy_sections.ld +++ b/boards/xtensa/esp32/common/scripts/legacy_sections.ld @@ -80,22 +80,34 @@ SECTIONS *libarch.a:esp32_irq.*(.literal .text .literal.* .text.*) *libarch.a:esp32_spicache.*(.literal .text .literal.* .text.*) *libarch.a:esp32_spiflash.*(.literal .text .literal.* .text.*) + *libarch.a:esp32_user.*(.literal .text .literal.* .text.*) *libarch.a:xtensa_assert.*(.literal .text .literal.* .text.*) *libarch.a:xtensa_cpuint.*(.literal .text .literal.* .text.*) *libarch.a:xtensa_cpupause.*(.literal .text .literal.* .text.*) *libarch.a:xtensa_irqdispatch.*(.literal .text .literal.* .text.*) *libarch.a:xtensa_modifyreg32.*(.literal .text .literal.* .text.*) + *libarch.a:xtensa_saveusercontext.*(.literal .text .literal.* .text.*) *libarch.a:xtensa_testset.*(.literal .text .literal.* .text.*) + *libc.a:lib_assert.*(.literal .text .literal.* .text.*) + *libc.a:lib_utsname.*(.literal .text .literal.* .text.*) +#ifdef CONFIG_ESP32_BLE + *libc.a:sq_remlast.*(.literal .text .literal.* .text.*) +#endif + *libdrivers.a:syslog_flush.*(.literal .text .literal.* .text.*) *libsched.a:assert.*(.literal .text .literal.* .text.*) *libsched.a:irq_csection.*(.literal .text .literal.* .text.*) *libsched.a:irq_dispatch.*(.literal .text .literal.* .text.*) *libsched.a:irq_spinlock.*(.literal .text .literal.* .text.*) + *libsched.a:panic_notifier.*(.literal.panic_notifier_call_chain .text.panic_notifier_call_chain) + *libsched.a:sched_gettcb.*(.literal .text .literal.* .text.*) + *libsched.a:sched_lock.*(.literal .text .literal.* .text.*) *libsched.a:sched_note.*(.literal .text .literal.* .text.*) *libsched.a:sched_suspendscheduler.*(.literal .text .literal.* .text.*) *libsched.a:sched_thistask.*(.literal .text .literal.* .text.*) + *libsched.a:sched_unlock.*(.literal .text .literal.* .text.*) *libsched.a:spinlock.*(.literal .text .literal.* .text.*) *(.wifirxiram .wifirxiram.*) @@ -204,11 +216,13 @@ SECTIONS *libc.a:lib_stackchk.*(.rodata .rodata.*) #endif *libarch.a:esp32_spiflash.*(.rodata .rodata.*) - *libarch.a:xtensa_cpupause.*(.rodata .rodata.*) + *libarch.a:xtensa_context.*(.rodata .rodata.*) *libarch.a:xtensa_copystate.*(.rodata .rodata.*) - *libarch.a:xtensa_interruptcontext.*(.rodata .rodata.*) + *libarch.a:xtensa_cpupause.*(.rodata .rodata.*) *libarch.a:xtensa_testset.*(.rodata .rodata.*) + *libdrivers.a:syslog_channel.*(.rodata .rodata.*) + *libsched.a:sched_suspendscheduler.*(.rodata .rodata.*) *libsched.a:sched_thistask.*(.rodata .rodata.*) *libsched.a:sched_note.*(.rodata .rodata.*) diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/ble/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/ble/defconfig index 1db421a79a..ec1bd9b4e1 100644 --- a/boards/xtensa/esp32/esp32-devkitc/configs/ble/defconfig +++ b/boards/xtensa/esp32/esp32-devkitc/configs/ble/defconfig @@ -6,6 +6,7 @@ # modifications. # # CONFIG_ARCH_LEDS is not set +# CONFIG_NDEBUG is not set # CONFIG_NSH_ARGCAT is not set # CONFIG_NSH_CMDOPT_HEXDUMP is not set CONFIG_ALLOW_BSD_COMPONENTS=y @@ -23,8 +24,6 @@ CONFIG_BCH=y CONFIG_BOARD_LOOPSPERMSEC=16717 CONFIG_BTSAK=y CONFIG_BUILTIN=y -CONFIG_DEBUG_ASSERTIONS=y -CONFIG_DEBUG_FEATURES=y CONFIG_DRIVERS_BLUETOOTH=y CONFIG_DRIVERS_IEEE80211=y CONFIG_DRIVERS_WIRELESS=y @@ -49,7 +48,8 @@ CONFIG_NSH_BUILTIN_APPS=y CONFIG_NSH_FILEIOSIZE=512 CONFIG_NSH_LINELEN=64 CONFIG_NSH_READLINE=y -CONFIG_PREALLOC_MQ_MSGS=32 +CONFIG_PREALLOC_MQ_IRQ_MSGS=1024 +CONFIG_PREALLOC_MQ_MSGS=256 CONFIG_PREALLOC_TIMERS=4 CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_RAM_SIZE=114688
