From aa0dccb7bcad993c558e392d61c1028cf078d278 Mon Sep 17 00:00:00 2001 From: Eren Terzioglu Date: Fri, 15 Dec 2023 15:16:24 +0300 Subject: [PATCH] risc-v/espressif: Add SPI Flash support --- arch/risc-v/src/common/espressif/Kconfig | 62 ++ arch/risc-v/src/common/espressif/Make.defs | 9 +- arch/risc-v/src/common/espressif/esp_irq.c | 96 +++ arch/risc-v/src/common/espressif/esp_irq.h | 32 + .../src/common/espressif/esp_spiflash.c | 594 ++++++++++++++++++ .../src/common/espressif/esp_spiflash.h | 188 ++++++ .../src/common/espressif/esp_spiflash_mtd.c | 540 ++++++++++++++++ .../src/common/espressif/esp_spiflash_mtd.h | 89 +++ arch/risc-v/src/esp32c3/hal_esp32c3.mk | 2 + arch/risc-v/src/esp32c6/hal_esp32c6.mk | 2 + arch/risc-v/src/esp32h2/hal_esp32h2.mk | 2 + boards/risc-v/esp32c3/common/Kconfig | 37 ++ .../common/include/esp_board_spiflash.h | 74 +++ boards/risc-v/esp32c3/common/src/Make.defs | 4 + .../esp32c3/common/src/esp_board_spiflash.c | 417 ++++++++++++ .../configs/spiflash/defconfig | 54 ++ .../esp32c3-generic/src/esp32c3_bringup.c | 9 + boards/risc-v/esp32c6/common/Kconfig | 37 ++ .../common/include/esp_board_spiflash.h | 74 +++ .../esp32c6/common/scripts/esp32c6_aliases.ld | 3 + boards/risc-v/esp32c6/common/src/Make.defs | 4 + .../esp32c6/common/src/esp_board_spiflash.c | 417 ++++++++++++ .../esp32c6-devkit/configs/spiflash/defconfig | 55 ++ .../esp32c6-devkit/src/esp32c6_bringup.c | 9 + boards/risc-v/esp32h2/common/Kconfig | 37 ++ .../common/include/esp_board_spiflash.h | 74 +++ .../esp32h2/common/scripts/esp32h2_aliases.ld | 3 + boards/risc-v/esp32h2/common/src/Make.defs | 4 + .../esp32h2/common/src/esp_board_spiflash.c | 417 ++++++++++++ .../esp32h2-devkit/configs/spiflash/defconfig | 55 ++ .../esp32h2-devkit/src/esp32h2_bringup.c | 9 + 31 files changed, 3408 insertions(+), 1 deletion(-) create mode 100644 arch/risc-v/src/common/espressif/esp_spiflash.c create mode 100644 arch/risc-v/src/common/espressif/esp_spiflash.h create mode 100644 arch/risc-v/src/common/espressif/esp_spiflash_mtd.c create mode 100644 arch/risc-v/src/common/espressif/esp_spiflash_mtd.h create mode 100644 boards/risc-v/esp32c3/common/include/esp_board_spiflash.h create mode 100644 boards/risc-v/esp32c3/common/src/esp_board_spiflash.c create mode 100644 boards/risc-v/esp32c3/esp32c3-generic/configs/spiflash/defconfig create mode 100644 boards/risc-v/esp32c6/common/include/esp_board_spiflash.h create mode 100644 boards/risc-v/esp32c6/common/src/esp_board_spiflash.c create mode 100644 boards/risc-v/esp32c6/esp32c6-devkit/configs/spiflash/defconfig create mode 100644 boards/risc-v/esp32h2/common/include/esp_board_spiflash.h create mode 100644 boards/risc-v/esp32h2/common/src/esp_board_spiflash.c create mode 100644 boards/risc-v/esp32h2/esp32h2-devkit/configs/spiflash/defconfig diff --git a/arch/risc-v/src/common/espressif/Kconfig b/arch/risc-v/src/common/espressif/Kconfig index c5aa9cc0d0..d7aa8236f1 100644 --- a/arch/risc-v/src/common/espressif/Kconfig +++ b/arch/risc-v/src/common/espressif/Kconfig @@ -43,6 +43,12 @@ config ESPRESSIF_FLASH_2M config ESPRESSIF_FLASH_4M bool "4 MB" +config ESPRESSIF_FLASH_8M + bool "8 MB" + +config ESPRESSIF_FLASH_16M + bool "16 MB" + endchoice # ESPRESSIF_FLASH config ESPRESSIF_FLASH_DETECT @@ -281,6 +287,10 @@ config ESPRESSIF_LEDC select PWM select ARCH_HAVE_PWM_MULTICHAN +config ESPRESSIF_SPIFLASH + bool "SPI Flash" + default n + config ESPRESSIF_HR_TIMER bool default RTC_DRIVER @@ -408,6 +418,35 @@ config ESPRESSIF_FLASH_MODE_QOUT endchoice # ESPRESSIF_FLASH_MODE +if ESPRESSIF_SPIFLASH +comment "General storage MTD configuration" + +config ESPRESSIF_MTD + bool "MTD driver" + default y + select MTD + select MTD_BYTE_WRITE + select MTD_PARTITION + ---help--- + Initialize an MTD driver for the SPI Flash, which will + add an entry at /dev for application access from userspace. + +config ESPRESSIF_SPIFLASH_MTD_BLKSIZE + int "Storage MTD block size" + default 64 + depends on ESPRESSIF_MTD + ---help--- + Block size for MTD driver in kB. This size must be divisible by 2 + +config ESPRESSIF_STORAGE_MTD_DEBUG + bool "Storage MTD Debug" + default n + depends on ESPRESSIF_MTD && DEBUG_FS_INFO + ---help--- + If this option is enabled, Storage MTD driver read and write functions + will output input parameters and return values (if applicable). +endif # ESPRESSIF_SPIFLASH + choice ESPRESSIF_FLASH_FREQ prompt "SPI Flash frequency" default ESPRESSIF_FLASH_FREQ_80M if ESPRESSIF_ESP32C3 || ESPRESSIF_ESP32C6 @@ -437,6 +476,29 @@ config ESPRESSIF_FLASH_FREQ_20M endchoice # ESPRESSIF_FLASH_FREQ +config ESPRESSIF_SPI_FLASH_USE_32BIT_ADDRESS + bool "SPI flash uses 32-bit address" + default n + ---help--- + SPI flash driver in ROM only support 24-bit address access, + if select the option, it will force to use source code instead + of functions in ROM, so that SPI flash driver can access full + 32-bit address. + +config ESPRESSIF_STORAGE_MTD_OFFSET + hex "Storage MTD base address in SPI Flash" + default 0x180000 + depends on ESPRESSIF_MTD + ---help--- + MTD base address in SPI Flash. + +config ESPRESSIF_STORAGE_MTD_SIZE + hex "Storage MTD size in SPI Flash" + default 0x100000 + depends on ESPRESSIF_MTD + ---help--- + MTD size in SPI Flash. + endmenu # SPI Flash Configuration menu "LEDC configuration" diff --git a/arch/risc-v/src/common/espressif/Make.defs b/arch/risc-v/src/common/espressif/Make.defs index 48710e581b..dabc97ce13 100644 --- a/arch/risc-v/src/common/espressif/Make.defs +++ b/arch/risc-v/src/common/espressif/Make.defs @@ -80,6 +80,13 @@ ifeq ($(CONFIG_ESP_RMT),y) endif endif +ifeq ($(CONFIG_ESPRESSIF_SPIFLASH),y) + CHIP_CSRCS += esp_spiflash.c + ifeq ($(CONFIG_ESPRESSIF_MTD),y) + CHIP_CSRCS += esp_spiflash_mtd.c + endif +endif + ############################################################################# # Espressif HAL for 3rd Party Platforms ############################################################################# @@ -88,7 +95,7 @@ endif ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty ifndef ESP_HAL_3RDPARTY_VERSION - ESP_HAL_3RDPARTY_VERSION = b6a943764f5e5a12d12edd8a6d71bdecc505428c + ESP_HAL_3RDPARTY_VERSION = 7951b5b282384ec43858a28ddfabbef7b6b326cb endif ifndef ESP_HAL_3RDPARTY_URL diff --git a/arch/risc-v/src/common/espressif/esp_irq.c b/arch/risc-v/src/common/espressif/esp_irq.c index 16c526a0cc..a70c1da339 100644 --- a/arch/risc-v/src/common/espressif/esp_irq.c +++ b/arch/risc-v/src/common/espressif/esp_irq.c @@ -115,6 +115,19 @@ static volatile uint8_t g_irq_map[NR_IRQS]; static uint32_t g_cpuint_freelist = ESP_CPUINT_PERIPHSET; +/* This bitmask has an 1 if the int should be disabled + * when the flash is disabled. + */ + +static uint32_t non_iram_int_mask[CONFIG_ESPRESSIF_NUM_CPUS]; + +/* This bitmask has 1 in it if the int was disabled + * using esp_intr_noniram_disable. + */ + +static uint32_t non_iram_int_disabled[CONFIG_ESPRESSIF_NUM_CPUS]; +static bool non_iram_int_disabled_flag[CONFIG_ESPRESSIF_NUM_CPUS]; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -280,6 +293,15 @@ static void esp_cpuint_initialize(void) void up_irqinitialize(void) { + /* All CPU ints are non-IRAM interrupts at the beginning and should be + * disabled during a SPI flash operation + */ + + for (int i = 0; i < CONFIG_SMP_NCPUS; i++) + { + non_iram_int_mask[i] = UINT32_MAX; + } + /* Indicate that no interrupt sources are assigned to CPU interrupts */ for (int i = 0; i < NR_IRQS; i++) @@ -584,3 +606,77 @@ irqstate_t up_irq_enable(void) flags = READ_AND_SET_CSR(mstatus, MSTATUS_MIE); return flags; } + +/**************************************************************************** + * Name: esp_intr_noniram_disable + * + * Description: + * Disable interrupts that aren't specifically marked as running from IRAM. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void IRAM_ATTR esp_intr_noniram_disable(void) +{ + uint32_t oldint; + irqstate_t irqstate; + uint32_t cpu; + uint32_t non_iram_ints; + + irqstate = enter_critical_section(); + cpu = esp_cpu_get_core_id(); + non_iram_ints = non_iram_int_mask[cpu]; + + if (non_iram_int_disabled_flag[cpu]) + { + abort(); + } + + non_iram_int_disabled_flag[cpu] = true; + oldint = esp_cpu_intr_get_enabled_mask(); + esp_cpu_intr_disable(non_iram_ints); + + /* Save disabled ints */ + + non_iram_int_disabled[cpu] = oldint & non_iram_ints; + leave_critical_section(irqstate); +} + +/**************************************************************************** + * Name: esp_intr_noniram_enable + * + * Description: + * Enable interrupts that aren't specifically marked as running from IRAM. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void IRAM_ATTR esp_intr_noniram_enable(void) +{ + irqstate_t irqstate; + uint32_t cpu; + int non_iram_ints; + + irqstate = enter_critical_section(); + cpu = esp_cpu_get_core_id(); + non_iram_ints = non_iram_int_disabled[cpu]; + + if (!non_iram_int_disabled_flag[cpu]) + { + abort(); + } + + non_iram_int_disabled_flag[cpu] = false; + esp_cpu_intr_enable(non_iram_ints); + leave_critical_section(irqstate); +} diff --git a/arch/risc-v/src/common/espressif/esp_irq.h b/arch/risc-v/src/common/espressif/esp_irq.h index 7a4391a486..9eb0692d7d 100644 --- a/arch/risc-v/src/common/espressif/esp_irq.h +++ b/arch/risc-v/src/common/espressif/esp_irq.h @@ -142,6 +142,38 @@ int esp_setup_irq(int source, irq_priority_t priority, irq_trigger_t type); void esp_teardown_irq(int source, int cpuint); +/**************************************************************************** + * Name: esp_intr_noniram_disable + * + * Description: + * Disable interrupts that aren't specifically marked as running from IRAM. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_intr_noniram_disable(void); + +/**************************************************************************** + * Name: esp_intr_noniram_enable + * + * Description: + * Enable interrupts that aren't specifically marked as running from IRAM. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_intr_noniram_enable(void); + #undef EXTERN #if defined(__cplusplus) } diff --git a/arch/risc-v/src/common/espressif/esp_spiflash.c b/arch/risc-v/src/common/espressif/esp_spiflash.c new file mode 100644 index 0000000000..c6329f4e4a --- /dev/null +++ b/arch/risc-v/src/common/espressif/esp_spiflash.c @@ -0,0 +1,594 @@ +/**************************************************************************** + * arch/risc-v/src/common/espressif/esp_spiflash.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 + +#include +#include +#include +#include +#include +#include +#include +#include "riscv_internal.h" +#include "riscv/rv_utils.h" + +#include +#include +#include "esp_spiflash.h" +#include "esp_attr.h" +#include "memspi_host_driver.h" +#include "spi_flash_defs.h" +#include "hal/spimem_flash_ll.h" +#include "hal/spi_flash_ll.h" +#include "esp_rom_spiflash.h" +#include "esp_irq.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* SPI buffer size */ + +# define SPI_BUFFER_WORDS (16) +# define SPI_BUFFER_BYTES (SPI_BUFFER_WORDS * 4) + +/* SPI flash hardware definition */ + +# define FLASH_SECTOR_SIZE (4096) + +/* SPI flash SR1 bits */ + +# define FLASH_SR1_BUSY ESP_ROM_SPIFLASH_BUSY_FLAG +# define FLASH_SR1_WREN ESP_ROM_SPIFLASH_WRENABLE_FLAG + +/* SPI flash operation */ + +# define FLASH_CMD_WRDI CMD_WRDI +# define FLASH_CMD_WREN CMD_WREN +# define FLASH_CMD_RDSR CMD_RDSR +#ifdef CONFIG_ESPRESSIF_SPI_FLASH_USE_32BIT_ADDRESS +# define ADDR_BITS(addr) (((addr) & 0xff000000) ? 32 : 24) +# define READ_CMD(addr) (ADDR_BITS(addr) == 32 ? \ + CMD_FASTRD_4B : CMD_FASTRD) +# define WRITE_CMD(addr) (ADDR_BITS(addr) == 32 ? CMD_PROGRAM_PAGE_4B : \ + CMD_PROGRAM_PAGE) +# define ERASE_CMD(addr) (ADDR_BITS(addr) == 32 ? CMD_SECTOR_ERASE_4B : \ + CMD_SECTOR_ERASE) +# define READ_DUMMY(addr) (8) +#else +# define ADDR_BITS(addr) (24) +# define READ_CMD(addr) CMD_FASTRD +# define WRITE_CMD(addr) CMD_PROGRAM_PAGE +# define ERASE_CMD(addr) CMD_SECTOR_ERASE +# define READ_DUMMY(addr) (8) +#endif + +# define SEND_CMD8_TO_FLASH(cmd) \ + esp_spi_trans((cmd), 8, \ + 0, 0, \ + NULL, 0, \ + NULL, 0, \ + 0) + +# define READ_SR1_FROM_FLASH(cmd, status) \ + esp_spi_trans((cmd), 8, \ + 0, 0, \ + NULL, 0, \ + (status), 1, \ + 0) + +# define ERASE_FLASH_SECTOR(addr) \ + esp_spi_trans(ERASE_CMD(addr), 8, \ + (addr), ADDR_BITS(addr), \ + NULL, 0, \ + NULL, 0, \ + 0) + +# define WRITE_DATA_TO_FLASH(addr, buffer, size) \ + esp_spi_trans(WRITE_CMD(addr), 8, \ + (addr), ADDR_BITS(addr), \ + buffer, size, \ + NULL, 0, \ + 0) + +# define READ_DATA_FROM_FLASH(addr, buffer, size) \ + esp_spi_trans(READ_CMD(addr), 8, \ + (addr), ADDR_BITS(addr), \ + NULL, 0, \ + buffer, size, \ + READ_DUMMY(addr)) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +spi_mem_dev_t *dev; + +/**************************************************************************** + * Private Functions Declaration + ****************************************************************************/ + +static void spiflash_start(void); +static void spiflash_end(void); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct spiflash_guard_funcs g_spi_flash_guard_funcs = +{ + .start = spiflash_start, + .end = spiflash_end, + .op_lock = NULL, + .op_unlock = NULL, + .address_is_safe = NULL, + .yield = NULL, +}; + +static mutex_t s_flash_op_mutex; +static uint32_t s_flash_op_cache_state[CONFIG_ESPRESSIF_NUM_CPUS]; +static volatile bool s_sched_suspended[CONFIG_ESPRESSIF_NUM_CPUS]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: spiflash_opstart + * + * Description: + * Prepare for an SPIFLASH operation. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static IRAM_ATTR void spiflash_start(void) +{ + extern uint32_t cache_suspend_icache(void); + int cpu; + irqstate_t flags; + uint32_t regval; + + nxmutex_lock(&s_flash_op_mutex); + flags = enter_critical_section(); + cpu = up_cpu_index(); + s_sched_suspended[cpu] = true; + + esp_intr_noniram_disable(); + + s_flash_op_cache_state[cpu] = cache_suspend_icache() << 16; + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: spiflash_opdone + * + * Description: + * Undo all the steps of opstart. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static IRAM_ATTR void spiflash_end(void) +{ + extern void cache_resume_icache(uint32_t); + int cpu; + irqstate_t flags; + + flags = enter_critical_section(); + + cpu = up_cpu_index(); + cache_resume_icache(s_flash_op_cache_state[cpu] >> 16); + + esp_intr_noniram_enable(); + s_sched_suspended[cpu] = false; + + leave_critical_section(flags); + nxmutex_unlock(&s_flash_op_mutex); +} + +/**************************************************************************** + * Name: esp_spi_trans + * + * Description: + * Transmit given command, address and data. + * + * Input Parameters: + * command - command value + * command_bits - command bits + * address - address value + * address_bits - address bits + * tx_buffer - write buffer + * tx_bytes - write buffer size + * rx_buffer - read buffer + * rx_bytes - read buffer size + * dummy_bits - dummy bits + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +static IRAM_ATTR void esp_spi_trans(uint32_t command, + uint32_t command_bits, + uint32_t address, + uint32_t address_bits, + uint32_t *tx_buffer, + uint32_t tx_bytes, + uint32_t *rx_buffer, + uint32_t rx_bytes, + uint32_t dummy_bits) +{ + /* Initiliaze SPI user register */ + + spi_flash_ll_reset(dev); + + while (!spi_flash_ll_host_idle(dev)); + + /* Set command bits and value, and command is always needed */ + + spi_flash_ll_set_command(dev, command, command_bits); + + /* Set address bits and value */ + + if (address_bits) + { + spi_flash_ll_set_addr_bitlen(dev, address_bits); + spi_flash_ll_set_address(dev, address); + } + + /* Set dummy */ + + if (dummy_bits) + { + spi_flash_ll_set_dummy(dev, dummy_bits); + } + + /* Set TX data */ + + if (tx_bytes) + { + spi_flash_ll_set_mosi_bitlen(dev, tx_bytes * 8); + spi_flash_ll_set_buffer_data(dev, tx_buffer, tx_bytes); + } + + /* Set RX data */ + + if (rx_bytes) + { + spi_flash_ll_set_miso_bitlen(dev, rx_bytes * 8); + } + + /* Set I/O mode */ + + spi_flash_ll_set_read_mode(dev, SPI_FLASH_FASTRD); + + /* Set clock and delay */ + + spimem_flash_ll_suspend_cmd_setup(dev, 0); + + /* Start transmision */ + + spi_flash_ll_user_start(dev); + + /* Wait until transmission is done */ + + while (!spi_flash_ll_cmd_is_done(dev)); + + /* Get read data */ + + if (rx_bytes) + { + spi_flash_ll_get_buffer_data(dev, rx_buffer, rx_bytes); + } +} + +/**************************************************************************** + * Name: wait_flash_idle + * + * Description: + * Wait until flash enters idle state + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static IRAM_ATTR void wait_flash_idle(void) +{ + while (!spi_flash_ll_host_idle(dev)); +} + +/**************************************************************************** + * Name: enable_flash_write + * + * Description: + * Enable Flash write mode + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static IRAM_ATTR void enable_flash_write(void) +{ + uint32_t status; + + do + { + SEND_CMD8_TO_FLASH(FLASH_CMD_WREN); + READ_SR1_FROM_FLASH(FLASH_CMD_RDSR, &status); + + if ((status & FLASH_SR1_WREN) != 0) + { + break; + } + } + while (1); +} + +/**************************************************************************** + * Name: disable_flash_write + * + * Description: + * Disable Flash write mode + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static IRAM_ATTR void disable_flash_write(void) +{ + uint32_t status; + + do + { + SEND_CMD8_TO_FLASH(FLASH_CMD_WRDI); + READ_SR1_FROM_FLASH(FLASH_CMD_RDSR, &status); + + if ((status & FLASH_SR1_WREN) == 0) + { + break; + } + } + while (1); +} + +/**************************************************************************** + * Name: spi_flash_read + * + * Description: + * Read data from Flash. + * + * Parameters: + * address - source address of the data in Flash. + * buffer - pointer to the destination buffer + * length - length of data + * + * Returned Values: + * Zero (OK) is returned or a negative error. + * + ****************************************************************************/ + +IRAM_ATTR int spi_flash_read(uint32_t address, void *buffer, uint32_t length) +{ + int ret = OK; + uint8_t *rx_buf = (uint8_t *)buffer; + uint32_t rx_bytes = length; + uint32_t rx_addr = address; + + spiflash_start(); + + for (uint32_t i = 0; i < length; i += SPI_BUFFER_BYTES) + { + uint32_t spi_buffer[SPI_BUFFER_WORDS]; + uint32_t n = MIN(rx_bytes, SPI_BUFFER_BYTES); + + READ_DATA_FROM_FLASH(rx_addr, spi_buffer, n); + + memcpy(rx_buf, spi_buffer, n); + rx_bytes -= n; + rx_buf += n; + rx_addr += n; + } + + spiflash_end(); + + return ret; +} + +/**************************************************************************** + * 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. + * + ****************************************************************************/ + +IRAM_ATTR int spi_flash_erase_sector(uint32_t sector) +{ + int ret = OK; + uint32_t addr = sector * FLASH_SECTOR_SIZE; + + spiflash_start(); + + wait_flash_idle(); + enable_flash_write(); + + ERASE_FLASH_SECTOR(addr); + + wait_flash_idle(); + disable_flash_write(); + + spiflash_end(); + + return ret; +} + +/**************************************************************************** + * 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. + * + ****************************************************************************/ + +IRAM_ATTR int spi_flash_erase_range(uint32_t start_address, uint32_t size) +{ + int ret = OK; + uint32_t addr = start_address; + + spiflash_start(); + + for (uint32_t i = 0; i < size; i += FLASH_SECTOR_SIZE) + { + wait_flash_idle(); + enable_flash_write(); + + ERASE_FLASH_SECTOR(addr); + addr += FLASH_SECTOR_SIZE; + } + + wait_flash_idle(); + disable_flash_write(); + + spiflash_end(); + + return ret; +} + +/**************************************************************************** + * Name: spi_flash_write + * + * Description: + * Write data to Flash. + * + * Parameters: + * dest_addr - Destination address in Flash. + * buffer - Pointer to the source buffer. + * size - Length of data, in bytes. + * + * Returned Values: + * Zero (OK) is returned or a negative error. + * + ****************************************************************************/ + +IRAM_ATTR int spi_flash_write(uint32_t dest_addr, + const void *buffer, + uint32_t size) +{ + int ret = OK; + const uint8_t *tx_buf = (const uint8_t *)buffer; + uint32_t tx_bytes = size; + uint32_t tx_addr = dest_addr; + + spiflash_start(); + + for (int i = 0; i < size; i += SPI_BUFFER_BYTES) + { + uint32_t spi_buffer[SPI_BUFFER_WORDS]; + uint32_t n = MIN(tx_bytes, SPI_BUFFER_BYTES); + + memcpy(spi_buffer, tx_buf, n); + + wait_flash_idle(); + enable_flash_write(); + + WRITE_DATA_TO_FLASH(tx_addr, spi_buffer, n); + + tx_bytes -= n; + tx_buf += n; + tx_addr += n; + } + + wait_flash_idle(); + disable_flash_write(); + + spiflash_end(); + + return ret; +} + +/**************************************************************************** + * Name: esp_spiflash_init + * + * Description: + * Initialize ESP SPI flash driver. + * + * Input Parameters: + * None. + * + * Returned Value: + * OK if success or a negative value if fail. + * + ****************************************************************************/ + +int esp_spiflash_init(void) +{ + extern void spi_flash_guard_set(const struct spiflash_guard_funcs *); + + nxmutex_init(&s_flash_op_mutex); + + spi_flash_guard_set(&g_spi_flash_guard_funcs); + dev = spimem_flash_ll_get_hw(SPI1_HOST); + + return OK; +} diff --git a/arch/risc-v/src/common/espressif/esp_spiflash.h b/arch/risc-v/src/common/espressif/esp_spiflash.h new file mode 100644 index 0000000000..0aedef7f51 --- /dev/null +++ b/arch/risc-v/src/common/espressif/esp_spiflash.h @@ -0,0 +1,188 @@ +/**************************************************************************** + * arch/risc-v/src/common/espressif/esp_spiflash.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_COMMON_ESPRESSIF_ESP_SPIFLASH_H +#define __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_SPIFLASH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/** + * 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 (spi_flash_write, spi_flash_read, + * spi_flash_erase_sector and spi_flash_erase_range): + * - '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". + * - '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". + * 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. + * + * 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 + ****************************************************************************/ + +/**************************************************************************** + * Name: spi_flash_read + * + * Description: + * Read data from Flash. + * + * Parameters: + * address - source address of the data in Flash. + * buffer - pointer to the destination buffer + * length - length of data + * + * Returned Values: + * Zero (OK) is returned or a negative error. + * + ****************************************************************************/ + +int spi_flash_read(uint32_t address, void *buffer, uint32_t length); + +/**************************************************************************** + * 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_write + * + * Description: + * Write data to Flash. + * + * 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 *buffer, uint32_t size); + +/**************************************************************************** + * Name: esp_spiflash_init + * + * Description: + * Initialize ESP SPI flash driver. + * + * Input Parameters: + * None. + * + * Returned Value: + * OK if success or a negative value if fail. + * + ****************************************************************************/ + +int esp_spiflash_init(void); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_SPIFLASH_H */ diff --git a/arch/risc-v/src/common/espressif/esp_spiflash_mtd.c b/arch/risc-v/src/common/espressif/esp_spiflash_mtd.c new file mode 100644 index 0000000000..bd033bc30f --- /dev/null +++ b/arch/risc-v/src/common/espressif/esp_spiflash_mtd.c @@ -0,0 +1,540 @@ +/**************************************************************************** + * arch/risc-v/src/common/espressif/esp_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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "esp_attr.h" +#include "esp_spiflash.h" +#include "esp_rom_spiflash.h" +#include "esp_rom_spiflash_defs.h" +#include "esp_spiflash_mtd.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MTD_BLK_SIZE CONFIG_ESPRESSIF_SPIFLASH_MTD_BLKSIZE +#define MTD_ERASE_SIZE 4096 +#define MTD_ERASED_STATE (0xff) + +#define MTD2PRIV(_dev) ((struct esp_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 + ****************************************************************************/ + +/* ESP SPI Flash device private data */ + +struct esp_mtd_dev_s +{ + struct mtd_dev_s mtd; + + /* SPI Flash data */ + + const esp_rom_spiflash_legacy_data_t **data; +}; + +/**************************************************************************** + * Private Functions Prototypes + ****************************************************************************/ + +/* MTD driver methods */ + +static int esp_erase(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks); +static ssize_t esp_read(struct mtd_dev_s *dev, off_t offset, + size_t nbytes, uint8_t *buffer); +static ssize_t esp_bread(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, uint8_t *buffer); +static ssize_t esp_write(struct mtd_dev_s *dev, off_t offset, + size_t nbytes, const uint8_t *buffer); +static ssize_t esp_bwrite(struct mtd_dev_s *dev, off_t startblock, + size_t nblocks, const uint8_t *buffer); +static int esp_ioctl(struct mtd_dev_s *dev, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct esp_mtd_dev_s g_esp_spiflash = +{ + .mtd = + { + .erase = esp_erase, + .bread = esp_bread, + .bwrite = esp_bwrite, + .read = esp_read, + .ioctl = esp_ioctl, +#ifdef CONFIG_MTD_BYTE_WRITE + .write = esp_write, +#endif + .name = "esp_spiflash" + }, + .data = (const esp_rom_spiflash_legacy_data_t **)&rom_spiflash_legacy_data, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_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 esp_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 esp_mtd_dev_s *priv = (struct esp_mtd_dev_s *)dev; + irqstate_t flags; + + if ((offset > MTD_SIZE(priv)) || ((offset + nbytes) > MTD_SIZE(priv))) + { + return -EINVAL; + } + +#ifdef CONFIG_ESPRESSIF_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 + + flags = enter_critical_section(); + ret = spi_flash_erase_range(offset, nbytes); + leave_critical_section(flags); + + if (ret == OK) + { + ret = nblocks; + } + else + { +#ifdef CONFIG_ESPRESSIF_STORAGE_MTD_DEBUG + finfo("Failed to erase the flash range!\n"); +#endif + ret = -1; + } + +#ifdef CONFIG_ESPRESSIF_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + +/**************************************************************************** + * Name: esp_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 esp_read(struct mtd_dev_s *dev, off_t offset, + size_t nbytes, uint8_t *buffer) +{ + ssize_t ret; + irqstate_t flags; + +#ifdef CONFIG_ESPRESSIF_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 + + flags = enter_critical_section(); + ret = spi_flash_read(offset, (uint32_t *)buffer, nbytes); + leave_critical_section(flags); + + if (ret == OK) + { + ret = nbytes; + } + +#ifdef CONFIG_ESPRESSIF_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + +/**************************************************************************** + * Name: esp_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 esp_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; + irqstate_t flags; + +#ifdef CONFIG_ESPRESSIF_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 + + flags = enter_critical_section(); + ret = spi_flash_read(addr, (uint32_t *)buffer, size); + leave_critical_section(flags); + + if (ret == OK) + { + ret = nblocks; + } + +#ifdef CONFIG_ESPRESSIF_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + +/**************************************************************************** + * Name: esp_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 esp_write(struct mtd_dev_s *dev, off_t offset, + size_t nbytes, const uint8_t *buffer) +{ + ssize_t ret; + struct esp_mtd_dev_s *priv = (struct esp_mtd_dev_s *)dev; + irqstate_t flags; + + ASSERT(buffer); + + if ((offset > MTD_SIZE(priv)) || ((offset + nbytes) > MTD_SIZE(priv))) + { + return -EINVAL; + } + +#ifdef CONFIG_ESPRESSIF_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 + + flags = enter_critical_section(); + ret = spi_flash_write(offset, (uint32_t *)buffer, nbytes); + leave_critical_section(flags); + + if (ret == OK) + { + ret = nbytes; + } + +#ifdef CONFIG_ESPRESSIF_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + +/**************************************************************************** + * Name: esp_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 esp_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; + irqstate_t flags; + +#ifdef CONFIG_ESPRESSIF_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 + + flags = enter_critical_section(); + ret = spi_flash_write(addr, (uint32_t *)buffer, size); + leave_critical_section(flags); + + if (ret == OK) + { + ret = nblocks; + } + +#ifdef CONFIG_ESPRESSIF_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + +/**************************************************************************** + * Name: esp_ioctl + * + * Description: + * Set/Get option to/from ESP SPI Flash MTD device data. + * + * Input Parameters: + * dev - ESP MTD device data + * cmd - operation command + * arg - operation argument + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +static int esp_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 esp_mtd_dev_s *priv = (struct esp_mtd_dev_s *)dev; + struct mtd_geometry_s *geo = (struct mtd_geometry_s *)arg; + if (geo) + { + memset(geo, 0, sizeof(*geo)); + + geo->blocksize = MTD_BLK_SIZE; + geo->erasesize = MTD_ERASE_SIZE; + geo->neraseblocks = MTD_SIZE(priv) / MTD_ERASE_SIZE; + ret = OK; + + finfo("blocksize: %" PRId32 " erasesize: %" PRId32 \ + " neraseblocks: %" PRId32 "\n", + geo->blocksize, geo->erasesize, geo->neraseblocks); + } + } + break; + + case BIOC_PARTINFO: + { + struct esp_mtd_dev_s *priv = (struct esp_mtd_dev_s *)dev; + struct partition_info_s *info = (struct partition_info_s *)arg; + if (info != NULL) + { + info->numsectors = MTD_SIZE(priv) / 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: esp_spiflash_alloc_mtdpart + * + * Description: + * Allocate an MTD partition from the ESP 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: + * ESP SPI Flash MTD data pointer if success or NULL if fail. + * + ****************************************************************************/ + +struct mtd_dev_s *esp_spiflash_alloc_mtdpart(uint32_t mtd_offset, + uint32_t mtd_size) +{ + const struct esp_mtd_dev_s *priv; + const esp_rom_spiflash_chip_t *chip; + struct mtd_dev_s *mtd_part; + uint32_t blocks; + uint32_t startblock; + uint32_t size; + + priv = &g_esp_spiflash; + + chip = &(*priv->data)->chip; + + finfo("ESP 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); + + ASSERT((mtd_offset + mtd_size) <= chip->chip_size); + ASSERT((mtd_offset % chip->sector_size) == 0); + ASSERT((mtd_size % chip->sector_size) == 0); + + 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((struct mtd_dev_s *)&priv->mtd, startblock, + blocks); + if (!mtd_part) + { + ferr("ERROR: Failed to create MTD partition\n"); + return NULL; + } + + return mtd_part; +} + +/**************************************************************************** + * Name: esp_spiflash_mtd + * + * Description: + * Get SPI Flash MTD. + * + * Input Parameters: + * None + * + * Returned Value: + * ESP SPI Flash MTD pointer. + * + ****************************************************************************/ + +struct mtd_dev_s *esp_spiflash_mtd(void) +{ + struct esp_mtd_dev_s *priv = + (struct esp_mtd_dev_s *)&g_esp_spiflash; + + return &priv->mtd; +} diff --git a/arch/risc-v/src/common/espressif/esp_spiflash_mtd.h b/arch/risc-v/src/common/espressif/esp_spiflash_mtd.h new file mode 100644 index 0000000000..83946835d5 --- /dev/null +++ b/arch/risc-v/src/common/espressif/esp_spiflash_mtd.h @@ -0,0 +1,89 @@ +/**************************************************************************** + * arch/risc-v/src/common/espressif/esp_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_COMMON_ESPRESSIF_ESP_SPIFLASH_MTD_H +#define __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_SPIFLASH_MTD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_spiflash_mtd + * + * Description: + * Get SPI Flash MTD. + * + * Input Parameters: + * None + * + * Returned Value: + * SPI Flash MTD pointer. + * + ****************************************************************************/ + +struct mtd_dev_s *esp_spiflash_mtd(void); + +/**************************************************************************** + * Name: esp_spiflash_alloc_mtdpart + * + * Description: + * Allocate an MTD partition from the 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 *esp_spiflash_alloc_mtdpart(uint32_t mtd_offset, + uint32_t mtd_size); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_SPIFLASH_MTD_H */ diff --git a/arch/risc-v/src/esp32c3/hal_esp32c3.mk b/arch/risc-v/src/esp32c3/hal_esp32c3.mk index 982bd28c59..62b6cf6668 100644 --- a/arch/risc-v/src/esp32c3/hal_esp32c3.mk +++ b/arch/risc-v/src/esp32c3/hal_esp32c3.mk @@ -49,6 +49,8 @@ INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/compone INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/riscv/include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/soc/include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/soc/$(CHIP_SERIES)/include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/spi_flash/include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/spi_flash/include/spi_flash ifeq ($(CONFIG_ESPRESSIF_SIMPLE_BOOT),y) INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/bootloader_support/include diff --git a/arch/risc-v/src/esp32c6/hal_esp32c6.mk b/arch/risc-v/src/esp32c6/hal_esp32c6.mk index 065bf55ea4..0752da95b2 100644 --- a/arch/risc-v/src/esp32c6/hal_esp32c6.mk +++ b/arch/risc-v/src/esp32c6/hal_esp32c6.mk @@ -49,6 +49,8 @@ INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/compone INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/riscv/include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/soc/include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/soc/$(CHIP_SERIES)/include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/spi_flash/include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/spi_flash/include/spi_flash # Linker scripts diff --git a/arch/risc-v/src/esp32h2/hal_esp32h2.mk b/arch/risc-v/src/esp32h2/hal_esp32h2.mk index 78ecfb79f2..6bf2177bac 100644 --- a/arch/risc-v/src/esp32h2/hal_esp32h2.mk +++ b/arch/risc-v/src/esp32h2/hal_esp32h2.mk @@ -49,6 +49,8 @@ INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/compone INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/riscv/include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/soc/include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/soc/$(CHIP_SERIES)/include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/spi_flash/include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)/chip/$(ESP_HAL_3RDPARTY_REPO)/components/spi_flash/include/spi_flash # Linker scripts diff --git a/boards/risc-v/esp32c3/common/Kconfig b/boards/risc-v/esp32c3/common/Kconfig index f2a26a919c..711e47f2d5 100644 --- a/boards/risc-v/esp32c3/common/Kconfig +++ b/boards/risc-v/esp32c3/common/Kconfig @@ -11,3 +11,40 @@ config ESPRESSIF_MERGE_BINS device. This is only useful when the path to binary files (e.g. bootloader) is provided via the ESPTOOL_BINDIR variable. + +choice ESPRESSIF_SPIFLASH_FS + prompt "Mount SPI Flash MTD on bring-up" + default ESPRESSIF_SPIFLASH_SMARTFS + depends on ESPRESSIF_MTD + optional + ---help--- + Mount the SPI Flash MTD with the selected File System format on board + bring-up. + If not selected, the MTD will be registered as a device node on /dev. + +config ESPRESSIF_SPIFLASH_SMARTFS + bool "SmartFS" + select FS_SMARTFS + select MTD_SMART + +config ESPRESSIF_SPIFLASH_NXFFS + bool "NXFFS" + select FS_NXFFS + +config ESPRESSIF_SPIFLASH_SPIFFS + bool "SPIFFS" + select FS_SPIFFS + +config ESPRESSIF_SPIFLASH_LITTLEFS + bool "LittleFS" + select FS_LITTLEFS + +config ESPRESSIF_SPIFLASH_MTD_CONFIG + bool "Non-volatile storage" + +endchoice # ESPRESSIF_SPIFLASH_FS + +config ESPRESSIF_SPIFLASH_FS_MOUNT_PT + string "File-system Mount Point" + depends on ESPRESSIF_SPIFLASH_LITTLEFS + default "/data" diff --git a/boards/risc-v/esp32c3/common/include/esp_board_spiflash.h b/boards/risc-v/esp32c3/common/include/esp_board_spiflash.h new file mode 100644 index 0000000000..9e647a384e --- /dev/null +++ b/boards/risc-v/esp32c3/common/include/esp_board_spiflash.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * boards/risc-v/esp32c3/common/include/esp_board_spiflash.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 __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_SPIFLASH_H +#define __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_SPIFLASH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: board_spiflash_init + * + * Description: + * Initialize the SPIFLASH and register the MTD device. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ESPRESSIF_SPIFLASH +int board_spiflash_init(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_SPIFLASH_H */ diff --git a/boards/risc-v/esp32c3/common/src/Make.defs b/boards/risc-v/esp32c3/common/src/Make.defs index adb8a5c594..1aefd6c61f 100644 --- a/boards/risc-v/esp32c3/common/src/Make.defs +++ b/boards/risc-v/esp32c3/common/src/Make.defs @@ -28,6 +28,10 @@ ifeq ($(CONFIG_ESP_RMT),y) CSRCS += esp_board_rmt.c endif +ifeq ($(CONFIG_ESPRESSIF_SPIFLASH),y) + CSRCS += esp_board_spiflash.c +endif + DEPPATH += --dep-path src VPATH += :src CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src diff --git a/boards/risc-v/esp32c3/common/src/esp_board_spiflash.c b/boards/risc-v/esp32c3/common/src/esp_board_spiflash.c new file mode 100644 index 0000000000..7e1c40ccb7 --- /dev/null +++ b/boards/risc-v/esp32c3/common/src/esp_board_spiflash.c @@ -0,0 +1,417 @@ +/**************************************************************************** + * boards/risc-v/esp32c3/common/src/esp_board_spiflash.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 + +#include + +#include "inttypes.h" +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#ifdef CONFIG_BCH +#include +#endif + +#include "espressif/esp_spiflash.h" +#include "espressif/esp_spiflash_mtd.h" + +#include "esp_board_spiflash.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: setup_smartfs + * + * Description: + * Provide a block driver wrapper around MTD partition and mount a + * SMART FS over it. + * + * Parameters: + * smartn - Number used to register the mtd partition: /dev/smartx, where + * x = smartn. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_SMARTFS) +static int setup_smartfs(int smartn, struct mtd_dev_s *mtd, + const char *mnt_pt) +{ + int ret = OK; + char path[22]; + + ret = smart_initialize(smartn, mtd, NULL); + if (ret < 0) + { + syslog(LOG_INFO, "smart_initialize failed, " + "Trying to erase first...\n"); + ret = mtd->ioctl(mtd, MTDIOC_BULKERASE, 0); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: ioctl(BULKERASE) failed: %d\n", ret); + return ret; + } + + syslog(LOG_INFO, "Erase successful, initializing it again.\n"); + ret = smart_initialize(smartn, mtd, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: smart_initialize failed: %d\n", ret); + return ret; + } + } + + if (mnt_pt != NULL) + { + snprintf(path, sizeof(path), "/dev/smart%d", smartn); + + ret = nx_mount(path, mnt_pt, "smartfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", ret); + if (ret == -ENODEV) + { + syslog(LOG_WARNING, "Smartfs seems unformatted. " + "Did you run 'mksmartfs /dev/smart%d'?\n", smartn); + } + + return ret; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: setup_littlefs + * + * Description: + * Register a mtd driver and mount a Little FS over it. + * + * Parameters: + * path - Path name used to register the mtd driver. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * priv - Privileges + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_LITTLEFS) +static int setup_littlefs(const char *path, struct mtd_dev_s *mtd, + const char *mnt_pt, int priv) +{ + int ret = OK; + + ret = register_mtddriver(path, mtd, priv, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ERROR; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(path, mnt_pt, "littlefs", 0, NULL); + if (ret < 0) + { + ret = nx_mount(path, mnt_pt, "littlefs", 0, "forceformat"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", + ret); + return ret; + } + } + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: setup_spiffs + * + * Description: + * Register a mtd driver and mount a SPIFFS over it. + * + * Parameters: + * path - Path name used to register the mtd driver. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * priv - Privileges + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_SPIFFS) +static int setup_spiffs(const char *path, struct mtd_dev_s *mtd, + const char *mnt_pt, int priv) +{ + int ret = OK; + + ret = register_mtddriver(path, mtd, priv, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ERROR; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(path, mnt_pt, "spiffs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", ret); + return ret; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: setup_nxffs + * + * Description: + * Register a mtd driver and mount a NXFFS over it. + * + * Parameters: + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_NXFFS) +static int setup_nxffs(struct mtd_dev_s *mtd, const char *mnt_pt) +{ + int ret = OK; + + ret = nxffs_initialize(mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: NXFFS init failed: %d\n", ret); + return ret; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(NULL, mnt_pt, "nxffs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", ret); + return ret; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: init_storage_partition + * + * Description: + * Initialize partition that is dedicated to general use. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int init_storage_partition(void) +{ + int ret = OK; + struct mtd_dev_s *mtd; + + mtd = esp_spiflash_alloc_mtdpart(CONFIG_ESPRESSIF_STORAGE_MTD_OFFSET, + CONFIG_ESPRESSIF_STORAGE_MTD_SIZE); + if (!mtd) + { + syslog(LOG_ERR, "ERROR: Failed to alloc MTD partition of SPI Flash\n"); + return ERROR; + } + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_SMARTFS) + + ret = setup_smartfs(0, mtd, "/data"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup smartfs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_NXFFS) + + ret = setup_nxffs(mtd, "/data"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup nxffs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_LITTLEFS) + + const char *path = "/dev/espflash"; + ret = setup_littlefs(path, mtd, "/data", 0755); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup littlefs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_SPIFFS) + + const char *path = "/dev/espflash"; + ret = setup_spiffs(path, mtd, "/data", 0755); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup spiffs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_MTD_CONFIG) + +# if defined (CONFIG_TESTING_MTD_CONFIG_FAIL_SAFE) + + /* To test power-loss resilient kv system, + * we write possible power-loss flash layout into flash + * then start kv system to see if it recovers. + * To do so, we need a mtd driver so that test code can + * write into flash. + */ + + const char *path = CONFIG_TESTING_MTD_CONFIG_FAIL_SAFE_MOUNTPT_NAME; + ret = register_mtddriver(path, mtd, 0777, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ret; + } + +# else + + ret = mtdconfig_register(mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup mtd config\n"); + return ret; + } + +# endif + +#else + + ret = register_mtddriver("/dev/espflash", mtd, 0755, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ret; + } + +#endif + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_spiflash_init + * + * Description: + * Initialize the SPI Flash and register the MTD device. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_spiflash_init(void) +{ + int ret = OK; + + esp_spiflash_init(); + + ret = init_storage_partition(); + if (ret < 0) + { + return ret; + } + + return ret; +} + diff --git a/boards/risc-v/esp32c3/esp32c3-generic/configs/spiflash/defconfig b/boards/risc-v/esp32c3/esp32c3-generic/configs/spiflash/defconfig new file mode 100644 index 0000000000..ee0a9f7a69 --- /dev/null +++ b/boards/risc-v/esp32c3/esp32c3-generic/configs/spiflash/defconfig @@ -0,0 +1,54 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32c3-generic" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32C3_GENERIC=y +CONFIG_ARCH_CHIP="esp32c3" +CONFIG_ARCH_CHIP_ESP32C3_GENERIC=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_ESPRESSIF_SPIFLASH=y +CONFIG_ESPRESSIF_SPIFLASH_SMARTFS=y +CONFIG_ESPRESSIF_STORAGE_MTD_OFFSET=0x110000 +CONFIG_ESPRESSIF_STORAGE_MTD_SIZE=0xf0000 +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NAME_MAX=48 +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_LOSMART=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_SMARTFS_MAXNAMLEN=48 +CONFIG_START_DAY=29 +CONFIG_START_MONTH=11 +CONFIG_START_YEAR=2019 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_FLASH_ERASEALL=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_FSTEST=y +CONFIG_TESTING_FSTEST_MOUNTPT="/mnt" +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c index 04f8cab22b..ba55f458b5 100644 --- a/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c +++ b/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c @@ -35,6 +35,7 @@ #include #include "esp_board_ledc.h" +#include "esp_board_spiflash.h" #ifdef CONFIG_WATCHDOG # include "espressif/esp_wdt.h" @@ -143,6 +144,14 @@ int esp_bringup(void) #endif #endif +#ifdef CONFIG_ESPRESSIF_SPIFLASH + ret = board_spiflash_init(); + if (ret) + { + syslog(LOG_ERR, "ERROR: Failed to initialize SPI Flash\n"); + } +#endif + #ifdef CONFIG_ONESHOT ret = esp_oneshot_initialize(); if (ret < 0) diff --git a/boards/risc-v/esp32c6/common/Kconfig b/boards/risc-v/esp32c6/common/Kconfig index f2a26a919c..711e47f2d5 100644 --- a/boards/risc-v/esp32c6/common/Kconfig +++ b/boards/risc-v/esp32c6/common/Kconfig @@ -11,3 +11,40 @@ config ESPRESSIF_MERGE_BINS device. This is only useful when the path to binary files (e.g. bootloader) is provided via the ESPTOOL_BINDIR variable. + +choice ESPRESSIF_SPIFLASH_FS + prompt "Mount SPI Flash MTD on bring-up" + default ESPRESSIF_SPIFLASH_SMARTFS + depends on ESPRESSIF_MTD + optional + ---help--- + Mount the SPI Flash MTD with the selected File System format on board + bring-up. + If not selected, the MTD will be registered as a device node on /dev. + +config ESPRESSIF_SPIFLASH_SMARTFS + bool "SmartFS" + select FS_SMARTFS + select MTD_SMART + +config ESPRESSIF_SPIFLASH_NXFFS + bool "NXFFS" + select FS_NXFFS + +config ESPRESSIF_SPIFLASH_SPIFFS + bool "SPIFFS" + select FS_SPIFFS + +config ESPRESSIF_SPIFLASH_LITTLEFS + bool "LittleFS" + select FS_LITTLEFS + +config ESPRESSIF_SPIFLASH_MTD_CONFIG + bool "Non-volatile storage" + +endchoice # ESPRESSIF_SPIFLASH_FS + +config ESPRESSIF_SPIFLASH_FS_MOUNT_PT + string "File-system Mount Point" + depends on ESPRESSIF_SPIFLASH_LITTLEFS + default "/data" diff --git a/boards/risc-v/esp32c6/common/include/esp_board_spiflash.h b/boards/risc-v/esp32c6/common/include/esp_board_spiflash.h new file mode 100644 index 0000000000..cf05e85b98 --- /dev/null +++ b/boards/risc-v/esp32c6/common/include/esp_board_spiflash.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * boards/risc-v/esp32c6/common/include/esp_board_spiflash.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 __BOARDS_RISCV_ESP32C6_COMMON_INCLUDE_ESP_BOARD_SPIFLASH_H +#define __BOARDS_RISCV_ESP32C6_COMMON_INCLUDE_ESP_BOARD_SPIFLASH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: board_spiflash_init + * + * Description: + * Initialize the SPIFLASH and register the MTD device. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ESPRESSIF_SPIFLASH +int board_spiflash_init(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_RISCV_ESP32C6_COMMON_INCLUDE_ESP_BOARD_SPIFLASH_H */ diff --git a/boards/risc-v/esp32c6/common/scripts/esp32c6_aliases.ld b/boards/risc-v/esp32c6/common/scripts/esp32c6_aliases.ld index 76606ad25f..467c87064a 100644 --- a/boards/risc-v/esp32c6/common/scripts/esp32c6_aliases.ld +++ b/boards/risc-v/esp32c6/common/scripts/esp32c6_aliases.ld @@ -18,6 +18,9 @@ * ****************************************************************************/ +cache_resume_icache = Cache_Resume_ICache; +cache_suspend_icache = Cache_Suspend_ICache; + #ifdef CONFIG_ESPRESSIF_BLE /* Lower-case aliases for BLE library symbols not compliant to nxstyle */ diff --git a/boards/risc-v/esp32c6/common/src/Make.defs b/boards/risc-v/esp32c6/common/src/Make.defs index bf8aa770e3..09b130c0cb 100644 --- a/boards/risc-v/esp32c6/common/src/Make.defs +++ b/boards/risc-v/esp32c6/common/src/Make.defs @@ -28,6 +28,10 @@ ifeq ($(CONFIG_ESP_RMT),y) CSRCS += esp_board_rmt.c endif +ifeq ($(CONFIG_ESPRESSIF_SPIFLASH),y) + CSRCS += esp_board_spiflash.c +endif + DEPPATH += --dep-path src VPATH += :src CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src diff --git a/boards/risc-v/esp32c6/common/src/esp_board_spiflash.c b/boards/risc-v/esp32c6/common/src/esp_board_spiflash.c new file mode 100644 index 0000000000..716d74fba5 --- /dev/null +++ b/boards/risc-v/esp32c6/common/src/esp_board_spiflash.c @@ -0,0 +1,417 @@ +/**************************************************************************** + * boards/risc-v/esp32c6/common/src/esp_board_spiflash.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 + +#include + +#include "inttypes.h" +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#ifdef CONFIG_BCH +#include +#endif + +#include "espressif/esp_spiflash.h" +#include "espressif/esp_spiflash_mtd.h" + +#include "esp_board_spiflash.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: setup_smartfs + * + * Description: + * Provide a block driver wrapper around MTD partition and mount a + * SMART FS over it. + * + * Parameters: + * smartn - Number used to register the mtd partition: /dev/smartx, where + * x = smartn. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_SMARTFS) +static int setup_smartfs(int smartn, struct mtd_dev_s *mtd, + const char *mnt_pt) +{ + int ret = OK; + char path[22]; + + ret = smart_initialize(smartn, mtd, NULL); + if (ret < 0) + { + syslog(LOG_INFO, "smart_initialize failed, " + "Trying to erase first...\n"); + ret = mtd->ioctl(mtd, MTDIOC_BULKERASE, 0); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: ioctl(BULKERASE) failed: %d\n", ret); + return ret; + } + + syslog(LOG_INFO, "Erase successful, initializing it again.\n"); + ret = smart_initialize(smartn, mtd, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: smart_initialize failed: %d\n", ret); + return ret; + } + } + + if (mnt_pt != NULL) + { + snprintf(path, sizeof(path), "/dev/smart%d", smartn); + + ret = nx_mount(path, mnt_pt, "smartfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", ret); + if (ret == -ENODEV) + { + syslog(LOG_WARNING, "Smartfs seems unformatted. " + "Did you run 'mksmartfs /dev/smart%d'?\n", smartn); + } + + return ret; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: setup_littlefs + * + * Description: + * Register a mtd driver and mount a Little FS over it. + * + * Parameters: + * path - Path name used to register the mtd driver. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * priv - Privileges + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_LITTLEFS) +static int setup_littlefs(const char *path, struct mtd_dev_s *mtd, + const char *mnt_pt, int priv) +{ + int ret = OK; + + ret = register_mtddriver(path, mtd, priv, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ERROR; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(path, mnt_pt, "littlefs", 0, NULL); + if (ret < 0) + { + ret = nx_mount(path, mnt_pt, "littlefs", 0, "forceformat"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", + ret); + return ret; + } + } + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: setup_spiffs + * + * Description: + * Register a mtd driver and mount a SPIFFS over it. + * + * Parameters: + * path - Path name used to register the mtd driver. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * priv - Privileges + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_SPIFFS) +static int setup_spiffs(const char *path, struct mtd_dev_s *mtd, + const char *mnt_pt, int priv) +{ + int ret = OK; + + ret = register_mtddriver(path, mtd, priv, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ERROR; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(path, mnt_pt, "spiffs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", ret); + return ret; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: setup_nxffs + * + * Description: + * Register a mtd driver and mount a NXFFS over it. + * + * Parameters: + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_NXFFS) +static int setup_nxffs(struct mtd_dev_s *mtd, const char *mnt_pt) +{ + int ret = OK; + + ret = nxffs_initialize(mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: NXFFS init failed: %d\n", ret); + return ret; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(NULL, mnt_pt, "nxffs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", ret); + return ret; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: init_storage_partition + * + * Description: + * Initialize partition that is dedicated to general use. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int init_storage_partition(void) +{ + int ret = OK; + struct mtd_dev_s *mtd; + + mtd = esp_spiflash_alloc_mtdpart(CONFIG_ESPRESSIF_STORAGE_MTD_OFFSET, + CONFIG_ESPRESSIF_STORAGE_MTD_SIZE); + if (!mtd) + { + syslog(LOG_ERR, "ERROR: Failed to alloc MTD partition of SPI Flash\n"); + return ERROR; + } + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_SMARTFS) + + ret = setup_smartfs(0, mtd, "/data"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup smartfs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_NXFFS) + + ret = setup_nxffs(mtd, "/data"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup nxffs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_LITTLEFS) + + const char *path = "/dev/espflash"; + ret = setup_littlefs(path, mtd, "/data", 0755); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup littlefs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_SPIFFS) + + const char *path = "/dev/espflash"; + ret = setup_spiffs(path, mtd, "/data", 0755); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup spiffs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_MTD_CONFIG) + +# if defined (CONFIG_TESTING_MTD_CONFIG_FAIL_SAFE) + + /* To test power-loss resilient kv system, + * we write possible power-loss flash layout into flash + * then start kv system to see if it recovers. + * To do so, we need a mtd driver so that test code can + * write into flash. + */ + + const char *path = CONFIG_TESTING_MTD_CONFIG_FAIL_SAFE_MOUNTPT_NAME; + ret = register_mtddriver(path, mtd, 0777, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ret; + } + +# else + + ret = mtdconfig_register(mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup mtd config\n"); + return ret; + } + +# endif + +#else + + ret = register_mtddriver("/dev/espflash", mtd, 0755, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ret; + } + +#endif + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_spiflash_init + * + * Description: + * Initialize the SPI Flash and register the MTD device. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_spiflash_init(void) +{ + int ret = OK; + + esp_spiflash_init(); + + ret = init_storage_partition(); + if (ret < 0) + { + return ret; + } + + return ret; +} + diff --git a/boards/risc-v/esp32c6/esp32c6-devkit/configs/spiflash/defconfig b/boards/risc-v/esp32c6/esp32c6-devkit/configs/spiflash/defconfig new file mode 100644 index 0000000000..814200948a --- /dev/null +++ b/boards/risc-v/esp32c6/esp32c6-devkit/configs/spiflash/defconfig @@ -0,0 +1,55 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32c6-devkit" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32C6_DEVKIT=y +CONFIG_ARCH_CHIP="esp32c6" +CONFIG_ARCH_CHIP_ESP32C6=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_ESPRESSIF_ESP32C6=y +CONFIG_ESPRESSIF_SPIFLASH=y +CONFIG_ESPRESSIF_SPIFLASH_SMARTFS=y +CONFIG_ESPRESSIF_STORAGE_MTD_OFFSET=0x110000 +CONFIG_ESPRESSIF_STORAGE_MTD_SIZE=0xf0000 +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NAME_MAX=48 +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_LOSMART=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_SMARTFS_MAXNAMLEN=48 +CONFIG_START_DAY=29 +CONFIG_START_MONTH=11 +CONFIG_START_YEAR=2019 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_FLASH_ERASEALL=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_FSTEST=y +CONFIG_TESTING_FSTEST_MOUNTPT="/mnt" +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/esp32c6/esp32c6-devkit/src/esp32c6_bringup.c b/boards/risc-v/esp32c6/esp32c6-devkit/src/esp32c6_bringup.c index 596df3a9f1..8e2477d839 100644 --- a/boards/risc-v/esp32c6/esp32c6-devkit/src/esp32c6_bringup.c +++ b/boards/risc-v/esp32c6/esp32c6-devkit/src/esp32c6_bringup.c @@ -35,6 +35,7 @@ #include #include "esp_board_ledc.h" +#include "esp_board_spiflash.h" #ifdef CONFIG_WATCHDOG # include "espressif/esp_wdt.h" @@ -175,6 +176,14 @@ int esp_bringup(void) } #endif +#ifdef CONFIG_ESPRESSIF_SPIFLASH + ret = board_spiflash_init(); + if (ret) + { + syslog(LOG_ERR, "ERROR: Failed to initialize SPI Flash\n"); + } +#endif + #ifdef CONFIG_DEV_GPIO ret = esp_gpio_init(); if (ret < 0) diff --git a/boards/risc-v/esp32h2/common/Kconfig b/boards/risc-v/esp32h2/common/Kconfig index f2a26a919c..711e47f2d5 100644 --- a/boards/risc-v/esp32h2/common/Kconfig +++ b/boards/risc-v/esp32h2/common/Kconfig @@ -11,3 +11,40 @@ config ESPRESSIF_MERGE_BINS device. This is only useful when the path to binary files (e.g. bootloader) is provided via the ESPTOOL_BINDIR variable. + +choice ESPRESSIF_SPIFLASH_FS + prompt "Mount SPI Flash MTD on bring-up" + default ESPRESSIF_SPIFLASH_SMARTFS + depends on ESPRESSIF_MTD + optional + ---help--- + Mount the SPI Flash MTD with the selected File System format on board + bring-up. + If not selected, the MTD will be registered as a device node on /dev. + +config ESPRESSIF_SPIFLASH_SMARTFS + bool "SmartFS" + select FS_SMARTFS + select MTD_SMART + +config ESPRESSIF_SPIFLASH_NXFFS + bool "NXFFS" + select FS_NXFFS + +config ESPRESSIF_SPIFLASH_SPIFFS + bool "SPIFFS" + select FS_SPIFFS + +config ESPRESSIF_SPIFLASH_LITTLEFS + bool "LittleFS" + select FS_LITTLEFS + +config ESPRESSIF_SPIFLASH_MTD_CONFIG + bool "Non-volatile storage" + +endchoice # ESPRESSIF_SPIFLASH_FS + +config ESPRESSIF_SPIFLASH_FS_MOUNT_PT + string "File-system Mount Point" + depends on ESPRESSIF_SPIFLASH_LITTLEFS + default "/data" diff --git a/boards/risc-v/esp32h2/common/include/esp_board_spiflash.h b/boards/risc-v/esp32h2/common/include/esp_board_spiflash.h new file mode 100644 index 0000000000..909eb2e230 --- /dev/null +++ b/boards/risc-v/esp32h2/common/include/esp_board_spiflash.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * boards/risc-v/esp32h2/common/include/esp_board_spiflash.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 __BOARDS_RISCV_ESP32H2_COMMON_INCLUDE_ESP_BOARD_SPIFLASH_H +#define __BOARDS_RISCV_ESP32H2_COMMON_INCLUDE_ESP_BOARD_SPIFLASH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: board_spiflash_init + * + * Description: + * Initialize the SPIFLASH and register the MTD device. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ESPRESSIF_SPIFLASH +int board_spiflash_init(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_RISCV_ESP32H2_COMMON_INCLUDE_ESP_BOARD_SPIFLASH_H */ diff --git a/boards/risc-v/esp32h2/common/scripts/esp32h2_aliases.ld b/boards/risc-v/esp32h2/common/scripts/esp32h2_aliases.ld index d90bc34503..d435206cca 100644 --- a/boards/risc-v/esp32h2/common/scripts/esp32h2_aliases.ld +++ b/boards/risc-v/esp32h2/common/scripts/esp32h2_aliases.ld @@ -18,6 +18,9 @@ * ****************************************************************************/ +cache_resume_icache = Cache_Resume_ICache; +cache_suspend_icache = Cache_Suspend_ICache; + #ifdef CONFIG_ESPRESSIF_BLE /* Lower-case aliases for BLE library symbols not compliant to nxstyle */ diff --git a/boards/risc-v/esp32h2/common/src/Make.defs b/boards/risc-v/esp32h2/common/src/Make.defs index 90b594c2e4..978ef6d94b 100644 --- a/boards/risc-v/esp32h2/common/src/Make.defs +++ b/boards/risc-v/esp32h2/common/src/Make.defs @@ -28,6 +28,10 @@ ifeq ($(CONFIG_ESP_RMT),y) CSRCS += esp_board_rmt.c endif +ifeq ($(CONFIG_ESPRESSIF_SPIFLASH),y) + CSRCS += esp_board_spiflash.c +endif + DEPPATH += --dep-path src VPATH += :src CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src diff --git a/boards/risc-v/esp32h2/common/src/esp_board_spiflash.c b/boards/risc-v/esp32h2/common/src/esp_board_spiflash.c new file mode 100644 index 0000000000..be7e840960 --- /dev/null +++ b/boards/risc-v/esp32h2/common/src/esp_board_spiflash.c @@ -0,0 +1,417 @@ +/**************************************************************************** + * boards/risc-v/esp32h2/common/src/esp_board_spiflash.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 + +#include + +#include "inttypes.h" +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#ifdef CONFIG_BCH +#include +#endif + +#include "espressif/esp_spiflash.h" +#include "espressif/esp_spiflash_mtd.h" + +#include "esp_board_spiflash.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: setup_smartfs + * + * Description: + * Provide a block driver wrapper around MTD partition and mount a + * SMART FS over it. + * + * Parameters: + * smartn - Number used to register the mtd partition: /dev/smartx, where + * x = smartn. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_SMARTFS) +static int setup_smartfs(int smartn, struct mtd_dev_s *mtd, + const char *mnt_pt) +{ + int ret = OK; + char path[22]; + + ret = smart_initialize(smartn, mtd, NULL); + if (ret < 0) + { + syslog(LOG_INFO, "smart_initialize failed, " + "Trying to erase first...\n"); + ret = mtd->ioctl(mtd, MTDIOC_BULKERASE, 0); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: ioctl(BULKERASE) failed: %d\n", ret); + return ret; + } + + syslog(LOG_INFO, "Erase successful, initializing it again.\n"); + ret = smart_initialize(smartn, mtd, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: smart_initialize failed: %d\n", ret); + return ret; + } + } + + if (mnt_pt != NULL) + { + snprintf(path, sizeof(path), "/dev/smart%d", smartn); + + ret = nx_mount(path, mnt_pt, "smartfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", ret); + if (ret == -ENODEV) + { + syslog(LOG_WARNING, "Smartfs seems unformatted. " + "Did you run 'mksmartfs /dev/smart%d'?\n", smartn); + } + + return ret; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: setup_littlefs + * + * Description: + * Register a mtd driver and mount a Little FS over it. + * + * Parameters: + * path - Path name used to register the mtd driver. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * priv - Privileges + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_LITTLEFS) +static int setup_littlefs(const char *path, struct mtd_dev_s *mtd, + const char *mnt_pt, int priv) +{ + int ret = OK; + + ret = register_mtddriver(path, mtd, priv, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ERROR; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(path, mnt_pt, "littlefs", 0, NULL); + if (ret < 0) + { + ret = nx_mount(path, mnt_pt, "littlefs", 0, "forceformat"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", + ret); + return ret; + } + } + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: setup_spiffs + * + * Description: + * Register a mtd driver and mount a SPIFFS over it. + * + * Parameters: + * path - Path name used to register the mtd driver. + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * priv - Privileges + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_SPIFFS) +static int setup_spiffs(const char *path, struct mtd_dev_s *mtd, + const char *mnt_pt, int priv) +{ + int ret = OK; + + ret = register_mtddriver(path, mtd, priv, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ERROR; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(path, mnt_pt, "spiffs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", ret); + return ret; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: setup_nxffs + * + * Description: + * Register a mtd driver and mount a NXFFS over it. + * + * Parameters: + * mtd - Pointer to a pre-allocated mtd partition. + * mnt_pt - Mount point + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_NXFFS) +static int setup_nxffs(struct mtd_dev_s *mtd, const char *mnt_pt) +{ + int ret = OK; + + ret = nxffs_initialize(mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: NXFFS init failed: %d\n", ret); + return ret; + } + + if (mnt_pt != NULL) + { + ret = nx_mount(NULL, mnt_pt, "nxffs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", ret); + return ret; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: init_storage_partition + * + * Description: + * Initialize partition that is dedicated to general use. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int init_storage_partition(void) +{ + int ret = OK; + struct mtd_dev_s *mtd; + + mtd = esp_spiflash_alloc_mtdpart(CONFIG_ESPRESSIF_STORAGE_MTD_OFFSET, + CONFIG_ESPRESSIF_STORAGE_MTD_SIZE); + if (!mtd) + { + syslog(LOG_ERR, "ERROR: Failed to alloc MTD partition of SPI Flash\n"); + return ERROR; + } + +#if defined (CONFIG_ESPRESSIF_SPIFLASH_SMARTFS) + + ret = setup_smartfs(0, mtd, "/data"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup smartfs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_NXFFS) + + ret = setup_nxffs(mtd, "/data"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup nxffs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_LITTLEFS) + + const char *path = "/dev/espflash"; + ret = setup_littlefs(path, mtd, "/data", 0755); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup littlefs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_SPIFFS) + + const char *path = "/dev/espflash"; + ret = setup_spiffs(path, mtd, "/data", 0755); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup spiffs\n"); + return ret; + } + +#elif defined (CONFIG_ESPRESSIF_SPIFLASH_MTD_CONFIG) + +# if defined (CONFIG_TESTING_MTD_CONFIG_FAIL_SAFE) + + /* To test power-loss resilient kv system, + * we write possible power-loss flash layout into flash + * then start kv system to see if it recovers. + * To do so, we need a mtd driver so that test code can + * write into flash. + */ + + const char *path = CONFIG_TESTING_MTD_CONFIG_FAIL_SAFE_MOUNTPT_NAME; + ret = register_mtddriver(path, mtd, 0777, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ret; + } + +# else + + ret = mtdconfig_register(mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to setup mtd config\n"); + return ret; + } + +# endif + +#else + + ret = register_mtddriver("/dev/espflash", mtd, 0755, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return ret; + } + +#endif + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_spiflash_init + * + * Description: + * Initialize the SPI Flash and register the MTD device. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_spiflash_init(void) +{ + int ret = OK; + + esp_spiflash_init(); + + ret = init_storage_partition(); + if (ret < 0) + { + return ret; + } + + return ret; +} + diff --git a/boards/risc-v/esp32h2/esp32h2-devkit/configs/spiflash/defconfig b/boards/risc-v/esp32h2/esp32h2-devkit/configs/spiflash/defconfig new file mode 100644 index 0000000000..92491e5a3c --- /dev/null +++ b/boards/risc-v/esp32h2/esp32h2-devkit/configs/spiflash/defconfig @@ -0,0 +1,55 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32h2-devkit" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32H2_DEVKIT=y +CONFIG_ARCH_CHIP="esp32h2" +CONFIG_ARCH_CHIP_ESP32H2=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_ESPRESSIF_ESP32H2=y +CONFIG_ESPRESSIF_SPIFLASH=y +CONFIG_ESPRESSIF_SPIFLASH_SMARTFS=y +CONFIG_ESPRESSIF_STORAGE_MTD_OFFSET=0x110000 +CONFIG_ESPRESSIF_STORAGE_MTD_SIZE=0xf0000 +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NAME_MAX=48 +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_LOSMART=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_SMARTFS_MAXNAMLEN=48 +CONFIG_START_DAY=29 +CONFIG_START_MONTH=11 +CONFIG_START_YEAR=2019 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_FLASH_ERASEALL=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_FSTEST=y +CONFIG_TESTING_FSTEST_MOUNTPT="/mnt" +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c b/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c index 03123200c5..5b30e2cecb 100644 --- a/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c +++ b/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c @@ -35,6 +35,7 @@ #include #include "esp_board_ledc.h" +#include "esp_board_spiflash.h" #ifdef CONFIG_WATCHDOG # include "espressif/esp_wdt.h" @@ -175,6 +176,14 @@ int esp_bringup(void) } #endif +#ifdef CONFIG_ESPRESSIF_SPIFLASH + ret = board_spiflash_init(); + if (ret) + { + syslog(LOG_ERR, "ERROR: Failed to initialize SPI Flash\n"); + } +#endif + #ifdef CONFIG_DEV_GPIO ret = esp_gpio_init(); if (ret < 0)