diff --git a/components/bootloader_support/src/flash_encrypt.c b/components/bootloader_support/src/flash_encrypt.c index 200ebef0f2..408b1b6b88 100644 --- a/components/bootloader_support/src/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encrypt.c @@ -71,11 +71,7 @@ void esp_flash_encryption_init_checks() void esp_flash_write_protect_crypt_cnt(void) { - uint8_t flash_crypt_cnt_wr_dis = 0; - esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &flash_crypt_cnt_wr_dis, 1); - if (!flash_crypt_cnt_wr_dis) { - esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, 1); - } + esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT); } esp_flash_enc_mode_t esp_get_flash_encryption_mode(void) diff --git a/components/efuse/include/esp_efuse.h b/components/efuse/include/esp_efuse.h index ca4d96f999..69b766e697 100644 --- a/components/efuse/include/esp_efuse.h +++ b/components/efuse/include/esp_efuse.h @@ -109,6 +109,23 @@ esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void */ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt); +/** + * @brief Write a single bit eFuse field to 1 + * + * For use with eFuse fields that are a single bit. This function will write the bit to value 1 if + * it is not already set, or does nothing if the bit is already set. + * + * This is equivalent to calling esp_efuse_write_field_cnt() with the cnt parameter equal to 1, + * except that it will return ESP_OK if the field is already set to 1. + * + * @param[in] field Pointer to the structure describing the efuse field. + * + * @return + * - ESP_OK: The operation was successfully completed, or the bit was already set to value 1. + * - ESP_ERR_INVALID_ARG: Error in the passed arugments, including if the efuse field is not 1 bit wide. + */ +esp_err_t esp_efuse_write_field_bit(const esp_efuse_desc_t* field[]); + /** * @brief Sets a write protection for the whole block. * diff --git a/components/efuse/src/esp_efuse_api.c b/components/efuse/src/esp_efuse_api.c index 6ed5399add..361b8cd578 100644 --- a/components/efuse/src/esp_efuse_api.c +++ b/components/efuse/src/esp_efuse_api.c @@ -131,6 +131,25 @@ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt) return err; } +esp_err_t esp_efuse_write_field_bit(const esp_efuse_desc_t* field[]) +{ + esp_err_t err; + uint8_t existing = 0; + const uint8_t one = 1; + + if (field == NULL || field[0]->bit_count != 1) { + return ESP_ERR_INVALID_ARG; + } + + /* Check existing value. esp_efuse_write_field_blob() also checks this, but will log an error */ + err = esp_efuse_read_field_blob(field, &existing, 1); + if (err != ESP_OK || existing) { + return err; // Error reading, or the bit is already written and we can no-op this + } + + return esp_efuse_write_field_blob(field, &one, 1); +} + // get the length of the field in bits int esp_efuse_get_field_size(const esp_efuse_desc_t* field[]) { diff --git a/components/efuse/test/test_efuse.c b/components/efuse/test/test_efuse.c index 7ba766cf84..caba83e1de 100644 --- a/components/efuse/test/test_efuse.c +++ b/components/efuse/test/test_efuse.c @@ -267,6 +267,27 @@ TEST_CASE("efuse test write_field_cnt", "[efuse]") test_write_cnt(); } +TEST_CASE("efuse test write_field_bit", "[efuse]") +{ + esp_efuse_utility_erase_virt_blocks(); + esp_efuse_utility_debug_dump_blocks(); + + uint8_t test_bit; + TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test_bit, 1)); + TEST_ASSERT_EQUAL_HEX8(0, test_bit); + + TEST_ESP_OK(esp_efuse_write_field_bit(ESP_EFUSE_TEST5_LEN_1)); + TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test_bit, 1)); + TEST_ASSERT_EQUAL_HEX8(1, test_bit); + + // Can write the bit again and it's a no-op + TEST_ESP_OK(esp_efuse_write_field_bit(ESP_EFUSE_TEST5_LEN_1)); + TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test_bit, 1)); + TEST_ASSERT_EQUAL_HEX8(1, test_bit); + + esp_efuse_utility_debug_dump_blocks(); +} + void cut_tail_arr(uint8_t *arr, int num_used_bits, size_t count_bits) { if ((num_used_bits + count_bits) % 8) {