mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feat/epi_flash_api_iram_save_4.2' into 'release/v4.2'
spi_flash: partially move API functions out of IRAM (v4.2) See merge request espressif/esp-idf!18304
This commit is contained in:
commit
32aa2ab24e
@ -23,7 +23,7 @@
|
||||
#include "unity.h"
|
||||
|
||||
#include "bootloader_common.h"
|
||||
#include "../include_bootloader/bootloader_flash.h"
|
||||
#include "../include_bootloader/bootloader_flash_priv.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_ota_ops.h"
|
||||
|
@ -309,6 +309,15 @@ menu "Bootloader config"
|
||||
in this area of memory, you can increase it. It must be a multiple of 4 bytes.
|
||||
This area (rtc_retain_mem_t) is reserved and has access from the bootloader and an application.
|
||||
|
||||
config BOOTLOADER_FLASH_XMC_SUPPORT
|
||||
bool "Enable the support for flash chips of XMC (READ HELP FIRST)"
|
||||
default y
|
||||
help
|
||||
Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow.
|
||||
XMC chips will be forbidden to be used, when this option is disabled.
|
||||
|
||||
DON'T DISABLE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
|
||||
|
||||
endmenu # Bootloader
|
||||
|
||||
|
||||
|
61
components/bootloader_support/include/bootloader_flash.h
Normal file
61
components/bootloader_support/include/bootloader_flash.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2020 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.
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Read flash ID by sending 0x9F command
|
||||
* @return flash raw ID
|
||||
* mfg_id = (ID >> 16) & 0xFF;
|
||||
flash_id = ID & 0xffff;
|
||||
*/
|
||||
uint32_t bootloader_read_flash_id(void);
|
||||
|
||||
#if SOC_CACHE_SUPPORT_WRAP
|
||||
/**
|
||||
* @brief Set the burst mode setting command for specified wrap mode.
|
||||
*
|
||||
* @param mode The specified warp mode.
|
||||
* @return always ESP_OK
|
||||
*/
|
||||
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Startup flow recommended by XMC. Call at startup before any erase/write operation.
|
||||
*
|
||||
* @return ESP_OK When startup successfully, otherwise ESP_FAIL (indiciating you should reboot before erase/write).
|
||||
*/
|
||||
esp_err_t bootloader_flash_xmc_startup(void);
|
||||
|
||||
/**
|
||||
* @brief Unlock Flash write protect.
|
||||
* Please do not call this function in SDK.
|
||||
*
|
||||
* @note This can be overridden because it's attribute weak.
|
||||
*/
|
||||
esp_err_t bootloader_flash_unlock(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -19,11 +19,28 @@
|
||||
#include <stdint.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include "sdkconfig.h"
|
||||
#include "bootloader_flash.h"
|
||||
|
||||
#define FLASH_SECTOR_SIZE 0x1000
|
||||
#define FLASH_BLOCK_SIZE 0x10000
|
||||
#define MMAP_ALIGNED_MASK 0x0000FFFF
|
||||
|
||||
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
|
||||
Suitable for use with the bootloader_execute_flash_command static function.
|
||||
*/
|
||||
#define CMD_RDID 0x9F
|
||||
#define CMD_WRSR 0x01
|
||||
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
|
||||
#define CMD_WREN 0x06
|
||||
#define CMD_WRDI 0x04
|
||||
#define CMD_RDSR 0x05
|
||||
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
|
||||
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
|
||||
#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */
|
||||
#define CMD_WRAP 0x77 /* Set burst with wrap command */
|
||||
|
||||
|
||||
/* Provide a Flash API for bootloader_support code,
|
||||
that can be used from bootloader or app code.
|
||||
|
||||
@ -136,4 +153,29 @@ static inline uint32_t bootloader_cache_pages_to_map(uint32_t size, uint32_t vad
|
||||
return (size + (vaddr - (vaddr & MMU_FLASH_MASK)) + MMU_BLOCK_SIZE - 1) / MMU_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Execute a user command on the flash
|
||||
*
|
||||
* @param command The command value to execute.
|
||||
* @param mosi_data MOSI data to send
|
||||
* @param mosi_len Length of MOSI data, in bits
|
||||
* @param miso_len Length of MISO data to receive, in bits
|
||||
* @return Received MISO data
|
||||
*/
|
||||
uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
|
||||
|
||||
/**
|
||||
* @brief Read the SFDP of the flash
|
||||
*
|
||||
* @param sfdp_addr Address of the parameter to read
|
||||
* @param miso_byte_num Bytes to read
|
||||
* @return The read SFDP, little endian, 4 bytes at most
|
||||
*/
|
||||
uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num);
|
||||
|
||||
/**
|
||||
* @brief Enable the flash write protect (WEL bit).
|
||||
*/
|
||||
void bootloader_enable_wp(void);
|
||||
|
||||
#endif
|
@ -13,6 +13,8 @@
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "esp32s2/rom/gpio.h"
|
||||
#endif
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
|
@ -13,13 +13,44 @@
|
||||
// limitations under the License.
|
||||
#include <stddef.h>
|
||||
|
||||
#include <bootloader_flash.h>
|
||||
#include <bootloader_flash_priv.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_flash_encrypt.h>
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
# include "soc/spi_struct.h"
|
||||
# include "soc/spi_reg.h"
|
||||
/* SPI flash controller */
|
||||
# define SPIFLASH SPI1
|
||||
#else
|
||||
# include "soc/spi_mem_struct.h"
|
||||
# include "soc/spi_mem_reg.h"
|
||||
/* SPI flash controller */
|
||||
# define SPIFLASH SPIMEM1
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/spi_flash.h" //For SPI_Encrypt_Write
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#endif
|
||||
|
||||
#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF)
|
||||
#define ISSI_ID 0x9D
|
||||
#define MXIC_ID 0xC2
|
||||
#define GD_Q_ID_HIGH 0xC8
|
||||
#define GD_Q_ID_MID 0x40
|
||||
#define GD_Q_ID_LOW 0x16
|
||||
|
||||
#define ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
|
||||
#define ESP_BOOTLOADER_SPIFLASH_QE_GD_SR2 BIT1 // QE position when you write 8 bits(for SR2) at one time.
|
||||
#define ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE BIT9 // QE position when you write 16 bits at one time.
|
||||
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
/* Normal app version maps to esp_spi_flash.h operations...
|
||||
*/
|
||||
@ -89,7 +120,7 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
return spi_flash_erase_range(start_addr, size);
|
||||
}
|
||||
|
||||
#else
|
||||
#else //BOOTLOADER_BUILD
|
||||
/* Bootloader version, uses ROM functions only */
|
||||
#include "soc/dport_reg.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@ -318,7 +349,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = spi_to_esp_err(esp_rom_spiflash_unlock());
|
||||
err = bootloader_flash_unlock();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
@ -364,4 +395,332 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
}
|
||||
return spi_to_esp_err(rc);
|
||||
}
|
||||
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
FORCE_INLINE_ATTR bool is_issi_chip(const esp_rom_spiflash_chip_t* chip)
|
||||
{
|
||||
return BYTESHIFT(chip->device_id, 2) == ISSI_ID;
|
||||
}
|
||||
|
||||
// For GD25Q32, GD25Q64, GD25Q127C, GD25Q128, which use single command to read/write different SR.
|
||||
FORCE_INLINE_ATTR bool is_gd_q_chip(const esp_rom_spiflash_chip_t* chip)
|
||||
{
|
||||
return BYTESHIFT(chip->device_id, 2) == GD_Q_ID_HIGH && BYTESHIFT(chip->device_id, 1) == GD_Q_ID_MID && BYTESHIFT(chip->device_id, 0) >= GD_Q_ID_LOW;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR bool is_mxic_chip(const esp_rom_spiflash_chip_t* chip)
|
||||
{
|
||||
return BYTESHIFT(chip->device_id, 2) == MXIC_ID;
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void)
|
||||
{
|
||||
// At the beginning status == new_status == status_sr2 == new_status_sr2 == 0.
|
||||
// If the register doesn't need to be updated, keep them the same (0), so that no command will be actually sent.
|
||||
uint16_t status = 0; // status for SR1 or SR1+SR2 if writing SR with 01H + 2Bytes.
|
||||
uint16_t new_status = 0;
|
||||
uint8_t status_sr2 = 0; // status_sr2 for SR2.
|
||||
uint8_t new_status_sr2 = 0;
|
||||
uint8_t sr1_bit_num = 0;
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
if (is_issi_chip(&g_rom_flashchip) || is_mxic_chip(&g_rom_flashchip)) {
|
||||
// Currently ISSI & MXIC share the same command and register layout, which is different from the default model.
|
||||
// If any code here needs to be modified, check both chips.
|
||||
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
|
||||
/* Clear all bits in the mask.
|
||||
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
|
||||
*/
|
||||
sr1_bit_num = 8;
|
||||
new_status = status & (~ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI);
|
||||
} else if (is_gd_q_chip(&g_rom_flashchip)) {
|
||||
/* The GD chips behaviour is to clear all bits in SR1 and clear bits in SR2 except QE bit.
|
||||
Use 01H to write SR1 and 31H to write SR2.
|
||||
*/
|
||||
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
sr1_bit_num = 8;
|
||||
new_status = 0;
|
||||
|
||||
status_sr2 = bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8);
|
||||
new_status_sr2 = status_sr2 & ESP_BOOTLOADER_SPIFLASH_QE_GD_SR2;
|
||||
} else {
|
||||
/* For common behaviour, like XMC chips, Use 01H+2Bytes to write both SR1 and SR2*/
|
||||
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
|
||||
|
||||
/* Clear all bits except QE, if it is set.
|
||||
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
|
||||
*/
|
||||
sr1_bit_num = 16;
|
||||
new_status = status & ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE;
|
||||
}
|
||||
|
||||
// When SR is written, set to true to indicate that WRDI need to be sent to ensure the protection is ON before return.
|
||||
bool status_written = false;
|
||||
// Skip if nothing needs to be changed. Meaningless writing to SR increases the risk during write and wastes time.
|
||||
if (status != new_status) {
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||
bootloader_execute_flash_command(CMD_WRSR, new_status, sr1_bit_num, 0);
|
||||
status_written = true;
|
||||
}
|
||||
|
||||
if (status_sr2 != new_status_sr2) {
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||
bootloader_execute_flash_command(CMD_WRSR2, new_status_sr2, 8, 0);
|
||||
status_written = true;
|
||||
}
|
||||
|
||||
if (status_written) {
|
||||
//Call esp_rom_spiflash_wait_idle to make sure previous WRSR is completed.
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
IRAM_ATTR static uint32_t bootloader_flash_execute_command_common(
|
||||
uint8_t command,
|
||||
uint32_t addr_len, uint32_t address,
|
||||
uint8_t dummy_len,
|
||||
uint8_t mosi_len, uint32_t mosi_data,
|
||||
uint8_t miso_len)
|
||||
{
|
||||
assert(mosi_len <= 32);
|
||||
assert(miso_len <= 32);
|
||||
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
|
||||
uint32_t old_user_reg = SPIFLASH.user.val;
|
||||
uint32_t old_user1_reg = SPIFLASH.user1.val;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#else
|
||||
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#endif
|
||||
//command phase
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
SPIFLASH.user2.usr_command_value = command;
|
||||
//addr phase
|
||||
SPIFLASH.user.usr_addr = addr_len > 0;
|
||||
SPIFLASH.user1.usr_addr_bitlen = addr_len - 1;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.addr = (addr_len > 0)? (address << (32-addr_len)) : 0;
|
||||
#else
|
||||
SPIFLASH.addr = address;
|
||||
#endif
|
||||
//dummy phase
|
||||
if (miso_len > 0) {
|
||||
uint32_t total_dummy = dummy_len + g_rom_spiflash_dummy_len_plus[1];
|
||||
SPIFLASH.user.usr_dummy = total_dummy > 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = total_dummy - 1;
|
||||
} else {
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = 0;
|
||||
}
|
||||
//output data
|
||||
SPIFLASH.user.usr_mosi = mosi_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
|
||||
#else
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
|
||||
#endif
|
||||
SPIFLASH.data_buf[0] = mosi_data;
|
||||
//input data
|
||||
SPIFLASH.user.usr_miso = miso_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
|
||||
#else
|
||||
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
|
||||
#endif
|
||||
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
SPIFLASH.ctrl.val = old_ctrl_reg;
|
||||
SPIFLASH.user.val = old_user_reg;
|
||||
SPIFLASH.user1.val = old_user1_reg;
|
||||
|
||||
uint32_t ret = SPIFLASH.data_buf[0];
|
||||
if (miso_len < 32) {
|
||||
//set unused bits to 0
|
||||
ret &= ~(UINT32_MAX << miso_len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
|
||||
{
|
||||
const uint8_t addr_len = 0;
|
||||
const uint8_t address = 0;
|
||||
const uint8_t dummy_len = 0;
|
||||
|
||||
return bootloader_flash_execute_command_common(command, addr_len, address,
|
||||
dummy_len, mosi_len, mosi_data, miso_len);
|
||||
}
|
||||
|
||||
// cmd(0x5A) + 24bit address + 8 cycles dummy
|
||||
uint32_t IRAM_ATTR bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num)
|
||||
{
|
||||
assert(miso_byte_num <= 4);
|
||||
const uint8_t command = CMD_RDSFDP;
|
||||
const uint8_t addr_len = 24;
|
||||
const uint8_t dummy_len = 8;
|
||||
const uint8_t mosi_len = 0;
|
||||
const uint32_t mosi_data = 0;
|
||||
const uint8_t miso_len = miso_byte_num * 8;
|
||||
|
||||
return bootloader_flash_execute_command_common(command, addr_len, sfdp_addr,
|
||||
dummy_len, mosi_len, mosi_data, miso_len);
|
||||
}
|
||||
|
||||
void bootloader_enable_wp(void)
|
||||
{
|
||||
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR bootloader_read_flash_id(void)
|
||||
{
|
||||
uint32_t id = bootloader_execute_flash_command(CMD_RDID, 0, 0, 24);
|
||||
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
|
||||
return id;
|
||||
}
|
||||
|
||||
#if SOC_CACHE_SUPPORT_WRAP
|
||||
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode)
|
||||
{
|
||||
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
|
||||
uint32_t reg_bkp_usr = SPIFLASH.user.val;
|
||||
SPIFLASH.user.fwrite_dio = 0;
|
||||
SPIFLASH.user.fwrite_dual = 0;
|
||||
SPIFLASH.user.fwrite_qio = 1;
|
||||
SPIFLASH.user.fwrite_quad = 0;
|
||||
SPIFLASH.ctrl.fcmd_dual = 0;
|
||||
SPIFLASH.ctrl.fcmd_quad = 0;
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 1;
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
SPIFLASH.user2.usr_command_value = CMD_WRAP;
|
||||
SPIFLASH.user1.usr_addr_bitlen = 23;
|
||||
SPIFLASH.addr = 0;
|
||||
SPIFLASH.user.usr_miso = 0;
|
||||
SPIFLASH.user.usr_mosi = 1;
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
|
||||
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while(SPIFLASH.cmd.usr != 0)
|
||||
{ }
|
||||
|
||||
SPIFLASH.ctrl.val = reg_bkp_ctrl;
|
||||
SPIFLASH.user.val = reg_bkp_usr;
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //SOC_CACHE_SUPPORT_WRAP
|
||||
|
||||
/*******************************************************************************
|
||||
* XMC startup flow
|
||||
******************************************************************************/
|
||||
|
||||
#define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT
|
||||
#define XMC_VENDOR_ID 0x20
|
||||
|
||||
#if BOOTLOADER_BUILD
|
||||
#define BOOTLOADER_FLASH_LOG(level, ...) ESP_LOG##level(TAG, ##__VA_ARGS__)
|
||||
#else
|
||||
static DRAM_ATTR char bootloader_flash_tag[] = "bootloader_flash";
|
||||
#define BOOTLOADER_FLASH_LOG(level, ...) ESP_DRAM_LOG##level(bootloader_flash_tag, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if XMC_SUPPORT
|
||||
//strictly check the model
|
||||
static IRAM_ATTR bool is_xmc_chip_strict(uint32_t rdid)
|
||||
{
|
||||
uint32_t vendor_id = BYTESHIFT(rdid, 2);
|
||||
uint32_t mfid = BYTESHIFT(rdid, 1);
|
||||
uint32_t cpid = BYTESHIFT(rdid, 0);
|
||||
|
||||
if (vendor_id != XMC_VENDOR_ID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool matched = false;
|
||||
if (mfid == 0x40) {
|
||||
if (cpid >= 0x13 && cpid <= 0x20) {
|
||||
matched = true;
|
||||
}
|
||||
} else if (mfid == 0x41) {
|
||||
if (cpid >= 0x17 && cpid <= 0x20) {
|
||||
matched = true;
|
||||
}
|
||||
} else if (mfid == 0x50) {
|
||||
if (cpid >= 0x15 && cpid <= 0x16) {
|
||||
matched = true;
|
||||
}
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
|
||||
{
|
||||
// If the RDID value is a valid XMC one, may skip the flow
|
||||
const bool fast_check = true;
|
||||
if (fast_check && is_xmc_chip_strict(g_rom_flashchip.device_id)) {
|
||||
BOOTLOADER_FLASH_LOG(D, "XMC chip detected by RDID (%08X), skip.", g_rom_flashchip.device_id);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Check the Manufacturer ID in SFDP registers (JEDEC standard). If not XMC chip, no need to run the flow
|
||||
const int sfdp_mfid_addr = 0x10;
|
||||
uint8_t mf_id = (bootloader_flash_read_sfdp(sfdp_mfid_addr, 1) & 0xff);
|
||||
if (mf_id != XMC_VENDOR_ID) {
|
||||
BOOTLOADER_FLASH_LOG(D, "non-XMC chip detected by SFDP Read (%02X), skip.", mf_id);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
BOOTLOADER_FLASH_LOG(I, "XM25QHxxC startup flow");
|
||||
// Enter DPD
|
||||
bootloader_execute_flash_command(0xB9, 0, 0, 0);
|
||||
// Enter UDPD
|
||||
bootloader_execute_flash_command(0x79, 0, 0, 0);
|
||||
// Exit UDPD
|
||||
bootloader_execute_flash_command(0xFF, 0, 0, 0);
|
||||
// Delay tXUDPD
|
||||
ets_delay_us(2000);
|
||||
// Release Power-down
|
||||
bootloader_execute_flash_command(0xAB, 0, 0, 0);
|
||||
ets_delay_us(20);
|
||||
// Read flash ID and check again
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
if (!is_xmc_chip_strict(g_rom_flashchip.device_id)) {
|
||||
BOOTLOADER_FLASH_LOG(E, "XMC flash startup fail");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
//only compare the vendor id
|
||||
static IRAM_ATTR bool is_xmc_chip(uint32_t rdid)
|
||||
{
|
||||
uint32_t vendor_id = (rdid >> 16) & 0xFF;
|
||||
return (vendor_id == XMC_VENDOR_ID);
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
|
||||
{
|
||||
if (is_xmc_chip(g_rom_flashchip.device_id)) {
|
||||
BOOTLOADER_FLASH_LOG(E, "XMC chip detected (%08X) while support disabled.", g_rom_flashchip.device_id);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif //XMC_SUPPORT
|
@ -17,7 +17,7 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_clock.h"
|
||||
|
@ -59,7 +59,7 @@
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "bootloader_common.h"
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_mem.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/dport_reg.h"
|
||||
@ -259,7 +260,7 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
@ -267,6 +268,8 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
|
||||
print_flash_info(&bootloader_image_hdr);
|
||||
update_flash_config(&bootloader_image_hdr);
|
||||
//ensure the flash is write-protected
|
||||
bootloader_enable_wp();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -452,6 +455,11 @@ esp_err_t bootloader_init(void)
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// Check and run XMC startup flow
|
||||
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
|
||||
goto err;
|
||||
}
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_mem.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
|
||||
#include "esp32s2/rom/cache.h"
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
@ -205,7 +206,7 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
@ -213,6 +214,8 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
|
||||
print_flash_info(&bootloader_image_hdr);
|
||||
update_flash_config(&bootloader_image_hdr);
|
||||
//ensure the flash is write-protected
|
||||
bootloader_enable_wp();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -374,6 +377,11 @@ esp_err_t bootloader_init(void)
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// Check and run XMC startup flow
|
||||
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
|
||||
goto err;
|
||||
}
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_image_format.h"
|
||||
@ -303,8 +303,8 @@ static esp_err_t encrypt_bootloader(void)
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "bootloader encrypted successfully");
|
||||
return err;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "esp_secure_boot.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_fault.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <esp_log.h>
|
||||
#include <esp_attr.h>
|
||||
#include <esp_spi_flash.h>
|
||||
#include <bootloader_flash.h>
|
||||
#include <bootloader_flash_priv.h>
|
||||
#include <bootloader_random.h>
|
||||
#include <bootloader_sha.h>
|
||||
#include "bootloader_util.h"
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <stdint.h>
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@ -25,30 +26,10 @@
|
||||
#include "esp32s2/rom/efuse.h"
|
||||
#include "soc/spi_mem_struct.h"
|
||||
#endif
|
||||
#include "soc/spi_struct.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* SPI flash controller */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define SPIFLASH SPI1
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define SPIFLASH SPIMEM1
|
||||
#endif
|
||||
|
||||
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
|
||||
Suitable for use with the execute_flash_command static function.
|
||||
*/
|
||||
#define CMD_RDID 0x9F
|
||||
#define CMD_WRSR 0x01
|
||||
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
|
||||
#define CMD_WREN 0x06
|
||||
#define CMD_WRDI 0x04
|
||||
#define CMD_RDSR 0x05
|
||||
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
|
||||
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
|
||||
|
||||
static const char *TAG = "qio_mode";
|
||||
|
||||
@ -126,56 +107,6 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
|
||||
The command passed here is always the on-the-wire command given to the SPI flash unit.
|
||||
*/
|
||||
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
uint32_t bootloader_read_flash_id(void)
|
||||
{
|
||||
uint32_t id = execute_flash_command(CMD_RDID, 0, 0, 24);
|
||||
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
|
||||
return id;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#define FLASH_WRAP_CMD 0x77
|
||||
typedef enum {
|
||||
FLASH_WRAP_MODE_8B = 0,
|
||||
FLASH_WRAP_MODE_16B = 2,
|
||||
FLASH_WRAP_MODE_32B = 4,
|
||||
FLASH_WRAP_MODE_64B = 6,
|
||||
FLASH_WRAP_MODE_DISABLE = 1
|
||||
} spi_flash_wrap_mode_t;
|
||||
static esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
|
||||
{
|
||||
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
|
||||
uint32_t reg_bkp_usr = SPIFLASH.user.val;
|
||||
SPIFLASH.user.fwrite_dio = 0;
|
||||
SPIFLASH.user.fwrite_dual = 0;
|
||||
SPIFLASH.user.fwrite_qio = 1;
|
||||
SPIFLASH.user.fwrite_quad = 0;
|
||||
SPIFLASH.ctrl.fcmd_dual = 0;
|
||||
SPIFLASH.ctrl.fcmd_quad = 0;
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 1;
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
|
||||
SPIFLASH.user1.usr_addr_bitlen = 23;
|
||||
SPIFLASH.addr = 0;
|
||||
SPIFLASH.user.usr_miso = 0;
|
||||
SPIFLASH.user.usr_mosi = 1;
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
|
||||
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
|
||||
SPIFLASH.ctrl.val = reg_bkp_ctrl;
|
||||
SPIFLASH.user.val = reg_bkp_usr;
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
void bootloader_enable_qio_mode(void)
|
||||
{
|
||||
@ -208,8 +139,8 @@ void bootloader_enable_qio_mode(void)
|
||||
enable_qio_mode(chip_data[i].read_status_fn,
|
||||
chip_data[i].write_status_fn,
|
||||
chip_data[i].status_qio_bit);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
|
||||
#if SOC_CACHE_SUPPORT_WRAP
|
||||
bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -226,7 +157,7 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
|
||||
|
||||
if ((status & (1 << status_qio_bit)) == 0) {
|
||||
execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||
write_status_fn(status | (1 << status_qio_bit));
|
||||
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
@ -264,95 +195,48 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
|
||||
static unsigned read_status_8b_rdsr(void)
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
}
|
||||
|
||||
static unsigned read_status_8b_rdsr2(void)
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR2, 0, 0, 8);
|
||||
return bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8);
|
||||
}
|
||||
|
||||
static unsigned read_status_16b_rdsr_rdsr2(void)
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR, 0, 0, 8) | (execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
|
||||
return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
|
||||
}
|
||||
|
||||
static void write_status_8b_wrsr(unsigned new_status)
|
||||
{
|
||||
execute_flash_command(CMD_WRSR, new_status, 8, 0);
|
||||
bootloader_execute_flash_command(CMD_WRSR, new_status, 8, 0);
|
||||
}
|
||||
|
||||
static void write_status_8b_wrsr2(unsigned new_status)
|
||||
{
|
||||
execute_flash_command(CMD_WRSR2, new_status, 8, 0);
|
||||
bootloader_execute_flash_command(CMD_WRSR2, new_status, 8, 0);
|
||||
}
|
||||
|
||||
static void write_status_16b_wrsr(unsigned new_status)
|
||||
{
|
||||
execute_flash_command(CMD_WRSR, new_status, 16, 0);
|
||||
bootloader_execute_flash_command(CMD_WRSR, new_status, 16, 0);
|
||||
}
|
||||
|
||||
static unsigned read_status_8b_xmc25qu64a(void)
|
||||
{
|
||||
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
|
||||
bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
uint32_t read_status = execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
|
||||
uint32_t read_status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
|
||||
return read_status;
|
||||
}
|
||||
|
||||
static void write_status_8b_xmc25qu64a(unsigned new_status)
|
||||
{
|
||||
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
|
||||
bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
execute_flash_command(CMD_WRSR, new_status, 8, 0);
|
||||
bootloader_execute_flash_command(CMD_WRSR, new_status, 8, 0);
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
|
||||
}
|
||||
|
||||
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
|
||||
{
|
||||
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#endif
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 0;
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
|
||||
SPIFLASH.user2.usr_command_value = command;
|
||||
SPIFLASH.user.usr_miso = miso_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
|
||||
#endif
|
||||
SPIFLASH.user.usr_mosi = mosi_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
|
||||
#endif
|
||||
SPIFLASH.data_buf[0] = mosi_data;
|
||||
|
||||
if (g_rom_spiflash_dummy_len_plus[1]) {
|
||||
/* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */
|
||||
if (miso_len > 0) {
|
||||
SPIFLASH.user.usr_dummy = 1;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1;
|
||||
} else {
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
|
||||
SPIFLASH.ctrl.val = old_ctrl_reg;
|
||||
return SPIFLASH.data_buf[0];
|
||||
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
@ -325,7 +325,7 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(sig_be);
|
||||
free(buf);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
@ -48,7 +48,7 @@ void esp_efuse_reset(void)
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
|
||||
#include "../include_bootloader/bootloader_flash.h"
|
||||
#include "../include_bootloader/bootloader_flash_priv.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
|
||||
static uint32_t esp_efuse_flash_offset = 0;
|
||||
|
@ -70,6 +70,7 @@
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_mem.h"
|
||||
|
||||
#ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||
@ -439,7 +440,7 @@ void start_cpu0_default(void)
|
||||
|
||||
extern void esp_rom_spiflash_attach(uint32_t, bool);
|
||||
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), false);
|
||||
esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
#else
|
||||
// This assumes that DROM is the first segment in the application binary, i.e. that we can read
|
||||
// the binary header through cache by accessing SOC_DROM_LOW address.
|
||||
|
@ -121,6 +121,7 @@ extern "C" {
|
||||
#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)
|
||||
|
||||
//Extra dummy for flash read
|
||||
#define ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M 0
|
||||
@ -259,7 +260,7 @@ esp_rom_spiflash_result_t esp_rom_spiflash_read_status(esp_rom_spiflash_chip_t *
|
||||
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.
|
||||
* @brief Write status to Flash status register.
|
||||
* Please do not call this function in SDK.
|
||||
*
|
||||
* @param esp_rom_spiflash_chip_t *spi : The information for Flash, which is exported from ld file.
|
||||
|
@ -9,6 +9,8 @@
|
||||
#define SOC_CPU_CORES_NUM 1
|
||||
#define SOC_SUPPORTS_SECURE_DL_MODE 1
|
||||
|
||||
#define SOC_CACHE_SUPPORT_WRAP 1
|
||||
|
||||
/*--------------- PHY REGISTER AND MEMORY SIZE CAPS --------------------------*/
|
||||
#define SOC_PHY_DIG_REGS_MEM_SIZE (21*4)
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
set(priv_requires bootloader_support soc)
|
||||
|
||||
if(BOOTLOADER_BUILD)
|
||||
if (CONFIG_IDF_TARGET_ESP32)
|
||||
# ESP32 Bootloader needs SPIUnlock from this file, but doesn't
|
||||
@ -10,6 +8,7 @@ if(BOOTLOADER_BUILD)
|
||||
set(srcs)
|
||||
endif()
|
||||
set(cache_srcs "")
|
||||
set(priv_requires bootloader_support soc)
|
||||
else()
|
||||
set(cache_srcs
|
||||
"cache_utils.c"
|
||||
|
@ -49,8 +49,9 @@ menu "SPI Flash driver"
|
||||
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.
|
||||
This option should be enabled, if any one of the following is true: (1) need to write
|
||||
to flash on ESP32-D2WD; (2) main SPI flash is connected to non-default pins; (3) main
|
||||
SPI flash chip is manufactured by ISSI.
|
||||
|
||||
choice SPI_FLASH_DANGEROUS_WRITE
|
||||
bool "Writing to dangerous flash regions"
|
||||
|
@ -21,8 +21,14 @@
|
||||
#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;
|
||||
@ -58,28 +64,46 @@ esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *sp
|
||||
about interrupts, CPU coordination, flash mapping. However some of
|
||||
the functions in esp_spi_flash.c call it.
|
||||
*/
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_unlock(void)
|
||||
__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 (esp_rom_spiflash_read_statushigh(&g_rom_spiflash_chip, &status) != ESP_ROM_SPIFLASH_RESULT_OK) {
|
||||
return ESP_ROM_SPIFLASH_RESULT_ERR;
|
||||
}
|
||||
if (is_issi_chip(&g_rom_spiflash_chip)) {
|
||||
// ISSI chips have different QE position
|
||||
|
||||
/* 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;
|
||||
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);
|
||||
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) {
|
||||
if (esp_rom_spiflash_write_status(&g_rom_spiflash_chip, new_status) != ESP_ROM_SPIFLASH_RESULT_OK) {
|
||||
return ESP_ROM_SPIFLASH_RESULT_ERR;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
#include "esp32s2/rom/cache.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "hal/spi_flash_hal.h"
|
||||
#include "esp_flash.h"
|
||||
#include "esp_log.h"
|
||||
@ -78,48 +79,22 @@ esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_a
|
||||
}
|
||||
}
|
||||
|
||||
#define FLASH_WRAP_CMD 0x77
|
||||
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
|
||||
{
|
||||
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
|
||||
uint32_t reg_bkp_usr = SPIFLASH.user.val;
|
||||
SPIFLASH.user.fwrite_dio = 0;
|
||||
SPIFLASH.user.fwrite_dual = 0;
|
||||
SPIFLASH.user.fwrite_qio = 1;
|
||||
SPIFLASH.user.fwrite_quad = 0;
|
||||
SPIFLASH.ctrl.fcmd_dual = 0;
|
||||
SPIFLASH.ctrl.fcmd_quad = 0;
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 1;
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
|
||||
SPIFLASH.user1.usr_addr_bitlen = 23;
|
||||
SPIFLASH.addr = 0;
|
||||
SPIFLASH.user.usr_miso = 0;
|
||||
SPIFLASH.user.usr_mosi = 1;
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
|
||||
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while(SPIFLASH.cmd.usr != 0)
|
||||
{ }
|
||||
|
||||
SPIFLASH.ctrl.val = reg_bkp_ctrl;
|
||||
SPIFLASH.user.val = reg_bkp_usr;
|
||||
return ESP_OK;
|
||||
return bootloader_flash_wrap_set(mode);
|
||||
}
|
||||
|
||||
esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
|
||||
{
|
||||
switch(wrap_size) {
|
||||
case 8:
|
||||
return spi_flash_wrap_set(FLASH_WRAP_MODE_8B);
|
||||
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_8B);
|
||||
case 16:
|
||||
return spi_flash_wrap_set(FLASH_WRAP_MODE_16B);
|
||||
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_16B);
|
||||
case 32:
|
||||
return spi_flash_wrap_set(FLASH_WRAP_MODE_32B);
|
||||
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_32B);
|
||||
case 64:
|
||||
return spi_flash_wrap_set(FLASH_WRAP_MODE_64B);
|
||||
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_64B);
|
||||
default:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@ -127,7 +102,7 @@ esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
|
||||
|
||||
void spi_flash_disable_wrap(void)
|
||||
{
|
||||
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
|
||||
bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
|
||||
}
|
||||
|
||||
bool spi_flash_support_wrap_size(uint32_t wrap_size)
|
||||
|
@ -502,7 +502,27 @@ esp_err_t IRAM_ATTR esp_flash_set_protected_region(esp_flash_t *chip, const esp_
|
||||
return spiflash_end(chip, err);
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length)
|
||||
static esp_err_t NOINLINE_ATTR IRAM_ATTR flash_read_core(esp_flash_t *chip, void* buffer_to_read, uint32_t address, uint32_t length_to_read, bool *out_read_success)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
bool read_success = false;
|
||||
|
||||
read_success = false;
|
||||
err = spiflash_start(chip);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
err = chip->chip_drv->read(chip, buffer_to_read, address, length_to_read);
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
read_success = true;
|
||||
}
|
||||
|
||||
err = spiflash_end(chip, err);
|
||||
*out_read_success = read_success;
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length)
|
||||
{
|
||||
if (length == 0) {
|
||||
return ESP_OK;
|
||||
@ -543,28 +563,17 @@ esp_err_t IRAM_ATTR esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t add
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
do {
|
||||
err = spiflash_start(chip);
|
||||
if (err != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
//if required (dma buffer allocated), read to the buffer instead of the original buffer
|
||||
uint8_t* buffer_to_read = (temp_buffer)? temp_buffer : buffer;
|
||||
|
||||
// Length we will read this iteration is either the chunk size or the remaining length, whichever is smaller
|
||||
size_t length_to_read = MIN(read_chunk_size, length);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
err = chip->chip_drv->read(chip, buffer_to_read, address, length_to_read);
|
||||
}
|
||||
if (err != ESP_OK) {
|
||||
spiflash_end(chip, err);
|
||||
break;
|
||||
}
|
||||
//even if this is failed, the data is still valid, copy before quit
|
||||
err = spiflash_end(chip, err);
|
||||
bool read_success;
|
||||
err = flash_read_core(chip, buffer_to_read, address, length_to_read, &read_success);
|
||||
|
||||
//copy back to the original buffer
|
||||
if (temp_buffer) {
|
||||
if (read_success && temp_buffer) {
|
||||
memcpy(buffer, temp_buffer, length_to_read);
|
||||
}
|
||||
address += length_to_read;
|
||||
@ -576,7 +585,28 @@ esp_err_t IRAM_ATTR esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t add
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR esp_flash_write(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length)
|
||||
// This function disable the cache, but when returning from this function, the cache should be enabled.
|
||||
static esp_err_t IRAM_ATTR NOINLINE_ATTR flash_write_core(esp_flash_t *chip,
|
||||
const void* write_buf, uint32_t write_addr, uint32_t write_len,
|
||||
uint32_t address, uint32_t length, bool final)
|
||||
{
|
||||
bool bus_acquire = false; //controls whether the flash_end_flush_cache() needs to disable the cache again.
|
||||
|
||||
esp_err_t err = spiflash_start(chip);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
bus_acquire = true;
|
||||
err = chip->chip_drv->write(chip, write_buf, write_addr, write_len);
|
||||
}
|
||||
|
||||
if (bus_acquire) {
|
||||
//on IDF v4.2, the flush is done in chip driver layer. Call spiflash_end() here.
|
||||
err = spiflash_end(chip, err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_flash_write(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length)
|
||||
{
|
||||
if (length == 0) {
|
||||
return ESP_OK;
|
||||
@ -595,31 +625,32 @@ esp_err_t IRAM_ATTR esp_flash_write(esp_flash_t *chip, const void *buffer, uint3
|
||||
by artificially cutting into MAX_WRITE_CHUNK parts (in an OS
|
||||
environment, this prevents writing from causing interrupt or higher priority task
|
||||
starvation.) */
|
||||
uint32_t write_addr = address;
|
||||
uint32_t len_remain = length;
|
||||
do {
|
||||
uint32_t write_len;
|
||||
const void *write_buf;
|
||||
uint32_t temp_buf[8];
|
||||
if (direct_write) {
|
||||
write_len = MIN(length, MAX_WRITE_CHUNK);
|
||||
write_len = MIN(len_remain, MAX_WRITE_CHUNK);
|
||||
write_buf = buffer;
|
||||
} else {
|
||||
write_len = MIN(length, sizeof(temp_buf));
|
||||
write_len = MIN(len_remain, sizeof(temp_buf));
|
||||
memcpy(temp_buf, buffer, write_len);
|
||||
write_buf = temp_buf;
|
||||
}
|
||||
|
||||
err = spiflash_start(chip);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
bool final = (len_remain == write_len);
|
||||
//This function ensures cache enabled when returned
|
||||
err = flash_write_core(chip, write_buf, write_addr, write_len, address, length, final);
|
||||
if (err != ESP_OK || final) {
|
||||
break;
|
||||
}
|
||||
|
||||
err = chip->chip_drv->write(chip, write_buf, address, write_len);
|
||||
|
||||
address += write_len;
|
||||
len_remain -= write_len;
|
||||
assert(len_remain < length);
|
||||
write_addr += write_len;
|
||||
buffer = (void *)((intptr_t)buffer + write_len);
|
||||
length -= write_len;
|
||||
|
||||
err = spiflash_end(chip, err);
|
||||
} while (err == ESP_OK && length > 0);
|
||||
return err;
|
||||
}
|
||||
|
@ -36,14 +36,13 @@
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
#include "esp32s2/rom/cache.h"
|
||||
#include "esp32s2/clk.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/spi_mem_struct.h"
|
||||
#endif
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "cache_utils.h"
|
||||
#include "esp_flash.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_timer.h"
|
||||
#include "bootloader_flash.h"
|
||||
|
||||
esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size);
|
||||
|
||||
@ -201,11 +200,8 @@ static esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock(void)
|
||||
static bool unlocked = false;
|
||||
if (!unlocked) {
|
||||
spi_flash_guard_start();
|
||||
esp_rom_spiflash_result_t rc = esp_rom_spiflash_unlock();
|
||||
bootloader_flash_unlock();
|
||||
spi_flash_guard_end();
|
||||
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
|
||||
return rc;
|
||||
}
|
||||
unlocked = true;
|
||||
}
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
@ -833,6 +829,7 @@ void spi_flash_dump_counters(void)
|
||||
|
||||
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
|
||||
|
||||
|
||||
#if defined(CONFIG_SPI_FLASH_USE_LEGACY_IMPL) && defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
// TODO esp32s2: Remove once ESP32S2 has new SPI Flash API support
|
||||
esp_flash_t *esp_flash_default_chip = NULL;
|
||||
|
@ -75,6 +75,11 @@ extern "C" int spi_flash_get_erase_cycles(size_t sector)
|
||||
return spiflash.get_erase_cycles(sector);
|
||||
}
|
||||
|
||||
extern "C" esp_err_t bootloader_flash_unlock(void)
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest, int32_t len)
|
||||
{
|
||||
return spiflash.read(target, dest, len);
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "test_utils.h"
|
||||
#include "ccomp_timer.h"
|
||||
#include "esp_log.h"
|
||||
#include "bootloader_flash.h" //for bootloader_flash_xmc_startup
|
||||
|
||||
|
||||
struct flash_test_ctx {
|
||||
uint32_t offset;
|
||||
@ -372,3 +374,22 @@ TEST_CASE("spi_flash deadlock with high priority busy-waiting task", "[spi_flash
|
||||
TEST_ASSERT_EQUAL_INT(uxTaskPriorityGet(NULL), UNITY_FREERTOS_PRIORITY);
|
||||
}
|
||||
#endif // portNUM_PROCESSORS > 1
|
||||
|
||||
|
||||
static IRAM_ATTR NOINLINE_ATTR void test_xmc_startup(void)
|
||||
{
|
||||
extern void spi_flash_disable_interrupts_caches_and_other_cpu(void);
|
||||
extern void spi_flash_enable_interrupts_caches_and_other_cpu(void);
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
spi_flash_disable_interrupts_caches_and_other_cpu();
|
||||
ret = bootloader_flash_xmc_startup();
|
||||
spi_flash_enable_interrupts_caches_and_other_cpu();
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, ret);
|
||||
}
|
||||
|
||||
TEST_CASE("bootloader_flash_xmc_startup can be called when cache disabled", "[spi_flash]")
|
||||
{
|
||||
test_xmc_startup();
|
||||
}
|
@ -394,6 +394,8 @@ done:
|
||||
|
||||
void test_spiffs_concurrent(const char* filename_prefix)
|
||||
{
|
||||
const int stack_size=3072;
|
||||
|
||||
char names[4][64];
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
snprintf(names[i], sizeof(names[i]), "%s%d", filename_prefix, i + 1);
|
||||
@ -406,8 +408,8 @@ void test_spiffs_concurrent(const char* filename_prefix)
|
||||
printf("writing f1 and f2\n");
|
||||
const int cpuid_0 = 0;
|
||||
const int cpuid_1 = portNUM_PROCESSORS - 1;
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw1", 2048, &args1, 3, NULL, cpuid_0);
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw2", 2048, &args2, 3, NULL, cpuid_1);
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw1", stack_size, &args1, 3, NULL, cpuid_0);
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw2", stack_size, &args2, 3, NULL, cpuid_1);
|
||||
|
||||
xSemaphoreTake(args1.done, portMAX_DELAY);
|
||||
printf("f1 done\n");
|
||||
@ -423,10 +425,10 @@ void test_spiffs_concurrent(const char* filename_prefix)
|
||||
|
||||
printf("reading f1 and f2, writing f3 and f4\n");
|
||||
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw3", 2048, &args3, 3, NULL, cpuid_1);
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw4", 2048, &args4, 3, NULL, cpuid_0);
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw1", 2048, &args1, 3, NULL, cpuid_0);
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw2", 2048, &args2, 3, NULL, cpuid_1);
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw3", stack_size, &args3, 3, NULL, cpuid_1);
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw4", stack_size, &args4, 3, NULL, cpuid_0);
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw1", stack_size, &args1, 3, NULL, cpuid_0);
|
||||
xTaskCreatePinnedToCore(&read_write_task, "rw2", stack_size, &args2, 3, NULL, cpuid_1);
|
||||
|
||||
xSemaphoreTake(args1.done, portMAX_DELAY);
|
||||
printf("f1 done\n");
|
||||
|
Loading…
Reference in New Issue
Block a user