xtensa/esp32s3: Add SPI-Flash support.

Signed-off-by: Abdelatif Guettouche <abdelatif.guettouche@espressif.com>
This commit is contained in:
Abdelatif Guettouche 2022-03-03 10:21:31 +01:00 committed by Xiang Xiao
parent d69cf37b73
commit 9d5b13cd0e
13 changed files with 2420 additions and 0 deletions

View File

@ -496,6 +496,40 @@ config ESP32S3_TICKLESS
select ARCH_HAVE_TICKLESS
select SCHED_TICKLESS
config ESP32S3_SPIFLASH
bool "SPI Flash MTD Partition"
default n
menu "SPI Flash configuration"
depends on ESP32S3_SPIFLASH
comment "General storage MTD configuration"
config ESP32S3_MTD
bool "MTD driver"
default y
select MTD
select MTD_BYTE_WRITE
select MTD_PARTITION
---help---
Initialize an MTD driver for the ESP32-S3 SPI Flash, which will
add an entry at /dev for application access from userspace.
config ESP32S3_SPIFLASH_MTD_BLKSIZE
int "Storage MTD block size"
default 256
depends on ESP32S3_MTD
config ESP32S3_STORAGE_MTD_DEBUG
bool "Storage MTD Debug"
default n
depends on ESP32S3_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).
endmenu # SPI Flash configuration
menu "Application Image Configuration"
choice

View File

@ -100,3 +100,11 @@ endif
ifeq ($(CONFIG_ESP32S3_FREERUN),y)
CHIP_CSRCS += esp32s3_freerun.c
endif
ifeq ($(CONFIG_ESP32S3_SPIFLASH),y)
CHIP_CSRCS += esp32s3_spiflash.c
ifeq ($(CONFIG_ESP32S3_MTD),y)
CHIP_CSRCS += esp32s3_spiflash_mtd.c
endif
endif

View File

@ -0,0 +1,151 @@
/****************************************************************************
* arch/xtensa/src/esp32s3/esp32s3_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 <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <debug.h>
#include <string.h>
#include <sys/types.h>
#include <inttypes.h>
#include <errno.h>
#include <nuttx/arch.h>
#include <nuttx/init.h>
#include "hardware/esp32s3_soc.h"
#include "esp32s3_irq.h"
#include "esp32s3_spiflash.h"
/****************************************************************************
* Private Types
****************************************************************************/
/* Structure holding SPI flash access critical sections management
* functions.
*/
struct spiflash_guard_funcs_s
{
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 */
};
struct spiflash_cachestate_s
{
uint32_t value;
irqstate_t flags;
};
/****************************************************************************
* Private Functions Declaration
****************************************************************************/
static void spiflash_start(void);
static void spiflash_end(void);
/****************************************************************************
* Public Functions Declaration
****************************************************************************/
extern void spi_flash_guard_set(const struct spiflash_guard_funcs_s *funcs);
extern uint32_t cache_suspend_icache(void);
extern void cache_resume_icache(uint32_t val);
/****************************************************************************
* Private Data
****************************************************************************/
static struct spiflash_guard_funcs_s g_spi_flash_guard_funcs =
{
.start = spiflash_start,
.end = spiflash_end,
.op_lock = NULL,
.op_unlock = NULL,
.address_is_safe = NULL,
.yield = NULL,
};
struct spiflash_cachestate_s g_state;
/****************************************************************************
* Name: spiflash_opstart
*
* Description:
* Prepare for an SPIFLASH operation.
*
****************************************************************************/
static IRAM_ATTR void spiflash_start(void)
{
g_state.flags = enter_critical_section();
g_state.value = cache_suspend_icache() << 16;
}
/****************************************************************************
* Name: spiflash_opdone
*
* Description:
* Undo all the steps of opstart.
*
****************************************************************************/
static IRAM_ATTR void spiflash_end(void)
{
cache_resume_icache(g_state.value >> 16);
leave_critical_section(g_state.flags);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: esp32s3_spiflash_init
*
* Description:
* Initialize ESP32-S3 SPI flash driver.
*
* Returned Value:
* OK if success or a negative value if fail.
*
****************************************************************************/
int esp32s3_spiflash_init(void)
{
spi_flash_guard_set(&g_spi_flash_guard_funcs);
return OK;
}

View File

@ -0,0 +1,68 @@
/****************************************************************************
* arch/xtensa/src/esp32s3/esp32s3_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_XTENSA_SRC_ESP32S3_ESP32S3_SPIFLASH_H
#define __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_SPIFLASH_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <nuttx/mtd/mtd.h>
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: esp32s3_spiflash_init
*
* Description:
* Initialize ESP32-S3 SPI flash driver.
*
* Returned Value:
* OK if success or a negative value if fail.
*
****************************************************************************/
int esp32s3_spiflash_init(void);
#ifdef __cplusplus
}
#endif
#undef EXTERN
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_SPIFLASH_H */

