From 9ca02bd8ac58e300dc9c71c074dffe498a22f1c2 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sat, 25 Apr 2020 14:58:30 +1000 Subject: [PATCH] efuse: Add new esp_efuse_write_field_bit() convenience function --- .../bootloader_support/src/flash_encrypt.c | 6 +----- components/efuse/include/esp_efuse.h | 17 +++++++++++++++ components/efuse/src/esp_efuse_api.c | 19 +++++++++++++++++ components/efuse/test/test_efuse.c | 21 +++++++++++++++++++ 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/components/bootloader_support/src/flash_encrypt.c b/components/bootloader_support/src/flash_encrypt.c index 951876a56b..845b5aec65 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() { - 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() diff --git a/components/efuse/include/esp_efuse.h b/components/efuse/include/esp_efuse.h index e4a0ba1d4d..d626e76760 100644 --- a/components/efuse/include/esp_efuse.h +++ b/components/efuse/include/esp_efuse.h @@ -123,6 +123,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 57a71970a3..24a855a4d9 100644 --- a/components/efuse/src/esp_efuse_api.c +++ b/components/efuse/src/esp_efuse_api.c @@ -140,6 +140,25 @@ esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk) return ESP_ERR_NOT_SUPPORTED; } +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 7ea2830774..cc9d4a4836 100644 --- a/components/efuse/test/test_efuse.c +++ b/components/efuse/test/test_efuse.c @@ -224,6 +224,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) {