risc-v/esp32c3: Refactor SPI Flash to support umask interrupt when R/W/E SPI Flash

This can fix BLE assert when erase SPI Flash.
This commit is contained in:
Dong Heng
2021-08-05 16:09:54 +08:00
committed by Masayuki Ishikawa
parent a0990ee416
commit 698f1f76ff
18 changed files with 1752 additions and 923 deletions
+30 -12
View File
@@ -169,6 +169,14 @@ config ESP32C3_WIRELESS
default n
select ESP32C3_RT_TIMER
config ESP32C3_EXCEPTION_ENABLE_CACHE
bool
default y
depends on ESP32C3_SPIFLASH
---help---
When exception triggers, panic function enables SPI Flash cache to
let functions be able to call functions which locate in SPI Flash.
menu "ESP32-C3 Peripheral Support"
config ESP32C3_ADC
@@ -264,9 +272,6 @@ config ESP32C3_TIMER1
config ESP32C3_SPIFLASH
bool "SPI Flash"
default n
select MTD
select MTD_BYTE_WRITE
select MTD_PARTITION
config ESP32C3_SPI2
bool "SPI 2"
@@ -856,10 +861,6 @@ endmenu # Wi-Fi configuration
menu "BLE Configuration"
depends on ESP32C3_BLE
config ESP32C3_BLE_PKTBUF_NUM
int "BLE netcard packet buffer number per netcard"
default 16
config ESP32C3_BLE_TTY_NAME
string "BLE TTY device name"
default "/dev/ttyHCI0"
@@ -871,7 +872,7 @@ config ESP32C3_BLE_TASK_STACK_SIZE
config ESP32C3_BLE_TASK_PRIORITY
int "Controller task priority"
default 110
default 253
endmenu # BLE Configuration
@@ -918,25 +919,42 @@ endif
comment "General storage MTD configuration"
config ESP32C3_MTD
bool "MTD driver"
default y
select MTD
select MTD_BYTE_WRITE
select MTD_PARTITION
---help---
Initialize an MTD driver for the ESP32-C3 SPI Flash, which will
add an entry at /dev for application access from userspace.
config ESP32C3_STORAGE_MTD_BLKSIZE
int "Storage MTD block size"
default 64
depends on ESP32C3_MTD
config ESP32C3_STORAGE_MTD_OFFSET
hex "Storage MTD base address in SPI Flash"
default 0x180000 if !ESP32C3_HAVE_OTA_PARTITION
default 0x250000 if ESP32C3_HAVE_OTA_PARTITION
depends on ESP32C3_MTD
---help---
MTD base address in SPI Flash.
config ESP32C3_STORAGE_MTD_SIZE
hex "Storage MTD size in SPI Flash"
default 0x100000
depends on ESP32C3_MTD
---help---
MTD size in SPI Flash.
config ESP32C3_SPIFLASH_DEBUG
bool "Debug SPI Flash"
config ESP32C3_STORAGE_MTD_DEBUG
bool "Storage MTD Debug"
default n
depends on DEBUG_FS_INFO
depends on ESP32C3_MTD && DEBUG_FS_INFO
---help---
If this option is enabled, SPI Flash driver read and write functions
If this option is enabled, Storage MTD driver read and write functions
will output input parameters and return values (if applicable).
if ESP32C3_APP_FORMAT_LEGACY
+3
View File
@@ -81,6 +81,9 @@ endif
ifeq ($(CONFIG_ESP32C3_SPIFLASH),y)
CHIP_CSRCS += esp32c3_spiflash.c
ifeq ($(CONFIG_ESP32C3_MTD),y)
CHIP_CSRCS += esp32c3_spiflash_mtd.c
endif
endif
ifeq ($(CONFIG_ESP32C3_PARTITION_TABLE),y)
-8
View File
@@ -51,18 +51,10 @@
* Pre-processor Definitions
****************************************************************************/
/* BLE packet buffer max number */
#define BLE_BUF_NUM CONFIG_ESP32C3_BLE_PKTBUF_NUM
/* BLE packet buffer max size */
#define BLE_BUF_SIZE 1024
/* Low-priority work queue process RX/TX */
#define BLE_WORK LPWORK
/****************************************************************************
* Private Types
****************************************************************************/
+107 -61
View File
@@ -41,7 +41,6 @@
#include <nuttx/mqueue.h>
#include <nuttx/spinlock.h>
#include <nuttx/irq.h>
#include <nuttx/semaphore.h>
#include <nuttx/kthread.h>
#include <nuttx/wdog.h>
#include <nuttx/wqueue.h>
@@ -49,11 +48,15 @@
#include <nuttx/signal.h>
#include "hardware/esp32c3_syscon.h"
#include "hardware/wdev_reg.h"
#include "rom/esp32c3_spiflash.h"
#include "espidf_wifi.h"
#include "esp32c3.h"
#include "esp32c3_attr.h"
#include "esp32c3_irq.h"
#include "esp32c3_rt_timer.h"
#include "esp32c3_spiflash.h"
#include "esp32c3_wireless.h"
#include "esp32c3_ble_adapter.h"
#include "esp32c3_wireless.h"
@@ -132,6 +135,14 @@ typedef struct btdm_lpstat_s
bool wakeup_timer_started; /* whether wakeup timer is started */
} btdm_lpstat_t;
struct bt_sem_s
{
sem_t sem;
#ifdef CONFIG_ESP32C3_SPIFLASH
struct esp32c3_wl_semcache_s sc;
#endif
};
#ifdef CONFIG_PM
/* wakeup request sources */
@@ -238,37 +249,37 @@ static void interrupt_set_wrapper(int cpu_no, int intr_source,
int intr_num, int intr_prio);
static void interrupt_clear_wrapper(int intr_source, int intr_num);
static void interrupt_handler_set_wrapper(int n, void *fn, void *arg);
static void IRAM_ATTR interrupt_disable(void);
static void IRAM_ATTR interrupt_restore(void);
static void IRAM_ATTR task_yield_from_isr(void);
static void interrupt_disable(void);
static void interrupt_restore(void);
static void task_yield_from_isr(void);
static void *semphr_create_wrapper(uint32_t max, uint32_t init);
static void semphr_delete_wrapper(void *semphr);
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);
static int semphr_take_wrapper(void *semphr, uint32_t block_time_ms);
static int semphr_give_wrapper(void *semphr);
static int semphr_take_from_isr_wrapper(void *semphr, void *hptw);
static int semphr_give_from_isr_wrapper(void *semphr, void *hptw);
static int semphr_take_wrapper(void *semphr, uint32_t block_time_ms);
static int semphr_give_wrapper(void *semphr);
static void *mutex_create_wrapper(void);
static void mutex_delete_wrapper(void *mutex);
static int mutex_lock_wrapper(void *mutex);
static int mutex_unlock_wrapper(void *mutex);
static int IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item,
void *hptw);
static int IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item,
static int queue_send_from_isr_wrapper(void *queue, void *item,
void *hptw);
static int queue_recv_from_isr_wrapper(void *queue, void *item,
void *hptw);
static int task_create_wrapper(void *task_func, const char *name,
uint32_t stack_depth, void *param,
uint32_t prio, void *task_handle,
uint32_t core_id);
static void task_delete_wrapper(void *task_handle);
static bool IRAM_ATTR is_in_isr_wrapper(void);
static bool is_in_isr_wrapper(void);
static void *malloc_wrapper(size_t size);
static void *malloc_internal_wrapper(size_t size);
static int IRAM_ATTR read_mac_wrapper(uint8_t mac[6]);
static void IRAM_ATTR srand_wrapper(unsigned int seed);
static int IRAM_ATTR rand_wrapper(void);
static uint32_t IRAM_ATTR btdm_lpcycles_2_hus(uint32_t cycles,
static int read_mac_wrapper(uint8_t mac[6]);
static void srand_wrapper(unsigned int seed);
static int rand_wrapper(void);
static uint32_t btdm_lpcycles_2_hus(uint32_t cycles,
uint32_t *error_corr);
static uint32_t IRAM_ATTR btdm_hus_2_lpcycles(uint32_t us);
static uint32_t btdm_hus_2_lpcycles(uint32_t us);
static void coex_wifi_sleep_set_hook(bool sleep);
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status);
static void coex_schm_status_bit_clear_wrapper(uint32_t type,
@@ -283,7 +294,7 @@ static int queue_recv_wrapper(void *queue, void *item,
static void queue_delete_wrapper(void *queue);
#ifdef CONFIG_PM
static bool IRAM_ATTR btdm_sleep_check_duration(int32_t *half_slot_cnt);
static bool btdm_sleep_check_duration(int32_t *half_slot_cnt);
static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles);
static void btdm_sleep_enter_phase2_wrapper(void);
static void btdm_sleep_exit_phase3_wrapper(void);
@@ -570,6 +581,9 @@ static void interrupt_set_wrapper(int cpu_no,
wlinfo("cpu_no=%d , intr_source=%d , intr_num=%d, intr_prio=%d\n",
cpu_no, intr_source, intr_num, intr_prio);
esp32c3_bind_irq(intr_num, intr_source, intr_prio, ESP32C3_INT_LEVEL);
#ifdef CONFIG_ESP32C3_SPIFLASH
esp32c3_spiflash_unmask_cpuint(intr_num);
#endif
}
/****************************************************************************
@@ -580,7 +594,7 @@ static void interrupt_set_wrapper(int cpu_no,
*
****************************************************************************/
static void interrupt_clear_wrapper(int intr_source, int intr_num)
static void IRAM_ATTR interrupt_clear_wrapper(int intr_source, int intr_num)
{
}
@@ -598,7 +612,7 @@ static void interrupt_clear_wrapper(int intr_source, int intr_num)
*
****************************************************************************/
static int esp_int_adpt_cb(int irq, void *context, void *arg)
static int IRAM_ATTR esp_int_adpt_cb(int irq, void *context, FAR void *arg)
{
struct irq_adpt_s *adapter = (struct irq_adpt_s *)arg;
@@ -628,10 +642,10 @@ static void interrupt_handler_set_wrapper(int n, void *fn, void *arg)
int ret;
struct irq_adpt_s *adapter;
if (g_ble_irq_bind)
{
return;
}
if (g_ble_irq_bind)
{
return;
}
adapter = kmm_malloc(sizeof(struct irq_adpt_s));
DEBUGASSERT(adapter);
@@ -700,7 +714,7 @@ static void interrupt_off_wrapper(int intr_num)
static void IRAM_ATTR interrupt_disable(void)
{
enter_critical_section();
g_inter_flags = enter_critical_section();
}
/****************************************************************************
@@ -737,7 +751,7 @@ static void IRAM_ATTR interrupt_restore(void)
*
****************************************************************************/
static void IRAM_ATTR task_yield_from_isr(void)
static void task_yield_from_isr(void)
{
}
@@ -759,17 +773,21 @@ 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);
DEBUGASSERT(sem);
tmp = sizeof(struct bt_sem_s);
bt_sem = kmm_malloc(tmp);
DEBUGASSERT(bt_sem);
ret = sem_init(sem, 0, init);
ret = sem_init(&bt_sem->sem, 0, init);
DEBUGASSERT(ret == OK);
return sem;
#ifdef CONFIG_ESP32C3_SPIFLASH
esp32c3_wl_init_semcache(&bt_sem->sc, &bt_sem->sem);
#endif
return bt_sem;
}
/****************************************************************************
@@ -788,16 +806,16 @@ static void *semphr_create_wrapper(uint32_t max, uint32_t init)
static void semphr_delete_wrapper(void *semphr)
{
sem_t *sem = (sem_t *)semphr;
sem_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);
}
/****************************************************************************
* Name: semphr_take_from_isr_wrapper
*
* Description:
* take a semaphore from an ISR
* Take a semaphore from an ISR.
*
* Input Parameters:
* semphr - Semaphore data pointer
@@ -807,9 +825,10 @@ static void semphr_delete_wrapper(void *semphr)
*
****************************************************************************/
static int IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
static int semphr_take_from_isr_wrapper(void *semphr, void *hptw)
{
return semphr_take_wrapper(semphr, 0);
DEBUGASSERT(0);
return false;
}
/****************************************************************************
@@ -828,7 +847,26 @@ 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_ESP32C3_SPIFLASH
if (spi_flash_cache_enabled())
{
ret = semphr_give_wrapper(&bt_sem->sem);
ret = esp_errno_trans(ret);
}
else
{
esp32c3_wl_post_semcache(&bt_sem->sc);
ret = true;
}
#else
ret = semphr_give_wrapper(&bt_sem->sem);
ret = esp_errno_trans(ret);
#endif
return ret;
}
/****************************************************************************
@@ -878,11 +916,11 @@ static int semphr_take_wrapper(void *semphr, uint32_t block_time_ms)
{
int ret;
struct timespec timeout;
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 = sem_wait(sem);
ret = sem_wait(&bt_sem->sem);
if (ret)
{
wlerr("Failed to wait sem\n");
@@ -890,19 +928,21 @@ static int semphr_take_wrapper(void *semphr, uint32_t block_time_ms)
}
else
{
ret = clock_gettime(CLOCK_REALTIME, &timeout);
if (ret < 0)
{
wlerr("Failed to get time\n");
return false;
}
if (block_time_ms)
if (block_time_ms > 0)
{
ret = clock_gettime(CLOCK_REALTIME, &timeout);
if (ret < 0)
{
wlerr("Failed to get time\n");
return false;
}
esp_update_time(&timeout, MSEC2TICK(block_time_ms));
ret = sem_timedwait(&bt_sem->sem, &timeout);
}
else
{
ret = sem_trywait(&bt_sem->sem);
}
ret = sem_timedwait(sem, &timeout);
}
return esp_errno_trans(ret);
@@ -925,9 +965,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 = sem_post(sem);
ret = sem_post(&bt_sem->sem);
if (ret)
{
wlerr("Failed to post sem error=%d\n", ret);
@@ -1149,11 +1189,10 @@ static int IRAM_ATTR queue_send_from_isr_wrapper(void *queue,
*
****************************************************************************/
static int IRAM_ATTR queue_recv_from_isr_wrapper(void *queue,
void *item,
void *hptw)
static int queue_recv_from_isr_wrapper(void *queue, void *item, void *hptw)
{
return 0;
DEBUGASSERT(0);
return false;
}
/****************************************************************************
@@ -1287,7 +1326,7 @@ static void *malloc_internal_wrapper(size_t size)
*
****************************************************************************/
static int IRAM_ATTR read_mac_wrapper(uint8_t mac[6])
static int read_mac_wrapper(uint8_t mac[6])
{
return 0;
}
@@ -1305,7 +1344,7 @@ static int IRAM_ATTR read_mac_wrapper(uint8_t mac[6])
*
****************************************************************************/
static void IRAM_ATTR srand_wrapper(unsigned int seed)
static void srand_wrapper(unsigned int seed)
{
/* empty function */
}
@@ -1323,9 +1362,9 @@ static void IRAM_ATTR srand_wrapper(unsigned int seed)
*
****************************************************************************/
static int IRAM_ATTR rand_wrapper(void)
static IRAM_ATTR int rand_wrapper(void)
{
return random();
return getreg32(WDEV_RND_REG);
}
/****************************************************************************
@@ -2054,6 +2093,13 @@ int esp32c3_bt_controller_init(void)
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
#ifdef CONFIG_ESP32C3_SPIFLASH
if (esp32c3_wl_init() < 0)
{
return -EIO;
}
#endif
return 0;
#ifdef CONFIG_PM
+20 -2
View File
@@ -38,6 +38,7 @@
#include "riscv_internal.h"
#include "hardware/esp32c3_interrupt.h"
#include "rom/esp32c3_spiflash.h"
#include "esp32c3.h"
#include "esp32c3_attr.h"
@@ -376,7 +377,24 @@ IRAM_ATTR uint32_t *esp32c3_dispatch_irq(uint32_t mcause, uint32_t *regs)
{
int irq;
DEBUGASSERT(g_current_regs == NULL);
if (((MCAUSE_INTERRUPT & mcause) == 0) &&
(mcause != MCAUSE_ECALL_M))
{
#ifdef CONFIG_ESP32C3_EXCEPTION_ENABLE_CACHE
if (!spi_flash_cache_enabled())
{
spi_flash_enable_cache(0);
_err("ERROR: Cache was disabled and re-enabled\n");
}
#endif
}
else
{
/* Check "g_current_regs" only in interrupt or ecall */
DEBUGASSERT(g_current_regs == NULL);
}
g_current_regs = regs;
irqinfo("INFO: mcause=%08" PRIX32 "\n", mcause);
@@ -404,7 +422,7 @@ IRAM_ATTR uint32_t *esp32c3_dispatch_irq(uint32_t mcause, uint32_t *regs)
/* Toggle the bit back to zero. */
resetbits(1 << cpuint, INTERRUPT_CPU_INT_CLEAR_REG);
putreg32(0, INTERRUPT_CPU_INT_CLEAR_REG);
}
else
{
+1 -1
View File
@@ -31,7 +31,7 @@
#include <nuttx/kmalloc.h>
#include "esp32c3_spiflash.h"
#include "esp32c3_spiflash_mtd.h"
/****************************************************************************
* Pre-processor Definitions
File diff suppressed because it is too large Load Diff
+28 -149
View File
@@ -46,114 +46,6 @@ extern "C"
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: esp32c3_spiflash_mtd
*
* Description:
* Get ESP32-C3 SPI Flash MTD.
*
* Input Parameters:
* None
*
* Returned Value:
* ESP32-C3 SPI Flash MTD pointer.
*
****************************************************************************/
struct mtd_dev_s *esp32c3_spiflash_mtd(void);
/****************************************************************************
* Name: esp32c3_spiflash_alloc_mtdpart
*
* Description:
* Allocate an MTD partition from the ESP32-C3 SPI Flash.
*
* Input Parameters:
* mtd_offset - MTD Partition offset from the base address in SPI Flash.
* mtd_size - Size for the MTD partition.
*
* Returned Value:
* ESP32-C3 SPI Flash MTD data pointer if success or NULL if fail
*
****************************************************************************/
struct mtd_dev_s *esp32c3_spiflash_alloc_mtdpart(uint32_t mtd_offset,
uint32_t mtd_size);
/****************************************************************************
* Name: esp32c3_spiflash_encrypt_mtd
*
* Description:
* Get ESP32-C3 SPI Flash encryption MTD.
*
* Input Parameters:
* None
*
* Returned Value:
* ESP32-C3 SPI Flash encryption MTD pointer.
*
****************************************************************************/
struct mtd_dev_s *esp32c3_spiflash_encrypt_mtd(void);
/****************************************************************************
* Name: spi_flash_write_encrypted
*
* Description:
* Write data encrypted to Flash.
*
* Flash encryption must be enabled for this function to work.
*
* Flash encryption must be enabled when calling this function.
* If flash encryption is disabled, the function returns
* ESP_ERR_INVALID_STATE. Use esp_flash_encryption_enabled()
* function to determine if flash encryption is enabled.
*
* Both dest_addr and size must be multiples of 16 bytes. For
* absolute best performance, both dest_addr and size arguments should
* be multiples of 32 bytes.
*
* Input Parameters:
* dest_addr - Destination address in Flash. Must be a multiple of 16
* bytes.
* src - Pointer to the source buffer.
* size - Length of data, in bytes. Must be a multiple of 16 bytes.
*
* Returned Values:
* Zero (OK) is returned or a negative error.
*
****************************************************************************/
int spi_flash_write_encrypted(uint32_t dest_addr, const void *src,
uint32_t size);
/****************************************************************************
* Name: spi_flash_write
*
* Description:
*
* Write data to Flash.
*
* Note: For fastest write performance, write a 4 byte aligned size at a
* 4 byte aligned offset in flash from a source buffer in DRAM. Varying
* any of these parameters will still work, but will be slower due to
* buffering.
*
* Writing more than 8KB at a time will be split into multiple
* write operations to avoid disrupting other tasks in the system.
*
* Parameters:
* dest_addr - Destination address in Flash.
* src - Pointer to the source buffer.
* size - Length of data, in bytes.
*
* Returned Values:
* Zero (OK) is returned or a negative error.
*
****************************************************************************/
int spi_flash_write(uint32_t dest_addr, const void *src, uint32_t size);
/****************************************************************************
* Name: spi_flash_read_encrypted
*
@@ -170,79 +62,66 @@ int spi_flash_write(uint32_t dest_addr, const void *src, uint32_t size);
* encryption is enabled.
*
* Parameters:
* src - source address of the data in Flash.
* dest - pointer to the destination buffer
* size - length of data
* addr - source address of the data in Flash.
* buffer - pointer to the destination buffer
* size - length of data
*
* Returned Values: esp_err_t
*
****************************************************************************/
int spi_flash_read_encrypted(uint32_t src, void *dest, uint32_t size);
int spi_flash_read_encrypted(uint32_t addr, void *buffer, uint32_t size);
/****************************************************************************
* Name: spi_flash_read
* Name: esp32c3_spiflash_unmask_cpuint
*
* Description:
* Read data from Flash.
* Unmask CPU interrupt and keep this interrupt work when read, write,
* erase SPI Flash.
*
* Note: For fastest read performance, all parameters should be
* 4 byte aligned. If source address and read size are not 4 byte
* aligned, read may be split into multiple flash operations. If
* destination buffer is not 4 byte aligned, a temporary buffer will
* be allocated on the stack.
* By default, all CPU interrupts are masked.
*
* Reading more than 16KB of data at a time will be split
* into multiple reads to avoid disruption to other tasks in the
* system. Consider using spi_flash_mmap() to read large amounts
* of data.
* Input Parameters:
* cpuint - CPU interrupt ID
*
* Parameters:
* src_addr - source address of the data in Flash.
* dest - pointer to the destination buffer
* size - length of data
*
* Returned Values:
* Zero (OK) is returned or a negative error.
* Returned Value:
* None.
*
****************************************************************************/
int spi_flash_read(uint32_t src_addr, void *dest, uint32_t size);
void esp32c3_spiflash_unmask_cpuint(int cpuint);
/****************************************************************************
* Name: spi_flash_erase_sector
* Name: esp32c3_spiflash_unmask_cpuint
*
* Description:
* Erase the Flash sector.
* Mask CPU interrupt and disable this interrupt when read, write,
* erase SPI Flash.
*
* Parameters:
* sector - Sector number, the count starts at sector 0, 4KB per sector.
* By default, all CPU interrupts are masked.
*
* Returned Values: esp_err_t
* Zero (OK) is returned or a negative error.
* Input Parameters:
* cpuint - CPU interrupt ID
*
* Returned Value:
* None.
*
****************************************************************************/
int spi_flash_erase_sector(uint32_t sector);
void esp32c3_spiflash_mask_cpuint(int cpuint);
/****************************************************************************
* Name: spi_flash_erase_range
* Name: esp32c3_spiflash_init
*
* Description:
* Erase a range of flash sectors
* Initialize ESP32-C3 SPI flash driver.
*
* Parameters:
* start_address - Address where erase operation has to start.
* Must be 4kB-aligned
* size - Size of erased range, in bytes. Must be divisible by
* 4kB.
*
* Returned Values:
* Zero (OK) is returned or a negative error.
* Returned Value:
* OK if success or a negative value if fail.
*
****************************************************************************/
int spi_flash_erase_range(uint32_t start_address, uint32_t size);
int esp32c3_spiflash_init(void);
#ifdef __cplusplus
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,105 @@
/****************************************************************************
* arch/risc-v/src/esp32c3/esp32c3_spiflash_mtd.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_RISCV_SRC_ESP32C3_ESP32C3_SPIFLASH_MTD_H
#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_SPIFLASH_MTD_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <nuttx/mtd/mtd.h>
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: esp32c3_spiflash_mtd
*
* Description:
* Get SPI Flash MTD.
*
* Input Parameters:
* None
*
* Returned Value:
* ESP32-C3 SPI Flash MTD pointer.
*
****************************************************************************/
struct mtd_dev_s *esp32c3_spiflash_mtd(void);
/****************************************************************************
* Name: esp32c3_spiflash_encrypt_mtd
*
* Description:
* Get SPI Flash encryption MTD.
*
* Input Parameters:
* None
*
* Returned Value:
* SPI Flash encryption MTD pointer.
*
****************************************************************************/
struct mtd_dev_s *esp32c3_spiflash_encrypt_mtd(void);
/****************************************************************************
* Name: esp32c3_spiflash_alloc_mtdpart
*
* Description:
* Allocate an MTD partition from the ESP32-C3 SPI Flash.
*
* Input Parameters:
* mtd_offset - MTD Partition offset from the base address in SPI Flash.
* mtd_size - Size for the MTD partition.
*
* Returned Value:
* SPI Flash MTD data pointer if success or NULL if fail.
*
****************************************************************************/
struct mtd_dev_s *esp32c3_spiflash_alloc_mtdpart(uint32_t mtd_offset,
uint32_t mtd_size);
#ifdef __cplusplus
}
#endif
#undef EXTERN
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_SPIFLASH_MTD_H */
+224
View File
@@ -25,13 +25,45 @@
#include <nuttx/config.h>
#include <nuttx/kmalloc.h>
#include <semaphore.h>
#include <debug.h>
#include "riscv_internal.h"
#include "hardware/esp32c3_system.h"
#include "hardware/esp32c3_soc.h"
#include "hardware/esp32c3_syscon.h"
#include "esp32c3.h"
#include "esp32c3_irq.h"
#include "esp32c3_attr.h"
#include "esp32c3_wireless.h"
#include "espidf_wifi.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Software Interrupt */
#define SWI_IRQ ESP32C3_IRQ_FROM_CPU_INT0
#define SWI_PERIPH ESP32C3_PERIPH_FROM_CPU_INT0
/****************************************************************************
* Private Types
****************************************************************************/
/* ESP32-C3 Wireless Private Data */
struct esp32c3_wl_priv_s
{
volatile int ref; /* Reference count */
int cpuint; /* CPU interrupt assigned to SWI */
struct list_node sc_list; /* Semaphore cache list */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@@ -69,6 +101,8 @@ static uint32_t *g_phy_digital_regs_mem = NULL;
static bool g_is_phy_calibrated = false;
static struct esp32c3_wl_priv_s g_esp32c3_wl_priv;
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -175,6 +209,52 @@ static void esp32c3_phy_disable_clock(void)
leave_critical_section(flags);
}
/****************************************************************************
* Name: esp32c3_wl_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 esp32c3_wl_swi_irq(int irq, void *context, FAR void *arg)
{
int i;
int ret;
struct esp32c3_wl_semcache_s *sc;
struct esp32c3_wl_semcache_s *tmp;
struct esp32c3_wl_priv_s *priv = &g_esp32c3_wl_priv;
putreg32(0, SYSTEM_CPU_INTR_FROM_CPU_0_REG);
list_for_every_entry_safe(&priv->sc_list, sc, tmp,
struct esp32c3_wl_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);
}
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -280,3 +360,147 @@ void esp32c3_phy_enable(void)
leave_critical_section(flags);
kmm_free(cal_data);
}
/****************************************************************************
* Name: esp32c3_wl_init_semcache
*
* Description:
* Initialize semaphore cache.
*
* Parameters:
* sc - Semaphore cache data pointer
* sem - Semaphore data pointer
*
* Returned Value:
* None.
*
****************************************************************************/
void esp32c3_wl_init_semcache(struct esp32c3_wl_semcache_s *sc,
sem_t *sem)
{
sc->sem = sem;
sc->count = 0;
list_initialize(&sc->node);
}
/****************************************************************************
* Name: esp32c3_wl_post_semcache
*
* Description:
* Store posting semaphore action into semaphore cache.
*
* Parameters:
* sc - Semaphore cache data pointer
*
* Returned Value:
* None.
*
****************************************************************************/
void IRAM_ATTR esp32c3_wl_post_semcache(
struct esp32c3_wl_semcache_s *sc)
{
struct esp32c3_wl_priv_s *priv = &g_esp32c3_wl_priv;
if (!sc->count)
{
list_add_tail(&priv->sc_list, &sc->node);
}
sc->count++;
putreg32(SYSTEM_CPU_INTR_FROM_CPU_0_M, SYSTEM_CPU_INTR_FROM_CPU_0_REG);
}
/****************************************************************************
* Name: esp32c3_wl_init
*
* Description:
* Initialize ESP32-C3 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 esp32c3_wl_init(void)
{
int ret;
irqstate_t flags;
struct esp32c3_wl_priv_s *priv = &g_esp32c3_wl_priv;
flags = enter_critical_section();
if (priv->ref != 0)
{
priv->ref++;
leave_critical_section(flags);
return OK;
}
priv->cpuint = esp32c3_request_irq(SWI_PERIPH,
ESP32C3_INT_PRIO_DEF,
ESP32C3_INT_LEVEL);
ret = irq_attach(SWI_IRQ, esp32c3_wl_swi_irq, NULL);
if (ret < 0)
{
esp32c3_free_cpuint(SWI_PERIPH);
leave_critical_section(flags);
wlerr("ERROR: Failed to attach IRQ ret=%d\n", ret);
return ret;
}
list_initialize(&priv->sc_list);
up_enable_irq(priv->cpuint);
priv->ref++;
leave_critical_section(flags);
return OK;
}
/****************************************************************************
* Name: esp32c3_wl_deinit
*
* Description:
* De-initialize ESP32-C3 wireless common components.
*
* Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned on
* failure.
*
****************************************************************************/
int esp32c3_wl_deinit(void)
{
irqstate_t flags;
struct esp32c3_wl_priv_s *priv = &g_esp32c3_wl_priv;
flags = enter_critical_section();
if (priv->ref == 0)
{
leave_critical_section(flags);
return OK;
}
up_disable_irq(priv->cpuint);
irq_detach(SWI_IRQ);
esp32c3_free_cpuint(SWI_PERIPH);
priv->ref--;
leave_critical_section(flags);
return OK;
}
+103
View File
@@ -26,6 +26,35 @@
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <stdint.h>
#include <semaphore.h>
#include <nuttx/list.h>
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Pre-processor Macros
****************************************************************************/
/* Semaphore Cache Data */
struct esp32c3_wl_semcache_s
{
struct list_node node;
sem_t *sem;
uint32_t count;
};
/****************************************************************************
* Public Function Prototypes
@@ -63,4 +92,78 @@ void esp32c3_phy_enable(void);
void esp32c3_phy_disable(void);
/****************************************************************************
* Name: esp32c3_wl_init_semcache
*
* Description:
* Initialize semaphore cache.
*
* Parameters:
* sc - Semaphore cache data pointer
* sem - Semaphore data pointer
*
* Returned Value:
* None.
*
****************************************************************************/
void esp32c3_wl_init_semcache(struct esp32c3_wl_semcache_s *sc,
sem_t *sem);
/****************************************************************************
* Name: esp32c3_wl_post_semcache
*
* Description:
* Store posting semaphore action into semaphore cache.
*
* Parameters:
* sc - Semaphore cache data pointer
*
* Returned Value:
* None.
*
****************************************************************************/
void esp32c3_wl_post_semcache(struct esp32c3_wl_semcache_s *sc);
/****************************************************************************
* Name: esp32c3_wl_init
*
* Description:
* Initialize ESP32-C3 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 esp32c3_wl_init(void);
/****************************************************************************
* Name: esp32c3_wl_deinit
*
* Description:
* De-initialize ESP32-C3 wireless common components.
*
* Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned on
* failure.
*
****************************************************************************/
int esp32c3_wl_deinit(void);
#ifdef __cplusplus
}
#endif
#undef EXTERN
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_WIRELESS_H */
@@ -31,7 +31,19 @@
* Pre-processor Definitions
****************************************************************************/
#define EXTMEM_ICACHE_CTRL_REG (DR_REG_EXTMEM_BASE + 0x000)
/* EXTMEM_ICACHE_ENABLE : R/W ;bitpos:[0] ;default: 1'b0.
* The bit is used to activate the data cache. 0: disable 1: enable
*/
#define EXTMEM_ICACHE_ENABLE (BIT(0))
#define EXTMEM_ICACHE_ENABLE_M (BIT(0))
#define EXTMEM_ICACHE_ENABLE_V 0x1
#define EXTMEM_ICACHE_ENABLE_S 0
#define EXTMEM_ICACHE_CTRL1_REG (DR_REG_EXTMEM_BASE + 0x004)
#define EXTMEM_ICACHE_TAG_POWER_CTRL_REG (DR_REG_EXTMEM_BASE + 0x008)
#define EXTMEM_CACHE_MMU_POWER_CTRL_REG (DR_REG_EXTMEM_BASE + 0x0ac)
@@ -154,6 +154,57 @@ struct spiflash_legacy_data_s
uint8_t sig_matrix;
};
/**
* Structure holding SPI flash access critical sections management functions.
*
* Flash API uses two types of functions for flash access management:
* 1) Functions which prepare/restore flash cache and interrupts before
* calling appropriate ROM functions (SPIWrite, SPIRead and
* SPIEraseBlock):
* - 'start' function should disable flash cache and non-IRAM interrupts
* and is invoked before the call to one of ROM functions from
* "struct spiflash_guard_funcs_s".
* - 'end' function should restore state of flash cache and non-IRAM
* interrupts and is invoked after the call to one of ROM
* functions from "struct spiflash_guard_funcs_s".
* These two functions are not reentrant.
* 2) Functions which synchronizes access to internal data used by flash API.
* These functions are mostly intended to synchronize access to flash API
* internal data in multithreaded environment and use OS primitives:
* - 'op_lock' locks access to flash API internal data.
* - 'op_unlock' unlocks access to flash API internal data.
* These two functions are reentrant and can be used around the outside of
* multiple calls to 'start' & 'end', in order to create atomic multi-part
* flash operations.
*
* Different versions of the guarding functions should be used depending on
* the context of execution (with or without functional OS). In normal
* conditions when flash API is called from task the functions use OS
* primitives.
* When there is no OS at all or when it is not guaranteed that OS is
* functional (accessing flash from exception handler) these functions cannot
* use OS primitives or even does not need them (multithreaded access is
* not possible).
*
* @note Structure and corresponding guard functions should not reside
* in flash. For example structure can be placed in DRAM and functions
* in IRAM sections.
*/
struct spiflash_guard_funcs
{
void (*start)(void); /* critical section start function */
void (*end)(void); /* critical section end function */
void (*op_lock)(void); /* flash access API lock function */
void (*op_unlock)(void); /* flash access API unlock function */
/* checks flash write addresses */
bool (*address_is_safe)(size_t addr, size_t size);
void (*yield)(void); /* yield to the OS during flash erase */
};
/*****************************************************************************
* Public Function Prototypes
*****************************************************************************/
@@ -792,6 +843,168 @@ esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp32c3_spiflash_chip_t
void esp_rom_spiflash_select_qio_pins(uint8_t wp_gpio_num,
uint32_t spiconfig);
/*****************************************************************************
* Name: spi_flash_guard_set
*
* Description:
* Sets guard functions to access flash.
*
* Input Parameters:
* funcs - funcs pointer to structure holding flash access guard functions
*
* Returned Value:
* None
*
*****************************************************************************/
void spi_flash_guard_set(const struct spiflash_guard_funcs *funcs);
/*****************************************************************************
* Name: spi_flash_write_encrypted
*
* Description:
* Write data encrypted to Flash.
*
* Flash encryption must be enabled for this function to work.
*
* Flash encryption must be enabled when calling this function.
* If flash encryption is disabled, the function returns
* ESP_ERR_INVALID_STATE. Use esp_flash_encryption_enabled()
* function to determine if flash encryption is enabled.
*
* Both dest_addr and size must be multiples of 16 bytes. For
* absolute best performance, both dest_addr and size arguments should
* be multiples of 32 bytes.
*
* Input Parameters:
* dest_addr - Destination address in Flash. Must be a multiple of 16
* bytes.
* src - Pointer to the source buffer.
* size - Length of data, in bytes. Must be a multiple of 16 bytes.
*
* Returned Values:
* Zero (OK) is returned or a negative error.
*
*****************************************************************************/
int spi_flash_write_encrypted(uint32_t dest_addr, const void *src,
uint32_t size);
/*****************************************************************************
* Name: spi_flash_write
*
* Description:
*
* Write data to Flash.
*
* Note: For fastest write performance, write a 4 byte aligned size at a
* 4 byte aligned offset in flash from a source buffer in DRAM. Varying
* any of these parameters will still work, but will be slower due to
* buffering.
*
* Writing more than 8KB at a time will be split into multiple
* write operations to avoid disrupting other tasks in the system.
*
* Parameters:
* dest_addr - Destination address in Flash.
* src - Pointer to the source buffer.
* size - Length of data, in bytes.
*
* Returned Values:
* Zero (OK) is returned or a negative error.
*
*****************************************************************************/
int spi_flash_write(uint32_t dest_addr, const void *src, uint32_t size);
/*****************************************************************************
* Name: spi_flash_read
*
* Description:
* Read data from Flash.
*
* Note: For fastest read performance, all parameters should be
* 4 byte aligned. If source address and read size are not 4 byte
* aligned, read may be split into multiple flash operations. If
* destination buffer is not 4 byte aligned, a temporary buffer will
* be allocated on the stack.
*
* Reading more than 16KB of data at a time will be split
* into multiple reads to avoid disruption to other tasks in the
* system. Consider using spi_flash_mmap() to read large amounts
* of data.
*
* Parameters:
* src_addr - source address of the data in Flash.
* dest - pointer to the destination buffer
* size - length of data
*
* Returned Values:
* Zero (OK) is returned or a negative error.
*
*****************************************************************************/
int spi_flash_read(uint32_t src_addr, void *dest, uint32_t size);
/*****************************************************************************
* Name: spi_flash_erase_sector
*
* Description:
* Erase the Flash sector.
*
* Parameters:
* sector - Sector number, the count starts at sector 0, 4KB per sector.
*
* Returned Values: esp_err_t
* Zero (OK) is returned or a negative error.
*
*****************************************************************************/
int spi_flash_erase_sector(uint32_t sector);
/*****************************************************************************
* Name: spi_flash_erase_range
*
* Description:
* Erase a range of flash sectors
*
* Parameters:
* start_address - Address where erase operation has to start.
* Must be 4kB-aligned
* size - Size of erased range, in bytes. Must be divisible by
* 4kB.
*
* Returned Values:
* Zero (OK) is returned or a negative error.
*
*****************************************************************************/
int spi_flash_erase_range(uint32_t start_address, uint32_t size);
/*****************************************************************************
* Name: spi_flash_cache_enabled
*
* Description:
* Check at runtime if flash cache is enabled on both CPUs.
*
* Returned Values:
* Return true if both CPUs have flash cache enabled, false otherwise.
*/
bool spi_flash_cache_enabled(void);
/*****************************************************************************
* Name: spi_flash_enable_cache
*
* Description:
* Re-enable cache for the core defined as cpuid parameter.
*
* Parameters:
* cpuid - core number to enable instruction cache for.
*/
void spi_flash_enable_cache(uint32_t cpuid);
/* Global esp32c3_spiflash_chip_t structure used by ROM functions */
extern esp32c3_spiflash_chip_t g_rom_flashchip;
@@ -36,6 +36,8 @@ SECTIONS
*(.iram1)
*(.iram1.*)
*libsched.a:irq_dispatch.*(.text .text.* .literal .literal.*)
*(.wifi0iram .wifi0iram.*)
*(.wifirxiram .wifirxiram.*)
*(.wifislpiram .wifislpiram.*)
@@ -205,7 +205,7 @@ int board_wlan_init(void);
#endif
/****************************************************************************
* Name: esp32c3_spiflash_init
* Name: board_spiflash_init
*
* Description:
* Initialize the SPIFLASH and register the MTD device.
@@ -213,7 +213,7 @@ int board_wlan_init(void);
****************************************************************************/
#ifdef CONFIG_ESP32C3_SPIFLASH
int esp32c3_spiflash_init(void);
int board_spiflash_init(void);
#endif
/****************************************************************************
@@ -145,7 +145,7 @@ int esp32c3_bringup(void)
#endif
#ifdef CONFIG_ESP32C3_SPIFLASH
ret = esp32c3_spiflash_init();
ret = board_spiflash_init();
if (ret)
{
syslog(LOG_ERR, "ERROR: Failed to initialize SPI Flash\n");
@@ -43,6 +43,7 @@
#endif
#include "esp32c3_spiflash.h"
#include "esp32c3_spiflash_mtd.h"
#include "esp32c3-devkit.h"
/****************************************************************************
@@ -497,16 +498,18 @@ static int init_storage_partition(void)
****************************************************************************/
/****************************************************************************
* Name: esp32c3_spiflash_init
* Name: board_spiflash_init
*
* Description:
* Initialize the SPIFLASH and register the MTD device.
****************************************************************************/
int esp32c3_spiflash_init(void)
int board_spiflash_init(void)
{
int ret = OK;
esp32c3_spiflash_init();
#ifdef CONFIG_ESP32C3_HAVE_OTA_PARTITION
ret = init_ota_partitions();
if (ret < 0)