mirror of
https://github.com/apache/nuttx.git
synced 2026-08-10 23:15:15 +00:00
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:
parent
a0990ee416
commit
698f1f76ff
18 changed files with 1752 additions and 923 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include "esp32c3_spiflash.h"
|
||||
#include "esp32c3_spiflash_mtd.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
|
@ -35,13 +34,14 @@
|
|||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/init.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
|
||||
#include "esp32c3_attr.h"
|
||||
#include "esp32c3.h"
|
||||
#include "esp32c3_spiflash.h"
|
||||
#include "esp32c3_irq.h"
|
||||
#include "rom/esp32c3_spiflash.h"
|
||||
#include "hardware/esp32c3_soc.h"
|
||||
#include "hardware/esp32c3_interrupt.h"
|
||||
#include "hardware/extmem_reg.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
@ -64,6 +64,11 @@
|
|||
|
||||
#define VADDR0_START_ADDR (0x3c020000)
|
||||
|
||||
/* Ibus virtual address */
|
||||
|
||||
#define IBUS_VADDR_START (0x42000000)
|
||||
#define IBUS_VADDR_END (0x44000000)
|
||||
|
||||
/* Flash MMU table for CPU */
|
||||
|
||||
#define MMU_TABLE ((volatile uint32_t *)DR_REG_MMU_TABLE)
|
||||
|
|
@ -73,33 +78,10 @@
|
|||
#define MMU_BYTES2PAGES(_n) (((_n) + SPI_FLASH_MMU_PAGE_SIZE - 1) / \
|
||||
SPI_FLASH_MMU_PAGE_SIZE)
|
||||
|
||||
#define SPI_FLASH_BLK_SIZE 256
|
||||
#define SPI_FLASH_ERASE_SIZE 4096
|
||||
#define SPI_FLASH_ERASED_STATE (0xff)
|
||||
#define SPI_FLASH_SIZE (4 * 1024 * 1024)
|
||||
|
||||
#define MTD2PRIV(_dev) ((struct esp32c3_spiflash_s *)_dev)
|
||||
#define MTD_SIZE(_priv) ((*(_priv)->data)->chip.chip_size)
|
||||
#define MTD_BLKSIZE(_priv) ((*(_priv)->data)->chip.page_size)
|
||||
#define MTD_ERASESIZE(_priv) ((*(_priv)->data)->chip.sector_size)
|
||||
#define MTD_BLK2SIZE(_priv, _b) (MTD_BLKSIZE(_priv) * (_b))
|
||||
#define MTD_SIZE2BLK(_priv, _s) ((_s) / MTD_BLKSIZE(_priv))
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* ESP32-C3 SPI Flash device private data */
|
||||
|
||||
struct esp32c3_spiflash_s
|
||||
{
|
||||
struct mtd_dev_s mtd;
|
||||
|
||||
/* SPI Flash data */
|
||||
|
||||
const struct spiflash_legacy_data_s **data;
|
||||
};
|
||||
|
||||
/* SPI Flash map request data */
|
||||
|
||||
struct spiflash_map_req_s
|
||||
|
|
@ -125,42 +107,12 @@ struct spiflash_map_req_s
|
|||
uint32_t page_cnt;
|
||||
};
|
||||
|
||||
struct spiflash_cachestate_s
|
||||
{
|
||||
irqstate_t flags;
|
||||
uint32_t val;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions Prototypes
|
||||
* Private Functions Declaration
|
||||
****************************************************************************/
|
||||
|
||||
/* MTD driver methods */
|
||||
|
||||
static int esp32c3_erase(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks);
|
||||
static ssize_t esp32c3_read(struct mtd_dev_s *dev, off_t offset,
|
||||
size_t nbytes, uint8_t *buffer);
|
||||
static ssize_t esp32c3_read_decrypt(struct mtd_dev_s *dev,
|
||||
off_t offset,
|
||||
size_t nbytes,
|
||||
uint8_t *buffer);
|
||||
static ssize_t esp32c3_bread(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks, uint8_t *buffer);
|
||||
static ssize_t esp32c3_bread_decrypt(struct mtd_dev_s *dev,
|
||||
off_t startblock,
|
||||
size_t nblocks,
|
||||
uint8_t *buffer);
|
||||
static ssize_t esp32c3_write(struct mtd_dev_s *dev, off_t offset,
|
||||
size_t nbytes, const uint8_t *buffer);
|
||||
static ssize_t esp32c3_bwrite(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks, const uint8_t *buffer);
|
||||
static ssize_t esp32c3_bwrite_encrypt(struct mtd_dev_s *dev,
|
||||
off_t startblock,
|
||||
size_t nblocks,
|
||||
const uint8_t *buffer);
|
||||
static int esp32c3_ioctl(struct mtd_dev_s *dev, int cmd,
|
||||
unsigned long arg);
|
||||
static void spiflash_start(void);
|
||||
static void spiflash_end(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions Declaration
|
||||
|
|
@ -170,57 +122,43 @@ extern int cache_invalidate_addr(uint32_t addr, uint32_t size);
|
|||
extern uint32_t cache_suspend_icache(void);
|
||||
extern void cache_resume_icache(uint32_t val);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
extern const struct spiflash_legacy_data_s *rom_spiflash_legacy_data;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct esp32c3_spiflash_s g_esp32c3_spiflash =
|
||||
static struct spiflash_guard_funcs g_spi_flash_guard_funcs =
|
||||
{
|
||||
.mtd =
|
||||
{
|
||||
.erase = esp32c3_erase,
|
||||
.bread = esp32c3_bread,
|
||||
.bwrite = esp32c3_bwrite,
|
||||
.read = esp32c3_read,
|
||||
.ioctl = esp32c3_ioctl,
|
||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||
.write = esp32c3_write,
|
||||
#endif
|
||||
.name = "esp32c3_spiflash"
|
||||
},
|
||||
.data = &rom_spiflash_legacy_data,
|
||||
.start = spiflash_start,
|
||||
.end = spiflash_end,
|
||||
.op_lock = NULL,
|
||||
.op_unlock = NULL,
|
||||
.address_is_safe = NULL,
|
||||
.yield = NULL,
|
||||
};
|
||||
|
||||
static struct esp32c3_spiflash_s g_esp32c3_spiflash_encrypt =
|
||||
{
|
||||
.mtd =
|
||||
{
|
||||
.erase = esp32c3_erase,
|
||||
.bread = esp32c3_bread_decrypt,
|
||||
.bwrite = esp32c3_bwrite_encrypt,
|
||||
.read = esp32c3_read_decrypt,
|
||||
.ioctl = esp32c3_ioctl,
|
||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||
.write = NULL,
|
||||
#endif
|
||||
.name = "esp32c3_spiflash_encrypt"
|
||||
}
|
||||
};
|
||||
|
||||
/* Ensure exclusive access to the driver */
|
||||
|
||||
static sem_t g_exclsem = SEM_INITIALIZER(1);
|
||||
static uint32_t g_icache_value;
|
||||
static uint32_t g_int_regval;
|
||||
static uint32_t g_int_unmask;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static IRAM_ATTR void disable_mask_int(void)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
g_int_regval = getreg32(INTERRUPT_CPU_INT_ENABLE_REG);
|
||||
regval = g_int_regval & g_int_unmask;
|
||||
|
||||
putreg32(regval, INTERRUPT_CPU_INT_ENABLE_REG);
|
||||
}
|
||||
|
||||
static IRAM_ATTR void enable_mask_int(void)
|
||||
{
|
||||
putreg32(g_int_regval, INTERRUPT_CPU_INT_ENABLE_REG);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spiflash_opstart
|
||||
*
|
||||
|
|
@ -229,10 +167,17 @@ static sem_t g_exclsem = SEM_INITIALIZER(1);
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void spiflash_opstart(struct spiflash_cachestate_s *state)
|
||||
static IRAM_ATTR void spiflash_start(void)
|
||||
{
|
||||
state->flags = enter_critical_section();
|
||||
state->val = cache_suspend_icache() << 16;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
disable_mask_int();
|
||||
|
||||
g_icache_value = cache_suspend_icache() << 16;
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -243,10 +188,17 @@ static inline void spiflash_opstart(struct spiflash_cachestate_s *state)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void spiflash_opdone(const struct spiflash_cachestate_s *state)
|
||||
static IRAM_ATTR void spiflash_end(void)
|
||||
{
|
||||
cache_resume_icache(state->val >> 16);
|
||||
leave_critical_section(state->flags);
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
cache_resume_icache(g_icache_value >> 16);
|
||||
|
||||
enable_mask_int();
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -267,7 +219,7 @@ static inline void spiflash_opdone(const struct spiflash_cachestate_s *state)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int IRAM_ATTR esp32c3_mmap(struct spiflash_map_req_s *req)
|
||||
static IRAM_ATTR int esp32c3_mmap(struct spiflash_map_req_s *req)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
|
@ -275,9 +227,8 @@ static int IRAM_ATTR esp32c3_mmap(struct spiflash_map_req_s *req)
|
|||
int flash_page;
|
||||
int page_cnt;
|
||||
uint32_t mapped_addr;
|
||||
struct spiflash_cachestate_s state;
|
||||
|
||||
spiflash_opstart(&state);
|
||||
spiflash_start();
|
||||
|
||||
for (start_page = DROM0_PAGES_START;
|
||||
start_page < DROM0_PAGES_END;
|
||||
|
|
@ -315,7 +266,7 @@ static int IRAM_ATTR esp32c3_mmap(struct spiflash_map_req_s *req)
|
|||
ret = -ENOBUFS;
|
||||
}
|
||||
|
||||
spiflash_opdone(&state);
|
||||
spiflash_end();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -334,23 +285,22 @@ static int IRAM_ATTR esp32c3_mmap(struct spiflash_map_req_s *req)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void IRAM_ATTR esp32c3_ummap(const struct spiflash_map_req_s *req)
|
||||
static IRAM_ATTR void esp32c3_ummap(const struct spiflash_map_req_s *req)
|
||||
{
|
||||
int i;
|
||||
struct spiflash_cachestate_s state;
|
||||
|
||||
spiflash_opstart(&state);
|
||||
spiflash_start();
|
||||
|
||||
for (i = req->start_page; i < req->start_page + req->page_cnt; ++i)
|
||||
{
|
||||
MMU_TABLE[i] = INVALID_MMU_VAL;
|
||||
}
|
||||
|
||||
spiflash_opdone(&state);
|
||||
spiflash_end();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_readdata_encrypted
|
||||
* Name: spi_flash_read_encrypted
|
||||
*
|
||||
* Description:
|
||||
* Read decrypted data from SPI Flash at designated address when
|
||||
|
|
@ -366,9 +316,7 @@ static void IRAM_ATTR esp32c3_ummap(const struct spiflash_map_req_s *req)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static IRAM_ATTR int esp32c3_readdata_encrypted(uint32_t addr,
|
||||
uint8_t *buffer,
|
||||
uint32_t size)
|
||||
int spi_flash_read_encrypted(uint32_t addr, void *buffer, uint32_t size)
|
||||
{
|
||||
int ret;
|
||||
struct spiflash_map_req_s req =
|
||||
|
|
@ -391,623 +339,91 @@ static IRAM_ATTR int esp32c3_readdata_encrypted(uint32_t addr,
|
|||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_erase
|
||||
* Name: esp32c3_icache2phys
|
||||
*
|
||||
* Description:
|
||||
* Erase SPI Flash designated sectors.
|
||||
* Get Absolute address in SPI Flash by input function pointer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* startblock - start block number, it is not equal to SPI Flash's block
|
||||
* nblocks - Number of blocks
|
||||
* func - Function pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Erased blocks if success or a negative value if fail.
|
||||
* Absolute address if success or negtive value if failed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int esp32c3_erase(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks)
|
||||
int32_t esp32c3_icache2phys(const void *func)
|
||||
{
|
||||
ssize_t ret;
|
||||
uint32_t offset = startblock * SPI_FLASH_ERASE_SIZE;
|
||||
uint32_t nbytes = nblocks * SPI_FLASH_ERASE_SIZE;
|
||||
intptr_t pages;
|
||||
intptr_t off;
|
||||
intptr_t c = (intptr_t)func;
|
||||
|
||||
if ((offset > SPI_FLASH_SIZE) || ((offset + nbytes) > SPI_FLASH_SIZE))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
off = (c - IBUS_VADDR_START) % SPI_FLASH_MMU_PAGE_SIZE;
|
||||
pages = (c - IBUS_VADDR_START) / SPI_FLASH_MMU_PAGE_SIZE;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("(%p, %d, %d)\n", dev, startblock, nblocks);
|
||||
#endif
|
||||
pages += MMU_TABLE[pages];
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("spi_flash_erase_range(%p, 0x%x, %d)\n", dev, offset, nbytes);
|
||||
#endif
|
||||
|
||||
ret = spi_flash_erase_range(offset, nbytes);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nblocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("Failed to erase the flash range!\n");
|
||||
#endif
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
return pages * SPI_FLASH_MMU_PAGE_SIZE + off;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_read
|
||||
* Name: esp32c3_spiflash_unmask_cpuint
|
||||
*
|
||||
* Description:
|
||||
* Read data from SPI Flash at designated address.
|
||||
* Unmask CPU interrupt and keep this interrupt work when read, write,
|
||||
* erase SPI Flash.
|
||||
*
|
||||
* By default, all CPU interrupts are masked.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* offset - target address offset
|
||||
* nbytes - data number
|
||||
* buffer - data buffer pointer
|
||||
* cpuint - CPU interrupt ID
|
||||
*
|
||||
* Returned Value:
|
||||
* Read data bytes if success or a negative value if fail.
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_read(struct mtd_dev_s *dev, off_t offset,
|
||||
size_t nbytes, uint8_t *buffer)
|
||||
void esp32c3_spiflash_unmask_cpuint(int cpuint)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
|
||||
#endif
|
||||
|
||||
/* Acquire the semaphore. */
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto error_with_buffer;
|
||||
}
|
||||
|
||||
ret = spi_flash_read(offset, buffer, nbytes);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nbytes;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
error_with_buffer:
|
||||
|
||||
return ret;
|
||||
g_int_unmask |= 1 << cpuint;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_bread
|
||||
* Name: esp32c3_spiflash_unmask_cpuint
|
||||
*
|
||||
* Description:
|
||||
* Read data from designated blocks.
|
||||
* Mask CPU interrupt and disable this interrupt when read, write,
|
||||
* erase SPI Flash.
|
||||
*
|
||||
* By default, all CPU interrupts are masked.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* startblock - start block number, it is not equal to SPI Flash's block
|
||||
* nblocks - blocks number
|
||||
* buffer - data buffer pointer
|
||||
* cpuint - CPU interrupt ID
|
||||
*
|
||||
* Returned Value:
|
||||
* Read block number if success or a negative value if fail.
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_bread(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks, uint8_t *buffer)
|
||||
void esp32c3_spiflash_mask_cpuint(int cpuint)
|
||||
{
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * SPI_FLASH_BLK_SIZE;
|
||||
uint32_t size = nblocks * SPI_FLASH_BLK_SIZE;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks,
|
||||
buffer);
|
||||
#endif
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_flash_read(addr, buffer, size);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nblocks;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
g_int_unmask &= ~(1 << cpuint);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_read_decrypt
|
||||
* Name: esp32c3_spiflash_init
|
||||
*
|
||||
* Description:
|
||||
* Read encrypted data and decrypt automatically from SPI Flash
|
||||
* at designated address.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* offset - target address offset
|
||||
* nbytes - data number
|
||||
* buffer - data buffer pointer
|
||||
* Initialize ESP32-C3 SPI flash driver.
|
||||
*
|
||||
* Returned Value:
|
||||
* Read data bytes if success or a negative value if fail.
|
||||
* OK if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_read_decrypt(struct mtd_dev_s *dev,
|
||||
off_t offset,
|
||||
size_t nbytes,
|
||||
uint8_t *buffer)
|
||||
int esp32c3_spiflash_init(void)
|
||||
{
|
||||
ssize_t ret;
|
||||
spi_flash_guard_set(&g_spi_flash_guard_funcs);
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
|
||||
#endif
|
||||
|
||||
/* Acquire the semaphore. */
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp32c3_readdata_encrypted(offset, buffer, nbytes);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nbytes;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_bread_decrypt
|
||||
*
|
||||
* Description:
|
||||
* Read encrypted data and decrypt automatically from designated blocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* startblock - start block number, it is not equal to SPI Flash's block
|
||||
* nblocks - blocks number
|
||||
* buffer - data buffer pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Read block number if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_bread_decrypt(struct mtd_dev_s *dev,
|
||||
off_t startblock,
|
||||
size_t nblocks,
|
||||
uint8_t *buffer)
|
||||
{
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * SPI_FLASH_BLK_SIZE;
|
||||
uint32_t size = nblocks * SPI_FLASH_BLK_SIZE;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks,
|
||||
buffer);
|
||||
#endif
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp32c3_readdata_encrypted(addr, buffer, size);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nblocks;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_write
|
||||
*
|
||||
* Description:
|
||||
* write data to SPI Flash at designated address.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* offset - target address offset
|
||||
* nbytes - data number
|
||||
* buffer - data buffer pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Writen bytes if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_write(struct mtd_dev_s *dev, off_t offset,
|
||||
size_t nbytes, const uint8_t *buffer)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ASSERT(buffer);
|
||||
|
||||
if ((offset > SPI_FLASH_SIZE) || ((offset + nbytes) > SPI_FLASH_SIZE))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
|
||||
#endif
|
||||
|
||||
/* Acquire the semaphore. */
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto error_with_buffer;
|
||||
}
|
||||
|
||||
ret = spi_flash_write(offset, buffer, nbytes);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nbytes;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
error_with_buffer:
|
||||
|
||||
return (ssize_t)ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_bwrite
|
||||
*
|
||||
* Description:
|
||||
* Write data to designated blocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* startblock - start MTD block number,
|
||||
* it is not equal to SPI Flash's block
|
||||
* nblocks - blocks number
|
||||
* buffer - data buffer pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Writen block number if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_bwrite(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks, const uint8_t *buffer)
|
||||
{
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * SPI_FLASH_BLK_SIZE;
|
||||
uint32_t size = nblocks * SPI_FLASH_BLK_SIZE;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock,
|
||||
nblocks, buffer);
|
||||
#endif
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_flash_write(addr, buffer, size);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nblocks;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_bwrite_encrypt
|
||||
*
|
||||
* Description:
|
||||
* Write data to designated blocks by SPI Flash hardware encryption.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* startblock - start MTD block number,
|
||||
* it is not equal to SPI Flash's block
|
||||
* nblocks - blocks number
|
||||
* buffer - data buffer pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Writen block number if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_bwrite_encrypt(struct mtd_dev_s *dev,
|
||||
off_t startblock,
|
||||
size_t nblocks,
|
||||
const uint8_t *buffer)
|
||||
{
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * SPI_FLASH_BLK_SIZE;
|
||||
uint32_t size = nblocks * SPI_FLASH_BLK_SIZE;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock,
|
||||
nblocks, buffer);
|
||||
#endif
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto error_with_buffer;
|
||||
}
|
||||
|
||||
ret = spi_flash_write_encrypted(addr, buffer, size);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nblocks;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_SPIFLASH_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
error_with_buffer:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_ioctl
|
||||
*
|
||||
* Description:
|
||||
* Set/Get option to/from ESP32-C3 SPI Flash MTD device data.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - ESP32-C3 MTD device data
|
||||
* cmd - operation command
|
||||
* arg - operation argument
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int esp32c3_ioctl(struct mtd_dev_s *dev, int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int ret = OK;
|
||||
|
||||
finfo("cmd: %d \n", cmd);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case MTDIOC_GEOMETRY:
|
||||
{
|
||||
struct mtd_geometry_s *geo = (struct mtd_geometry_s *)arg;
|
||||
if (geo)
|
||||
{
|
||||
geo->blocksize = SPI_FLASH_BLK_SIZE;
|
||||
geo->erasesize = SPI_FLASH_ERASE_SIZE;
|
||||
geo->neraseblocks = SPI_FLASH_SIZE / SPI_FLASH_ERASE_SIZE;
|
||||
ret = OK;
|
||||
|
||||
finfo("blocksize: %" PRId32 " erasesize: %" PRId32 \
|
||||
" neraseblocks: %" PRId32 "\n",
|
||||
geo->blocksize, geo->erasesize, geo->neraseblocks);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BIOC_PARTINFO:
|
||||
{
|
||||
struct partition_info_s *info = (struct partition_info_s *)arg;
|
||||
if (info != NULL)
|
||||
{
|
||||
info->numsectors = SPI_FLASH_SIZE / SPI_FLASH_BLK_SIZE;
|
||||
info->sectorsize = SPI_FLASH_BLK_SIZE;
|
||||
info->startsector = 0;
|
||||
info->parent[0] = '\0';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MTDIOC_ERASESTATE:
|
||||
{
|
||||
uint8_t *result = (uint8_t *)arg;
|
||||
*result = SPI_FLASH_ERASED_STATE;
|
||||
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
finfo("return %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* 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)
|
||||
{
|
||||
struct esp32c3_spiflash_s *priv = &g_esp32c3_spiflash;
|
||||
const esp32c3_spiflash_chip_t *chip = &(*priv->data)->chip;
|
||||
struct mtd_dev_s *mtd_part;
|
||||
uint32_t blocks;
|
||||
uint32_t startblock;
|
||||
uint32_t size;
|
||||
|
||||
ASSERT((mtd_offset + mtd_size) <= chip->chip_size);
|
||||
ASSERT((mtd_offset % chip->sector_size) == 0);
|
||||
ASSERT((mtd_size % chip->sector_size) == 0);
|
||||
|
||||
finfo("ESP32-C3 SPI Flash information:\n");
|
||||
finfo("\tID = 0x%" PRIx32 "\n", chip->device_id);
|
||||
finfo("\tStatus mask = 0x%" PRIx32 "\n", chip->status_mask);
|
||||
finfo("\tChip size = %" PRId32 " KB\n", chip->chip_size / 1024);
|
||||
finfo("\tPage size = %" PRId32 " B\n", chip->page_size);
|
||||
finfo("\tSector size = %" PRId32 " KB\n", chip->sector_size / 1024);
|
||||
finfo("\tBlock size = %" PRId32 " KB\n", chip->block_size / 1024);
|
||||
|
||||
if (mtd_size == 0)
|
||||
{
|
||||
size = chip->chip_size - mtd_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = mtd_size;
|
||||
}
|
||||
|
||||
finfo("\tMTD offset = 0x%" PRIx32 "\n", mtd_offset);
|
||||
finfo("\tMTD size = 0x%" PRIx32 "\n", size);
|
||||
|
||||
startblock = MTD_SIZE2BLK(priv, mtd_offset);
|
||||
blocks = MTD_SIZE2BLK(priv, size);
|
||||
|
||||
mtd_part = mtd_partition(&priv->mtd, startblock, blocks);
|
||||
if (!mtd_part)
|
||||
{
|
||||
ferr("ERROR: Failed to create MTD partition\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mtd_part;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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)
|
||||
{
|
||||
struct esp32c3_spiflash_s *priv = &g_esp32c3_spiflash;
|
||||
|
||||
return &priv->mtd;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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)
|
||||
{
|
||||
struct esp32c3_spiflash_s *priv = &g_esp32c3_spiflash_encrypt;
|
||||
|
||||
return &priv->mtd;
|
||||
return OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
795
arch/risc-v/src/esp32c3/esp32c3_spiflash_mtd.c
Normal file
795
arch/risc-v/src/esp32c3/esp32c3_spiflash_mtd.c
Normal file
|
|
@ -0,0 +1,795 @@
|
|||
/****************************************************************************
|
||||
* arch/risc-v/src/esp32c3/esp32c3_spiflash_mtd.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/init.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
|
||||
#include "esp32c3_attr.h"
|
||||
#include "esp32c3_spiflash.h"
|
||||
#include "rom/esp32c3_spiflash.h"
|
||||
#include "hardware/esp32c3_soc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define MTD_BLK_SIZE CONFIG_ESP32C3_STORAGE_MTD_BLKSIZE
|
||||
#define MTD_ERASE_SIZE 4096
|
||||
#define MTD_ERASED_STATE (0xff)
|
||||
|
||||
#define MTD_PART_OFFSET CONFIG_ESP32C3_STORAGE_MTD_OFFSET
|
||||
#define MTD_PART_SIZE CONFIG_ESP32C3_STORAGE_MTD_SIZE
|
||||
|
||||
#define MTD2PRIV(_dev) ((struct esp32c3_mtd_dev_s *)_dev)
|
||||
#define MTD_SIZE(_priv) ((*(_priv)->data)->chip.chip_size)
|
||||
#define MTD_BLK2SIZE(_priv, _b) (MTD_BLK_SIZE * (_b))
|
||||
#define MTD_SIZE2BLK(_priv, _s) ((_s) / MTD_BLK_SIZE)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* ESP32-C3 SPI Flash device private data */
|
||||
|
||||
struct esp32c3_mtd_dev_s
|
||||
{
|
||||
struct mtd_dev_s mtd;
|
||||
|
||||
/* SPI Flash data */
|
||||
|
||||
const struct spiflash_legacy_data_s **data;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* MTD driver methods */
|
||||
|
||||
static int esp32c3_erase(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks);
|
||||
static ssize_t esp32c3_read(struct mtd_dev_s *dev, off_t offset,
|
||||
size_t nbytes, uint8_t *buffer);
|
||||
static ssize_t esp32c3_read_decrypt(struct mtd_dev_s *dev,
|
||||
off_t offset,
|
||||
size_t nbytes,
|
||||
uint8_t *buffer);
|
||||
static ssize_t esp32c3_bread(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks, uint8_t *buffer);
|
||||
static ssize_t esp32c3_bread_decrypt(struct mtd_dev_s *dev,
|
||||
off_t startblock,
|
||||
size_t nblocks,
|
||||
uint8_t *buffer);
|
||||
static ssize_t esp32c3_write(struct mtd_dev_s *dev, off_t offset,
|
||||
size_t nbytes, const uint8_t *buffer);
|
||||
static ssize_t esp32c3_bwrite(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks, const uint8_t *buffer);
|
||||
static ssize_t esp32c3_bwrite_encrypt(struct mtd_dev_s *dev,
|
||||
off_t startblock,
|
||||
size_t nblocks,
|
||||
const uint8_t *buffer);
|
||||
static int esp32c3_ioctl(struct mtd_dev_s *dev, int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
extern const struct spiflash_legacy_data_s *rom_spiflash_legacy_data;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct esp32c3_mtd_dev_s g_esp32c3_spiflash =
|
||||
{
|
||||
.mtd =
|
||||
{
|
||||
.erase = esp32c3_erase,
|
||||
.bread = esp32c3_bread,
|
||||
.bwrite = esp32c3_bwrite,
|
||||
.read = esp32c3_read,
|
||||
.ioctl = esp32c3_ioctl,
|
||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||
.write = esp32c3_write,
|
||||
#endif
|
||||
.name = "esp32c3_spiflash"
|
||||
},
|
||||
.data = &rom_spiflash_legacy_data,
|
||||
};
|
||||
|
||||
static const struct esp32c3_mtd_dev_s g_esp32c3_spiflash_encrypt =
|
||||
{
|
||||
.mtd =
|
||||
{
|
||||
.erase = esp32c3_erase,
|
||||
.bread = esp32c3_bread_decrypt,
|
||||
.bwrite = esp32c3_bwrite_encrypt,
|
||||
.read = esp32c3_read_decrypt,
|
||||
.ioctl = esp32c3_ioctl,
|
||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||
.write = NULL,
|
||||
#endif
|
||||
.name = "esp32c3_spiflash_encrypt"
|
||||
}
|
||||
};
|
||||
|
||||
/* Ensure exclusive access to the driver */
|
||||
|
||||
static sem_t g_exclsem = SEM_INITIALIZER(1);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_erase
|
||||
*
|
||||
* Description:
|
||||
* Erase SPI Flash designated sectors.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* startblock - start block number, it is not equal to SPI Flash's block
|
||||
* nblocks - Number of blocks
|
||||
*
|
||||
* Returned Value:
|
||||
* Erased blocks if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int esp32c3_erase(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks)
|
||||
{
|
||||
ssize_t ret;
|
||||
uint32_t offset = startblock * MTD_ERASE_SIZE;
|
||||
uint32_t nbytes = nblocks * MTD_ERASE_SIZE;
|
||||
struct esp32c3_mtd_dev_s *priv = (struct esp32c3_mtd_dev_s *)dev;
|
||||
|
||||
if ((offset > MTD_SIZE(priv)) || ((offset + nbytes) > MTD_SIZE(priv)))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d)\n", __func__, dev, startblock, nblocks);
|
||||
|
||||
finfo("spi_flash_erase_range(0x%x, %d)\n", offset, nbytes);
|
||||
#endif
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_flash_erase_range(offset, nbytes);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nblocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("Failed to erase the flash range!\n");
|
||||
#endif
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_read
|
||||
*
|
||||
* Description:
|
||||
* Read data from SPI Flash at designated address.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* offset - target address offset
|
||||
* nbytes - data number
|
||||
* buffer - data buffer pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Read data bytes if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_read(struct mtd_dev_s *dev, off_t offset,
|
||||
size_t nbytes, uint8_t *buffer)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
|
||||
|
||||
finfo("spi_flash_read(0x%x, %p, %d)\n", offset, buffer, nbytes);
|
||||
#endif
|
||||
|
||||
/* Acquire the semaphore. */
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto error_with_buffer;
|
||||
}
|
||||
|
||||
ret = spi_flash_read(offset, buffer, nbytes);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nbytes;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
error_with_buffer:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_bread
|
||||
*
|
||||
* Description:
|
||||
* Read data from designated blocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* startblock - start block number, it is not equal to SPI Flash's block
|
||||
* nblocks - blocks number
|
||||
* buffer - data buffer pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Read block number if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_bread(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks, uint8_t *buffer)
|
||||
{
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * MTD_BLK_SIZE;
|
||||
uint32_t size = nblocks * MTD_BLK_SIZE;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks,
|
||||
buffer);
|
||||
|
||||
finfo("spi_flash_read(0x%x, %p, %d)\n", addr, buffer, size);
|
||||
#endif
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_flash_read(addr, buffer, size);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nblocks;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_read_decrypt
|
||||
*
|
||||
* Description:
|
||||
* Read encrypted data and decrypt automatically from SPI Flash
|
||||
* at designated address.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* offset - target address offset
|
||||
* nbytes - data number
|
||||
* buffer - data buffer pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Read data bytes if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_read_decrypt(struct mtd_dev_s *dev,
|
||||
off_t offset,
|
||||
size_t nbytes,
|
||||
uint8_t *buffer)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
|
||||
|
||||
finfo("spi_flash_read_encrypted(0x%x, %p, %d)\n", offset, buffer,
|
||||
nbytes);
|
||||
#endif
|
||||
|
||||
/* Acquire the semaphore. */
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_flash_read_encrypted(offset, buffer, nbytes);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nbytes;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_bread_decrypt
|
||||
*
|
||||
* Description:
|
||||
* Read encrypted data and decrypt automatically from designated blocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* startblock - start block number, it is not equal to SPI Flash's block
|
||||
* nblocks - blocks number
|
||||
* buffer - data buffer pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Read block number if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_bread_decrypt(struct mtd_dev_s *dev,
|
||||
off_t startblock,
|
||||
size_t nblocks,
|
||||
uint8_t *buffer)
|
||||
{
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * MTD_BLK_SIZE;
|
||||
uint32_t size = nblocks * MTD_BLK_SIZE;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks,
|
||||
buffer);
|
||||
|
||||
finfo("spi_flash_read_encrypted(0x%x, %p, %d)\n", addr, buffer, size);
|
||||
#endif
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_flash_read_encrypted(addr, buffer, size);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nblocks;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_write
|
||||
*
|
||||
* Description:
|
||||
* write data to SPI Flash at designated address.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* offset - target address offset
|
||||
* nbytes - data number
|
||||
* buffer - data buffer pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Writen bytes if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_write(struct mtd_dev_s *dev, off_t offset,
|
||||
size_t nbytes, const uint8_t *buffer)
|
||||
{
|
||||
int ret;
|
||||
struct esp32c3_mtd_dev_s *priv = (struct esp32c3_mtd_dev_s *)dev;
|
||||
|
||||
ASSERT(buffer);
|
||||
|
||||
if ((offset > MTD_SIZE(priv)) || ((offset + nbytes) > MTD_SIZE(priv)))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
|
||||
|
||||
finfo("spi_flash_write(0x%x, %p, %d)\n", offset, buffer, nbytes);
|
||||
#endif
|
||||
|
||||
/* Acquire the semaphore. */
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto error_with_buffer;
|
||||
}
|
||||
|
||||
ret = spi_flash_write(offset, buffer, nbytes);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nbytes;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
error_with_buffer:
|
||||
|
||||
return (ssize_t)ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_bwrite
|
||||
*
|
||||
* Description:
|
||||
* Write data to designated blocks.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* startblock - start MTD block number,
|
||||
* it is not equal to SPI Flash's block
|
||||
* nblocks - blocks number
|
||||
* buffer - data buffer pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Writen block number if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_bwrite(struct mtd_dev_s *dev, off_t startblock,
|
||||
size_t nblocks, const uint8_t *buffer)
|
||||
{
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * MTD_BLK_SIZE;
|
||||
uint32_t size = nblocks * MTD_BLK_SIZE;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock,
|
||||
nblocks, buffer);
|
||||
|
||||
finfo("spi_flash_write(0x%x, %p, %d)\n", addr, buffer, size);
|
||||
#endif
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_flash_write(addr, buffer, size);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nblocks;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_bwrite_encrypt
|
||||
*
|
||||
* Description:
|
||||
* Write data to designated blocks by SPI Flash hardware encryption.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - MTD device data
|
||||
* startblock - start MTD block number,
|
||||
* it is not equal to SPI Flash's block
|
||||
* nblocks - blocks number
|
||||
* buffer - data buffer pointer
|
||||
*
|
||||
* Returned Value:
|
||||
* Writen block number if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t esp32c3_bwrite_encrypt(struct mtd_dev_s *dev,
|
||||
off_t startblock,
|
||||
size_t nblocks,
|
||||
const uint8_t *buffer)
|
||||
{
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * MTD_BLK_SIZE;
|
||||
uint32_t size = nblocks * MTD_BLK_SIZE;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock,
|
||||
nblocks, buffer);
|
||||
|
||||
finfo("spi_flash_write_encrypted(0x%x, %p, %d)\n", addr, buffer, size);
|
||||
#endif
|
||||
|
||||
ret = nxsem_wait(&g_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto error_with_buffer;
|
||||
}
|
||||
|
||||
ret = spi_flash_write_encrypted(addr, buffer, size);
|
||||
|
||||
nxsem_post(&g_exclsem);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = nblocks;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s()=%d\n", __func__, ret);
|
||||
#endif
|
||||
|
||||
error_with_buffer:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_ioctl
|
||||
*
|
||||
* Description:
|
||||
* Set/Get option to/from ESP32-C3 SPI Flash MTD device data.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - ESP32-C3 MTD device data
|
||||
* cmd - operation command
|
||||
* arg - operation argument
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 if success or a negative value if fail.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int esp32c3_ioctl(struct mtd_dev_s *dev, int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int ret = OK;
|
||||
finfo("cmd: %d \n", cmd);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case MTDIOC_GEOMETRY:
|
||||
{
|
||||
struct mtd_geometry_s *geo = (struct mtd_geometry_s *)arg;
|
||||
if (geo)
|
||||
{
|
||||
geo->blocksize = MTD_BLK_SIZE;
|
||||
geo->erasesize = MTD_ERASE_SIZE;
|
||||
geo->neraseblocks = MTD_PART_SIZE / MTD_ERASE_SIZE;
|
||||
ret = OK;
|
||||
|
||||
finfo("blocksize: %" PRId32 " erasesize: %" PRId32 \
|
||||
" neraseblocks: %" PRId32 "\n",
|
||||
geo->blocksize, geo->erasesize, geo->neraseblocks);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BIOC_PARTINFO:
|
||||
{
|
||||
struct partition_info_s *info = (struct partition_info_s *)arg;
|
||||
if (info != NULL)
|
||||
{
|
||||
info->numsectors = MTD_PART_SIZE / MTD_BLK_SIZE;
|
||||
info->sectorsize = MTD_BLK_SIZE;
|
||||
info->startsector = 0;
|
||||
info->parent[0] = '\0';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MTDIOC_ERASESTATE:
|
||||
{
|
||||
uint8_t *result = (uint8_t *)arg;
|
||||
*result = MTD_ERASED_STATE;
|
||||
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
finfo("return %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32c3_spiflash_alloc_mtdpart
|
||||
*
|
||||
* Description:
|
||||
* Allocate SPI Flash MTD.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
struct esp32c3_mtd_dev_s *priv =
|
||||
(struct esp32c3_mtd_dev_s *)&g_esp32c3_spiflash;
|
||||
const esp32c3_spiflash_chip_t *chip = &(*priv->data)->chip;
|
||||
struct mtd_dev_s *mtd_part;
|
||||
uint32_t blocks;
|
||||
uint32_t startblock;
|
||||
uint32_t size;
|
||||
|
||||
ASSERT((mtd_offset + mtd_size) <= chip->chip_size);
|
||||
ASSERT((mtd_offset % chip->sector_size) == 0);
|
||||
ASSERT((mtd_size % chip->sector_size) == 0);
|
||||
|
||||
finfo("ESP32-C3 SPI Flash information:\n");
|
||||
finfo("\tID = 0x%" PRIx32 "\n", chip->device_id);
|
||||
finfo("\tStatus mask = 0x%" PRIx32 "\n", chip->status_mask);
|
||||
finfo("\tChip size = %" PRId32 " KB\n", chip->chip_size / 1024);
|
||||
finfo("\tPage size = %" PRId32 " B\n", chip->page_size);
|
||||
finfo("\tSector size = %" PRId32 " KB\n", chip->sector_size / 1024);
|
||||
finfo("\tBlock size = %" PRId32 " KB\n", chip->block_size / 1024);
|
||||
|
||||
if (mtd_size == 0)
|
||||
{
|
||||
size = chip->chip_size - mtd_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = mtd_size;
|
||||
}
|
||||
|
||||
finfo("\tMTD offset = 0x%" PRIx32 "\n", mtd_offset);
|
||||
finfo("\tMTD size = 0x%" PRIx32 "\n", size);
|
||||
|
||||
startblock = MTD_SIZE2BLK(priv, mtd_offset);
|
||||
blocks = MTD_SIZE2BLK(priv, size);
|
||||
|
||||
mtd_part = mtd_partition(&priv->mtd, startblock, blocks);
|
||||
if (!mtd_part)
|
||||
{
|
||||
ferr("ERROR: Failed to create MTD partition\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mtd_part;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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)
|
||||
{
|
||||
struct esp32c3_mtd_dev_s *priv =
|
||||
(struct esp32c3_mtd_dev_s *)&g_esp32c3_spiflash;
|
||||
|
||||
return &priv->mtd;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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)
|
||||
{
|
||||
struct esp32c3_mtd_dev_s *priv =
|
||||
(struct esp32c3_mtd_dev_s *)&g_esp32c3_spiflash_encrypt;
|
||||
|
||||
return &priv->mtd;
|
||||
}
|
||||
105
arch/risc-v/src/esp32c3/esp32c3_spiflash_mtd.h
Normal file
105
arch/risc-v/src/esp32c3/esp32c3_spiflash_mtd.h
Normal file
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue