mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-07 14:44:32 +02:00
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:
197ba605...5c6962e8
See merge request !144
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
# basically runs Make in the src/ directory but it needs to zero some variables
|
# 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.
|
# 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_COMPONENT_PATH := $(COMPONENT_PATH)
|
||||||
BOOTLOADER_BUILD_DIR=$(abspath $(BUILD_DIR_BASE)/bootloader)
|
BOOTLOADER_BUILD_DIR=$(abspath $(BUILD_DIR_BASE)/bootloader)
|
||||||
|
@@ -4,12 +4,13 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
PROJECT_NAME := bootloader
|
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.
|
# 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 tells the component Makefile.projbuild to be a no-op
|
||||||
IS_BOOTLOADER_BUILD := 1
|
IS_BOOTLOADER_BUILD := 1
|
||||||
|
export IS_BOOTLOADER_BUILD
|
||||||
|
|
||||||
#We cannot include the esp32 component directly but we need its includes.
|
#We cannot include the esp32 component directly but we need its includes.
|
||||||
#This is fixed by adding CFLAGS from Makefile.projbuild
|
#This is fixed by adding CFLAGS from Makefile.projbuild
|
||||||
|
@@ -51,7 +51,7 @@ enum {
|
|||||||
SPI_SPEED_20M,
|
SPI_SPEED_20M,
|
||||||
SPI_SPEED_80M = 0xF
|
SPI_SPEED_80M = 0xF
|
||||||
};
|
};
|
||||||
/*suppport flash size in esp32 */
|
/*supported flash sizes*/
|
||||||
enum {
|
enum {
|
||||||
SPI_SIZE_1MB = 0,
|
SPI_SIZE_1MB = 0,
|
||||||
SPI_SIZE_2MB,
|
SPI_SIZE_2MB,
|
||||||
|
@@ -58,6 +58,7 @@ void IRAM_ATTR set_cache_and_start_app(uint32_t drom_addr,
|
|||||||
uint32_t irom_load_addr,
|
uint32_t irom_load_addr,
|
||||||
uint32_t irom_size,
|
uint32_t irom_size,
|
||||||
uint32_t entry_addr);
|
uint32_t entry_addr);
|
||||||
|
static void update_flash_config(struct flash_hdr* pfhdr);
|
||||||
|
|
||||||
|
|
||||||
void IRAM_ATTR call_start_cpu0()
|
void IRAM_ATTR call_start_cpu0()
|
||||||
@@ -258,7 +259,7 @@ void bootloader_main()
|
|||||||
memset(&bs, 0, sizeof(bs));
|
memset(&bs, 0, sizeof(bs));
|
||||||
|
|
||||||
ESP_LOGI(TAG, "compile time " __TIME__ );
|
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( RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN );
|
||||||
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
|
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
|
||||||
SPIUnlock();
|
SPIUnlock();
|
||||||
@@ -269,6 +270,8 @@ void bootloader_main()
|
|||||||
|
|
||||||
print_flash_info(&fhdr);
|
print_flash_info(&fhdr);
|
||||||
|
|
||||||
|
update_flash_config(&fhdr);
|
||||||
|
|
||||||
if (!load_partition_table(&bs, PARTITION_ADD)) {
|
if (!load_partition_table(&bs, PARTITION_ADD)) {
|
||||||
ESP_LOGE(TAG, "load partition table error!");
|
ESP_LOGE(TAG, "load partition table error!");
|
||||||
return;
|
return;
|
||||||
@@ -364,7 +367,7 @@ void unpack_load_app(const partition_pos_t* partition)
|
|||||||
uint32_t irom_size = 0;
|
uint32_t irom_size = 0;
|
||||||
|
|
||||||
/* Reload the RTC memory sections whenever a non-deepsleep reset
|
/* 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;
|
bool load_rtc_memory = rtc_get_reset_reason(0) != DEEPSLEEP_RESET;
|
||||||
|
|
||||||
ESP_LOGD(TAG, "bin_header: %u %u %u %u %08x", image_header.magic,
|
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)();
|
(*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)
|
void print_flash_info(struct flash_hdr* pfhdr)
|
||||||
{
|
{
|
||||||
|
@@ -218,7 +218,7 @@ void SelectSpiFunction(uint32_t ishspi);
|
|||||||
void spi_flash_attach(uint32_t ishspi, bool legacy);
|
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.
|
* Please do not call this function in SDK.
|
||||||
*
|
*
|
||||||
* @param SpiFlashChip *spi : The information for Flash, which is exported from ld file.
|
* @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);
|
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.
|
* Please do not call this function in SDK.
|
||||||
*
|
*
|
||||||
* @param SpiFlashChip *spi : The information for Flash, which is exported from ld file.
|
* @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_ERR : read error.
|
||||||
* SPI_FLASH_RESULT_TIMEOUT : read timeout.
|
* 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.
|
* @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);
|
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
@@ -286,6 +286,7 @@ PROVIDE ( _global_impure_ptr = 0x3ffae0b0 );
|
|||||||
PROVIDE ( gmtime = 0x40059848 );
|
PROVIDE ( gmtime = 0x40059848 );
|
||||||
PROVIDE ( gmtime_r = 0x40059868 );
|
PROVIDE ( gmtime_r = 0x40059868 );
|
||||||
PROVIDE ( g_phyFuns_instance = 0x3ffae0c4 );
|
PROVIDE ( g_phyFuns_instance = 0x3ffae0c4 );
|
||||||
|
PROVIDE ( g_rom_flashchip = 0x3ffae270 );
|
||||||
PROVIDE ( gpio_init = 0x40009c20 );
|
PROVIDE ( gpio_init = 0x40009c20 );
|
||||||
PROVIDE ( gpio_input_get = 0x40009b88 );
|
PROVIDE ( gpio_input_get = 0x40009b88 );
|
||||||
PROVIDE ( gpio_input_get_high = 0x40009b9c );
|
PROVIDE ( gpio_input_get_high = 0x40009b9c );
|
||||||
@@ -1584,6 +1585,8 @@ PROVIDE ( SPIEraseBlock = 0x40062c4c );
|
|||||||
PROVIDE ( SPIEraseChip = 0x40062c14 );
|
PROVIDE ( SPIEraseChip = 0x40062c14 );
|
||||||
PROVIDE ( SPIEraseSector = 0x40062ccc );
|
PROVIDE ( SPIEraseSector = 0x40062ccc );
|
||||||
PROVIDE ( spi_flash_attach = 0x40062a6c );
|
PROVIDE ( spi_flash_attach = 0x40062a6c );
|
||||||
|
/* NB: SPIUnlock @ 0x400628b0 has been replaced with an updated
|
||||||
|
version in the "spi_flash" component */
|
||||||
PROVIDE ( SPILock = 0x400628f0 );
|
PROVIDE ( SPILock = 0x400628f0 );
|
||||||
PROVIDE ( SPIMasterReadModeCnfig = 0x40062b64 );
|
PROVIDE ( SPIMasterReadModeCnfig = 0x40062b64 );
|
||||||
PROVIDE ( spi_modes = 0x3ff99270 );
|
PROVIDE ( spi_modes = 0x3ff99270 );
|
||||||
@@ -1595,9 +1598,8 @@ PROVIDE ( SPIReadModeCnfig = 0x40062944 );
|
|||||||
PROVIDE ( SPI_read_status = 0x4006226c );
|
PROVIDE ( SPI_read_status = 0x4006226c );
|
||||||
/* This is static function, but can be used, not generated by script*/
|
/* This is static function, but can be used, not generated by script*/
|
||||||
PROVIDE ( SPI_read_status_high = 0x40062448 );
|
PROVIDE ( SPI_read_status_high = 0x40062448 );
|
||||||
PROVIDE ( SPIUnlock = 0x400628b0 );
|
|
||||||
PROVIDE ( SPI_user_command_read = 0x400621b0 );
|
PROVIDE ( SPI_user_command_read = 0x400621b0 );
|
||||||
PROVIDE ( spi_w25q16 = 0x3ffae270 );
|
PROVIDE ( SPI_flashchip_data = 0x3ffae270 );
|
||||||
PROVIDE ( SPIWrite = 0x40062d50 );
|
PROVIDE ( SPIWrite = 0x40062d50 );
|
||||||
/* This is static function, but can be used, not generated by script*/
|
/* This is static function, but can be used, not generated by script*/
|
||||||
PROVIDE ( SPI_write_enable = 0x40062320 );
|
PROVIDE ( SPI_write_enable = 0x40062320 );
|
||||||
|
@@ -94,4 +94,31 @@ config ESPTOOLPY_FLASHFREQ
|
|||||||
default "26m" if ESPTOOLPY_FLASHFREQ_26M
|
default "26m" if ESPTOOLPY_FLASHFREQ_26M
|
||||||
default "20m" if ESPTOOLPY_FLASHFREQ_20M
|
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
|
endmenu
|
||||||
|
@@ -4,6 +4,7 @@ ESPPORT ?= $(CONFIG_ESPTOOLPY_PORT)
|
|||||||
ESPBAUD ?= $(CONFIG_ESPTOOLPY_BAUD)
|
ESPBAUD ?= $(CONFIG_ESPTOOLPY_BAUD)
|
||||||
ESPFLASHMODE ?= $(CONFIG_ESPTOOLPY_FLASHMODE)
|
ESPFLASHMODE ?= $(CONFIG_ESPTOOLPY_FLASHMODE)
|
||||||
ESPFLASHFREQ ?= $(CONFIG_ESPTOOLPY_FLASHFREQ)
|
ESPFLASHFREQ ?= $(CONFIG_ESPTOOLPY_FLASHFREQ)
|
||||||
|
ESPFLASHSIZE ?= $(CONFIG_ESPTOOLPY_FLASHSIZE)
|
||||||
|
|
||||||
PYTHON ?= $(call dequote,$(CONFIG_PYTHON))
|
PYTHON ?= $(call dequote,$(CONFIG_PYTHON))
|
||||||
|
|
||||||
@@ -15,13 +16,15 @@ ESPTOOLPY_SRC := $(COMPONENT_PATH)/esptool/esptool.py
|
|||||||
ESPTOOLPY := $(PYTHON) $(ESPTOOLPY_SRC) --chip esp32
|
ESPTOOLPY := $(PYTHON) $(ESPTOOLPY_SRC) --chip esp32
|
||||||
ESPTOOLPY_SERIAL := $(ESPTOOLPY) --port $(ESPPORT) --baud $(ESPBAUD)
|
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
|
# 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)
|
ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN)
|
||||||
|
|
||||||
$(APP_BIN): $(APP_ELF) $(ESPTOOLPY_SRC)
|
$(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)
|
flash: all_binaries $(ESPTOOLPY_SRC)
|
||||||
@echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(CONFIG_APP_OFFSET))..."
|
@echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(CONFIG_APP_OFFSET))..."
|
||||||
|
Submodule components/esptool_py/esptool updated: 197ba605fe...5c6962e894
@@ -1,3 +1,8 @@
|
|||||||
COMPONENT_ADD_INCLUDEDIRS := include
|
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
|
include $(IDF_PATH)/make/component_common.mk
|
||||||
|
72
components/spi_flash/spi_flash_rom_patch.c
Normal file
72
components/spi_flash/spi_flash_rom_patch.c
Normal file
@@ -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;
|
||||||
|
}
|
Reference in New Issue
Block a user