spi_flash: Fixed bug in SPI flash ROM driver to work with embedded flash chip

1) fixed SPI_read_status: added check for flash busy flag in matrix mode
2) fixed SPI_page_program: enable write before writing data to SPI FIFO
3) SPI flash ROM funcs replacement is controlled via menuconfig option
This commit is contained in:
Alexey Gerenkov 2017-03-09 10:29:00 +03:00 committed by Ivan Grokhotkov
parent 375b28650b
commit 0860f46220
15 changed files with 982 additions and 321 deletions

View file

@ -248,7 +248,7 @@ void bootloader_main()
#endif
esp_image_header_t fhdr;
bootloader_state_t bs;
SpiFlashOpResult spiRet1,spiRet2;
esp_rom_spiflash_result_t spiRet1,spiRet2;
esp_ota_select_entry_t sa,sb;
const esp_ota_select_entry_t *ota_select_map;
@ -258,7 +258,7 @@ void bootloader_main()
/* disable watch dog here */
REG_CLR_BIT( RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN );
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
SPIUnlock();
esp_rom_spiflash_unlock();
ESP_LOGI(TAG, "Enabling RNG early entropy source...");
bootloader_random_enable();
@ -298,7 +298,7 @@ void bootloader_main()
memcpy(&sb, (uint8_t *)ota_select_map + SPI_SEC_SIZE, sizeof(esp_ota_select_entry_t));
bootloader_munmap(ota_select_map);
if(sa.ota_seq == 0xFFFFFFFF && sb.ota_seq == 0xFFFFFFFF) {
// init status flash
// init status flash
if (bs.factory.offset != 0) { // if have factory bin,boot factory bin
load_part_pos = bs.factory;
} else {
@ -308,19 +308,19 @@ void bootloader_main()
sb.ota_seq = 0x00;
sb.crc = ota_select_crc(&sb);
Cache_Read_Disable(0);
spiRet1 = SPIEraseSector(bs.ota_info.offset/0x1000);
spiRet2 = SPIEraseSector(bs.ota_info.offset/0x1000+1);
if (spiRet1 != SPI_FLASH_RESULT_OK || spiRet2 != SPI_FLASH_RESULT_OK ) {
Cache_Read_Disable(0);
spiRet1 = esp_rom_spiflash_erase_sector(bs.ota_info.offset/0x1000);
spiRet2 = esp_rom_spiflash_erase_sector(bs.ota_info.offset/0x1000+1);
if (spiRet1 != ESP_ROM_SPIFLASH_RESULT_OK || spiRet2 != ESP_ROM_SPIFLASH_RESULT_OK ) {
ESP_LOGE(TAG, SPI_ERROR_LOG);
return;
}
spiRet1 = SPIWrite(bs.ota_info.offset,(uint32_t *)&sa,sizeof(esp_ota_select_entry_t));
spiRet2 = SPIWrite(bs.ota_info.offset + 0x1000,(uint32_t *)&sb,sizeof(esp_ota_select_entry_t));
if (spiRet1 != SPI_FLASH_RESULT_OK || spiRet2 != SPI_FLASH_RESULT_OK ) {
}
spiRet1 = esp_rom_spiflash_write(bs.ota_info.offset,(uint32_t *)&sa,sizeof(esp_ota_select_entry_t));
spiRet2 = esp_rom_spiflash_write(bs.ota_info.offset + 0x1000,(uint32_t *)&sb,sizeof(esp_ota_select_entry_t));
if (spiRet1 != ESP_ROM_SPIFLASH_RESULT_OK || spiRet2 != ESP_ROM_SPIFLASH_RESULT_OK ) {
ESP_LOGE(TAG, SPI_ERROR_LOG);
return;
}
}
Cache_Read_Enable(0);
}
//TODO:write data in ota info
@ -545,7 +545,7 @@ static void set_cache_and_start_app(
uint32_t drom_size,
uint32_t irom_addr,
uint32_t irom_load_addr,
uint32_t irom_size,
uint32_t irom_size,
uint32_t entry_addr)
{
ESP_LOGD(TAG, "configure drom and irom and start");
@ -602,7 +602,7 @@ static void update_flash_config(const esp_image_header_t* pfhdr)
}
Cache_Read_Disable( 0 );
// Set flash chip size
SPIParamCfg(g_rom_flashchip.deviceId, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
// TODO: set mode
// TODO: set frequency
Cache_Flush(0);

View file

@ -11,6 +11,10 @@ LINKER_SCRIPTS := \
$(IDF_PATH)/components/esp32/ld/esp32.peripherals.ld \
esp32.bootloader.rom.ld
ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
LINKER_SCRIPTS += $(IDF_PATH)/components/esp32/ld/esp32.rom.spiflash.ld
endif
COMPONENT_ADD_LDFLAGS := -L $(COMPONENT_PATH) -lmain $(addprefix -T ,$(LINKER_SCRIPTS))
COMPONENT_ADD_LINKER_DEPS := $(LINKER_SCRIPTS)

View file

@ -110,7 +110,7 @@ void bootloader_enable_qio_mode(void)
int i;
ESP_LOGD(TAG, "Probing for QIO mode enable...");
SPI_Wait_Idle(&g_rom_flashchip);
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
/* Set up some of the SPIFLASH user/ctrl variables which don't change
while we're probing using execute_flash_command() */
@ -150,7 +150,7 @@ static void enable_qio_mode(read_status_fn_t read_status_fn,
{
uint32_t status;
SPI_Wait_Idle(&g_rom_flashchip);
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
status = read_status_fn();
ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
@ -159,7 +159,7 @@ static void enable_qio_mode(read_status_fn_t read_status_fn,
execute_flash_command(CMD_WREN, 0, 0, 0);
write_status_fn(status | (1<<status_qio_bit));
SPI_Wait_Idle(&g_rom_flashchip);
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
status = read_status_fn();
ESP_LOGD(TAG, "Updated flash chip status 0x%x", status);
@ -174,13 +174,13 @@ static void enable_qio_mode(read_status_fn_t read_status_fn,
ESP_LOGD(TAG, "Enabling QIO mode...");
SpiFlashRdMode mode;
esp_rom_spiflash_read_mode_t mode;
#if CONFIG_FLASHMODE_QOUT
mode = SPI_FLASH_QOUT_MODE;
mode = ESP_ROM_SPIFLASH_QOUT_MODE;
#else
mode = SPI_FLASH_QIO_MODE;
mode = ESP_ROM_SPIFLASH_QIO_MODE;
#endif
SPIMasterReadModeCnfig(mode);
esp_rom_spiflash_master_config_readmode(mode);
}
static unsigned read_status_8b_rdsr()

View file

@ -127,14 +127,14 @@ void bootloader_munmap(const void *mapping)
}
}
static esp_err_t spi_to_esp_err(SpiFlashOpResult r)
static esp_err_t spi_to_esp_err(esp_rom_spiflash_result_t r)
{
switch(r) {
case SPI_FLASH_RESULT_OK:
case ESP_ROM_SPIFLASH_RESULT_OK:
return ESP_OK;
case SPI_FLASH_RESULT_ERR:
case ESP_ROM_SPIFLASH_RESULT_ERR:
return ESP_ERR_FLASH_OP_FAIL;
case SPI_FLASH_RESULT_TIMEOUT:
case ESP_ROM_SPIFLASH_RESULT_TIMEOUT:
return ESP_ERR_FLASH_OP_TIMEOUT;
default:
return ESP_FAIL;
@ -145,7 +145,7 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
{
Cache_Read_Disable(0);
Cache_Flush(0);
SpiFlashOpResult r = SPIRead(src_addr, dest, size);
esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
Cache_Read_Enable(0);
return spi_to_esp_err(r);
@ -221,21 +221,21 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
return ESP_FAIL;
}
err = spi_to_esp_err(SPIUnlock());
err = spi_to_esp_err(esp_rom_spiflash_unlock());
if (err != ESP_OK) {
return err;
}
if (write_encrypted) {
return spi_to_esp_err(SPI_Encrypt_Write(dest_addr, src, size));
return spi_to_esp_err(esp_rom_spiflash_write_encrypted(dest_addr, src, size));
} else {
return spi_to_esp_err(SPIWrite(dest_addr, src, size));
return spi_to_esp_err(esp_rom_spiflash_write(dest_addr, src, size));
}
}
esp_err_t bootloader_flash_erase_sector(size_t sector)
{
return spi_to_esp_err(SPIEraseSector(sector));
return spi_to_esp_err(esp_rom_spiflash_erase_sector(sector));
}
#endif

View file

@ -17,6 +17,10 @@ ifeq ("$(CONFIG_NEWLIB_NANO_FORMAT)","y")
LINKER_SCRIPTS += esp32.rom.nanofmt.ld
endif
ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
LINKER_SCRIPTS += esp32.rom.spiflash.ld
endif
COMPONENT_ADD_LDFLAGS := -lesp32 \
$(COMPONENT_PATH)/libhal.a \
-L$(COMPONENT_PATH)/lib \

View file

@ -65,81 +65,81 @@ extern "C" {
*************************************************************
*/
#define PERIPHS_SPI_FLASH_CMD SPI_CMD(1)
#define PERIPHS_SPI_FLASH_ADDR SPI_ADDR(1)
#define PERIPHS_SPI_FLASH_CTRL SPI_CTRL(1)
#define PERIPHS_SPI_FLASH_CTRL1 SPI_CTRL1(1)
#define PERIPHS_SPI_FLASH_STATUS SPI_RD_STATUS(1)
#define PERIPHS_SPI_FLASH_USRREG SPI_USER(1)
#define PERIPHS_SPI_FLASH_USRREG1 SPI_USER1(1)
#define PERIPHS_SPI_FLASH_USRREG2 SPI_USER2(1)
#define PERIPHS_SPI_FLASH_C0 SPI_W0(1)
#define PERIPHS_SPI_FLASH_C1 SPI_W1(1)
#define PERIPHS_SPI_FLASH_C2 SPI_W2(1)
#define PERIPHS_SPI_FLASH_C3 SPI_W3(1)
#define PERIPHS_SPI_FLASH_C4 SPI_W4(1)
#define PERIPHS_SPI_FLASH_C5 SPI_W5(1)
#define PERIPHS_SPI_FLASH_C6 SPI_W6(1)
#define PERIPHS_SPI_FLASH_C7 SPI_W7(1)
#define PERIPHS_SPI_FLASH_TX_CRC SPI_TX_CRC(1)
#define PERIPHS_SPI_FLASH_CMD SPI_CMD_REG(1)
#define PERIPHS_SPI_FLASH_ADDR SPI_ADDR_REG(1)
#define PERIPHS_SPI_FLASH_CTRL SPI_CTRL_REG(1)
#define PERIPHS_SPI_FLASH_CTRL1 SPI_CTRL1_REG(1)
#define PERIPHS_SPI_FLASH_STATUS SPI_RD_STATUS_REG(1)
#define PERIPHS_SPI_FLASH_USRREG SPI_USER_REG(1)
#define PERIPHS_SPI_FLASH_USRREG1 SPI_USER1_REG(1)
#define PERIPHS_SPI_FLASH_USRREG2 SPI_USER2_REG(1)
#define PERIPHS_SPI_FLASH_C0 SPI_W0_REG(1)
#define PERIPHS_SPI_FLASH_C1 SPI_W1_REG(1)
#define PERIPHS_SPI_FLASH_C2 SPI_W2_REG(1)
#define PERIPHS_SPI_FLASH_C3 SPI_W3_REG(1)
#define PERIPHS_SPI_FLASH_C4 SPI_W4_REG(1)
#define PERIPHS_SPI_FLASH_C5 SPI_W5_REG(1)
#define PERIPHS_SPI_FLASH_C6 SPI_W6_REG(1)
#define PERIPHS_SPI_FLASH_C7 SPI_W7_REG(1)
#define PERIPHS_SPI_FLASH_TX_CRC SPI_TX_CRC_REG(1)
#define SPI0_R_QIO_DUMMY_CYCLELEN 3
#define SPI0_R_QIO_ADDR_BITSLEN 31
#define SPI0_R_FAST_DUMMY_CYCLELEN 7
#define SPI0_R_DIO_DUMMY_CYCLELEN 3
#define SPI0_R_FAST_ADDR_BITSLEN 23
#define SPI0_R_SIO_ADDR_BITSLEN 23
#define SPI0_R_QIO_DUMMY_CYCLELEN 3
#define SPI0_R_QIO_ADDR_BITSLEN 31
#define SPI0_R_FAST_DUMMY_CYCLELEN 7
#define SPI0_R_DIO_DUMMY_CYCLELEN 3
#define SPI0_R_FAST_ADDR_BITSLEN 23
#define SPI0_R_SIO_ADDR_BITSLEN 23
#define SPI1_R_QIO_DUMMY_CYCLELEN 3
#define SPI1_R_QIO_ADDR_BITSLEN 31
#define SPI1_R_FAST_DUMMY_CYCLELEN 7
#define SPI1_R_DIO_DUMMY_CYCLELEN 3
#define SPI1_R_DIO_ADDR_BITSLEN 31
#define SPI1_R_FAST_ADDR_BITSLEN 23
#define SPI1_R_SIO_ADDR_BITSLEN 23
#define SPI1_R_QIO_DUMMY_CYCLELEN 3
#define SPI1_R_QIO_ADDR_BITSLEN 31
#define SPI1_R_FAST_DUMMY_CYCLELEN 7
#define SPI1_R_DIO_DUMMY_CYCLELEN 3
#define SPI1_R_DIO_ADDR_BITSLEN 31
#define SPI1_R_FAST_ADDR_BITSLEN 23
#define SPI1_R_SIO_ADDR_BITSLEN 23
#define SPI_W_SIO_ADDR_BITSLEN 23
#define ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN 23
#define TWO_BYTE_STATUS_EN SPI_WRSR_2B
#define ESP_ROM_SPIFLASH_TWO_BYTE_STATUS_EN SPI_WRSR_2B
//SPI address register
#define SPI_FLASH_BYTES_LEN 24
#define SPI_BUFF_BYTE_WRITE_NUM 32
#define SPI_BUFF_BYTE_READ_NUM 64
#define SPI_BUFF_BYTE_READ_BITS 0x3f
#define ESP_ROM_SPIFLASH_BYTES_LEN 24
#define ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM 32
#define ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM 64
#define ESP_ROM_SPIFLASH_BUFF_BYTE_READ_BITS 0x3f
//SPI status register
#define SPI_FLASH_BUSY_FLAG BIT0
#define SPI_FLASH_WRENABLE_FLAG BIT1
#define SPI_FLASH_BP0 BIT2
#define SPI_FLASH_BP1 BIT3
#define SPI_FLASH_BP2 BIT4
#define FLASH_WR_PROTECT (SPI_FLASH_BP0|SPI_FLASH_BP1|SPI_FLASH_BP2)
#define SPI_FLASH_QE BIT9
#define ESP_ROM_SPIFLASH_BUSY_FLAG BIT0
#define ESP_ROM_SPIFLASH_WRENABLE_FLAG BIT1
#define ESP_ROM_SPIFLASH_BP0 BIT2
#define ESP_ROM_SPIFLASH_BP1 BIT3
#define ESP_ROM_SPIFLASH_BP2 BIT4
#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2)
#define ESP_ROM_SPIFLASH_QE BIT9
typedef enum {
SPI_FLASH_QIO_MODE = 0,
SPI_FLASH_QOUT_MODE,
SPI_FLASH_DIO_MODE,
SPI_FLASH_DOUT_MODE,
SPI_FLASH_FASTRD_MODE,
SPI_FLASH_SLOWRD_MODE
} SpiFlashRdMode;
ESP_ROM_SPIFLASH_QIO_MODE = 0,
ESP_ROM_SPIFLASH_QOUT_MODE,
ESP_ROM_SPIFLASH_DIO_MODE,
ESP_ROM_SPIFLASH_DOUT_MODE,
ESP_ROM_SPIFLASH_FASTRD_MODE,
ESP_ROM_SPIFLASH_SLOWRD_MODE
} esp_rom_spiflash_read_mode_t;
typedef enum {
SPI_FLASH_RESULT_OK,
SPI_FLASH_RESULT_ERR,
SPI_FLASH_RESULT_TIMEOUT
} SpiFlashOpResult;
ESP_ROM_SPIFLASH_RESULT_OK,
ESP_ROM_SPIFLASH_RESULT_ERR,
ESP_ROM_SPIFLASH_RESULT_TIMEOUT
} esp_rom_spiflash_result_t;
typedef struct {
uint32_t deviceId;
uint32_t device_id;
uint32_t chip_size; // chip size in bytes
uint32_t block_size;
uint32_t sector_size;
uint32_t page_size;
uint32_t status_mask;
} SpiFlashChip;
} esp_rom_spiflash_chip_t;
typedef struct {
uint8_t data_length;
@ -148,7 +148,7 @@ typedef struct {
uint8_t write_cmd;
uint16_t data_mask;
uint16_t data;
} SpiCommonCmd;
} esp_rom_spiflash_common_cmd_t;
/**
* @brief Fix the bug in SPI hardware communication with Flash/Ext-SRAM in High Speed.
@ -160,7 +160,7 @@ typedef struct {
*
* @return None
*/
void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv);
void esp_rom_spiflash_fix_dummylen(uint8_t spi, uint8_t freqdiv);
/**
* @brief Select SPI Flash to QIO mode when WP pad is read from Flash.
@ -173,7 +173,7 @@ void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv);
*
* @return None
*/
void SelectSpiQIO(uint8_t wp_gpio_num, uint32_t ishspi);
void esp_rom_spiflash_select_qiomode(uint8_t wp_gpio_num, uint32_t ishspi);
/**
* @brief Set SPI Flash pad drivers.
@ -191,7 +191,7 @@ void SelectSpiQIO(uint8_t wp_gpio_num, uint32_t ishspi);
*
* @return None
*/
void SetSpiDrvs(uint8_t wp_gpio_num, uint32_t ishspi, uint8_t *drvs);
void esp_rom_spiflash_set_drvs(uint8_t wp_gpio_num, uint32_t ishspi, uint8_t *drvs);
/**
* @brief Select SPI Flash function for pads.
@ -202,7 +202,7 @@ void SetSpiDrvs(uint8_t wp_gpio_num, uint32_t ishspi, uint8_t *drvs);
*
* @return None
*/
void SelectSpiFunction(uint32_t ishspi);
void esp_rom_spiflash_select_padsfunc(uint32_t ishspi);
/**
* @brief SPI Flash init, clock divisor is 4, use 1 line Slow read mode.
@ -215,89 +215,89 @@ void SelectSpiFunction(uint32_t ishspi);
*
* @return None
*/
void spi_flash_attach(uint32_t ishspi, bool legacy);
void esp_rom_spiflash_attach(uint32_t ishspi, bool legacy);
/**
* @brief SPI Read Flash status register. We use CMD 0x05 (RDSR).
* Please do not call this function in SDK.
*
* @param SpiFlashChip *spi : The information for Flash, which is exported from ld file.
* @param esp_rom_spiflash_chip_t *spi : The information for Flash, which is exported from ld file.
*
* @param uint32_t *status : The pointer to which to return the Flash status value.
*
* @return SPI_FLASH_RESULT_OK : read OK.
* SPI_FLASH_RESULT_ERR : read error.
* SPI_FLASH_RESULT_TIMEOUT : read timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : read OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : read error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : read timeout.
*/
SpiFlashOpResult SPI_read_status(SpiFlashChip *spi, uint32_t *status);
esp_rom_spiflash_result_t esp_rom_spiflash_read_status(esp_rom_spiflash_chip_t *spi, uint32_t *status);
/**
* @brief SPI Read Flash status register bits 8-15. We use CMD 0x35 (RDSR2).
* Please do not call this function in SDK.
*
* @param SpiFlashChip *spi : The information for Flash, which is exported from ld file.
* @param esp_rom_spiflash_chip_t *spi : The information for Flash, which is exported from ld file.
*
* @param uint32_t *status : The pointer to which to return the Flash status value.
*
* @return SPI_FLASH_RESULT_OK : read OK.
* SPI_FLASH_RESULT_ERR : read error.
* SPI_FLASH_RESULT_TIMEOUT : read timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : read OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : read error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : read timeout.
*/
SpiFlashOpResult SPI_read_status_high(uint32_t *status);
esp_rom_spiflash_result_t esp_rom_spiflash_read_statushigh(esp_rom_spiflash_chip_t *spi, uint32_t *status);
/**
* @brief Write status to Falsh status register.
* Please do not call this function in SDK.
*
* @param SpiFlashChip *spi : The information for Flash, which is exported from ld file.
* @param esp_rom_spiflash_chip_t *spi : The information for Flash, which is exported from ld file.
*
* @param uint32_t status_value : Value to .
*
* @return SPI_FLASH_RESULT_OK : write OK.
* SPI_FLASH_RESULT_ERR : write error.
* SPI_FLASH_RESULT_TIMEOUT : write timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : write OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : write error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : write timeout.
*/
SpiFlashOpResult SPI_write_status(SpiFlashChip *spi, uint32_t status_value);
esp_rom_spiflash_result_t esp_rom_spiflash_write_status(esp_rom_spiflash_chip_t *spi, uint32_t status_value);
/**
* @brief Use a command to Read Flash status register.
* Please do not call this function in SDK.
*
* @param SpiFlashChip *spi : The information for Flash, which is exported from ld file.
* @param esp_rom_spiflash_chip_t *spi : The information for Flash, which is exported from ld file.
*
* @param uint32_t*status : The pointer to which to return the Flash status value.
*
* @return SPI_FLASH_RESULT_OK : read OK.
* SPI_FLASH_RESULT_ERR : read error.
* SPI_FLASH_RESULT_TIMEOUT : read timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : read OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : read error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : read timeout.
*/
SpiFlashOpResult SPI_user_command_read(uint32_t *status, uint8_t cmd);
esp_rom_spiflash_result_t esp_rom_spiflash_read_user_cmd(uint32_t *status, uint8_t cmd);
/**
* @brief Config SPI Flash read mode when init.
* Please do not call this function in SDK.
*
* @param SpiFlashRdMode mode : QIO/QOUT/DIO/DOUT/FastRD/SlowRD.
* @param esp_rom_spiflash_read_mode_t mode : QIO/QOUT/DIO/DOUT/FastRD/SlowRD.
*
* @param uint8_t legacy: In legacy mode, more SPI command is used in line.
*
* @return SPI_FLASH_RESULT_OK : config OK.
* SPI_FLASH_RESULT_ERR : config error.
* SPI_FLASH_RESULT_TIMEOUT : config timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : config OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : config error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : config timeout.
*/
SpiFlashOpResult SPIReadModeCnfig(SpiFlashRdMode mode, bool legacy);
esp_rom_spiflash_result_t esp_rom_spiflash_config_readmode(esp_rom_spiflash_read_mode_t mode, bool legacy);
/**
* @brief Config SPI Flash read mode when Flash is running in some mode.
* Please do not call this function in SDK.
*
* @param SpiFlashRdMode mode : QIO/QOUT/DIO/DOUT/FastRD/SlowRD.
* @param esp_rom_spiflash_read_mode_t mode : QIO/QOUT/DIO/DOUT/FastRD/SlowRD.
*
* @return SPI_FLASH_RESULT_OK : config OK.
* SPI_FLASH_RESULT_ERR : config error.
* SPI_FLASH_RESULT_TIMEOUT : config timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : config OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : config error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : config timeout.
*/
SpiFlashOpResult SPIMasterReadModeCnfig(SpiFlashRdMode mode);
esp_rom_spiflash_result_t esp_rom_spiflash_master_config_readmode(esp_rom_spiflash_read_mode_t mode);
/**
* @brief Config SPI Flash clock divisor.
@ -307,23 +307,23 @@ SpiFlashOpResult SPIMasterReadModeCnfig(SpiFlashRdMode mode);
*
* @param uint8_t spi: 0 for SPI0, 1 for SPI1.
*
* @return SPI_FLASH_RESULT_OK : config OK.
* SPI_FLASH_RESULT_ERR : config error.
* SPI_FLASH_RESULT_TIMEOUT : config timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : config OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : config error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : config timeout.
*/
SpiFlashOpResult SPIClkConfig(uint8_t freqdiv, uint8_t spi);
esp_rom_spiflash_result_t esp_rom_spiflash_config_clk(uint8_t freqdiv, uint8_t spi);
/**
* @brief Send CommonCmd to Flash so that is can go into QIO mode, some Flash use different CMD.
* Please do not call this function in SDK.
*
* @param SpiCommonCmd *cmd : A struct to show the action of a command.
* @param esp_rom_spiflash_common_cmd_t *cmd : A struct to show the action of a command.
*
* @return uint16_t 0 : do not send command any more.
* 1 : go to the next command.
* n > 1 : skip (n - 1) commands.
*/
uint16_t SPI_Common_Command(SpiCommonCmd *cmd);
uint16_t esp_rom_spiflash_common_cmd(esp_rom_spiflash_common_cmd_t *cmd);
/**
* @brief Unlock SPI write protect.
@ -331,11 +331,11 @@ uint16_t SPI_Common_Command(SpiCommonCmd *cmd);
*
* @param None.
*
* @return SPI_FLASH_RESULT_OK : Unlock OK.
* SPI_FLASH_RESULT_ERR : Unlock error.
* SPI_FLASH_RESULT_TIMEOUT : Unlock timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Unlock OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : Unlock error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Unlock timeout.
*/
SpiFlashOpResult SPIUnlock(void);
esp_rom_spiflash_result_t esp_rom_spiflash_unlock(void);
/**
* @brief SPI write protect.
@ -343,11 +343,11 @@ SpiFlashOpResult SPIUnlock(void);
*
* @param None.
*
* @return SPI_FLASH_RESULT_OK : Lock OK.
* SPI_FLASH_RESULT_ERR : Lock error.
* SPI_FLASH_RESULT_TIMEOUT : Lock timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Lock OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : Lock error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Lock timeout.
*/
SpiFlashOpResult SPILock(void);
esp_rom_spiflash_result_t esp_rom_spiflash_lock(void);
/**
* @brief Update SPI Flash parameter.
@ -365,11 +365,12 @@ SpiFlashOpResult SPILock(void);
*
* @param uint32_t status_mask : The Mask used when read status from Flash(use single CMD).
*
* @return SPI_FLASH_RESULT_OK : Update OK.
* SPI_FLASH_RESULT_ERR : Update error.
* SPI_FLASH_RESULT_TIMEOUT : Update timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Update OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : Update error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Update timeout.
*/
SpiFlashOpResult SPIParamCfg(uint32_t deviceId, uint32_t chip_size, uint32_t block_size, uint32_t sector_size, uint32_t page_size, uint32_t status_mask);
esp_rom_spiflash_result_t esp_rom_spiflash_config_param(uint32_t deviceId, uint32_t chip_size, uint32_t block_size,
uint32_t sector_size, uint32_t page_size, uint32_t status_mask);
/**
* @brief Erase whole flash chip.
@ -377,11 +378,11 @@ SpiFlashOpResult SPIParamCfg(uint32_t deviceId, uint32_t chip_size, uint32_t blo
*
* @param None
*
* @return SPI_FLASH_RESULT_OK : Erase OK.
* SPI_FLASH_RESULT_ERR : Erase error.
* SPI_FLASH_RESULT_TIMEOUT : Erase timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Erase OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : Erase error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Erase timeout.
*/
SpiFlashOpResult SPIEraseChip(void);
esp_rom_spiflash_result_t esp_rom_spiflash_erase_chip(void);
/**
* @brief Erase a 64KB block of flash
@ -390,11 +391,11 @@ SpiFlashOpResult SPIEraseChip(void);
*
* @param uint32_t block_num : Which block to erase.
*
* @return SPI_FLASH_RESULT_OK : Erase OK.
* SPI_FLASH_RESULT_ERR : Erase error.
* SPI_FLASH_RESULT_TIMEOUT : Erase timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Erase OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : Erase error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Erase timeout.
*/
SpiFlashOpResult SPIEraseBlock(uint32_t block_num);
esp_rom_spiflash_result_t esp_rom_spiflash_erase_block(uint32_t block_num);
/**
* @brief Erase a sector of flash.
@ -403,11 +404,11 @@ SpiFlashOpResult SPIEraseBlock(uint32_t block_num);
*
* @param uint32_t sector_num : Which sector to erase.
*
* @return SPI_FLASH_RESULT_OK : Erase OK.
* SPI_FLASH_RESULT_ERR : Erase error.
* SPI_FLASH_RESULT_TIMEOUT : Erase timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Erase OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : Erase error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Erase timeout.
*/
SpiFlashOpResult SPIEraseSector(uint32_t sector_num);
esp_rom_spiflash_result_t esp_rom_spiflash_erase_sector(uint32_t sector_num);
/**
* @brief Erase some sectors.
@ -417,11 +418,11 @@ SpiFlashOpResult SPIEraseSector(uint32_t sector_num);
*
* @param uint32_t area_len : Length to erase, should be sector aligned.
*
* @return SPI_FLASH_RESULT_OK : Erase OK.
* SPI_FLASH_RESULT_ERR : Erase error.
* SPI_FLASH_RESULT_TIMEOUT : Erase timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Erase OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : Erase error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Erase timeout.
*/
SpiFlashOpResult SPIEraseArea(uint32_t start_addr, uint32_t area_len);
esp_rom_spiflash_result_t esp_rom_spiflash_erase_area(uint32_t start_addr, uint32_t area_len);
/**
* @brief Write Data to Flash, you should Erase it yourself if need.
@ -433,11 +434,11 @@ SpiFlashOpResult SPIEraseArea(uint32_t start_addr, uint32_t area_len);
*
* @param uint32_t len : Length to write, should be 4 bytes aligned.
*
* @return SPI_FLASH_RESULT_OK : Write OK.
* SPI_FLASH_RESULT_ERR : Write error.
* SPI_FLASH_RESULT_TIMEOUT : Write timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Write OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : Write error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Write timeout.
*/
SpiFlashOpResult SPIWrite(uint32_t dest_addr, const uint32_t *src, int32_t len);
esp_rom_spiflash_result_t esp_rom_spiflash_write(uint32_t dest_addr, const uint32_t *src, int32_t len);
/**
* @brief Read Data from Flash, you should Erase it yourself if need.
@ -449,11 +450,11 @@ SpiFlashOpResult SPIWrite(uint32_t dest_addr, const uint32_t *src, int32_t len);
*
* @param uint32_t len : Length to read, should be 4 bytes aligned.
*
* @return SPI_FLASH_RESULT_OK : Read OK.
* SPI_FLASH_RESULT_ERR : Read error.
* SPI_FLASH_RESULT_TIMEOUT : Read timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Read OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : Read error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Read timeout.
*/
SpiFlashOpResult SPIRead(uint32_t src_addr, uint32_t *dest, int32_t len);
esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t src_addr, uint32_t *dest, int32_t len);
/**
* @brief SPI1 go into encrypto mode.
@ -463,7 +464,7 @@ SpiFlashOpResult SPIRead(uint32_t src_addr, uint32_t *dest, int32_t len);
*
* @return None
*/
void SPI_Write_Encrypt_Enable(void);
void esp_rom_spiflash_write_encrypted_enable(void);
/**
* @brief Prepare 32 Bytes data to encrpto writing, you should Erase it yourself if need.
@ -473,11 +474,11 @@ void SPI_Write_Encrypt_Enable(void);
*
* @param uint32_t *data : The pointer to data which is to write.
*
* @return SPI_FLASH_RESULT_OK : Prepare OK.
* SPI_FLASH_RESULT_ERR : Prepare error.
* SPI_FLASH_RESULT_TIMEOUT : Prepare timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Prepare OK.
* ESP_ROM_SPIFLASH_RESULT_ERR : Prepare error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Prepare timeout.
*/
SpiFlashOpResult SPI_Prepare_Encrypt_Data(uint32_t flash_addr, uint32_t *data);
esp_rom_spiflash_result_t esp_rom_spiflash_prepare_encrypted_data(uint32_t flash_addr, uint32_t *data);
/**
* @brief SPI1 go out of encrypto mode.
@ -487,7 +488,7 @@ SpiFlashOpResult SPI_Prepare_Encrypt_Data(uint32_t flash_addr, uint32_t *data);
*
* @return None
*/
void SPI_Write_Encrypt_Disable(void);
void esp_rom_spiflash_write_encrypted_disable(void);
/**
* @brief Write data to flash with transparent encryption.
@ -503,11 +504,11 @@ void SPI_Write_Encrypt_Disable(void);
*
* @param uint32_t len : Length to write, should be 32 bytes aligned.
*
* @return SPI_FLASH_RESULT_OK : Data written successfully.
* SPI_FLASH_RESULT_ERR : Encryption write error.
* SPI_FLASH_RESULT_TIMEOUT : Encrypto write timeout.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Data written successfully.
* ESP_ROM_SPIFLASH_RESULT_ERR : Encryption write error.
* ESP_ROM_SPIFLASH_RESULT_TIMEOUT : Encrypto write timeout.
*/
SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, uint32_t *data, uint32_t len);
esp_rom_spiflash_result_t esp_rom_spiflash_write_encrypted(uint32_t flash_addr, uint32_t *data, uint32_t len);
/** @brief Wait until SPI flash write operation is complete
@ -517,16 +518,16 @@ SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, uint32_t *data, uint32_t
* Reads the Write In Progress bit of the SPI flash status register,
* repeats until this bit is zero (indicating write complete).
*
* @return SPI_FLASH_RESULT_OK : Write is complete
* SPI_FLASH_RESULT_ERR : Error while reading status.
* @return ESP_ROM_SPIFLASH_RESULT_OK : Write is complete
* ESP_ROM_SPIFLASH_RESULT_ERR : Error while reading status.
*/
SpiFlashOpResult SPI_Wait_Idle(SpiFlashChip *spi);
esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *spi);
/** @brief Global SpiFlashChip structure used by ROM functions
/** @brief Global esp_rom_spiflash_chip_t structure used by ROM functions
*
*/
extern SpiFlashChip g_rom_flashchip;
extern esp_rom_spiflash_chip_t g_rom_flashchip;
/**
* @}

View file

@ -97,6 +97,7 @@ SECTIONS
*libnet80211.a:ieee80211_misc.o(.literal .text .literal.* .text.*)
*libhal.a:(.literal .text .literal.* .text.*)
*libcoexist.a:(.literal .text .literal.* .text.*)
*libspi_flash.a:spi_flash_rom_patch.o(.literal .text .literal.* .text.*)
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg

View file

@ -125,7 +125,7 @@ PROVIDE ( __divdi3 = 0x4000ca84 );
PROVIDE ( __divsc3 = 0x40064200 );
PROVIDE ( __divsf3 = 0x4000234c );
PROVIDE ( __divsi3 = 0x4000c7b8 );
PROVIDE ( dummy_len_plus = 0x3ffae290 );
PROVIDE ( g_rom_spiflash_dummy_len_plus = 0x3ffae290 );
PROVIDE ( __dummy_lock = 0x4000c728 );
PROVIDE ( __dummy_lock_try = 0x4000c730 );
PROVIDE ( ecc_env = 0x3ffb8d60 );
@ -1349,13 +1349,10 @@ PROVIDE ( sbrk = 0x400017f4 );
PROVIDE ( _sbrk_r = 0x4000bce4 );
PROVIDE ( __sccl = 0x4000c498 );
PROVIDE ( __sclose = 0x400011b8 );
PROVIDE ( SelectSpiFunction = 0x40061f84 );
PROVIDE ( SelectSpiQIO = 0x40061ddc );
PROVIDE ( __seofread = 0x40001148 );
PROVIDE ( setjmp = 0x40056268 );
PROVIDE ( setlocale = 0x40059568 );
PROVIDE ( _setlocale_r = 0x4005950c );
PROVIDE ( SetSpiDrvs = 0x40061e78 );
PROVIDE ( __sf_fake_stderr = 0x3ff96458 );
PROVIDE ( __sf_fake_stdin = 0x3ff96498 );
PROVIDE ( __sf_fake_stdout = 0x3ff96478 );
@ -1404,40 +1401,6 @@ PROVIDE ( slc_set_host_io_max_window = 0x4000b89c );
PROVIDE ( slc_to_host_chain_recycle = 0x4000b758 );
PROVIDE ( __smakebuf_r = 0x40059108 );
PROVIDE ( specialModP256 = 0x4001600c );
PROVIDE ( spi_cache_sram_init = 0x400626e4 );
PROVIDE ( SPIClkConfig = 0x40062bc8 );
PROVIDE ( SPI_Common_Command = 0x4006246c );
PROVIDE ( spi_dummy_len_fix = 0x40061d90 );
PROVIDE ( SPI_Encrypt_Write = 0x40062e78 );
PROVIDE ( SPIEraseArea = 0x400631ac );
PROVIDE ( SPIEraseBlock = 0x40062c4c );
PROVIDE ( SPIEraseChip = 0x40062c14 );
PROVIDE ( SPIEraseSector = 0x40062ccc );
PROVIDE ( spi_flash_attach = 0x40062a6c );
/* NB: SPIUnlock @ 0x400628b0 has been replaced with an updated
version in the "spi_flash" component */
PROVIDE ( SPILock = 0x400628f0 );
PROVIDE ( SPIMasterReadModeCnfig = 0x40062b64 );
PROVIDE ( spi_modes = 0x3ff99270 );
PROVIDE ( SPIParamCfg = 0x40063238 );
PROVIDE ( SPI_Prepare_Encrypt_Data = 0x40062e1c );
PROVIDE ( SPIRead = 0x40062ed8 );
PROVIDE ( SPIReadModeCnfig = 0x40062944 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( SPI_read_status = 0x4006226c );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( SPI_read_status_high = 0x40062448 );
PROVIDE ( SPI_user_command_read = 0x400621b0 );
PROVIDE ( SPI_flashchip_data = 0x3ffae270 );
PROVIDE ( SPIWrite = 0x40062d50 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( SPI_write_enable = 0x40062320 );
PROVIDE ( SPI_Write_Encrypt_Disable = 0x40062e60 );
PROVIDE ( SPI_Write_Encrypt_Enable = 0x40062df4 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( SPI_write_status = 0x400622f0 );
/* This is static function, but can be used, not generated by script */
PROVIDE ( SPI_Wait_Idle = 0x400622c0 );
PROVIDE ( srand = 0x40001004 );
PROVIDE ( __sread = 0x40001118 );
PROVIDE ( __srefill_r = 0x400593d4 );
@ -1569,6 +1532,12 @@ PROVIDE ( xthal_set_intclear = 0x4000c1ec );
PROVIDE ( _xtos_set_intlevel = 0x4000bfdc );
PROVIDE ( g_ticks_per_us_pro = 0x3ffe01e0 );
PROVIDE ( g_ticks_per_us_app = 0x3ffe40f0 );
PROVIDE ( esp_rom_spiflash_config_param = 0x40063238 );
PROVIDE ( esp_rom_spiflash_read_user_cmd = 0x400621b0 );
PROVIDE ( esp_rom_spiflash_write_encrypted_disable = 0x40062e60 );
PROVIDE ( esp_rom_spiflash_write_encrypted_enable = 0x40062df4 );
PROVIDE ( esp_rom_spiflash_prepare_encrypted_data = 0x40062e1c );
PROVIDE ( g_rom_spiflash_chip = 0x3ffae270 );
/*
These functions are xtos-related (or call xtos-related functions) and do not play well

View file

@ -0,0 +1,23 @@
/*
Address table for SPI driver functions in ESP32 ROM.
These functions are only linked from ROM when SPI_FLASH_ROM_DRIVER_PATCH is not set in configuration.
*/
PROVIDE ( esp_rom_spiflash_write_encrypted = 0x40062e78 );
PROVIDE ( esp_rom_spiflash_erase_area = 0x400631ac );
PROVIDE ( esp_rom_spiflash_erase_block = 0x40062c4c );
PROVIDE ( esp_rom_spiflash_erase_chip = 0x40062c14 );
PROVIDE ( esp_rom_spiflash_erase_sector = 0x40062ccc );
PROVIDE ( esp_rom_spiflash_lock = 0x400628f0 );
PROVIDE ( esp_rom_spiflash_read = 0x40062ed8 );
PROVIDE ( esp_rom_spiflash_config_readmode = 0x40062944 );
PROVIDE ( esp_rom_spiflash_read_status = 0x4006226c );
PROVIDE ( esp_rom_spiflash_read_statushigh = 0x40062448 );
PROVIDE ( esp_rom_spiflash_write = 0x40062d50 );
PROVIDE ( esp_rom_spiflash_enable_write = 0x40062320 );
PROVIDE ( esp_rom_spiflash_write_status = 0x400622f0 );
/* always using patched versions of these functions
PROVIDE ( esp_rom_spiflash_wait_idle = 0x400622c0 );
PROVIDE ( esp_rom_spiflash_unlock = 0x400????? );
*/

View file

@ -11,6 +11,14 @@ config SPI_FLASH_ENABLE_COUNTERS
These APIs may be used to collect performance data for spi_flash APIs
and to help understand behaviour of libraries which use SPI flash.
config SPI_FLASH_ROM_DRIVER_PATCH
bool "Enable SPI flash ROM driver patched functions"
default y
help
Enable this flag to use patched versions of SPI flash ROM driver functions.
This option is needed to write to flash on ESP32-D2WD, and any configuration
where external SPI flash is connected to non-default pins.
endmenu

View file

@ -42,7 +42,7 @@
#define MAX_READ_CHUNK 16384
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
static const char* TAG = "spi_flash";
static const char *TAG = "spi_flash";
static spi_flash_counters_t s_flash_stats;
#define COUNTER_START() uint32_t ts_begin = xthal_get_ccount()
@ -64,20 +64,20 @@ static spi_flash_counters_t s_flash_stats;
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc);
static esp_err_t spi_flash_translate_rc(esp_rom_spiflash_result_t rc);
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = {
.start = spi_flash_disable_interrupts_caches_and_other_cpu,
.end = spi_flash_enable_interrupts_caches_and_other_cpu,
.op_lock = spi_flash_op_lock,
.op_unlock = spi_flash_op_unlock
.start = spi_flash_disable_interrupts_caches_and_other_cpu,
.end = spi_flash_enable_interrupts_caches_and_other_cpu,
.op_lock = spi_flash_op_lock,
.op_unlock = spi_flash_op_unlock
};
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_no_os_ops = {
.start = spi_flash_disable_interrupts_caches_and_other_cpu_no_os,
.end = spi_flash_enable_interrupts_caches_no_os,
.op_lock = 0,
.op_unlock = 0
.start = spi_flash_disable_interrupts_caches_and_other_cpu_no_os,
.end = spi_flash_enable_interrupts_caches_no_os,
.op_lock = 0,
.op_unlock = 0
};
static const spi_flash_guard_funcs_t *s_flash_guard_ops;
@ -90,7 +90,7 @@ void spi_flash_init()
#endif
}
void IRAM_ATTR spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs)
void IRAM_ATTR spi_flash_guard_set(const spi_flash_guard_funcs_t *funcs)
{
s_flash_guard_ops = funcs;
}
@ -128,19 +128,19 @@ static inline void IRAM_ATTR spi_flash_guard_op_unlock()
}
}
static SpiFlashOpResult IRAM_ATTR spi_flash_unlock()
static esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock()
{
static bool unlocked = false;
if (!unlocked) {
spi_flash_guard_start();
SpiFlashOpResult rc = SPIUnlock();
esp_rom_spiflash_result_t rc = esp_rom_spiflash_unlock();
spi_flash_guard_end();
if (rc != SPI_FLASH_RESULT_OK) {
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
return rc;
}
unlocked = true;
}
return SPI_FLASH_RESULT_OK;
return ESP_ROM_SPIFLASH_RESULT_OK;
}
esp_err_t IRAM_ATTR spi_flash_erase_sector(size_t sec)
@ -163,16 +163,17 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
size_t end = start + size / SPI_FLASH_SEC_SIZE;
const size_t sectors_per_block = BLOCK_ERASE_SIZE / SPI_FLASH_SEC_SIZE;
COUNTER_START();
SpiFlashOpResult rc = spi_flash_unlock();
if (rc == SPI_FLASH_RESULT_OK) {
for (size_t sector = start; sector != end && rc == SPI_FLASH_RESULT_OK; ) {
esp_rom_spiflash_result_t rc;
rc = spi_flash_unlock();
if (rc == ESP_ROM_SPIFLASH_RESULT_OK) {
for (size_t sector = start; sector != end && rc == ESP_ROM_SPIFLASH_RESULT_OK; ) {
spi_flash_guard_start();
if (sector % sectors_per_block == 0 && end - sector > sectors_per_block) {
rc = SPIEraseBlock(sector / sectors_per_block);
rc = esp_rom_spiflash_erase_block(sector / sectors_per_block);
sector += sectors_per_block;
COUNTER_ADD_BYTES(erase, sectors_per_block * SPI_FLASH_SEC_SIZE);
} else {
rc = SPIEraseSector(sector);
rc = esp_rom_spiflash_erase_sector(sector);
++sector;
COUNTER_ADD_BYTES(erase, SPI_FLASH_SEC_SIZE);
}
@ -194,7 +195,7 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
return ESP_OK;
}
SpiFlashOpResult rc = SPI_FLASH_RESULT_OK;
esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK;
COUNTER_START();
const char *srcc = (const char *) srcv;
/*
@ -210,16 +211,16 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
size_t right_off = left_size + mid_size;
size_t right_size = size - mid_size - left_size;
rc = spi_flash_unlock();
if (rc != SPI_FLASH_RESULT_OK) {
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
if (left_size > 0) {
uint32_t t = 0xffffffff;
memcpy(((uint8_t *) &t) + (dst - left_off), srcc, left_size);
spi_flash_guard_start();
rc = SPIWrite(left_off, &t, 4);
rc = esp_rom_spiflash_write(left_off, &t, 4);
spi_flash_guard_end();
if (rc != SPI_FLASH_RESULT_OK) {
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
COUNTER_ADD_BYTES(write, 4);
@ -234,7 +235,7 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
#else
bool direct_write = true;
#endif
while(mid_size > 0 && rc == SPI_FLASH_RESULT_OK) {
while(mid_size > 0 && rc == ESP_ROM_SPIFLASH_RESULT_OK) {
uint32_t write_buf[8];
uint32_t write_size;
const uint32_t *write_src = (const uint32_t *) (srcc + mid_off);
@ -246,13 +247,13 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
write_src = write_buf;
}
spi_flash_guard_start();
rc = SPIWrite(dst + mid_off, write_src, write_size);
rc = esp_rom_spiflash_write(dst + mid_off, (const uint32_t *) (srcc + mid_off), mid_size);
spi_flash_guard_end();
COUNTER_ADD_BYTES(write, write_size);
mid_size -= write_size;
mid_off += write_size;
}
if (rc != SPI_FLASH_RESULT_OK) {
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
}
@ -261,9 +262,9 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
uint32_t t = 0xffffffff;
memcpy(&t, srcc + right_off, right_size);
spi_flash_guard_start();
rc = SPIWrite(dst + right_off, &t, 4);
rc = esp_rom_spiflash_write(dst + right_off, &t, 4);
spi_flash_guard_end();
if (rc != SPI_FLASH_RESULT_OK) {
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
COUNTER_ADD_BYTES(write, 4);
@ -289,13 +290,13 @@ esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src,
}
COUNTER_START();
SpiFlashOpResult rc = spi_flash_unlock();
if (rc == SPI_FLASH_RESULT_OK) {
/* SPI_Encrypt_Write encrypts data in RAM as it writes,
esp_rom_spiflash_result_t rc;
rc = spi_flash_unlock();
if (rc == ESP_ROM_SPIFLASH_RESULT_OK) {
/* esp_rom_spiflash_write_encrypted encrypts data in RAM as it writes,
so copy to a temporary buffer - 32 bytes at a time.
Each call to SPI_Encrypt_Write takes a 32 byte "row" of
Each call to esp_rom_spiflash_write_encrypted takes a 32 byte "row" of
data to encrypt, and each row is two 16 byte AES blocks
that share a key (as derived from flash address).
*/
@ -311,25 +312,23 @@ esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src,
memcpy(encrypt_buf + 16, ssrc + i, 16);
/* decrypt the first block from flash, will reencrypt to same bytes */
spi_flash_read_encrypted(row_addr, encrypt_buf, 16);
}
else if (size - i == 16) {
} else if (size - i == 16) {
/* 16 bytes left, is first block of a 32 byte row */
row_size = 16;
/* copy to first block in buffer */
memcpy(encrypt_buf, ssrc + i, 16);
/* decrypt the second block from flash, will reencrypt to same bytes */
spi_flash_read_encrypted(row_addr + 16, encrypt_buf + 16, 16);
}
else {
} else {
/* Writing a full 32 byte row (2 blocks) */
row_size = 32;
memcpy(encrypt_buf, ssrc + i, 32);
}
spi_flash_guard_start();
rc = SPI_Encrypt_Write(row_addr, (uint32_t *)encrypt_buf, 32);
rc = esp_rom_spiflash_write_encrypted(row_addr, (uint32_t *)encrypt_buf, 32);
spi_flash_guard_end();
if (rc != SPI_FLASH_RESULT_OK) {
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
break;
}
}
@ -356,7 +355,7 @@ esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
return ESP_OK;
}
SpiFlashOpResult rc = SPI_FLASH_RESULT_OK;
esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK;
COUNTER_START();
spi_flash_guard_start();
/* To simplify boundary checks below, we handle small reads separately. */
@ -365,8 +364,8 @@ esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
uint32_t read_src = src & ~3U;
uint32_t left_off = src & 3U;
uint32_t read_size = (left_off + size + 3) & ~3U;
rc = SPIRead(read_src, t, read_size);
if (rc != SPI_FLASH_RESULT_OK) {
rc = esp_rom_spiflash_read(read_src, t, read_size);
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
COUNTER_ADD_BYTES(read, read_size);
@ -402,8 +401,8 @@ esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
uint32_t mid_read = 0;
while (mid_remaining > 0) {
uint32_t read_size = MIN(mid_remaining, MAX_READ_CHUNK);
rc = SPIRead(src + src_mid_off + mid_read, (uint32_t *) (dstc + dst_mid_off + mid_read), read_size);
if (rc != SPI_FLASH_RESULT_OK) {
rc = esp_rom_spiflash_read(src + src_mid_off + mid_read, (uint32_t *) (dstc + dst_mid_off + mid_read), read_size);
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
mid_remaining -= read_size;
@ -426,8 +425,8 @@ esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
}
if (pad_left_size > 0) {
uint32_t t;
rc = SPIRead(pad_left_src, &t, 4);
if (rc != SPI_FLASH_RESULT_OK) {
rc = esp_rom_spiflash_read(pad_left_src, &t, 4);
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
COUNTER_ADD_BYTES(read, 4);
@ -436,8 +435,8 @@ esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
if (pad_right_size > 0) {
uint32_t t[2];
int32_t read_size = (pad_right_size <= 4 ? 4 : 8);
rc = SPIRead(pad_right_src, t, read_size);
if (rc != SPI_FLASH_RESULT_OK) {
rc = esp_rom_spiflash_read(pad_right_src, t, read_size);
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
COUNTER_ADD_BYTES(read, read_size);
@ -461,7 +460,7 @@ esp_err_t IRAM_ATTR spi_flash_read_encrypted(size_t src, void *dstv, size_t size
esp_err_t err;
const uint8_t *map;
spi_flash_mmap_handle_t map_handle;
size_t map_src = src & ~(SPI_FLASH_MMU_PAGE_SIZE-1);
size_t map_src = src & ~(SPI_FLASH_MMU_PAGE_SIZE - 1);
size_t map_size = size + (src - map_src);
err = spi_flash_mmap(map_src, map_size, SPI_FLASH_MMAP_DATA, (const void **)&map, &map_handle);
@ -474,14 +473,14 @@ esp_err_t IRAM_ATTR spi_flash_read_encrypted(size_t src, void *dstv, size_t size
}
static esp_err_t IRAM_ATTR spi_flash_translate_rc(SpiFlashOpResult rc)
static esp_err_t IRAM_ATTR spi_flash_translate_rc(esp_rom_spiflash_result_t rc)
{
switch (rc) {
case SPI_FLASH_RESULT_OK:
case ESP_ROM_SPIFLASH_RESULT_OK:
return ESP_OK;
case SPI_FLASH_RESULT_TIMEOUT:
case ESP_ROM_SPIFLASH_RESULT_TIMEOUT:
return ESP_ERR_FLASH_OP_TIMEOUT;
case SPI_FLASH_RESULT_ERR:
case ESP_ROM_SPIFLASH_RESULT_ERR:
default:
return ESP_ERR_FLASH_OP_FAIL;
}
@ -489,13 +488,13 @@ static esp_err_t IRAM_ATTR spi_flash_translate_rc(SpiFlashOpResult rc)
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
static inline void dump_counter(spi_flash_counter_t* counter, const char* name)
static inline void dump_counter(spi_flash_counter_t *counter, const char *name)
{
ESP_LOGI(TAG, "%s count=%8d time=%8dus bytes=%8d\n", name,
counter->count, counter->time, counter->bytes);
}
const spi_flash_counters_t* spi_flash_get_counters()
const spi_flash_counters_t *spi_flash_get_counters()
{
return &s_flash_stats;
}

View file

@ -11,34 +11,37 @@
// 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.
#include "rom/ets_sys.h"
#include "rom/gpio.h"
#include "rom/spi_flash.h"
#include "soc/spi_reg.h"
#include "sdkconfig.h"
static const uint32_t STATUS_QIE_BIT = (1 << 9); /* Quad Enable */
#define SPI_IDX 1
#define OTH_IDX 0
#define SPI_IDX 1
#define OTH_IDX 0
extern esp_rom_spiflash_chip_t g_rom_spiflash_chip;
#ifndef BOOTLOADER_BUILD
#define ATTR IRAM_ATTR
#else
#define ATTR
#endif // BOOTLOADER_BUILD
extern SpiFlashChip SPI_flashchip_data;
static void ATTR Wait_SPI_Idle(void)
esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *spi)
{
/* Wait for SPI state machine to be idle */
while((REG_READ(SPI_EXT2_REG(SPI_IDX)) & SPI_ST)) {
}
while(REG_READ(SPI_EXT2_REG(OTH_IDX)) & SPI_ST) {
}
uint32_t status;
//wait for spi control ready
while ((REG_READ(SPI_EXT2_REG(1)) & SPI_ST)) {
}
while ((REG_READ(SPI_EXT2_REG(0)) & SPI_ST)) {
}
//wait for flash status ready
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_status(spi, &status)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
/* Modified version of SPIUnlock() that replaces version in ROM.
This works around a bug where SPIUnlock sometimes reads the wrong
/* Modified version of esp_rom_spiflash_unlock() that replaces version in ROM.
This works around a bug where esp_rom_spiflash_unlock sometimes reads the wrong
high status byte (RDSR2 result) and then copies it back to the
flash status, which can cause the CMP bit or Status Register
Protect bit to become set.
@ -48,31 +51,680 @@ static void ATTR Wait_SPI_Idle(void)
about interrupts, CPU coordination, flash mapping. However some of
the functions in esp_spi_flash.c call it.
*/
SpiFlashOpResult ATTR SPIUnlock(void)
esp_rom_spiflash_result_t esp_rom_spiflash_unlock()
{
uint32_t status;
uint32_t status;
Wait_SPI_Idle();
esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
if (SPI_read_status_high(&status) != SPI_FLASH_RESULT_OK) {
return SPI_FLASH_RESULT_ERR;
}
if (esp_rom_spiflash_read_statushigh(&g_rom_spiflash_chip, &status) != ESP_ROM_SPIFLASH_RESULT_OK) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
/* Clear all bits except QIE, if it is set.
(This is different from ROM SPIUnlock, which keeps all bits as-is.)
*/
status &= STATUS_QIE_BIT;
/* Clear all bits except QIE, if it is set.
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
*/
status &= ESP_ROM_SPIFLASH_QE;
Wait_SPI_Idle();
REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WREN);
while(REG_READ(SPI_CMD_REG(SPI_IDX)) != 0) {
}
Wait_SPI_Idle();
esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WREN);
while (REG_READ(SPI_CMD_REG(SPI_IDX)) != 0) {
}
esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B);
if (SPI_write_status(&SPI_flashchip_data, status) != SPI_FLASH_RESULT_OK) {
return SPI_FLASH_RESULT_ERR;
}
SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B);
if (esp_rom_spiflash_write_status(&g_rom_spiflash_chip, status) != ESP_ROM_SPIFLASH_RESULT_OK) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
return SPI_FLASH_RESULT_OK;
return ESP_ROM_SPIFLASH_RESULT_OK;
}
#if CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
extern uint8_t g_rom_spiflash_dummy_len_plus[];
static esp_rom_spiflash_result_t esp_rom_spiflash_enable_write(esp_rom_spiflash_chip_t *spi);
static esp_rom_spiflash_result_t esp_rom_spiflash_enable_qmode(esp_rom_spiflash_chip_t *spi);
static esp_rom_spiflash_result_t esp_rom_spiflash_disable_qmode(esp_rom_spiflash_chip_t *spi);
//only support spi1
static esp_rom_spiflash_result_t esp_rom_spiflash_erase_chip_internal(esp_rom_spiflash_chip_t *spi)
{
esp_rom_spiflash_wait_idle(spi);
// Chip erase.
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_CE);
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
// check erase is finished.
esp_rom_spiflash_wait_idle(spi);
return ESP_ROM_SPIFLASH_RESULT_OK;
}
//only support spi1
static esp_rom_spiflash_result_t esp_rom_spiflash_erase_sector_internal(esp_rom_spiflash_chip_t *spi, uint32_t addr)
{
//check if addr is 4k alignment
if (0 != (addr & 0xfff)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
esp_rom_spiflash_wait_idle(spi);
// sector erase 4Kbytes erase is sector erase.
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, addr & 0xffffff);
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_SE);
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
esp_rom_spiflash_wait_idle(spi);
return ESP_ROM_SPIFLASH_RESULT_OK;
}
//only support spi1
static esp_rom_spiflash_result_t esp_rom_spiflash_erase_block_internal(esp_rom_spiflash_chip_t *spi, uint32_t addr)
{
esp_rom_spiflash_wait_idle(spi);
// sector erase 4Kbytes erase is sector erase.
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, addr & 0xffffff);
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_BE);
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
esp_rom_spiflash_wait_idle(spi);
return ESP_ROM_SPIFLASH_RESULT_OK;
}
//only support spi1
static esp_rom_spiflash_result_t esp_rom_spiflash_program_page_internal(esp_rom_spiflash_chip_t *spi, uint32_t spi_addr,
uint32_t *addr_source, int32_t byte_length)
{
uint32_t temp_addr;
int32_t temp_bl;
uint8_t i;
uint8_t remain_word_num;
//check 4byte alignment
if (0 != (byte_length & 0x3)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
//check if write in one page
if ((spi->page_size) < ((spi_addr % (spi->page_size)) + byte_length)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
esp_rom_spiflash_wait_idle(spi);
temp_addr = spi_addr;
temp_bl = byte_length;
while (temp_bl > 0 ) {
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(spi)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
if ( temp_bl >= ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM ) {
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, (temp_addr & 0xffffff) | ( ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM << ESP_ROM_SPIFLASH_BYTES_LEN )); // 32 byte a block
for (i = 0; i < (ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM >> 2); i++) {
WRITE_PERI_REG(PERIPHS_SPI_FLASH_C0 + i * 4, *addr_source++);
}
temp_bl = temp_bl - 32;
temp_addr = temp_addr + 32;
} else {
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, (temp_addr & 0xffffff) | (temp_bl << ESP_ROM_SPIFLASH_BYTES_LEN ));
remain_word_num = (0 == (temp_bl & 0x3)) ? (temp_bl >> 2) : (temp_bl >> 2) + 1;
for (i = 0; i < remain_word_num; i++) {
WRITE_PERI_REG(PERIPHS_SPI_FLASH_C0 + i * 4, *addr_source++);
temp_bl = temp_bl - 4;
}
temp_bl = 0;
}
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_PP);
while ( READ_PERI_REG(PERIPHS_SPI_FLASH_CMD ) != 0 );
esp_rom_spiflash_wait_idle(spi);
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
//only support spi1
static esp_rom_spiflash_result_t esp_rom_spiflash_read_data(esp_rom_spiflash_chip_t *spi, uint32_t flash_addr,
uint32_t *addr_dest, int32_t byte_length)
{
uint32_t temp_addr;
int32_t temp_length;
uint8_t i;
uint8_t remain_word_num;
//address range check
if ((flash_addr + byte_length) > (spi->chip_size)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
temp_addr = flash_addr;
temp_length = byte_length;
esp_rom_spiflash_wait_idle(spi);
while (temp_length > 0) {
if (temp_length >= ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM) {
//WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr |(ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM << ESP_ROM_SPIFLASH_BYTES_LEN));
REG_WRITE(SPI_MISO_DLEN_REG(1), ((ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM << 3) - 1) << SPI_USR_MISO_DBITLEN_S);
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr << 8);
REG_WRITE(PERIPHS_SPI_FLASH_CMD, SPI_USR);
while (REG_READ(PERIPHS_SPI_FLASH_CMD) != 0);
for (i = 0; i < (ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM >> 2); i++) {
*addr_dest++ = READ_PERI_REG(PERIPHS_SPI_FLASH_C0 + i * 4);
}
temp_length = temp_length - ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM;
temp_addr = temp_addr + ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM;
} else {
//WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr |(temp_length << ESP_ROM_SPIFLASH_BYTES_LEN ));
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr << 8);
REG_WRITE(SPI_MISO_DLEN_REG(1), ((ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM << 3) - 1) << SPI_USR_MISO_DBITLEN_S);
REG_WRITE(PERIPHS_SPI_FLASH_CMD, SPI_USR);
while (REG_READ(PERIPHS_SPI_FLASH_CMD) != 0);
remain_word_num = (0 == (temp_length & 0x3)) ? (temp_length >> 2) : (temp_length >> 2) + 1;
for (i = 0; i < remain_word_num; i++) {
*addr_dest++ = READ_PERI_REG(PERIPHS_SPI_FLASH_C0 + i * 4);
}
temp_length = 0;
}
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
esp_rom_spiflash_result_t esp_rom_spiflash_read_status(esp_rom_spiflash_chip_t *spi, uint32_t *status)
{
uint32_t status_value = ESP_ROM_SPIFLASH_BUSY_FLAG;
if (g_rom_spiflash_dummy_len_plus[1] == 0) {
while (ESP_ROM_SPIFLASH_BUSY_FLAG == (status_value & ESP_ROM_SPIFLASH_BUSY_FLAG)) {
WRITE_PERI_REG(PERIPHS_SPI_FLASH_STATUS, 0); // clear regisrter
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_RDSR);
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
status_value = READ_PERI_REG(PERIPHS_SPI_FLASH_STATUS) & (spi->status_mask);
}
} else {
while (ESP_ROM_SPIFLASH_BUSY_FLAG == (status_value & ESP_ROM_SPIFLASH_BUSY_FLAG)) {
esp_rom_spiflash_read_user_cmd(&status_value, 0x05);
}
}
*status = status_value;
return ESP_ROM_SPIFLASH_RESULT_OK;
}
esp_rom_spiflash_result_t esp_rom_spiflash_read_statushigh(esp_rom_spiflash_chip_t *spi, uint32_t *status)
{
esp_rom_spiflash_result_t ret;
esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
ret = esp_rom_spiflash_read_user_cmd(status, 0x35);
*status = *status << 8;
return ret;
}
esp_rom_spiflash_result_t esp_rom_spiflash_write_status(esp_rom_spiflash_chip_t *spi, uint32_t status_value)
{
esp_rom_spiflash_wait_idle(spi);
// update status value by status_value
WRITE_PERI_REG(PERIPHS_SPI_FLASH_STATUS, status_value); // write status regisrter
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_WRSR);
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
esp_rom_spiflash_wait_idle(spi);
return ESP_ROM_SPIFLASH_RESULT_OK;
}
static esp_rom_spiflash_result_t esp_rom_spiflash_enable_write(esp_rom_spiflash_chip_t *spi)
{
uint32_t flash_status = 0;
esp_rom_spiflash_wait_idle(spi);
//enable write
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_WREN); // enable write operation
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
// make sure the flash is ready for writing
while (ESP_ROM_SPIFLASH_WRENABLE_FLAG != (flash_status & ESP_ROM_SPIFLASH_WRENABLE_FLAG)) {
esp_rom_spiflash_read_status(spi, &flash_status);
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
static esp_rom_spiflash_result_t esp_rom_spiflash_enable_qmode(esp_rom_spiflash_chip_t *spi)
{
uint32_t flash_status;
uint32_t status;
//read QE bit, not write if QE
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_statushigh(spi, &status)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
if (status & ESP_ROM_SPIFLASH_QE) {
return ESP_ROM_SPIFLASH_RESULT_OK;
}
//enable 2 byte status writing
SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, ESP_ROM_SPIFLASH_TWO_BYTE_STATUS_EN);
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(spi)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
esp_rom_spiflash_read_status(spi, &flash_status);
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_write_status(spi, flash_status | ESP_ROM_SPIFLASH_QE)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
static esp_rom_spiflash_result_t esp_rom_spiflash_disable_qmode(esp_rom_spiflash_chip_t *spi)
{
uint32_t flash_status;
uint32_t status;
//read QE bit, not write if not QE
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_statushigh(spi, &status)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
//ets_printf("status %08x, line:%u\n", status, __LINE__);
if (!(status & ESP_ROM_SPIFLASH_QE)) {
return ESP_ROM_SPIFLASH_RESULT_OK;
}
//enable 2 byte status writing
SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, ESP_ROM_SPIFLASH_TWO_BYTE_STATUS_EN);
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(spi)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
esp_rom_spiflash_read_status(spi, &flash_status);
//keep low 8 bit
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_write_status(spi, flash_status & 0xff)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
static void spi_cache_mode_switch(uint32_t modebit)
{
if ((modebit & SPI_FREAD_QIO) && (modebit & SPI_FASTRD_MODE)) {
REG_CLR_BIT(SPI_USER_REG(0), SPI_USR_MOSI);
REG_SET_BIT(SPI_USER_REG(0), SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR);
REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN, SPI0_R_QIO_ADDR_BITSLEN);
REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, SPI0_R_QIO_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0xEB);
} else if (modebit & SPI_FASTRD_MODE) {
REG_CLR_BIT(SPI_USER_REG(0), SPI_USR_MOSI);
REG_SET_BIT(SPI_USER_REG(0), SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR);
REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN, SPI0_R_FAST_ADDR_BITSLEN);
if ((modebit & SPI_FREAD_QUAD)) {
REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0x6B);
REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, SPI0_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
} else if ((modebit & SPI_FREAD_DIO)) {
REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, SPI0_R_DIO_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0xBB);
} else if ((modebit & SPI_FREAD_DUAL)) {
REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, SPI0_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0x3B);
} else {
REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, SPI0_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0x0B);
}
} else {
REG_CLR_BIT(SPI_USER_REG(0), SPI_USR_MOSI);
if (g_rom_spiflash_dummy_len_plus[0] == 0) {
REG_CLR_BIT(SPI_USER_REG(0), SPI_USR_DUMMY);
} else {
REG_SET_BIT(SPI_USER_REG(0), SPI_USR_DUMMY);
REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, g_rom_spiflash_dummy_len_plus[0] - 1);
}
REG_SET_BIT(SPI_USER_REG(0), SPI_USR_MISO | SPI_USR_ADDR);
REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN, SPI0_R_SIO_ADDR_BITSLEN);
REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0x03);
}
}
esp_rom_spiflash_result_t esp_rom_spiflash_lock()
{
uint32_t status;
//read QE bit, not write if not QE
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_statushigh(&g_rom_spiflash_chip, &status)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
//enable 2 byte status writing
SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, ESP_ROM_SPIFLASH_TWO_BYTE_STATUS_EN);
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(&g_rom_spiflash_chip)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_write_status(&g_rom_spiflash_chip, status | ESP_ROM_SPIFLASH_WR_PROTECT)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
esp_rom_spiflash_result_t esp_rom_spiflash_config_readmode(esp_rom_spiflash_read_mode_t mode, bool legacy)
{
uint32_t modebit;
while ((REG_READ(SPI_EXT2_REG(1)) & SPI_ST)) {
}
while ((REG_READ(SPI_EXT2_REG(0)) & SPI_ST)) {
}
//clear old mode bit
CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FREAD_QIO | SPI_FREAD_QUAD | SPI_FREAD_DIO | SPI_FREAD_DUAL | SPI_FASTRD_MODE);
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(0), SPI_FREAD_QIO | SPI_FREAD_QUAD | SPI_FREAD_DIO | SPI_FREAD_DUAL | SPI_FASTRD_MODE);
//configure read mode
switch (mode) {
case ESP_ROM_SPIFLASH_QIO_MODE : modebit = SPI_FREAD_QIO | SPI_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_QOUT_MODE : modebit = SPI_FREAD_QUAD | SPI_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_DIO_MODE : modebit = SPI_FREAD_DIO | SPI_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_DOUT_MODE : modebit = SPI_FREAD_DUAL | SPI_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_FASTRD_MODE: modebit = SPI_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_SLOWRD_MODE: modebit = 0; break;
default : modebit = 0;
}
if ((ESP_ROM_SPIFLASH_QIO_MODE == mode) || (ESP_ROM_SPIFLASH_QOUT_MODE == mode)) {
esp_rom_spiflash_enable_qmode(&g_rom_spiflash_chip);
} else {
//do not need disable QMode in faster boot
if (legacy) {
esp_rom_spiflash_disable_qmode(&g_rom_spiflash_chip);
}
}
SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, modebit);
SET_PERI_REG_MASK(SPI_CTRL_REG(0), modebit);
spi_cache_mode_switch(modebit);
return ESP_ROM_SPIFLASH_RESULT_OK;
}
esp_rom_spiflash_result_t esp_rom_spiflash_erase_chip()
{
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(&g_rom_spiflash_chip)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_chip_internal(&g_rom_spiflash_chip)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
esp_rom_spiflash_result_t esp_rom_spiflash_erase_block(uint32_t block_num)
{
// flash write is always 1 line currently
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
//check program size
if (block_num >= ((g_rom_spiflash_chip.chip_size) / (g_rom_spiflash_chip.block_size))) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(&g_rom_spiflash_chip)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_block_internal(&g_rom_spiflash_chip, block_num * (g_rom_spiflash_chip.block_size))) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
esp_rom_spiflash_result_t esp_rom_spiflash_erase_sector(uint32_t sector_num)
{
// flash write is always 1 line currently
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
//check program size
if (sector_num >= ((g_rom_spiflash_chip.chip_size) / (g_rom_spiflash_chip.sector_size))) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(&g_rom_spiflash_chip)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_sector_internal(&g_rom_spiflash_chip, sector_num * (g_rom_spiflash_chip.sector_size))) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
esp_rom_spiflash_result_t esp_rom_spiflash_write(uint32_t target, const uint32_t *src_addr, int32_t len)
{
uint32_t page_size;
uint32_t pgm_len, pgm_num;
uint8_t i;
// flash write is always 1 line currently
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
//check program size
if ( (target + len) > (g_rom_spiflash_chip.chip_size)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
page_size = g_rom_spiflash_chip.page_size;
pgm_len = page_size - (target % page_size);
if (len < pgm_len) {
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_program_page_internal(&g_rom_spiflash_chip,
target, (uint32_t *)src_addr, len)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
} else {
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_program_page_internal(&g_rom_spiflash_chip,
target, (uint32_t *)src_addr, pgm_len)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
//whole page program
pgm_num = (len - pgm_len) / page_size;
for (i = 0; i < pgm_num; i++) {
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_program_page_internal(&g_rom_spiflash_chip,
target + pgm_len, (uint32_t *)src_addr + (pgm_len >> 2), page_size)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
pgm_len += page_size;
}
//remain parts to program
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_program_page_internal(&g_rom_spiflash_chip,
target + pgm_len, (uint32_t *)src_addr + (pgm_len >> 2), len - pgm_len)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
esp_rom_spiflash_result_t esp_rom_spiflash_write_encrypted(uint32_t flash_addr, uint32_t *data, uint32_t len)
{
esp_rom_spiflash_result_t ret = ESP_ROM_SPIFLASH_RESULT_OK;
uint32_t i;
if ((flash_addr & 0x1f) || (len & 0x1f)) { //check 32 byte alignment
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
esp_rom_spiflash_write_encrypted_enable();
for (i = 0; i < (len >> 5); i++) {
if ((ret = esp_rom_spiflash_prepare_encrypted_data(flash_addr + (i << 5), data + (i << 3))) != ESP_ROM_SPIFLASH_RESULT_OK) {
break;
}
if ((ret = esp_rom_spiflash_write(flash_addr + (i << 5), data, 32)) != ESP_ROM_SPIFLASH_RESULT_OK) {
break;
}
}
esp_rom_spiflash_write_encrypted_disable();
return ret;
}
esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest_addr, int32_t len)
{
// QIO or SIO, non-QIO regard as SIO
uint32_t modebit;
modebit = READ_PERI_REG(PERIPHS_SPI_FLASH_CTRL);
if ((modebit & SPI_FREAD_QIO) && (modebit & SPI_FASTRD_MODE)) {
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MOSI);
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_QIO_ADDR_BITSLEN);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_DUMMY_CYCLELEN, SPI1_R_QIO_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[1]);
//REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0xEB);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0xEB);
} else if (modebit & SPI_FASTRD_MODE) {
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MOSI);
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MISO | SPI_USR_ADDR);
if (modebit & SPI_FREAD_DIO) {
if (g_rom_spiflash_dummy_len_plus[1] == 0) {
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_DIO_ADDR_BITSLEN);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0xBB);
} else {
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_DIO_ADDR_BITSLEN);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_DUMMY_CYCLELEN, g_rom_spiflash_dummy_len_plus[1] - 1);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0xBB);
}
} else {
if ((modebit & SPI_FREAD_QUAD)) {
//REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0x6B);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x6B);
} else if ((modebit & SPI_FREAD_DUAL)) {
//REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0x3B);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x3B);
} else {
//REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0x0B);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x0B);
}
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_FAST_ADDR_BITSLEN);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_DUMMY_CYCLELEN, SPI1_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[1]);
}
} else {
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MOSI);
if (g_rom_spiflash_dummy_len_plus[1] == 0) {
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
} else {
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_DUMMY_CYCLELEN, g_rom_spiflash_dummy_len_plus[1] - 1);
}
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MISO | SPI_USR_ADDR);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_SIO_ADDR_BITSLEN);
//REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0x03);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x03);
}
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_data(&g_rom_spiflash_chip, target, dest_addr, len)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
esp_rom_spiflash_result_t esp_rom_spiflash_erase_area(uint32_t start_addr, uint32_t area_len)
{
int32_t total_sector_num;
int32_t head_sector_num;
uint32_t sector_no;
uint32_t sector_num_per_block;
//set read mode to Fastmode ,not QDIO mode for erase
esp_rom_spiflash_config_readmode(ESP_ROM_SPIFLASH_SLOWRD_MODE, true);
//check if area is oversize of flash
if ((start_addr + area_len) > g_rom_spiflash_chip.chip_size) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
//start_addr is aligned as sector boundary
if (0 != (start_addr % g_rom_spiflash_chip.sector_size)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
//Unlock flash to enable erase
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_unlock(/*&g_rom_spiflash_chip*/)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
sector_no = start_addr / g_rom_spiflash_chip.sector_size;
sector_num_per_block = g_rom_spiflash_chip.block_size / g_rom_spiflash_chip.sector_size;
total_sector_num = (0 == (area_len % g_rom_spiflash_chip.sector_size)) ? area_len / g_rom_spiflash_chip.sector_size :
1 + (area_len / g_rom_spiflash_chip.sector_size);
//check if erase area reach over block boundary
head_sector_num = sector_num_per_block - (sector_no % sector_num_per_block);
head_sector_num = (head_sector_num >= total_sector_num) ? total_sector_num : head_sector_num;
//JJJ, BUG of 6.0 erase
//middle part of area is aligned by blocks
total_sector_num -= head_sector_num;
//head part of area is erased
while (0 != head_sector_num) {
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_sector(sector_no)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
sector_no++;
head_sector_num--;
}
while (total_sector_num > sector_num_per_block) {
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_block(sector_no / sector_num_per_block)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
sector_no += sector_num_per_block;
total_sector_num -= sector_num_per_block;
}
//tail part of area burn
while (0 < total_sector_num) {
if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_sector(sector_no)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
sector_no++;
total_sector_num--;
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
#endif

View file

@ -23,6 +23,7 @@
#include <unity.h>
#include <test_utils.h>
#include <esp_partition.h>
#include <esp_attr.h>
TEST_CASE("Test erase partition", "[spi_flash]")
{
@ -40,7 +41,7 @@ TEST_CASE("Test erase partition", "[spi_flash]")
#endif
// put some dummy data on sector boundaries
const char *some_data = "abcdefghijklmn";
const static DRAM_ATTR char some_data[] = "abcdefghijklmn";
for (int i = 0; i < part->size; i+= 4096) {
ESP_ERROR_CHECK( esp_partition_write(part, i, some_data, strlen(some_data)) );
}
@ -64,5 +65,4 @@ TEST_CASE("Test erase partition", "[spi_flash]")
TEST_ASSERT_EQUAL_HEX8(0xFF, buf[i]);
}
}
}

View file

@ -71,18 +71,18 @@ static void IRAM_ATTR test_read(int src_off, int dst_off, int len)
{
uint32_t src_buf[16];
char dst_buf[64], dst_gold[64];
fprintf(stderr, "src=%d dst=%d len=%d\n", src_off, dst_off, len);
memset(src_buf, 0xAA, sizeof(src_buf));
fill(((char *) src_buf) + src_off, src_off, len);
ESP_ERROR_CHECK(spi_flash_erase_sector((start + src_off) / SPI_FLASH_SEC_SIZE));
spi_flash_disable_interrupts_caches_and_other_cpu();
SpiFlashOpResult rc = SPIWrite(start, src_buf, sizeof(src_buf));
esp_rom_spiflash_result_t rc = esp_rom_spiflash_write(start, src_buf, sizeof(src_buf));
spi_flash_enable_interrupts_caches_and_other_cpu();
TEST_ASSERT_EQUAL_INT(rc, SPI_FLASH_RESULT_OK);
TEST_ASSERT_EQUAL_INT(rc, ESP_ROM_SPIFLASH_RESULT_OK);
memset(dst_buf, 0x55, sizeof(dst_buf));
memset(dst_gold, 0x55, sizeof(dst_gold));
fill(dst_gold + dst_off, src_off, len);
ESP_ERROR_CHECK(spi_flash_read(start + src_off, dst_buf + dst_off, len));
TEST_ASSERT_EQUAL_INT(cmp_or_dump(dst_buf, dst_gold, sizeof(dst_buf)), 0);
}
@ -159,9 +159,9 @@ static void IRAM_ATTR test_write(int dst_off, int src_off, int len)
}
ESP_ERROR_CHECK(spi_flash_write(start + dst_off, src_buf + src_off, len));
spi_flash_disable_interrupts_caches_and_other_cpu();
SpiFlashOpResult rc = SPIRead(start, dst_buf, sizeof(dst_buf));
esp_rom_spiflash_result_t rc = esp_rom_spiflash_read(start, dst_buf, sizeof(dst_buf));
spi_flash_enable_interrupts_caches_and_other_cpu();
TEST_ASSERT_EQUAL_INT(rc, SPI_FLASH_RESULT_OK);
TEST_ASSERT_EQUAL_INT(rc, ESP_ROM_SPIFLASH_RESULT_OK);
TEST_ASSERT_EQUAL_INT(cmp_or_dump(dst_buf, dst_gold, sizeof(dst_buf)), 0);
}

View file

@ -108,7 +108,7 @@ Where possible, we recommend using the partition write function ``esp_partition_
The ``esp_spi_flash_write`` function will write data when the write_encrypted parameter is set to true. Otherwise, data will be written unencrypted.
The ROM function ``SPI_Encrypt_Write`` will write encrypted data to flash, the ROM function ``SPIWrite`` will write unencrypted to flash. (these function are not supported in esp-idf apps).
The ROM function ``esp_rom_spiflash_write_encrypted`` will write encrypted data to flash, the ROM function ``SPIWrite`` will write unencrypted to flash. (these function are not supported in esp-idf apps).
The minimum write size for unencrypted data is 4 bytes (and the alignment is 4 bytes). Because data is encrypted in blocks, the minimum write size for encrypted data is 16 bytes (and the alignment is 16 bytes.)