mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 04:59:55 +00:00 
			
		
		
		
	 fefdee1349
			
		
	
	fefdee1349
	
	
	
		
			
			1. The 2nd bootloader always call `rom_spiflash_unlock()`, but never help to clear the WEL bit when exit. This may cause system unstability. This commit helps to clear WEL when flash configuration is done. **RISK:** When the app starts, it didn't have to clear the WEL before it actually write/erase. But now the very first write/erase operation should be done after a WEL clear. Though the risk is little (all the following write/erase also need to clear the WEL), we still have to test this carefully, especially for those functions used by the OTA. 2. The `rom_spiflash_unlock()` function in the patch of ESP32 may (1) trigger the QPI, (2) clear the QE or (3) fail to unlock the ISSI chips. Status register bitmap of ISSI chip and GD chip: | SR | ISSI | GD25LQ32C | | -- | ---- | --------- | | 0 | WIP | WIP | | 1 | WEL | WEL | | 2 | BP0 | BP0 | | 3 | BP1 | BP1 | | 4 | BP2 | BP2 | | 5 | BP3 | BP3 | | 6 | QE | BP4 | | 7 | SRWD | SRP0 | | 8 | | SRP1 | | 9 | | QE | | 10 | | SUS2 | | 11 | | LB1 | | 12 | | LB2 | | 13 | | LB3 | | 14 | | CMP | | 15 | | SUS1 | QE bit of other chips are at the bit 9 of the status register (i.e. bit 1 of SR2), which should be read by RDSR2 command. However, the RDSR2 (35H, Read Status 2) command for chip of other vendors happens to be the QIOEN (Enter QPI mode) command of ISSI chips. When the `rom_spiflash_unlock()` function trys to read SR2, it may trigger the QPI of ISSI chips. Moreover, when `rom_spiflash_unlock()` try to clear the BP4 bit in the status register, QE (bit 6) of ISSI chip may be cleared by accident. Or if the ISSI chip doesn't accept WRSR command with argument of two bytes (since it only have status register of one byte), it may fail to clear the other protect bits (BP0~BP3) as expected. This commit makes the `rom_spiflash_unlock()` check whether the vendor is issi. if so, `rom_spiflash_unlock()` only send RDSR to read the status register, send WRSR with only 1 byte argument, and also avoid clearing the QE bit (bit 6). 3. `rom_spiflash_unlock()` always send WRSR command to clear protection bits even when there is no protection bit active. And the execution of clearing status registers, which takes about 700us, will also happen even when there's no bits cleared. This commit skips the clearing of status register if there is no protection bits active. Also move the execute_flash_command to be a bootloader API; move implementation of spi_flash_wrap_set to the bootloader
		
			
				
	
	
		
			301 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			301 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * copyright (c) Espressif System 2019
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #ifndef _ROM_OPI_FLASH_H_
 | |
| #define _ROM_OPI_FLASH_H_
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <stdint.h>
 | |
| #include "spi_flash.h"
 | |
| 
 | |
| #ifdef __cplusplus
 | |
