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.
This commit is contained in:
parent
f94daf09b2
commit
18718316dc
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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.*)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user