View File

@ -0,0 +1,577 @@
/****************************************************************************
* arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <debug.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <inttypes.h>
#include <errno.h>
#include <nuttx/arch.h>
#include <nuttx/init.h>
#include <nuttx/semaphore.h>
#include <nuttx/mtd/mtd.h>
#include "hardware/esp32s3_soc.h"
#include "xtensa_attr.h"
#include "esp32s3_spiflash.h"
#include "rom/esp32s3_spiflash.h"
#include "esp32s3_spiflash_mtd.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MTD_BLK_SIZE CONFIG_ESP32S3_SPIFLASH_MTD_BLKSIZE
#define MTD_ERASE_SIZE 4096
#define MTD_ERASED_STATE (0xff)
#define MTD2PRIV(_dev) ((struct esp32s3_mtd_dev_s *)_dev)
#define MTD_SIZE(_priv) ((*(_priv)->data)->chip.chip_size)
#define MTD_BLK2SIZE(_priv, _b) (MTD_BLK_SIZE * (_b))
#define MTD_SIZE2BLK(_priv, _s) ((_s) / MTD_BLK_SIZE)
/****************************************************************************
* Private Types
****************************************************************************/
/* ESP32-S3 SPI Flash device private data */
struct esp32s3_mtd_dev_s
{
struct mtd_dev_s mtd;
/* SPI Flash data */
const struct spiflash_legacy_data_s **data;
};
/****************************************************************************
* Private Functions Prototypes
****************************************************************************/
/* MTD driver methods */
static int esp32s3_erase(struct mtd_dev_s *dev, off_t startblock,
size_t nblocks);
static ssize_t esp32s3_read(struct mtd_dev_s *dev, off_t offset,
size_t nbytes, uint8_t *buffer);
static ssize_t esp32s3_bread(struct mtd_dev_s *dev, off_t startblock,
size_t nblocks, uint8_t *buffer);
static ssize_t esp32s3_write(struct mtd_dev_s *dev, off_t offset,
size_t nbytes, const uint8_t *buffer);
static ssize_t esp32s3_bwrite(struct mtd_dev_s *dev, off_t startblock,
size_t nblocks, const uint8_t *buffer);
static int esp32s3_ioctl(struct mtd_dev_s *dev, int cmd,
unsigned long arg);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct esp32s3_mtd_dev_s g_esp32s3_spiflash =
{
.mtd =
{
.erase = esp32s3_erase,
.bread = esp32s3_bread,
.bwrite = esp32s3_bwrite,
.read = esp32s3_read,
.ioctl = esp32s3_ioctl,
#ifdef CONFIG_MTD_BYTE_WRITE
.write = esp32s3_write,
#endif
.name = "esp32s3_spiflash"
},
.data = &rom_spiflash_legacy_data,
};
/* Ensure exclusive access to the driver */
static sem_t g_exclsem = SEM_INITIALIZER(1);
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: esp32s3_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 esp32s3_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 esp32s3_mtd_dev_s *priv = (struct esp32s3_mtd_dev_s *)dev;
if ((offset > MTD_SIZE(priv)) || ((offset + nbytes) > MTD_SIZE(priv)))
{
return -EINVAL;
}
#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG
finfo("%s(%p, 0x%x, %d)\n", __func__, dev, startblock, nblocks);
finfo("spi_flash_erase_range(0x%x, %d)\n", offset, nbytes);
#endif
ret = nxsem_wait(&g_exclsem);
if (ret < 0)
{
return ret;
}
ret = spi_flash_erase_range(offset, nbytes);
nxsem_post(&g_exclsem);
if (ret == OK)
{
ret = nblocks;
}
else
{
#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG
finfo("Failed to erase the flash range!\n");
#endif
ret = -1;
}
#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG
finfo("%s()=%d\n", __func__, ret);
#endif
return ret;
}
/****************************************************************************
* Name: esp32s3_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 esp32s3_read(struct mtd_dev_s *dev, off_t offset,
size_t nbytes, uint8_t *buffer)
{
ssize_t ret;
#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
finfo("spi_flash_read(0x%x, %p, %d)\n", offset, buffer, nbytes);
#endif
/* Acquire the semaphore. */
ret = nxsem_wait(&g_exclsem);
if (ret < 0)
{
goto error_with_buffer;
}
ret = spi_flash_read(offset, buffer, nbytes);
nxsem_post(&g_exclsem);
if (ret == OK)
{
ret = nbytes;
}
#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG
finfo("%s()=%d\n", __func__, ret);
#endif
error_with_buffer:
return ret;
}
/****************************************************************************
* Name: esp32s3_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 esp32s3_bread(struct mtd_dev_s *dev, off_t startblock,
size_t nblocks, uint8_t *buffer)
{
ssize_t ret;
uint32_t addr = startblock * MTD_BLK_SIZE;
uint32_t size = nblocks * MTD_BLK_SIZE;
#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks,
buffer);
finfo("spi_flash_read(0x%x, %p, %d)\n", addr, buffer, size);
#endif
ret = nxsem_wait(&g_exclsem);
if (ret < 0)
{
return ret;
}
ret = spi_flash_read(addr, buffer, size);
nxsem_post(&g_exclsem);
if (ret == OK)
{
ret = nblocks;
}
#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG
finfo("%s()=%d\n", __func__, ret);
#endif
return ret;
}
/****************************************************************************
* Name: esp32s3_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 esp32s3_write(struct mtd_dev_s *dev, off_t offset,
size_t nbytes, const uint8_t *buffer)
{
int ret;
struct esp32s3_mtd_dev_s *priv = (struct esp32s3_mtd_dev_s *)dev;
ASSERT(buffer);
if ((offset > MTD_SIZE(priv)) || ((offset + nbytes) > MTD_SIZE(priv)))
{
return -EINVAL;
}
#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
finfo("spi_flash_write(0x%x, %p, %d)\n", offset, buffer, nbytes);
#endif
/* Acquire the semaphore. */
ret = nxsem_wait(&g_exclsem);
if (ret < 0)
{
goto error_with_buffer;
}
ret = spi_flash_write(offset, buffer, nbytes);
nxsem_post(&g_exclsem);
if (ret == OK)
{
ret = nbytes;
}
#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG
finfo("%s()=%d\n", __func__, ret);
#endif
error_with_buffer:
return (ssize_t)ret;
}
/****************************************************************************
* Name: esp32s3_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 esp32s3_bwrite(struct mtd_dev_s *dev, off_t startblock,
size_t nblocks, const uint8_t *buffer)
{
ssize_t ret;
uint32_t addr = startblock * MTD_BLK_SIZE;
uint32_t size = nblocks * MTD_BLK_SIZE;
#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock,
nblocks, buffer);
finfo("spi_flash_write(0x%x, %p, %d)\n", addr, buffer, size);
#endif
ret = nxsem_wait(&g_exclsem);
if (ret < 0)
{
return ret;
}
ret = spi_flash_write(addr, buffer, size);
nxsem_post(&g_exclsem);
if (ret == OK)
{
ret = nblocks;
}
#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG
finfo("%s()=%d\n", __func__, ret);
#endif
return ret;
}
/****************************************************************************
* Name: esp32s3_ioctl
*
* Description:
* Set/Get option to/from ESP32-S3 SPI Flash MTD device data.
*
* Input Parameters:
* dev - ESP32-S3 MTD device data
* cmd - operation command
* arg - operation argument
*
* Returned Value:
* 0 if success or a negative value if fail.
*
****************************************************************************/
static int esp32s3_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 esp32s3_mtd_dev_s *priv = (struct esp32s3_mtd_dev_s *)dev;
struct mtd_geometry_s *geo = (struct mtd_geometry_s *)arg;
if (geo)
{
geo->blocksize = MTD_BLK_SIZE;
geo->erasesize = MTD_ERASE_SIZE;
geo->neraseblocks = MTD_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 esp32s3_mtd_dev_s *priv = (struct esp32s3_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: esp32s3_spiflash_alloc_mtdpart
*
* Description:
* Allocate an MTD partition from the ESP32-S3 SPI Flash.
*
* Input Parameters:
* mtd_offset - MTD Partition offset from the base address in SPI Flash.
* mtd_size - Size for the MTD partition.
*
* Returned Value:
* ESP32-S3 SPI Flash MTD data pointer if success or NULL if fail.
*
****************************************************************************/
struct mtd_dev_s *esp32s3_spiflash_alloc_mtdpart(uint32_t mtd_offset,
uint32_t mtd_size)
{
const struct esp32s3_mtd_dev_s *priv;
const esp32s3_spiflash_chip_t *chip;
struct mtd_dev_s *mtd_part;
uint32_t blocks;
uint32_t startblock;
uint32_t size;
priv = &g_esp32s3_spiflash;
chip = &(*priv->data)->chip;
finfo("ESP32-S3 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: esp32s3_spiflash_mtd
*
* Description:
* Get SPI Flash MTD.
*
* Input Parameters:
* None
*
* Returned Value:
* ESP32-S3 SPI Flash MTD pointer.
*
****************************************************************************/
struct mtd_dev_s *esp32s3_spiflash_mtd(void)
{
struct esp32s3_mtd_dev_s *priv =
(struct esp32s3_mtd_dev_s *)&g_esp32s3_spiflash;
return &priv->mtd;
}

View File

@ -0,0 +1,91 @@
/****************************************************************************
* arch/xtensa/src/esp32s3/esp32s3_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_XTENSA_SRC_ESP32S3_ESP32S3_SPIFLASH_MTD_H
#define __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_SPIFLASH_MTD_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <nuttx/mtd/mtd.h>
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: esp32s3_spiflash_mtd
*
* Description:
* Get SPI Flash MTD.
*
* Input Parameters:
* None
*
* Returned Value:
* ESP32-S3 SPI Flash MTD pointer.
*
****************************************************************************/
struct mtd_dev_s *esp32s3_spiflash_mtd(void);
/****************************************************************************
* Name: esp32s3_spiflash_alloc_mtdpart
*
* Description:
* Allocate an MTD partition from the ESP32-S3 SPI Flash.
*
* Input Parameters:
* mtd_offset - MTD Partition offset from the base address in SPI Flash.
* mtd_size - Size for the MTD partition.
* encrypted - Flag indicating whether the newly allocated partition will
* have its content encrypted.
*
* Returned Value:
* SPI Flash MTD data pointer if success or NULL if fail.
*
****************************************************************************/
struct mtd_dev_s *esp32s3_spiflash_alloc_mtdpart(uint32_t mtd_offset,
uint32_t mtd_size);
#ifdef __cplusplus
}
#endif
#undef EXTERN
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_SPIFLASH_MTD_H */

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,10 @@ ifeq ($(CONFIG_WATCHDOG),y)
CSRCS += esp32s3_board_wdt.c
endif
ifeq ($(CONFIG_ESP32S3_SPIFLASH),y)
CSRCS += esp32s3_board_spiflash.c
endif
DEPPATH += --dep-path src
VPATH += :src
CFLAGS += $(shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src)

View File

@ -0,0 +1,354 @@
/****************************************************************************
* boards/xtensa/esp32s3/common/src/esp32s3_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 <nuttx/config.h>
#include <sys/mount.h>
#include "inttypes.h"
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/spi/spi.h>
#include <nuttx/mtd/mtd.h>
#include <nuttx/fs/nxffs.h>
#ifdef CONFIG_BCH
#include <nuttx/drivers/drivers.h>
#endif
#include "esp32s3_spiflash.h"
#include "esp32s3_spiflash_mtd.h"
#include "esp32s3-devkit.h"
/****************************************************************************
* 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_ESP32S3_SPIFLASH_SMARTFS)
static int setup_smartfs(int smartn, FAR struct mtd_dev_s *mtd,
const char *mnt_pt)
{
int ret = OK;
char path[22];
ret = smart_initialize(smartn, mtd, NULL);
if (ret < 0)
{
finfo("smart_initialize failed, Trying to erase first...\n");
ret = mtd->ioctl(mtd, MTDIOC_BULKERASE, 0);
if (ret < 0)
{
ferr("ERROR: ioctl(BULKERASE) failed: %d\n", ret);
return ret;
}
finfo("Erase successful, initializing it again.\n");
ret = smart_initialize(smartn, mtd, NULL);
if (ret < 0)
{
ferr("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)
{
ferr("ERROR: Failed to mount the FS volume: %d\n", ret);
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_ESP32S3_SPIFLASH_LITTLEFS)
static int setup_littlefs(const char *path, FAR struct mtd_dev_s *mtd,
const char *mnt_pt, int priv)
{
int ret = OK;
ret = register_mtddriver(path, mtd, priv, NULL);
if (ret < 0)
{
ferr("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)
{
ferr("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_ESP32S3_SPIFLASH_SPIFFS)
static int setup_spiffs(const char *path, FAR struct mtd_dev_s *mtd,
const char *mnt_pt, int priv)
{
int ret = OK;
ret = register_mtddriver(path, mtd, priv, NULL);
if (ret < 0)
{
ferr("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)
{
ferr("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 SPIFFS 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_ESP32S3_SPIFLASH_NXFFS)
static int setup_nxffs(FAR struct mtd_dev_s *mtd, const char *mnt_pt)
{
int ret = OK;
ret = nxffs_initialize(mtd);
if (ret < 0)
{
ferr("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)
{
ferr("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.
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/
static int init_storage_partition(void)
{
int ret = OK;
FAR struct mtd_dev_s *mtd;
mtd = esp32s3_spiflash_alloc_mtdpart(CONFIG_ESP32S3_STORAGE_MTD_OFFSET,
CONFIG_ESP32S3_STORAGE_MTD_SIZE);
if (!mtd)
{
ferr("ERROR: Failed to alloc MTD partition of SPI Flash\n");
return ERROR;
}
#if defined (CONFIG_ESP32S3_SPIFLASH_SMARTFS)
ret = setup_smartfs(0, mtd, NULL);
if (ret < 0)
{
ferr("ERROR: Failed to setup smartfs\n");
return ret;
}
#elif defined (CONFIG_ESP32S3_SPIFLASH_NXFFS)
ret = setup_nxffs(mtd, "/mnt");
if (ret < 0)
{
ferr("ERROR: Failed to setup nxffs\n");
return ret;
}
#elif defined (CONFIG_ESP32S3_SPIFLASH_LITTLEFS)
const char *path = "/dev/esp32s3flash";
ret = setup_littlefs(path, mtd, NULL, 0755);
if (ret < 0)
{
ferr("ERROR: Failed to setup littlefs\n");
return ret;
}
#elif defined (CONFIG_ESP32S3_SPIFLASH_SPIFFS)
const char *path = "/dev/esp32s3flash";
ret = setup_spiffs(path, mtd, NULL, 0755);
if (ret < 0)
{
ferr("ERROR: Failed to setup spiffs\n");
return ret;
}
#else
ret = register_mtddriver("/dev/esp32s3flash", mtd, 0755, NULL);
if (ret < 0)
{
ferr("ERROR: Failed to register MTD: %d\n", ret);
return ret;
}
#endif
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: board_spiflash_init
*
* Description:
* Initialize the SPIFLASH and register the MTD device.
*
****************************************************************************/
int board_spiflash_init(void)
{
int ret = OK;
ret = esp32s3_spiflash_init();
if (ret < 0)
{
return ret;
}
ret = init_storage_partition();
if (ret < 0)
{
return ret;
}
return ret;
}

View File

@ -5,4 +5,47 @@
if ARCH_BOARD_ESP32S3_DEVKIT
config ESP32S3_STORAGE_MTD_OFFSET
hex "Storage MTD base address in SPI Flash"
default 0x180000
depends on ESP32S3_MTD
---help---
MTD base address in SPI Flash.
config ESP32S3_STORAGE_MTD_SIZE
hex "Storage MTD size in SPI Flash"
default 0x100000
depends on ESP32S3_MTD
---help---
MTD size in SPI Flash.
choice ESP32S3_SPIFLASH_FS
prompt "Mount SPI Flash MTD on bring-up"
default ESP32S3_SPIFLASH_SMARTFS
depends on ESP32S3_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 ESP32S3_SPIFLASH_SMARTFS
bool "SmartFS"
select FS_SMARTFS
select MTD_SMART
config ESP32S3_SPIFLASH_NXFFS
bool "NXFFS"
select FS_NXFFS
config ESP32S3_SPIFLASH_SPIFFS
bool "SPIFFS"
select FS_SPIFFS
config ESP32S3_SPIFLASH_LITTLEFS
bool "LittleFS"
select FS_LITTLEFS
endchoice
endif # ARCH_BOARD_ESP32S3_DEVKIT

View File

@ -0,0 +1,50 @@
#
# 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_ARCH_LEDS is not set
# CONFIG_NSH_ARGCAT is not set
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
# CONFIG_NSH_CMDPARMS is not set
CONFIG_ARCH="xtensa"
CONFIG_ARCH_BOARD="esp32s3-devkit"
CONFIG_ARCH_BOARD_ESP32S3_DEVKIT=y
CONFIG_ARCH_CHIP="esp32s3"
CONFIG_ARCH_CHIP_ESP32S3=y
CONFIG_ARCH_CHIP_ESP32S3WROOM1=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARCH_XTENSA=y
CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_BUILTIN=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_ESP32S3_SPIFLASH=y
CONFIG_ESP32S3_SPIFLASH_LITTLEFS=y
CONFIG_ESP32S3_UART0=y
CONFIG_FS_PROCFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_HOST_MACOS=y
CONFIG_IDLETHREAD_STACKSIZE=3072
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INTELHEX_BINARY=y
CONFIG_MM_REGIONS=3
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_LINELEN=64
CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_SYSTEM_NSH=y
CONFIG_UART0_SERIAL_CONSOLE=y

View File

@ -63,5 +63,17 @@
int esp32s3_bringup(void);
/****************************************************************************
* Name: board_spiflash_init
*
* Description:
* Initialize the SPIFLASH and register the MTD device.
*
****************************************************************************/
#ifdef CONFIG_ESP32S3_SPIFLASH
int board_spiflash_init(void);
#endif
#endif /* __ASSEMBLY__ */
#endif /* __BOARDS_XTENSA_ESP32S3_ESP32S3_DEVKIT_SRC_ESP32S3_DEVKIT_H */

View File

@ -111,6 +111,14 @@ int esp32s3_bringup(void)
}
#endif
#ifdef CONFIG_ESP32S3_SPIFLASH
ret = board_spiflash_init();
if (ret)
{
syslog(LOG_ERR, "ERROR: Failed to initialize SPI Flash\n");
}
#endif
/* If we got here then perhaps not all initialization was successful, but
* at least enough succeeded to bring-up NSH with perhaps reduced
* capabilities.