| extern "C" {
 | |
| #endif
 | |
| 
 | |
| typedef struct {
 | |
|     uint16_t cmd;                /*!< Command value */
 | |
|     uint16_t cmdBitLen;          /*!< Command byte length*/
 | |
|     uint32_t *addr;              /*!< Point to address value*/
 | |
|     uint32_t addrBitLen;         /*!< Address byte length*/
 | |
|     uint32_t *txData;            /*!< Point to send data buffer*/
 | |
|     uint32_t txDataBitLen;       /*!< Send data byte length.*/
 | |
|     uint32_t *rxData;            /*!< Point to recevie data buffer*/
 | |
|     uint32_t rxDataBitLen;       /*!< Recevie Data byte length.*/
 | |
|     uint32_t dummyBitLen;
 | |
| } esp_rom_spi_cmd_t;
 | |
| 
 | |
| #define ESP_ROM_OPIFLASH_MUX_TAKE()
 | |
| #define ESP_ROM_OPIFLASH_MUX_GIVE()
 | |
| #define ESP_ROM_OPIFLASH_SEL_CS0     (BIT(0))
 | |
| #define ESP_ROM_OPIFLASH_SEL_CS1     (BIT(1))
 | |
| 
 | |
| // Definition of MX25UM25645G Octa Flash
 | |
| // SPI status register
 | |
| #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
 | |
| #define ESP_ROM_SPIFLASH_BP_MASK_ISSI        (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
 | |
| 
 | |
| #define FLASH_OP_MODE_RDCMD_DOUT       0x3B
 | |
| #define ESP_ROM_FLASH_SECTOR_SIZE      0x1000
 | |
| #define ESP_ROM_FLASH_BLOCK_SIZE_64K   0x10000
 | |
| #define ESP_ROM_FLASH_PAGE_SIZE        256
 | |
| 
 | |
| // FLASH commands
 | |
| #define ROM_FLASH_CMD_RDID             0x9F
 | |
| #define ROM_FLASH_CMD_WRSR             0x01
 | |
| #define ROM_FLASH_CMD_WRSR2            0x31 /* Not all SPI flash uses this command */
 | |
| #define ROM_FLASH_CMD_WREN             0x06
 | |
| #define ROM_FLASH_CMD_WRDI             0x04
 | |
| #define ROM_FLASH_CMD_RDSR             0x05
 | |
| #define ROM_FLASH_CMD_RDSR2            0x35 /* Not all SPI flash uses this command */
 | |
| #define ROM_FLASH_CMD_ERASE_SEC        0x20
 | |
| #define ROM_FLASH_CMD_ERASE_BLK_32K    0x52
 | |
| #define ROM_FLASH_CMD_ERASE_BLK_64K    0xD8
 | |
| #define ROM_FLASH_CMD_OTPEN            0x3A /* Enable OTP mode, not all SPI flash uses this command */
 | |
| #define ROM_FLASH_CMD_RSTEN            0x66
 | |
| #define ROM_FLASH_CMD_RST              0x99
 | |
| 
 | |
| #define ROM_FLASH_CMD_SE4B             0x21
 | |
| #define ROM_FLASH_CMD_SE4B_OCT         0xDE21
 | |
| #define ROM_FLASH_CMD_BE4B             0xDC
 | |
| #define ROM_FLASH_CMD_BE4B_OCT         0x23DC
 | |
| #define ROM_FLASH_CMD_RSTEN_OCT        0x9966
 | |
| #define ROM_FLASH_CMD_RST_OCT          0x6699
 | |
| 
 | |
| #define ROM_FLASH_CMD_FSTRD4B_STR      0x13EC
 | |
| #define ROM_FLASH_CMD_FSTRD4B_DTR      0x11EE
 | |
| #define ROM_FLASH_CMD_FSTRD4B          0x0C
 | |
| #define ROM_FLASH_CMD_PP4B             0x12
 | |
| #define ROM_FLASH_CMD_PP4B_OCT         0xED12
 | |
| 
 | |
| #define ROM_FLASH_CMD_RDID_OCT         0x609F
 | |
| #define ROM_FLASH_CMD_WREN_OCT         0xF906
 | |
| #define ROM_FLASH_CMD_RDSR_OCT         0xFA05
 | |
| #define ROM_FLASH_CMD_RDCR2            0x71
 | |
| #define ROM_FLASH_CMD_RDCR2_OCT        0x8E71
 | |
| #define ROM_FLASH_CMD_WRCR2            0x72
 | |
| #define ROM_FLASH_CMD_WRCR2_OCT        0x8D72
 | |
| 
 | |
| // Definitions for GigaDevice GD25LX256E Flash
 | |
| #define ROM_FLASH_CMD_RDFSR_GD            0x70
 | |
| #define ROM_FLASH_CMD_RD_GD               0x03
 | |
| #define ROM_FLASH_CMD_RD4B_GD             0x13
 | |
| #define ROM_FLASH_CMD_FSTRD_GD            0x0B
 | |
| #define ROM_FLASH_CMD_FSTRD4B_GD          0x0C
 | |
| #define ROM_FLASH_CMD_FSTRD_OOUT_GD       0x8B
 | |
| #define ROM_FLASH_CMD_FSTRD4B_OOUT_GD     0x7C
 | |
| #define ROM_FLASH_CMD_FSTRD_OIOSTR_GD     0xCB
 | |
| #define ROM_FLASH_CMD_FSTRD4B_OIOSTR_GD   0xCC
 | |
| #define ROM_FLASH_CMD_FSTRD4B_OIODTR_GD   0xFD
 | |
| 
 | |
| #define ROM_FLASH_CMD_PP_GD               0x02
 | |
| #define ROM_FLASH_CMD_PP4B_GD             0x12
 | |
| #define ROM_FLASH_CMD_PP_OOUT_GD          0x82
 | |
| #define ROM_FLASH_CMD_PP4B_OOUT_GD        0x84
 | |
| #define ROM_FLASH_CMD_PP_OIO_GD           0xC2
 | |
| #define ROM_FLASH_CMD_PP4B_OIOSTR_GD      0x8E
 | |
| 
 | |
| #define ROM_FLASH_CMD_SE_GD               0x20
 | |
| #define ROM_FLASH_CMD_SE4B_GD             0x21
 | |
| #define ROM_FLASH_CMD_BE32K_GD            0x52
 | |
| #define ROM_FLASH_CMD_BE32K4B_GD          0x5C
 | |
| #define ROM_FLASH_CMD_BE64K_GD            0xD8
 | |
| #define ROM_FLASH_CMD_BE64K4B_GD          0xDC
 | |
| 
 | |
| #define ROM_FLASH_CMD_EN4B_GD             0xB7
 | |
| #define ROM_FLASH_CMD_DIS4B_GD            0xE9
 | |
| 
 | |
| // spi user mode command config
 | |
| 
 | |
| /**
 | |
|  * @brief Config the spi user command
 | |
|  * @param spi_num spi port
 | |
|  * @param pcmd pointer to accept the spi command struct
 | |
|  */
 | |
| void esp_rom_spi_cmd_config(int spi_num, esp_rom_spi_cmd_t* pcmd);
 | |
| 
 | |
| /**
 | |
|  * @brief Start a spi user command sequence
 | |
|  * @param spi_num spi port
 | |
|  * @param rx_buf buffer pointer to receive data
 | |
|  * @param rx_len receive data length in byte
 | |
|  * @param cs_en_mask decide which cs to use, 0 for cs0, 1 for cs1
 | |
|  * @param is_write_erase to indicate whether this is a write or erase operation, since the CPU would check permission
 | |
|  */
 | |
| void esp_rom_spi_cmd_start(int spi_num, uint8_t* rx_buf, uint16_t rx_len, uint8_t cs_en_mask, bool is_write_erase);
 | |
| 
 | |
| /**
 | |
|  * @brief Config opi flash pads according to efuse settings.
 | |
|  */
 | |
| void esp_rom_opiflash_pin_config(void);
 | |
| 
 | |
| // set SPI read/write mode
 | |
| /**
 | |
|  * @brief Set SPI operation mode
 | |
|  * @param spi_num spi port
 | |
|  * @param mode Flash Read Mode
 | |
|  */
 | |
| void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode);
 | |
