| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include "sdkconfig.h"
- #include "esp32/rom/spi_flash.h"
- #include "soc/spi_periph.h"
- #include "spi_flash_defs.h"
- #define SPI_IDX 1
- #define OTH_IDX 0
- extern esp_rom_spiflash_chip_t g_rom_spiflash_chip;
- static inline bool is_issi_chip(const esp_rom_spiflash_chip_t* chip)
- {
- return (((chip->device_id >> 16)&0xff) == 0x9D);
- }
- esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *spi)
- {
- uint32_t status;
- #if CONFIG_IDF_TARGET_ESP32
- //wait for spi control ready
- while ((REG_READ(SPI_EXT2_REG(1)) & SPI_ST)) {
- }
- while ((REG_READ(SPI_EXT2_REG(0)) & SPI_ST)) {
- }
- #elif CONFIG_IDF_TARGET_ESP32S2
- while ((REG_READ(SPI_MEM_FSM_REG(1)) & SPI_MEM_ST)) {
- }
- while ((REG_READ(SPI_MEM_FSM_REG(0)) & SPI_MEM_ST)) {
- }
- #endif
- //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 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.
- Like other ROM SPI functions, this function is not designed to be
- called directly from an RTOS environment without taking precautions
- about interrupts, CPU coordination, flash mapping. However some of
- the functions in esp_spi_flash.c call it.
- */
- __attribute__((__unused__)) esp_rom_spiflash_result_t esp_rom_spiflash_unlock(void)
- {
- uint32_t status;
- uint32_t new_status;
- esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
- if (is_issi_chip(&g_rom_spiflash_chip)) {
- // ISSI chips have different QE position
- if (esp_rom_spiflash_read_status(&g_rom_spiflash_chip, &status) != ESP_ROM_SPIFLASH_RESULT_OK) {
- return ESP_ROM_SPIFLASH_RESULT_ERR;
- }
- /* Clear all bits in the mask.
- (This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
- */
- new_status = status & (~ESP_ROM_SPIFLASH_BP_MASK_ISSI);
- // Skip if nothing needs to be cleared. Otherwise will waste time waiting for the flash to clear nothing.
- if (new_status == status) return ESP_ROM_SPIFLASH_RESULT_OK;
- CLEAR_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B);
- } else {
- 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 QE, if it is set.
- (This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
- */
- new_status = status & ESP_ROM_SPIFLASH_QE;
- SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B);
- }
- 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);
- esp_rom_spiflash_result_t ret = esp_rom_spiflash_write_status(&g_rom_spiflash_chip, new_status);
- // WEL bit should be cleared after operations regardless of writing succeed or not.
- esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
- REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WRDI);
- while (REG_READ(SPI_CMD_REG(SPI_IDX)) != 0) {
- }
- return ret;
- }
- #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);
- //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;
- }
- 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;
- }
- //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;
- }
- 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 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_ADDR_BITLEN, SPI0_R_DIO_ADDR_BITSLEN);
- 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(void)
- {
- 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)
- {
- 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;
- }
- 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(void)
- {
- 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
- //
- // TODO: this is probably a bug as it doesn't re-enable QIO mode, not serious as this
- // function is not used in IDF.
- esp_rom_spiflash_config_readmode(ESP_ROM_SPIFLASH_SLOWRD_MODE);
- //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;
- }
- esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void)
- {
- REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WRDI);
- while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
- return ESP_ROM_SPIFLASH_RESULT_OK;
- }
- #endif
|