浏览代码

Merge branch 'bugfix/esptool_write_protect' into 'master'

Fix flash write protect bug

As reported in github #50 and on forum.

Incorporates other esptool.py changes:
https://github.com/themadinventor/esptool/compare/197ba605...5c6962e8


See merge request !144

Angus Gratton 9 年之前
父节点
当前提交
f988dc9587

+ 1 - 1
components/bootloader/Makefile.projbuild

@@ -8,7 +8,7 @@
 # basically runs Make in the src/ directory but it needs to zero some variables
 # the ESP-IDF project.mk makefile exports first, to not let them interfere.
 #
-ifeq ("$(IS_BOOTLOADER_BUILD)","")
+ifndef IS_BOOTLOADER_BUILD
 
 BOOTLOADER_COMPONENT_PATH := $(COMPONENT_PATH)
 BOOTLOADER_BUILD_DIR=$(abspath $(BUILD_DIR_BASE)/bootloader)

+ 2 - 1
components/bootloader/src/Makefile

@@ -4,12 +4,13 @@
 #
 
 PROJECT_NAME := bootloader
-COMPONENTS := esptool_py bootloader log
+COMPONENTS := esptool_py bootloader log spi_flash
 
 # The bootloader pseudo-component is also included in this build, for its Kconfig.projbuild to be included.
 #
 # IS_BOOTLOADER_BUILD tells the component Makefile.projbuild to be a no-op
 IS_BOOTLOADER_BUILD := 1
+export IS_BOOTLOADER_BUILD
 
 #We cannot include the esp32 component directly but we need its includes. 
 #This is fixed by adding CFLAGS from Makefile.projbuild

+ 1 - 1
components/bootloader/src/main/bootloader_config.h

@@ -51,7 +51,7 @@ enum {
     SPI_SPEED_20M,
     SPI_SPEED_80M = 0xF
 };