| 
 | |
| /**
 | |
|  * @brief Set data swap mode in DTR(DDR) mode
 | |
|  * @param spi_num spi port
 | |
|  * @param wr_swap to decide whether to swap fifo data in dtr write operation
 | |
|  * @param rd_swap to decide whether to swap fifo data in dtr read operation
 | |
|  */
 | |
| void esp_rom_spi_set_dtr_swap_mode(int spi, bool wr_swap, bool rd_swap);
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * @brief to send reset command in spi/opi-str/opi-dtr mode(for MX25UM25645G)
 | |
|  * @param spi_num spi port
 | |
|  */
 | |
| void esp_rom_opiflash_mode_reset(int spi_num);
 | |
| 
 | |
| #if 0
 | |
| // MX25UM25645G opi flash interface
 | |
| /**
 | |
|  * @brief To execute a flash operation command
 | |
|  * @param spi_num spi port
 | |
|  * @param mode Flash Read Mode
 | |
|  * @param cmd data to send in command field
 | |
|  * @param cmd_bit_len bit length of command field
 | |
|  * @param addr data to send in address field
 | |
|  * @param addr_bit_len bit length of address field
 | |
|  * @param dummy_bits bit length of dummy field
 | |
|  * @param mosi_data data buffer to be sent in mosi field
 | |
|  * @param mosi_bit_len bit length of data buffer to be sent in mosi field
 | |
|  * @param miso_data data buffer to accept data in miso field
 | |
|  * @param miso_bit_len bit length of data buffer to accept data in miso field
 | |
|  * @param cs_mark decide which cs pin to use. 0: cs0, 1: cs1
 | |
|  * @param is_write_erase_operation to indicate whether this a write or erase flash operation
 | |
|  */
 | |
