feat(efuse): Defer WR_DIS eFuse burning

This commit is contained in:
Konstantin Kondrashov
2025-12-29 18:38:24 +02:00
committed by Konstantin Kondrashov
parent de1901c1b0
commit be517fa8c0
19 changed files with 99 additions and 98 deletions
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -68,12 +68,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -58,12 +58,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -88,12 +88,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -73,12 +73,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -73,12 +73,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -73,12 +73,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -73,12 +73,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -73,12 +73,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
@@ -73,12 +73,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -73,12 +73,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -73,12 +73,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -73,12 +73,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
@@ -72,12 +72,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
+9
View File
@@ -26,6 +26,7 @@ extern "C" {
#define ESP_ERR_CODING (ESP_ERR_EFUSE + 0x04) /*!< Error while a encoding operation. */
#define ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS (ESP_ERR_EFUSE + 0x05) /*!< Error not enough unused key blocks available */
#define ESP_ERR_DAMAGED_READING (ESP_ERR_EFUSE + 0x06) /*!< Error. Burn or reset was done during a reading operation leads to damage read data. This error is internal to the efuse component and not returned by any public API. */
#define ESP_ERR_BURN_WR_DIS (ESP_ERR_EFUSE + 0x07) /*!< Error to burn WR_DIS field. */
/**
* @brief Type definition for an eFuse field
@@ -175,6 +176,7 @@ esp_err_t esp_efuse_write_field_bit(const esp_efuse_desc_t* field[]);
* - ESP_ERR_INVALID_ARG: Error in the passed arguments.
* - ESP_ERR_EFUSE_CNT_IS_FULL: Not all requested cnt bits is set.
* - ESP_ERR_NOT_SUPPORTED: The block does not support this command.
* - ESP_ERR_BURN_WR_DIS: Failed to burn WR_DIS field.
*/
esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk);
@@ -498,6 +500,8 @@ esp_err_t esp_efuse_batch_write_cancel(void);
* @return
* - ESP_OK: Successful.
* - ESP_ERR_INVALID_STATE: The deferred writing mode was not set.
* - ESP_FAIL: Failed to write efuse fields.
* - ESP_ERR_BURN_WR_DIS: Failed to burn WR_DIS field.
*/
esp_err_t esp_efuse_batch_write_commit(void);
@@ -553,6 +557,7 @@ bool esp_efuse_get_key_dis_write(esp_efuse_block_t block);
* - ESP_ERR_INVALID_ARG: Error in the passed arguments.
* - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden.
* - ESP_ERR_CODING: Error range of data does not match the coding scheme.
* - ESP_ERR_BURN_WR_DIS: Failed to burn WR_DIS field.
*/
esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block);
@@ -651,6 +656,7 @@ esp_err_t esp_efuse_set_key_purpose(esp_efuse_block_t block, esp_efuse_purpose_t
* - ESP_ERR_INVALID_ARG: Error in the passed arguments.
* - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden.
* - ESP_ERR_CODING: Error range of data does not match the coding scheme.
* - ESP_ERR_BURN_WR_DIS: Failed to burn WR_DIS field.
*/
esp_err_t esp_efuse_set_keypurpose_dis_write(esp_efuse_block_t block);
@@ -715,6 +721,7 @@ bool esp_efuse_get_write_protect_of_digest_revoke(unsigned num_digest);
* - ESP_ERR_INVALID_ARG: Error in the passed arguments.
* - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden.
* - ESP_ERR_CODING: Error range of data does not match the coding scheme.
* - ESP_ERR_BURN_WR_DIS: Failed to burn WR_DIS field.
*/
esp_err_t esp_efuse_set_write_protect_of_digest_revoke(unsigned num_digest);
@@ -742,6 +749,7 @@ esp_err_t esp_efuse_set_write_protect_of_digest_revoke(unsigned num_digest);
* - ESP_ERR_INVALID_STATE: Error in efuses state, unused block not found.
* - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden.
* - ESP_ERR_CODING: Error range of data does not match the coding scheme.
* - ESP_ERR_BURN_WR_DIS: Failed to burn WR_DIS field.
*/
esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpose, const void *key, size_t key_size_bytes);
@@ -767,6 +775,7 @@ esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpo
* - ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS: Error not enough unused key blocks available
* - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden.
* - ESP_ERR_CODING: Error range of data does not match the coding scheme.
* - ESP_ERR_BURN_WR_DIS: Failed to burn WR_DIS field.
*/
esp_err_t esp_efuse_write_keys(const esp_efuse_purpose_t purposes[], uint8_t keys[][32], unsigned number_of_keys);
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -62,12 +62,6 @@ esp_err_t esp_efuse_utility_check_errors(void)
return ESP_OK;
}
// Burn values written to the efuse write registers
esp_err_t esp_efuse_utility_burn_chip(void)
{
return esp_efuse_utility_burn_chip_opt(false, true);
}
esp_err_t esp_efuse_utility_burn_chip_opt(bool ignore_coding_errors, bool verify_written_data)
{
esp_err_t error = ESP_OK;
+53 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,6 +12,7 @@
#include "assert.h"
#include "sdkconfig.h"
#include <sys/param.h>
#include "esp_efuse_table.h"
ESP_LOG_ATTR_TAG(TAG, "efuse");
@@ -493,3 +494,54 @@ bool esp_efuse_utility_is_correct_written_data(esp_efuse_block_t block, unsigned
}
return correct_written_data;
}
// This function defers the programming of ESP_EFUSE_WR_DIS efuse field.
// This field is very critical, because it disables any further programming of some efuses.
// We want to defer its programming until all other efuses are programmed successfully.
// Returns the staged WR_DIS data, so that it can be restored later for programming.
static uint32_t defer_wr_dis(void)
{
// ESP_EFUSE_WR_DIS is always in reg 0 of block 0, the only length is varied from chip to chip.
uint32_t staged_reg = REG_READ(range_write_addr_blocks[0].start); // array of staged write registers
uint32_t wr_dis_reg_mask = get_mask(ESP_EFUSE_WR_DIS[0]->bit_count, ESP_EFUSE_WR_DIS[0]->bit_start);
// Clear WR_DIS field and keep other bits in the staged register unchanged
REG_WRITE(range_write_addr_blocks[0].start, staged_reg & ~wr_dis_reg_mask);
// return WR_DIS value, excluding other bits in the staged register.
return staged_reg & wr_dis_reg_mask;
}
static inline void restore_deferred_wr_dis(uint32_t staged_wr_dis_data)
{
REG_WRITE(range_write_addr_blocks[0].start, staged_wr_dis_data);
}
esp_err_t esp_efuse_utility_burn_chip(void)
{
// Always defer the WR_DIS field burning to ensure that if any error occurs during the burn process of BLOCK0,
// the chip will have a chance to be recovered by the repeating burning mechanism in esp_efuse_utility_burn_chip_opt.
// This is critical because WR_DIS permanently disables further eFuse programming of some efuse fields.
uint32_t staged_wr_dis_data = defer_wr_dis();
esp_err_t err = esp_efuse_utility_burn_chip_opt(false, true);
if (err == ESP_OK) {
if (staged_wr_dis_data != 0) {
restore_deferred_wr_dis(staged_wr_dis_data);
err = esp_efuse_utility_burn_chip_opt(false, true);
if (err != ESP_OK) {
err = ESP_ERR_BURN_WR_DIS;
ESP_LOGE(TAG, "Failed to burn WR_DIS = 0x%08" PRIx32, staged_wr_dis_data);
}
}
} else {
ESP_LOGE(TAG, "Failed to burn eFuses");
if (staged_wr_dis_data != 0) {
ESP_LOGW(TAG, "WR_DIS efuse was not burned (deferred): 0x%08" PRIx32, staged_wr_dis_data);
}
}
return err;
}
+15 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -869,3 +869,17 @@ TEST_CASE("Test chip_ver_pkg APIs return the same value", "[efuse]")
esp_efuse_utility_update_virt_blocks();
TEST_ASSERT_EQUAL_INT(esp_efuse_get_pkg_ver(), efuse_ll_get_chip_ver_pkg());
}
TEST_CASE("Test deferred WR_DIS programming", "[efuse]")
{
esp_efuse_utility_erase_virt_blocks();
esp_efuse_utility_update_virt_blocks();
esp_efuse_batch_write_begin();
TEST_ESP_OK(esp_efuse_set_write_protect(EFUSE_BLK_KEY0));
TEST_ESP_OK(esp_efuse_set_read_protect(EFUSE_BLK_KEY0));
esp_efuse_batch_write_commit();
TEST_ASSERT_TRUE(esp_efuse_get_key_dis_write(EFUSE_BLK_KEY0));
TEST_ASSERT_TRUE(esp_efuse_get_key_dis_read(EFUSE_BLK_KEY0));
}
@@ -321,6 +321,9 @@ static const esp_err_msg_t esp_err_msg_table[] = {
data. This error is internal to the
efuse component and not returned by any
public API. */
# endif
# ifdef ESP_ERR_BURN_WR_DIS
ERR_TBL_IT(ESP_ERR_BURN_WR_DIS), /* 5639 0x1607 Error to burn WR_DIS field. */
# endif
// components/bootloader_support/include/esp_image_format.h
# ifdef ESP_ERR_IMAGE_BASE
+7
View File
@@ -570,6 +570,13 @@ To get a dump for all eFuse registers.
.. include:: inc/espefuse_summary_{IDF_TARGET_NAME}_dump.rst
Deferred WR_DIS Burning
-----------------------
``WR_DIS`` (Write Disable) is a special eFuse field that implements permanent write-protection. Each bit in ``WR_DIS`` disables further programming of one (or more) associated eFuse fields. Once burned, the affected fields can no longer be modified.
When burning staged data in BLOCK0, ``WR_DIS`` bits are burned separately after all other BLOCK0 data to ensure the retry mechanism of the burn function can recover from coding errors. This approach guarantees that write-protection is applied only after other BLOCK0 data is successfully burned.
Application Examples
--------------------