-/*suppport flash size in esp32 */
+/*supported flash sizes*/
 enum {
     SPI_SIZE_1MB = 0,
     SPI_SIZE_2MB,

+ 35 - 2
components/bootloader/src/main/bootloader_start.c

@@ -58,6 +58,7 @@ void IRAM_ATTR set_cache_and_start_app(uint32_t drom_addr,
     uint32_t irom_load_addr,
     uint32_t irom_size,
     uint32_t entry_addr);
+static void update_flash_config(struct flash_hdr* pfhdr);
 
 
 void IRAM_ATTR call_start_cpu0()
@@ -258,7 +259,7 @@ void bootloader_main()
     memset(&bs, 0, sizeof(bs));
 
     ESP_LOGI(TAG, "compile time " __TIME__ );
-    /* close watch dog here */
+    /* 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();
@@ -269,6 +270,8 @@ void bootloader_main()
 
     print_flash_info(&fhdr);
 
+    update_flash_config(&fhdr);
+
     if (!load_partition_table(&bs, PARTITION_ADD)) {
         ESP_LOGE(TAG, "load partition table error!");
         return;
@@ -364,7 +367,7 @@ void unpack_load_app(const partition_pos_t* partition)
     uint32_t irom_size = 0;
 
     /* Reload the RTC memory sections whenever a non-deepsleep reset
-       is occuring */
+       is occurring */
     bool load_rtc_memory = rtc_get_reset_reason(0) != DEEPSLEEP_RESET;
 
     ESP_LOGD(TAG, "bin_header: %u %u %u %u %08x", image_header.magic,
@@ -482,6 +485,36 @@ void IRAM_ATTR set_cache_and_start_app(
     (*entry)();
 }
 
+static void update_flash_config(struct flash_hdr* pfhdr)
+{
+    uint32_t size;
+    switch(pfhdr->spi_size) {
+        case SPI_SIZE_1MB:
+            size = 1;
+            break;
+        case SPI_SIZE_2MB:
+            size = 2;
+            break;
+        case SPI_SIZE_4MB:
+            size = 4;
+            break;
+        case SPI_SIZE_8MB:
+            size = 8;
+            break;
+        case SPI_SIZE_16MB:
+            size = 16;
+            break;
+        default:
+            size = 2;
+    }
+    Cache_Read_Disable( 0 );
+    // Set flash chip size
+    SPIParamCfg(g_rom_flashchip.deviceId, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
+    // TODO: set mode
+    // TODO: set frequency
+    Cache_Flush(0);
+    Cache_Read_Enable( 0 );
+}
 
 void print_flash_info(struct flash_hdr* pfhdr)
 {

+ 9 - 3
components/esp32/include/rom/spi_flash.h

@@ -218,7 +218,7 @@ void SelectSpiFunction(uint32_t ishspi);
 void spi_flash_attach(uint32_t ishspi, bool legacy);
 
 /**
-  * @brief SPI Read Flash status register. We use CMD 0x05.
+  * @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.
@@ -232,7 +232,7 @@ void spi_flash_attach(uint32_t ishspi, bool legacy);
 SpiFlashOpResult SPI_read_status(SpiFlashChip *spi, uint32_t *status);
 
 /**
-  * @brief SPI Read Flash status register high 16 bit. We use CMD 0x35.
+  * @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.
@@ -243,7 +243,7 @@ SpiFlashOpResult SPI_read_status(SpiFlashChip *spi, uint32_t *status);
   *         SPI_FLASH_RESULT_ERR : read error.
   *         SPI_FLASH_RESULT_TIMEOUT : read timeout.
   */
-SpiFlashOpResult SPI_read_status_high(SpiFlashChip *spi, uint32_t *status);
+SpiFlashOpResult SPI_read_status_high(uint32_t *status);
 
 /**
   * @brief Write status to Falsh status register.
@@ -503,6 +503,12 @@ void SPI_Write_Encrypt_Disable(void);
   */
 SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, uint32_t *data, uint32_t len);
 
+
+/** @brief Global SpiFlashChip structure used by ROM functions
+ *
+ */
+extern SpiFlashChip g_rom_flashchip;
+
 /**
   * @}
   */

+ 4 - 2
components/esp32/ld/esp32.rom.ld

@@ -286,6 +286,7 @@ PROVIDE ( _global_impure_ptr = 0x3ffae0b0 );
 PROVIDE ( gmtime = 0x40059848 );
 PROVIDE ( gmtime_r = 0x40059868 );
 PROVIDE ( g_phyFuns_instance = 0x3ffae0c4 );
+PROVIDE ( g_rom_flashchip = 0x3ffae270 );
 PROVIDE ( gpio_init = 0x40009c20 );
 PROVIDE ( gpio_input_get = 0x40009b88 );
 PROVIDE ( gpio_input_get_high = 0x40009b9c );
@@ -1584,6 +1585,8 @@ 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 );
@@ -1595,9 +1598,8 @@ PROVIDE ( SPIReadModeCnfig = 0x40062944 );
 PROVIDE ( SPI_read_status = 0x4006226c );
 /* This is static function, but can be used, not generated by script*/
 PROVIDE ( SPI_read_status_high = 0x40062448 );
-PROVIDE ( SPIUnlock = 0x400628b0 );
 PROVIDE ( SPI_user_command_read = 0x400621b0 );
-PROVIDE ( spi_w25q16 = 0x3ffae270 );
+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 );

+ 27 - 0
components/esptool_py/Kconfig.projbuild

@@ -94,4 +94,31 @@ config ESPTOOLPY_FLASHFREQ
 	default "26m" if ESPTOOLPY_FLASHFREQ_26M
 	default "20m" if ESPTOOLPY_FLASHFREQ_20M
 
+
+choice ESPTOOLPY_FLASHSIZE
+	prompt "Flash size"
+	default ESPTOOLPY_FLASHSIZE_2MB
+	help
+		SPI flash size, in megabytes
+
+config ESPTOOLPY_FLASHSIZE_1MB
+	bool "1 MB"
+config ESPTOOLPY_FLASHSIZE_2MB
+	bool "2 MB"
+config ESPTOOLPY_FLASHSIZE_4MB
+	bool "4 MB"
+config ESPTOOLPY_FLASHSIZE_8MB
+	bool "8 MB"
+config ESPTOOLPY_FLASHSIZE_16MB
+	bool "16 MB"
+endchoice
+
+config ESPTOOLPY_FLASHSIZE
+	string
+	default "1MB" if ESPTOOLPY_FLASHSIZE_1MB
+	default "2MB" if ESPTOOLPY_FLASHSIZE_2MB
+	default "4MB" if ESPTOOLPY_FLASHSIZE_4MB
+	default "8MB" if ESPTOOLPY_FLASHSIZE_8MB
+	default "16MB" if ESPTOOLPY_FLASHSIZE_16MB
+
 endmenu

+ 5 - 2
components/esptool_py/Makefile.projbuild

@@ -4,6 +4,7 @@ ESPPORT ?= $(CONFIG_ESPTOOLPY_PORT)
 ESPBAUD ?= $(CONFIG_ESPTOOLPY_BAUD)
 ESPFLASHMODE ?= $(CONFIG_ESPTOOLPY_FLASHMODE)
 ESPFLASHFREQ ?= $(CONFIG_ESPTOOLPY_FLASHFREQ)
+ESPFLASHSIZE ?= $(CONFIG_ESPTOOLPY_FLASHSIZE)
 
 PYTHON ?= $(call dequote,$(CONFIG_PYTHON))
 
@@ -15,13 +16,15 @@ ESPTOOLPY_SRC := $(COMPONENT_PATH)/esptool/esptool.py
 ESPTOOLPY := $(PYTHON) $(ESPTOOLPY_SRC) --chip esp32
 ESPTOOLPY_SERIAL := $(ESPTOOLPY) --port $(ESPPORT) --baud $(ESPBAUD)
 
+ESPTOOL_FLASH_OPTIONS := --flash_mode $(ESPFLASHMODE) --flash_freq $(ESPFLASHFREQ) --flash_size $(ESPFLASHSIZE)
+
 # the no-stub argument is temporary until esptool.py fully supports compressed uploads
-ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z) --flash_mode $(ESPFLASHMODE) --flash_freq $(ESPFLASHFREQ)
+ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z) $(ESPTOOL_FLASH_OPTIONS)
 
 ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN)
 
 $(APP_BIN): $(APP_ELF) $(ESPTOOLPY_SRC)
