You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2024/02/26 15:38:36 UTC
(nuttx) branch master updated: xtensa/esp32s3: Fix issue of system blocking when SPIRAM is used as stack 1. Fix issue of system blocking due to disable dcache. 2. Support Ext-SRAM-Cache mmu mapping in SMP mode.
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 638df3329b xtensa/esp32s3: Fix issue of system blocking when SPIRAM is used as stack 1. Fix issue of system blocking due to disable dcache. 2. Support Ext-SRAM-Cache mmu mapping in SMP mode.
638df3329b is described below
commit 638df3329b59b1326252cdb5c6a8c461bcf65c00
Author: chenwen@espressif.com <ch...@espressif.com>
AuthorDate: Thu Dec 28 11:48:41 2023 +0800
xtensa/esp32s3: Fix issue of system blocking when SPIRAM is used as stack
1. Fix issue of system blocking due to disable dcache.
2. Support Ext-SRAM-Cache mmu mapping in SMP mode.
Signed-off-by: chenwen@espressif.com <ch...@espressif.com>
---
arch/xtensa/src/esp32s3/esp32s3_himem.c | 46 +-----
arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.c | 65 +++++++-
arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.h | 18 +++
arch/xtensa/src/esp32s3/esp32s3_spiram.c | 197 +++++++++++++++++++++++++
arch/xtensa/src/esp32s3/esp32s3_spiram.h | 18 +++
5 files changed, 293 insertions(+), 51 deletions(-)
diff --git a/arch/xtensa/src/esp32s3/esp32s3_himem.c b/arch/xtensa/src/esp32s3/esp32s3_himem.c
index e1855d3f6d..25d832c029 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_himem.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_himem.c
@@ -32,6 +32,7 @@
#include "xtensa.h"
#include "esp32s3_spiram.h"
#include "esp32s3_himem.h"
+#include "esp32s3_spiflash_mtd.h"
#include "hardware/esp32s3_soc.h"
#include "hardware/esp32s3_cache_memory.h"
#include "hardware/esp32s3_extmem.h"
@@ -82,7 +83,6 @@
# define SPIRAM_BANKSWITCH_RESERVE 0
#endif
-#define MMU_PAGE_SIZE 0x10000
#define MMU_PAGE_TO_BYTES(page_num) ((page_num) * MMU_PAGE_SIZE)
#define BYTES_TO_MMU_PAGE(bytes) ((bytes) / MMU_PAGE_SIZE)
@@ -129,7 +129,6 @@ extern int cache_dbus_mmu_set(uint32_t ext_ram, uint32_t vaddr,
static inline bool ramblock_idx_valid(int ramblock_idx);
static inline bool rangeblock_idx_valid(int rangeblock_idx);
-static void set_bank(int virt_bank, int phys_bank, int ct);
static uint32_t esp_himem_get_range_start(void);
static uint32_t esp_himem_get_range_block(void);
static uint32_t esp_himem_get_phy_block(void);
@@ -209,47 +208,6 @@ static inline bool rangeblock_idx_valid(int rangeblock_idx)
return (rangeblock_idx >= 0 && rangeblock_idx < g_rangeblockcnt);
}
-/****************************************************************************
- * Name: set_bank
- *
- * Description:
- * Set DCache mmu mapping.
- *
- * Input Parameters:
- * virt_bank - Beginning of the virtual bank
- * phys_bank - Beginning of the physical bank
- * ct - Number of banks
- *
- * Returned Value:
- * None.
- *
- ****************************************************************************/
-
-static void set_bank(int virt_bank, int phys_bank, int ct)
-{
- uint32_t regval;
-
- /* Suspend DRAM Case during configuration */
-
- cache_suspend_dcache();
- ASSERT(cache_dbus_mmu_set(MMU_ACCESS_SPIRAM,
- SOC_EXTRAM_DATA_LOW +
- MMU_PAGE_TO_BYTES(virt_bank),
- MMU_PAGE_TO_BYTES(phys_bank), 64, ct, 0) == 0);
-
- regval = getreg32(EXTMEM_DCACHE_CTRL1_REG);
- regval &= ~EXTMEM_DCACHE_SHUT_CORE0_BUS;
- putreg32(regval, EXTMEM_DCACHE_CTRL1_REG);
-
-#if defined(CONFIG_SMP)
- regval = getreg32(EXTMEM_DCACHE_CTRL1_REG);
- regval &= ~EXTMEM_DCACHE_SHUT_CORE1_BUS;
- putreg32(regval, EXTMEM_DCACHE_CTRL1_REG);
-#endif
-
- cache_resume_dcache(0);
-}
-
/****************************************************************************
* Name: esp_himem_get_range_start
*
@@ -974,7 +932,7 @@ int esp_himem_map(esp_himem_handle_t handle,
{
virt_bank = himem_mmu_start + range->block_start + i + range_block;
phys_bank = himem_phy_start + handle->block[i + ram_block];
- set_bank(virt_bank, phys_bank, 1);
+ esp32s3_set_bank(virt_bank, phys_bank, 1);
}
/* Set out pointer */
diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.c b/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.c
index 2ac6d66424..24eb4a6b56 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.c
@@ -39,9 +39,11 @@
#include <nuttx/mtd/mtd.h>
#include "hardware/esp32s3_soc.h"
+#include "hardware/esp32s3_cache_memory.h"
#include "xtensa_attr.h"
#include "esp32s3_spiflash.h"
+#include "esp32s3_spiram.h"
#include "rom/esp32s3_spiflash.h"
#include "esp32s3_spiflash_mtd.h"
@@ -71,6 +73,7 @@ enum spiflash_op_code_e
SPIFLASH_OP_CODE_WRITE = 0,
SPIFLASH_OP_CODE_READ,
SPIFLASH_OP_CODE_ERASE,
+ SPIFLASH_OP_CODE_SET_BANK,
SPIFLASH_OP_CODE_ENCRYPT_READ,
SPIFLASH_OP_CODE_ENCRYPT_WRITE
};
@@ -99,6 +102,7 @@ struct spiflash_work_arg
uint32_t addr;
uint8_t *buffer;
uint32_t size;
+ uint32_t paddr;
} op_arg;
volatile int ret;
@@ -144,7 +148,8 @@ static void esp32s3_spiflash_work(void *arg);
static int esp32s3_async_op(enum spiflash_op_code_e opcode,
uint32_t addr,
const uint8_t *buffer,
- uint32_t size);
+ uint32_t size,
+ uint32_t paddr);
#endif
/****************************************************************************
@@ -259,6 +264,12 @@ static void esp32s3_spiflash_work(void *arg)
work_arg->ret = spi_flash_erase_range(work_arg->op_arg.addr,
work_arg->op_arg.size);
}
+ else if (work_arg->op_code == SPIFLASH_OP_CODE_SET_BANK)
+ {
+ work_arg->ret = cache_dbus_mmu_map(work_arg->op_arg.addr,
+ work_arg->op_arg.paddr,
+ work_arg->op_arg.size);
+ }
else if (work_arg->op_code == SPIFLASH_OP_CODE_ENCRYPT_READ)
{
work_arg->ret = spi_flash_read_encrypted(work_arg->op_arg.addr,
@@ -300,7 +311,8 @@ static void esp32s3_spiflash_work(void *arg)
static int esp32s3_async_op(enum spiflash_op_code_e opcode,
uint32_t addr,
const uint8_t *buffer,
- uint32_t size)
+ uint32_t size,
+ uint32_t paddr)
{
int ret;
struct spiflash_work_arg work_arg =
@@ -311,6 +323,7 @@ static int esp32s3_async_op(enum spiflash_op_code_e opcode,
.addr = addr,
.buffer = (uint8_t *)buffer,
.size = size,
+ .paddr = paddr,
},
.sem = NXSEM_INITIALIZER(0, 0)
};
@@ -370,7 +383,8 @@ static int esp32s3_erase(struct mtd_dev_s *dev, off_t startblock,
#ifdef CONFIG_ESP32S3_SPI_FLASH_SUPPORT_PSRAM_STACK
if (stack_is_psram())
{
- ret = esp32s3_async_op(SPIFLASH_OP_CODE_ERASE, offset, NULL, nbytes);
+ ret = esp32s3_async_op(SPIFLASH_OP_CODE_ERASE, offset, NULL,
+ nbytes, 0);
}
else
#endif
@@ -438,7 +452,7 @@ static ssize_t esp32s3_read(struct mtd_dev_s *dev, off_t offset,
if (stack_is_psram())
{
ret = esp32s3_async_op(SPIFLASH_OP_CODE_READ, offset,
- buffer, nbytes);
+ buffer, nbytes, 0);
}
else
#endif
@@ -544,7 +558,7 @@ static ssize_t esp32s3_read_decrypt(struct mtd_dev_s *dev,
if (stack_is_psram())
{
ret = esp32s3_async_op(SPIFLASH_OP_CODE_ENCRYPT_READ, offset,
- buffer, nbytes);
+ buffer, nbytes, 0);
}
else
#endif
@@ -656,7 +670,7 @@ static ssize_t esp32s3_write(struct mtd_dev_s *dev, off_t offset,
if (stack_is_psram())
{
ret = esp32s3_async_op(SPIFLASH_OP_CODE_WRITE, offset,
- buffer, nbytes);
+ buffer, nbytes, 0);
}
else
#endif
@@ -720,7 +734,7 @@ static ssize_t esp32s3_bwrite_encrypt(struct mtd_dev_s *dev,
if (stack_is_psram())
{
ret = esp32s3_async_op(SPIFLASH_OP_CODE_ENCRYPT_WRITE, addr,
- buffer, size);
+ buffer, size, 0);
}
else
#endif
@@ -863,6 +877,43 @@ static int esp32s3_ioctl(struct mtd_dev_s *dev, int cmd,
* Public Functions
****************************************************************************/
+/****************************************************************************
+ * Name: esp32s3_set_bank
+ *
+ * Description:
+ * Set Ext-SRAM-Cache mmu mapping.
+ *
+ * Input Parameters:
+ * virt_bank - Beginning of the virtual bank
+ * phys_bank - Beginning of the physical bank
+ * ct - Number of banks
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+void esp32s3_set_bank(int virt_bank, int phys_bank, int ct)
+{
+ int ret;
+ uint32_t vaddr = SOC_EXTRAM_DATA_LOW + MMU_PAGE_SIZE * virt_bank;
+ uint32_t paddr = phys_bank * MMU_PAGE_SIZE;
+#ifdef CONFIG_ESP32S3_SPI_FLASH_SUPPORT_PSRAM_STACK
+ if (stack_is_psram())
+ {
+ ret = esp32s3_async_op(SPIFLASH_OP_CODE_SET_BANK, vaddr, NULL, ct,
+ paddr);
+ }
+ else
+#endif
+ {
+ ret = cache_dbus_mmu_map(vaddr, paddr, ct);
+ }
+
+ DEBUGASSERT(ret == 0);
+ UNUSED(ret);
+}
+
/****************************************************************************
* Name: esp32s3_spiflash_alloc_mtdpart
*
diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.h b/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.h
index 86f1c1f174..d459fe7cd9 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.h
+++ b/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.h
@@ -46,6 +46,24 @@ extern "C"
* Public Function Prototypes
****************************************************************************/
+/****************************************************************************
+ * Name: esp32s3_set_bank
+ *
+ * Description:
+ * Set Ext-SRAM-Cache mmu mapping.
+ *
+ * Input Parameters:
+ * virt_bank - Beginning of the virtual bank
+ * phys_bank - Beginning of the physical bank
+ * ct - Number of banks
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+void esp32s3_set_bank(int virt_bank, int phys_bank, int ct);
+
/****************************************************************************
* Name: esp32s3_spiflash_mtd
*
diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiram.c b/arch/xtensa/src/esp32s3/esp32s3_spiram.c
index 8edf42e447..39e24347d1 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_spiram.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_spiram.c
@@ -33,6 +33,7 @@
#include <sys/param.h>
#include <nuttx/config.h>
#include <nuttx/spinlock.h>
+#include <nuttx/init.h>
#include <assert.h>
#include "xtensa.h"
@@ -66,6 +67,22 @@
#define SPIRAM_VADDR_MAP_SIZE 0
#endif
+/* Max MMU available paddr page num.
+ * `MMU_MAX_PADDR_PAGE_NUM * MMU_PAGE_SIZE` means the max paddr
+ * address supported by the MMU. e.g.: 16384 * 64KB, means MMU can
+ * support 1GB paddr at most
+ */
+
+#define MMU_MAX_PADDR_PAGE_NUM 16384
+
+/* This is the mask used for mapping. e.g.: 0x4200_0000 & MMU_VADDR_MASK */
+
+#define MMU_VADDR_MASK 0x1FFFFFF
+
+/* MMU entry num */
+
+#define MMU_ENTRY_NUM 512
+
static bool g_spiram_inited;
/* These variables are in bytes */
@@ -109,6 +126,7 @@ extern void cache_resume_dcache(uint32_t val);
extern int cache_dbus_mmu_set(uint32_t ext_ram, uint32_t vaddr,
uint32_t paddr, uint32_t psize,
uint32_t num, uint32_t fixed);
+extern int cache_invalidate_addr(uint32_t addr, uint32_t size);
/****************************************************************************
* Private Functions
@@ -142,10 +160,189 @@ static inline uint32_t mmu_valid_space(uint32_t *start_address)
return 0;
}
+/****************************************************************************
+ * Name: mmu_check_valid_paddr_region
+ *
+ * Description:
+ * Check if the paddr region is valid.
+ *
+ * Input Parameters:
+ * paddr_start - start of the physical address
+ * len - length, in bytes
+ *
+ * Returned Value:
+ * True for valid.
+ *
+ ****************************************************************************/
+
+static inline bool mmu_check_valid_paddr_region(uint32_t paddr_start,
+ uint32_t len)
+{
+ return (paddr_start < (MMU_PAGE_SIZE * MMU_MAX_PADDR_PAGE_NUM)) &&
+ (len < (MMU_PAGE_SIZE * MMU_MAX_PADDR_PAGE_NUM)) &&
+ ((paddr_start + len - 1) <
+ (MMU_PAGE_SIZE * MMU_MAX_PADDR_PAGE_NUM));
+}
+
+/****************************************************************************
+ * Name: mmu_check_valid_ext_vaddr_region
+ *
+ * Description:
+ * Check if the external memory vaddr region is valid.
+ *
+ * Input Parameters:
+ * vaddr_start - start of the virtual address
+ * len - length, in bytes
+ *
+ * Returned Value:
+ * True for valid.
+ *
+ ****************************************************************************/
+
+static inline bool mmu_check_valid_ext_vaddr_region(uint32_t vaddr_start,
+ uint32_t len)
+{
+ uint32_t vaddr_end = vaddr_start + len - 1;
+ bool valid = false;
+ valid |= (ADDRESS_IN_IRAM0_CACHE(vaddr_start) &&
+ ADDRESS_IN_IRAM0_CACHE(vaddr_end)) |
+ (ADDRESS_IN_DRAM0_CACHE(vaddr_start) &&
+ ADDRESS_IN_DRAM0_CACHE(vaddr_end));
+ return valid;
+}
+
+/****************************************************************************
+ * Name: esp_mmu_map_region
+ *
+ * Description:
+ * To map a virtual address block to a physical memory block.
+ *
+ * Input Parameters:
+ * vaddr - Virtual address in CPU address space
+ * paddr - Physical address in Ext-SRAM
+ * len - Length to be mapped, in bytes
+ * mem_type - MMU target physical memory
+ *
+ * Returned Value:
+ * Actual mapped length.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp_mmu_map_region(uint32_t vaddr, uint32_t paddr,
+ uint32_t len, uint32_t mem_type)
+{
+ DEBUGASSERT(vaddr % MMU_PAGE_SIZE == 0);
+ DEBUGASSERT(paddr % MMU_PAGE_SIZE == 0);
+ DEBUGASSERT(mmu_check_valid_paddr_region(paddr, len));
+ DEBUGASSERT(mmu_check_valid_ext_vaddr_region(vaddr, len));
+
+ uint32_t mmu_val;
+ uint32_t entry_id;
+ uint32_t page_num = (len + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
+ uint32_t ret = page_num * MMU_PAGE_SIZE;
+ mmu_val = paddr >> 16;
+ bool write_back = false;
+
+ while (page_num)
+ {
+ entry_id = (vaddr & MMU_VADDR_MASK) >> 16;
+ DEBUGASSERT(entry_id < MMU_ENTRY_NUM);
+ if (write_back == false && FLASH_MMU_TABLE[entry_id] != MMU_INVALID)
+ {
+ esp_spiram_writeback_cache();
+ write_back = true;
+ }
+
+ FLASH_MMU_TABLE[entry_id] = mmu_val | mem_type;
+ vaddr += MMU_PAGE_SIZE;
+ mmu_val++;
+ page_num--;
+ }
+
+ return ret;
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
+/****************************************************************************
+ * Name: cache_dbus_mmu_map
+ *
+ * Description:
+ * Set Ext-SRAM-Cache mmu mapping.
+ *
+ * Input Parameters:
+ * vaddr - Virtual address in CPU address space
+ * paddr - Physical address in Ext-SRAM
+ * num - Pages to be set
+ *
+ * Returned Value:
+ * 0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+int IRAM_ATTR cache_dbus_mmu_map(int vaddr, int paddr, int num)
+{
+ uint32_t regval;
+ irqstate_t flags;
+ uint32_t actual_mapped_len;
+ uint32_t cache_state[CONFIG_SMP_NCPUS];
+ int cpu = up_cpu_index();
+#ifdef CONFIG_SMP
+ bool smp_start = OSINIT_OS_READY();
+ int other_cpu = cpu ? 0 : 1;
+#endif
+
+ /* The MMU registers are implemented in such a way that lookups from the
+ * cache subsystem may collide with CPU access to the MMU registers. We use
+ * cache_suspend_dcache to make sure the cache is disabled.
+ */
+
+ flags = enter_critical_section();
+
+#ifdef CONFIG_SMP
+ /* The other CPU might be accessing the cache at the same time, just by
+ * using variables in external RAM.
+ */
+
+ if (smp_start)
+ {
+ up_cpu_pause(other_cpu);
+ }
+
+ cache_state[other_cpu] = cache_suspend_dcache();
+#endif
+ cache_state[cpu] = cache_suspend_dcache();
+
+ esp_mmu_map_region(vaddr, paddr, num * MMU_PAGE_SIZE, MMU_ACCESS_SPIRAM);
+
+ regval = getreg32(EXTMEM_DCACHE_CTRL1_REG);
+ regval &= ~EXTMEM_DCACHE_SHUT_CORE0_BUS;
+ putreg32(regval, EXTMEM_DCACHE_CTRL1_REG);
+
+#if defined(CONFIG_SMP)
+ regval = getreg32(EXTMEM_DCACHE_CTRL1_REG);
+ regval &= ~EXTMEM_DCACHE_SHUT_CORE1_BUS;
+ putreg32(regval, EXTMEM_DCACHE_CTRL1_REG);
+#endif
+
+ cache_invalidate_addr(vaddr, num * MMU_PAGE_SIZE);
+
+ cache_resume_dcache(cache_state[cpu]);
+
+#ifdef CONFIG_SMP
+ cache_resume_dcache(cache_state[other_cpu]);
+ if (smp_start)
+ {
+ up_cpu_resume(other_cpu);
+ }
+#endif
+
+ leave_critical_section(flags);
+ return 0;
+}
+
/* Initially map all psram physical address to virtual address.
* If psram physical size is larger than virtual address range, then only
* map the virtual address range.
diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiram.h b/arch/xtensa/src/esp32s3/esp32s3_spiram.h
index be46bf53a9..6bd24ec7cc 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_spiram.h
+++ b/arch/xtensa/src/esp32s3/esp32s3_spiram.h
@@ -34,6 +34,24 @@ extern "C"
{
#endif
+/****************************************************************************
+ * Name: cache_dbus_mmu_map
+ *
+ * Description:
+ * Set Ext-SRAM-Cache mmu mapping.
+ *
+ * Input Parameters:
+ * vaddr - Virtual address in CPU address space
+ * paddr - Physical address in Ext-SRAM
+ * num - Pages to be set
+ *
+ * Returned Value:
+ * 0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+int cache_dbus_mmu_map(int vaddr, int paddr, int num);
+
/* Initialize spiram interface/hardware. Normally called from
* cpu_start.c.
*