xtensa/esp32s3: Invalidate cache if the flash address used has a cache mapping.
Signed-off-by: chenwen@espressif.com <chenwen@espressif.com>
This commit is contained in:
parent
e852f28710
commit
e2a82f008a
@ -41,7 +41,9 @@
|
|||||||
|
|
||||||
#include "xtensa.h"
|
#include "xtensa.h"
|
||||||
#include "xtensa_attr.h"
|
#include "xtensa_attr.h"
|
||||||
|
#include "hardware/esp32s3_extmem.h"
|
||||||
#include "hardware/esp32s3_spi_mem_reg.h"
|
#include "hardware/esp32s3_spi_mem_reg.h"
|
||||||
|
#include "hardware/esp32s3_cache_memory.h"
|
||||||
#include "rom/esp32s3_spiflash.h"
|
#include "rom/esp32s3_spiflash.h"
|
||||||
#include "rom/esp32s3_opi_flash.h"
|
#include "rom/esp32s3_opi_flash.h"
|
||||||
#include "esp32s3_irq.h"
|
#include "esp32s3_irq.h"
|
||||||
@ -54,31 +56,36 @@
|
|||||||
/* RO data page in MMU index */
|
/* RO data page in MMU index */
|
||||||
|
|
||||||
#define DROM0_PAGES_START (2)
|
#define DROM0_PAGES_START (2)
|
||||||
#define DROM0_PAGES_END (128)
|
#define DROM0_PAGES_END (512)
|
||||||
|
|
||||||
/* MMU invalid value */
|
|
||||||
|
|
||||||
#define INVALID_MMU_VAL (0x100)
|
|
||||||
|
|
||||||
/* MMU page size */
|
|
||||||
|
|
||||||
#define SPI_FLASH_MMU_PAGE_SIZE (0x10000)
|
|
||||||
|
|
||||||
/* MMU base virtual mapped address */
|
/* MMU base virtual mapped address */
|
||||||
|
|
||||||
#define VADDR0_START_ADDR (0x3c020000)
|
#define VADDR0_START_ADDR (0x3c020000)
|
||||||
|
|
||||||
|
#define VADDR1_START_ADDR (0x42000000)
|
||||||
|
|
||||||
/* Flash MMU table for CPU */
|
/* Flash MMU table for CPU */
|
||||||
|
|
||||||
#define MMU_TABLE ((volatile uint32_t *)DR_REG_MMU_TABLE)
|
#define MMU_TABLE ((volatile uint32_t *)DR_REG_MMU_TABLE)
|
||||||
|
|
||||||
#define MMU_ADDR2PAGE(_addr) ((_addr) / SPI_FLASH_MMU_PAGE_SIZE)
|
#define MMU_ADDR2PAGE(_addr) ((_addr) / MMU_PAGE_SIZE)
|
||||||
#define MMU_ADDR2OFF(_addr) ((_addr) % SPI_FLASH_MMU_PAGE_SIZE)
|
#define MMU_ADDR2OFF(_addr) ((_addr) % MMU_PAGE_SIZE)
|
||||||
#define MMU_BYTES2PAGES(_n) (((_n) + SPI_FLASH_MMU_PAGE_SIZE - 1) / \
|
#define MMU_BYTES2PAGES(_n) (((_n) + MMU_PAGE_SIZE - 1) / \
|
||||||
SPI_FLASH_MMU_PAGE_SIZE)
|
MMU_PAGE_SIZE)
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S3_SPI_FLASH_DONT_USE_ROM_CODE
|
#ifdef CONFIG_ESP32S3_SPI_FLASH_DONT_USE_ROM_CODE
|
||||||
|
|
||||||
|
#define g_rom_flashchip (rom_spiflash_legacy_data->chip)
|
||||||
|
|
||||||
|
#define MMU_ALIGNUP_SIZE(_s) (((_s) + MMU_PAGE_SIZE - 1) \
|
||||||
|
& ~(MMU_PAGE_SIZE - 1))
|
||||||
|
#define MMU_ALIGNDOWN_SIZE(_s) ((_s) & ~(MMU_PAGE_SIZE - 1))
|
||||||
|
|
||||||
|
/* Flash MMU table for APP CPU */
|
||||||
|
|
||||||
|
#define PRO_IRAM0_FIRST_PAGE (0)
|
||||||
|
#define IROM0_PAGES_END (2)
|
||||||
|
|
||||||
/* SPI port number */
|
/* SPI port number */
|
||||||
|
|
||||||
# define SPI_PORT (1)
|
# define SPI_PORT (1)
|
||||||
@ -170,35 +177,6 @@
|
|||||||
|
|
||||||
#endif /* CONFIG_ESP32S3_SPI_FLASH_DONT_USE_ROM_CODE */
|
#endif /* CONFIG_ESP32S3_SPI_FLASH_DONT_USE_ROM_CODE */
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Types
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/* SPI Flash map request data */
|
|
||||||
|
|
||||||
struct spiflash_map_req_s
|
|
||||||
{
|
|
||||||
/* Request mapping SPI Flash base address */
|
|
||||||
|
|
||||||
uint32_t src_addr;
|
|
||||||
|
|
||||||
/* Request mapping SPI Flash size */
|
|
||||||
|
|
||||||
uint32_t size;
|
|
||||||
|
|
||||||
/* Mapped memory pointer */
|
|
||||||
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
/* Mapped started MMU page index */
|
|
||||||
|
|
||||||
uint32_t start_page;
|
|
||||||
|
|
||||||
/* Mapped MMU page count */
|
|
||||||
|
|
||||||
uint32_t page_cnt;
|
|
||||||
};
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions Declaration
|
* Private Functions Declaration
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -208,6 +186,7 @@ static void spiflash_end(void);
|
|||||||
static void spi_flash_disable_cache(uint32_t cpuid);
|
static void spi_flash_disable_cache(uint32_t cpuid);
|
||||||
static void spi_flash_restore_cache(uint32_t cpuid);
|
static void spi_flash_restore_cache(uint32_t cpuid);
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
static int spi_flash_op_block_task(int argc, char *argv[]);
|
||||||
static int spiflash_init_spi_flash_op_block_task(int cpu);
|
static int spiflash_init_spi_flash_op_block_task(int cpu);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -220,6 +199,7 @@ extern uint32_t cache_suspend_dcache(void);
|
|||||||
extern void cache_resume_icache(uint32_t val);
|
extern void cache_resume_icache(uint32_t val);
|
||||||
extern void cache_resume_dcache(uint32_t val);
|
extern void cache_resume_dcache(uint32_t val);
|
||||||
extern int cache_invalidate_addr(uint32_t addr, uint32_t size);
|
extern int cache_invalidate_addr(uint32_t addr, uint32_t size);
|
||||||
|
extern void cache_invalidate_icache_all(void);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
@ -371,6 +351,7 @@ static void spiflash_end(void)
|
|||||||
DEBUGASSERT(other_cpu != cpu);
|
DEBUGASSERT(other_cpu != cpu);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
cache_invalidate_icache_all();
|
||||||
spiflash_resume_cache();
|
spiflash_resume_cache();
|
||||||
|
|
||||||
/* Signal to spi_flash_op_block_task that flash operation is complete */
|
/* Signal to spi_flash_op_block_task that flash operation is complete */
|
||||||
@ -645,362 +626,108 @@ static void disable_flash_write(void)
|
|||||||
}
|
}
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_ESP32S3_SPI_FLASH_DONT_USE_ROM_CODE */
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: esp32s3_mmap
|
* Name: spiflash_pagecached
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Mapped SPI Flash address to ESP32-S3's address bus, so that software
|
* Check if the given page is cached.
|
||||||
* can read SPI Flash data by reading data from memory access.
|
|
||||||
*
|
|
||||||
* If SPI Flash hardware encryption is enable, the read from mapped
|
|
||||||
* address is decrypted.
|
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* req - SPI Flash mapping requesting parameters
|
* phypage - physical address page.
|
||||||
|
* ptr - Pointer to the virtual address.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* 0 if success or a negative value if fail.
|
* True if flash address has corresponding cache mapping, false otherwise.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int esp32s3_mmap(struct spiflash_map_req_s *req)
|
static bool IRAM_ATTR spiflash_pagecached(uint32_t phypage, uint32_t *ptr)
|
||||||
{
|
{
|
||||||
int ret;
|
int start[2];
|
||||||
|
int end[2];
|
||||||
int i;
|
int i;
|
||||||
int start_page;
|
int j;
|
||||||
int flash_page;
|
|
||||||
int page_cnt;
|
|
||||||
uint32_t mapped_addr;
|
|
||||||
|
|
||||||
spiflash_start();
|
/* Data ROM start and end pages */
|
||||||
|
|
||||||
for (start_page = DROM0_PAGES_START;
|
start[0] = DROM0_PAGES_START;
|
||||||
start_page < DROM0_PAGES_END;
|
end[0] = DROM0_PAGES_END;
|
||||||
++start_page)
|
|
||||||
|
/* Instruction RAM start and end pages */
|
||||||
|
|
||||||
|
start[1] = PRO_IRAM0_FIRST_PAGE;
|
||||||
|
end[1] = IROM0_PAGES_END;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
if (MMU_TABLE[start_page] == INVALID_MMU_VAL)
|
for (j = start[i]; j < end[i]; j++)
|
||||||
{
|
{
|
||||||
break;
|
if (MMU_TABLE[j] == phypage)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
/* SPI_FLASH_MMAP_DATA */
|
||||||
|
|
||||||
|
*ptr = (VADDR0_START_ADDR +
|
||||||
|
MMU_PAGE_SIZE * (j - start[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* SPI_FLASH_MMAP_INST */
|
||||||
|
|
||||||
|
*ptr = (VADDR1_START_ADDR +
|
||||||
|
MMU_PAGE_SIZE * (j - start[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flash_page = MMU_ADDR2PAGE(req->src_addr);
|
return false;
|
||||||
page_cnt = MMU_BYTES2PAGES(MMU_ADDR2OFF(req->src_addr) + req->size);
|
|
||||||
|
|
||||||
if (start_page + page_cnt < DROM0_PAGES_END)
|
|
||||||
{
|
|
||||||
mapped_addr = (start_page - DROM0_PAGES_START) *
|
|
||||||
SPI_FLASH_MMU_PAGE_SIZE +
|
|
||||||
VADDR0_START_ADDR;
|
|
||||||
|
|
||||||
for (i = 0; i < page_cnt; i++)
|
|
||||||
{
|
|
||||||
MMU_TABLE[start_page + i] = flash_page + i;
|
|
||||||
cache_invalidate_addr(mapped_addr + i * SPI_FLASH_MMU_PAGE_SIZE,
|
|
||||||
SPI_FLASH_MMU_PAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
req->start_page = start_page;
|
|
||||||
req->page_cnt = page_cnt;
|
|
||||||
req->ptr = (void *)(mapped_addr + MMU_ADDR2OFF(req->src_addr));
|
|
||||||
ret = OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = -ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
spiflash_end();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: esp32s3_ummap
|
* Name: spiflash_flushmapped
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Unmap SPI Flash address in ESP32-S3's address bus, and free resource.
|
* Writeback PSRAM data and invalidate the cache if the address is mapped.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* req - SPI Flash mapping requesting parameters
|
* start - SPI Flash address.
|
||||||
|
* size - SPI Flash size.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* None.
|
* None.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void esp32s3_ummap(const struct spiflash_map_req_s *req)
|
static void IRAM_ATTR spiflash_flushmapped(size_t start, size_t size)
|
||||||
{
|
{
|
||||||
int i;
|
uint32_t page_start;
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t page;
|
||||||
|
uint32_t vaddr;
|
||||||
|
|
||||||
spiflash_start();
|
page_start = MMU_ALIGNDOWN_SIZE(start);
|
||||||
|
size += (start - page_start);
|
||||||
|
size = MMU_ALIGNUP_SIZE(size);
|
||||||
|
|
||||||
for (i = req->start_page; i < req->start_page + req->page_cnt; ++i)
|
for (addr = page_start; addr < page_start + size;
|
||||||
|
addr += MMU_PAGE_SIZE)
|
||||||
{
|
{
|
||||||
MMU_TABLE[i] = INVALID_MMU_VAL;
|
page = addr / MMU_PAGE_SIZE;
|
||||||
}
|
if (addr >= g_rom_flashchip.chip_size)
|
||||||
|
|
||||||
spiflash_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Public Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: spi_flash_read_encrypted
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Read decrypted data from SPI Flash at designated address when
|
|
||||||
* enable SPI Flash hardware encryption.
|
|
||||||
*
|
|
||||||
* Input Parameters:
|
|
||||||
* addr - target address
|
|
||||||
* buffer - data buffer pointer
|
|
||||||
* size - data number
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* OK if success or a negative value if fail.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
int spi_flash_read_encrypted(uint32_t addr, void *buffer, uint32_t size)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
struct spiflash_map_req_s req =
|
|
||||||
{
|
|
||||||
.src_addr = addr,
|
|
||||||
.size = size
|
|
||||||
};
|
|
||||||
|
|
||||||
ret = esp32s3_mmap(&req);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer, req.ptr, size);
|
|
||||||
|
|
||||||
esp32s3_ummap(&req);
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S3_SPI_FLASH_DONT_USE_ROM_CODE
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
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.
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
int ret = OK;
|
|
||||||
const uint8_t *tx_buf = (const uint8_t *)buffer;
|
|
||||||
uint32_t tx_bytes = size;
|
|
||||||
uint32_t tx_addr = dest_addr;
|
|
||||||
#ifdef CONFIG_ESP32S3_SPIRAM
|
|
||||||
bool buffer_in_psram = esp32s3_ptr_extram(buffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S3_SPIRAM
|
|
||||||
|
|
||||||
/* Re-enable cache, and then copy data from PSRAM to SRAM */
|
|
||||||
|
|
||||||
if (buffer_in_psram)
|
|
||||||
{
|
{
|
||||||
spiflash_resume_cache();
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
memcpy(spi_buffer, tx_buf, n);
|
if (spiflash_pagecached(page, &vaddr))
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S3_SPIRAM
|
|
||||||
|
|
||||||
/* Disable cache, and then write data from SRAM to flash */
|
|
||||||
|
|
||||||
if (buffer_in_psram)
|
|
||||||
{
|
{
|
||||||
spiflash_suspend_cache();
|
cache_invalidate_addr(vaddr, MMU_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
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: spi_flash_read
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Read data from Flash.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* src_addr - source address of the data in Flash.
|
|
||||||
* dest - pointer to the destination buffer
|
|
||||||
* size - length of data
|
|
||||||
*
|
|
||||||
* Returned Values:
|
|
||||||
* Zero (OK) is returned or a negative error.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
int spi_flash_read(uint32_t src_addr, void *dest, uint32_t size)
|
|
||||||
{
|
|
||||||
int ret = OK;
|
|
||||||
uint8_t *rx_buf = (uint8_t *)dest;
|
|
||||||
uint32_t rx_bytes = size;
|
|
||||||
uint32_t rx_addr = src_addr;
|
|
||||||
#ifdef CONFIG_ESP32S3_SPIRAM
|
|
||||||
bool buffer_in_psram = esp32s3_ptr_extram(dest);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
spiflash_start();
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < size; 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);
|
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S3_SPIRAM
|
|
||||||
|
|
||||||
/* Re-enable cache, and then copy data from SRAM to PSRAM */
|
|
||||||
|
|
||||||
if (buffer_in_psram)
|
|
||||||
{
|
|
||||||
spiflash_resume_cache();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memcpy(rx_buf, spi_buffer, n);
|
|
||||||
rx_bytes -= n;
|
|
||||||
rx_buf += n;
|
|
||||||
rx_addr += n;
|
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S3_SPIRAM
|
|
||||||
|
|
||||||
/* Disable cache, and then read data from flash to SRAM */
|
|
||||||
|
|
||||||
if (buffer_in_psram)
|
|
||||||
{
|
|
||||||
spiflash_suspend_cache();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
spiflash_end();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_ESP32S3_SPI_FLASH_DONT_USE_ROM_CODE */
|
#endif /* CONFIG_ESP32S3_SPI_FLASH_DONT_USE_ROM_CODE */
|
||||||
|
|
||||||
@ -1132,7 +859,7 @@ static int spi_flash_op_block_task(int argc, char *argv[])
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int spiflash_init_spi_flash_op_block_task(int cpu)
|
static int spiflash_init_spi_flash_op_block_task(int cpu)
|
||||||
{
|
{
|
||||||
int pid;
|
int pid;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
@ -1175,6 +902,367 @@ int spiflash_init_spi_flash_op_block_task(int cpu)
|
|||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32s3_mmap
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Mapped SPI Flash address to ESP32-S3's address bus, so that software
|
||||||
|
* can read SPI Flash data by reading data from memory access.
|
||||||
|
*
|
||||||
|
* If SPI Flash hardware encryption is enable, the read from mapped
|
||||||
|
* address is decrypted.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* req - SPI Flash mapping requesting parameters
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* 0 if success or a negative value if fail.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int esp32s3_mmap(struct spiflash_map_req_s *req)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
int start_page;
|
||||||
|
int flash_page;
|
||||||
|
int page_cnt;
|
||||||
|
uint32_t mapped_addr;
|
||||||
|
|
||||||
|
spiflash_start();
|
||||||
|
|
||||||
|
for (start_page = DROM0_PAGES_START;
|
||||||
|
start_page < DROM0_PAGES_END;
|
||||||
|
++start_page)
|
||||||
|
{
|
||||||
|
if (MMU_TABLE[start_page] == MMU_INVALID)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flash_page = MMU_ADDR2PAGE(req->src_addr);
|
||||||
|
page_cnt = MMU_BYTES2PAGES(MMU_ADDR2OFF(req->src_addr) + req->size);
|
||||||
|
|
||||||
|
if (start_page + page_cnt < DROM0_PAGES_END)
|
||||||
|
{
|
||||||
|
mapped_addr = (start_page - DROM0_PAGES_START) *
|
||||||
|
MMU_PAGE_SIZE +
|
||||||
|
VADDR0_START_ADDR;
|
||||||
|
|
||||||
|
for (i = 0; i < page_cnt; i++)
|
||||||
|
{
|
||||||
|
MMU_TABLE[start_page + i] = flash_page + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
req->start_page = start_page;
|
||||||
|
req->page_cnt = page_cnt;
|
||||||
|
req->ptr = (void *)(mapped_addr + MMU_ADDR2OFF(req->src_addr));
|
||||||
|
ret = OK;
|
||||||
|
int 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(mapped_addr, page_cnt * MMU_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = -ENOBUFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
spiflash_end();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32s3_ummap
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Unmap SPI Flash address in ESP32-S3's address bus, and free resource.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* req - SPI Flash mapping requesting parameters
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void esp32s3_ummap(const struct spiflash_map_req_s *req)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
spiflash_start();
|
||||||
|
|
||||||
|
for (i = req->start_page; i < req->start_page + req->page_cnt; ++i)
|
||||||
|
{
|
||||||
|
MMU_TABLE[i] = MMU_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
spiflash_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: spi_flash_read_encrypted
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Read decrypted data from SPI Flash at designated address when
|
||||||
|
* enable SPI Flash hardware encryption.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* addr - target address
|
||||||
|
* buffer - data buffer pointer
|
||||||
|
* size - data number
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* OK if success or a negative value if fail.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int spi_flash_read_encrypted(uint32_t addr, void *buffer, uint32_t size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct spiflash_map_req_s req =
|
||||||
|
{
|
||||||
|
.src_addr = addr,
|
||||||
|
.size = size
|
||||||
|
};
|
||||||
|
|
||||||
|
ret = esp32s3_mmap(&req);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, req.ptr, size);
|
||||||
|
|
||||||
|
esp32s3_ummap(&req);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32S3_SPI_FLASH_DONT_USE_ROM_CODE
|
||||||
|
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_flushmapped(addr, FLASH_SECTOR_SIZE);
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
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_flushmapped(start_address, FLASH_SECTOR_SIZE * size);
|
||||||
|
spiflash_end();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
int ret = OK;
|
||||||
|
const uint8_t *tx_buf = (const uint8_t *)buffer;
|
||||||
|
uint32_t tx_bytes = size;
|
||||||
|
uint32_t tx_addr = dest_addr;
|
||||||
|
#ifdef CONFIG_ESP32S3_SPIRAM
|
||||||
|
bool buffer_in_psram = esp32s3_ptr_extram(buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32S3_SPIRAM
|
||||||
|
|
||||||
|
/* Re-enable cache, and then copy data from PSRAM to SRAM */
|
||||||
|
|
||||||
|
if (buffer_in_psram)
|
||||||
|
{
|
||||||
|
spiflash_resume_cache();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memcpy(spi_buffer, tx_buf, n);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32S3_SPIRAM
|
||||||
|
|
||||||
|
/* Disable cache, and then write data from SRAM to flash */
|
||||||
|
|
||||||
|
if (buffer_in_psram)
|
||||||
|
{
|
||||||
|
spiflash_suspend_cache();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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_flushmapped(dest_addr, size);
|
||||||
|
spiflash_end();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: spi_flash_read
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Read data from Flash.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* src_addr - source address of the data in Flash.
|
||||||
|
* dest - pointer to the destination buffer
|
||||||
|
* size - length of data
|
||||||
|
*
|
||||||
|
* Returned Values:
|
||||||
|
* Zero (OK) is returned or a negative error.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int spi_flash_read(uint32_t src_addr, void *dest, uint32_t size)
|
||||||
|
{
|
||||||
|
int ret = OK;
|
||||||
|
uint8_t *rx_buf = (uint8_t *)dest;
|
||||||
|
uint32_t rx_bytes = size;
|
||||||
|
uint32_t rx_addr = src_addr;
|
||||||
|
#ifdef CONFIG_ESP32S3_SPIRAM
|
||||||
|
bool buffer_in_psram = esp32s3_ptr_extram(dest);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
spiflash_start();
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < size; 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);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32S3_SPIRAM
|
||||||
|
|
||||||
|
/* Re-enable cache, and then copy data from SRAM to PSRAM */
|
||||||
|
|
||||||
|
if (buffer_in_psram)
|
||||||
|
{
|
||||||
|
spiflash_resume_cache();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memcpy(rx_buf, spi_buffer, n);
|
||||||
|
rx_bytes -= n;
|
||||||
|
rx_buf += n;
|
||||||
|
rx_addr += n;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32S3_SPIRAM
|
||||||
|
|
||||||
|
/* Disable cache, and then read data from flash to SRAM */
|
||||||
|
|
||||||
|
if (buffer_in_psram)
|
||||||
|
{
|
||||||
|
spiflash_suspend_cache();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
spiflash_end();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_ESP32S3_SPI_FLASH_DONT_USE_ROM_CODE */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: esp32s3_spiflash_init
|
* Name: esp32s3_spiflash_init
|
||||||
*
|
*
|
||||||
|
@ -42,10 +42,75 @@ extern "C"
|
|||||||
#define EXTERN extern
|
#define EXTERN extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* SPI Flash map request data */
|
||||||
|
|
||||||
|
struct spiflash_map_req_s
|
||||||
|
{
|
||||||
|
/* Request mapping SPI Flash base address */
|
||||||
|
|
||||||
|
uint32_t src_addr;
|
||||||
|
|
||||||
|
/* Request mapping SPI Flash size */
|
||||||
|
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
/* Mapped memory pointer */
|
||||||
|
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
/* Mapped started MMU page index */
|
||||||
|
|
||||||
|
uint32_t start_page;
|
||||||
|
|
||||||
|
/* Mapped MMU page count */
|
||||||
|
|
||||||
|
uint32_t page_cnt;
|
||||||
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32s3_mmap
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Mapped SPI Flash address to ESP32-S3's address bus, so that software
|
||||||
|
* can read SPI Flash data by reading data from memory access.
|
||||||
|
*
|
||||||
|
* If SPI Flash hardware encryption is enable, the read from mapped
|
||||||
|
* address is decrypted.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* req - SPI Flash mapping requesting parameters
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* 0 if success or a negative value if fail.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int esp32s3_mmap(struct spiflash_map_req_s *req);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32s3_ummap
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Unmap SPI Flash address in ESP32-S3's address bus, and free resource.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* req - SPI Flash mapping requesting parameters
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void esp32s3_ummap(const struct spiflash_map_req_s *req);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: spi_flash_read_encrypted
|
* Name: spi_flash_read_encrypted
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user