| void esp_rom_opiflash_exec_cmd(int spi_num, esp_rom_spiflash_read_mode_t mode,
 | |
|                                   uint32_t cmd, int cmd_bit_len,
 | |
|                                   uint32_t addr, int addr_bit_len,
 | |
|                                   int dummy_bits,
 | |
|                                   uint8_t* mosi_data, int mosi_bit_len,
 | |
|                                   uint8_t* miso_data, int miso_bit_len,
 | |
|                                   uint32_t cs_mask,
 | |
|                                   bool is_write_erase_operation);
 | |
| 
 | |
| /**
 | |
|  * @brief send reset command to opi flash
 | |
|  * @param spi_num spi port
 | |
|  * @param mode Flash Operation Mode
 | |
|  */
 | |
| void esp_rom_opiflash_soft_reset(int spi_num, esp_rom_spiflash_read_mode_t mode);
 | |
| 
 | |
| /**
 | |
|  * @brief to read opi flash ID(for MX25UM25645G)
 | |
|  * @param spi_num spi port
 | |
|  * @param mode Flash Operation Mode
 | |
|  * @return opi flash id
 | |
|  */
 | |
| uint32_t esp_rom_opiflash_read_id(int spi_num, esp_rom_spiflash_read_mode_t mode);
 | |
| 
 | |
| /**
 | |
|  * @brief to read opi flash status register(for MX25UM25645G)
 | |
|  * @param spi_num spi port
 | |
|  * @param mode Flash Operation Mode
 | |
|  * @return opi flash status value
 | |
|  */
 | |
| uint8_t esp_rom_opiflash_rdsr(int spi_num, esp_rom_spiflash_read_mode_t mode);
 | |
| 
 | |
| /**
 | |
|  * @brief wait opi flash status register to be idle
 | |
|  * @param spi_num spi port
 | |
|  * @param mode Flash Operation Mode
 | |
|  */
 | |
| void esp_rom_opiflash_wait_idle(int spi_num, esp_rom_spiflash_read_mode_t mode);
 | |
| 
 | |
| /**
 | |
|  * @brief to read the config register2(for MX25UM25645G)
 | |
|  * @param spi_num spi port
 | |
|  * @param mode Flash Operation Mode
 | |
|  * @param addr the address of configure register
 | |
|  * @return value of config register2
 | |
|  */
 | |
| uint8_t esp_rom_opiflash_rdcr2(int spi_num, esp_rom_spiflash_read_mode_t mode, uint32_t addr);
 | |