-	$(Q) $(ESPTOOLPY) elf2image --flash_mode $(ESPFLASHMODE) --flash_freq $(ESPFLASHFREQ) -o $@ $<
+	$(Q) $(ESPTOOLPY) elf2image $(ESPTOOL_FLASH_OPTIONS) -o $@ $<
 
 flash: all_binaries $(ESPTOOLPY_SRC)
 	@echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(CONFIG_APP_OFFSET))..."

+ 1 - 1
components/esptool_py/esptool

@@ -1 +1 @@
-Subproject commit 197ba605fe0c05e16bf4c5ec07b726adc8d86abc
+Subproject commit 5c6962e894e0a118c9a4b5760876433493449260

+ 5 - 0
components/spi_flash/component.mk

@@ -1,3 +1,8 @@
 COMPONENT_ADD_INCLUDEDIRS := include
 
+ifdef IS_BOOTLOADER_BUILD
+# Bootloader needs updated SPIUnlock from this file
+COMPONENT_OBJS := spi_flash_rom_patch.o
+endif
+
 include $(IDF_PATH)/make/component_common.mk

+ 72 - 0
components/spi_flash/spi_flash_rom_patch.c

@@ -0,0 +1,72 @@
+// 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 "rom/spi_flash.h"
+#include "soc/spi_reg.h"
+
+static const uint32_t STATUS_QIE_BIT = (1 << 9); /* Quad Enable */
+
+#define SPI_IDX 1
+#define OTH_IDX 0
+
+extern SpiFlashChip SPI_flashchip_data;
+
+static void IRAM_ATTR Wait_SPI_Idle(void)
+{
+  /* 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) {
+  }
+}
+
+/* Modified version of SPIUnlock() that replaces version in ROM.
+
+   This works around a bug where SPIUnlock 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.
+ */
+SpiFlashOpResult IRAM_ATTR SPIUnlock(void)
+{
+  uint32_t status;
+
+  Wait_SPI_Idle();
+
+  if (SPI_read_status_high(&status) != SPI_FLASH_RESULT_OK) {
+    return SPI_FLASH_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;
+
+  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();
+
+  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;
+  }
+
+  return SPI_FLASH_RESULT_OK;
+}