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

Reply via email to