| 
 | |
| /**
 | |
|  * @brief to write the config register2(for MX25UM25645G)
 | |
|  * @param spi_num spi port
 | |
|  * @param mode Flash Operation Mode
 | |
|  * @param addr the address of config register
 | |
|  * @param val the value to write
 | |
|  */
 | |
| void esp_rom_opiflash_wrcr2(int spi_num, esp_rom_spiflash_read_mode_t mode, uint32_t addr, uint8_t val);
 | |
| 
 | |
| /**
 | |
|  * @brief to erase flash sector(for MX25UM25645G)
 | |
|  * @param spi_num spi port
 | |
|  * @param address the sector address to be erased
 | |
|  * @param mode Flash operation mode
 | |
|  * @return flash operation result
 | |
|  */
 | |
| esp_rom_spiflash_result_t esp_rom_opiflash_erase_sector(int spi_num, uint32_t address, esp_rom_spiflash_read_mode_t mode);
 | |
| 
 | |
| /**
 | |
|  * @brief to erase flash block(for MX25UM25645G)
 | |
|  * @param spi_num spi port
 | |
|  * @param address the block address to be erased
 | |
|  * @param mode Flash operation mode
 | |
|  * @return flash operation result
 | |
|  */
 | |
| esp_rom_spiflash_result_t esp_rom_opiflash_erase_block_64k(int spi_num, uint32_t address, esp_rom_spiflash_read_mode_t mode);
 | |
| 
 | |
| /**
 | |
|  * @brief to erase a flash area define by start address and length(for MX25UM25645G)
 | |
|  * @param spi_num spi port
 | |
|  * @param start_addr the start address to be erased
 | |
|  * @param area_len the erea length to be erased
 | |
|  * @param mode flash operation mode
 | |
|  * @return flash operation result
 | |
|  */
 | |
| esp_rom_spiflash_result_t esp_rom_opiflash_erase_area(int spi_num, uint32_t start_addr, uint32_t area_len, esp_rom_spiflash_read_mode_t mode);
 | |
| 
 | |
| /**
 | |
|  * @brief to read data from opi flash(for MX25UM25645G)
 | |
|  * @param spi_num spi port
 | |
|  * @param mode flash operation mode
 | |
|  * @param flash_addr flash address to read data from
 | |
|  * @param data_addr data buffer to accept the data
 | |
|  * @param len data length to be read
 | |
|  * @return flash operation result
 | |
|  */
 | |
| esp_rom_spiflash_result_t esp_rom_opiflash_read(int spi_num, esp_rom_spiflash_read_mode_t mode, uint32_t flash_addr, uint8_t *data_addr, int len);
 | |
| 
 | |
| /**
 | |
|  * @brief to write data to opi flash(for MX25UM25645G)
 | |
|  * @param spi_num spi port
 | |
|  * @param mode flash operation mode
 | |
|  * @param flash_addr flash address to write data to
 | |
|  * @param data_addr data buffer to write to flash
 | |
|  * @param len data length to write
 | |
|  * @return flash operation result
 | |
|  */
 | |
| esp_rom_spiflash_result_t esp_rom_opiflash_write(int spi_num, esp_rom_spiflash_read_mode_t mode, uint32_t flash_addr, uint8_t *data_addr, uint32_t len);
 | |
| 
 | |
| /**
 | |
|  * @brief to set opi flash operation mode(for MX25UM25645G)
 | |
|  * @param spi_num spi port
 | |
|  * @param cur_mode current operation mode
 | |
|  * @param target the target operation mode to be set
 | |
|  */
 | |
| void esp_rom_opiflash_set_mode(int spi_num, esp_rom_spiflash_read_mode_t cur_mode, esp_rom_spiflash_read_mode_t target_mode);
 | |
| #endif
 | |
| 
 | |
| #ifdef __cplusplus
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #endif
 |