From 114608142a271eb5a196e64990912d593500f26c Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Tue, 5 Apr 2022 23:02:22 +0800 Subject: [PATCH 1/6] efuse: Validates data after burning and re-burnes it if necessary It checks the content of the written data and encoding errors. --- components/efuse/esp32/esp_efuse_utility.c | 202 +++++++++++------- components/efuse/esp32c3/esp_efuse_utility.c | 65 +++++- components/efuse/esp32h2/esp_efuse_utility.c | 63 +++++- components/efuse/esp32s2/esp_efuse_utility.c | 63 +++++- components/efuse/esp32s3/esp_efuse_utility.c | 63 +++++- .../efuse/private_include/esp_efuse_utility.h | 13 ++ components/efuse/src/esp_efuse_utility.c | 26 +++ 7 files changed, 411 insertions(+), 84 deletions(-) diff --git a/components/efuse/esp32/esp_efuse_utility.c b/components/efuse/esp32/esp_efuse_utility.c index 2f3cb16c20..ff32ea2486 100644 --- a/components/efuse/esp32/esp_efuse_utility.c +++ b/components/efuse/esp32/esp_efuse_utility.c @@ -26,12 +26,14 @@ const esp_efuse_range_addr_t range_read_addr_blocks[] = { {EFUSE_BLK3_RDATA0_REG, EFUSE_BLK3_RDATA7_REG} // range address of EFUSE_BLK3 }; -/*Range addresses to write blocks*/ +static uint32_t write_mass_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK] = { 0 }; + +/*Range addresses to write blocks (it is not real regs, it is a buffer) */ const esp_efuse_range_addr_t range_write_addr_blocks[] = { - {EFUSE_BLK0_WDATA0_REG, EFUSE_BLK0_WDATA6_REG}, // range address of EFUSE_BLK0 - {EFUSE_BLK1_WDATA0_REG, EFUSE_BLK1_WDATA7_REG}, // range address of EFUSE_BLK1 - {EFUSE_BLK2_WDATA0_REG, EFUSE_BLK2_WDATA7_REG}, // range address of EFUSE_BLK2 - {EFUSE_BLK3_WDATA0_REG, EFUSE_BLK3_WDATA7_REG} // range address of EFUSE_BLK3 + {(uint32_t) &write_mass_blocks[EFUSE_BLK0][0], (uint32_t) &write_mass_blocks[EFUSE_BLK0][6]}, + {(uint32_t) &write_mass_blocks[EFUSE_BLK1][0], (uint32_t) &write_mass_blocks[EFUSE_BLK1][7]}, + {(uint32_t) &write_mass_blocks[EFUSE_BLK2][0], (uint32_t) &write_mass_blocks[EFUSE_BLK2][7]}, + {(uint32_t) &write_mass_blocks[EFUSE_BLK3][0], (uint32_t) &write_mass_blocks[EFUSE_BLK3][7]}, }; #define EFUSE_CONF_WRITE 0x5A5A /* eFuse_pgm_op_ena, force no rd/wr disable. */ @@ -40,6 +42,16 @@ const esp_efuse_range_addr_t range_write_addr_blocks[] = { #define EFUSE_CMD_READ 0x01 /* Command to read. */ #ifndef CONFIG_EFUSE_VIRTUAL +/* Addresses to write blocks*/ +const uint32_t start_write_addr[] = { + EFUSE_BLK0_WDATA0_REG, + EFUSE_BLK1_WDATA0_REG, + EFUSE_BLK2_WDATA0_REG, + EFUSE_BLK3_WDATA0_REG, +}; + +static void apply_repeat_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len); + // Update Efuse timing configuration static esp_err_t esp_efuse_set_timing(void) { @@ -63,6 +75,31 @@ static esp_err_t esp_efuse_set_timing(void) REG_SET_FIELD(EFUSE_CLK_REG, EFUSE_CLK_SEL1, clk_sel1); return ESP_OK; } + +__attribute__((always_inline)) static inline bool efuse_ll_get_dec_warnings(unsigned block) +{ + if (block == 0 || block > 4) { + return false; + } + uint32_t error_reg = REG_GET_FIELD(EFUSE_DEC_STATUS_REG, EFUSE_DEC_WARNINGS); + if (((error_reg >> (4 * (block - 1))) & 0x0F) != 0) { + return true; + } + return false; +} + +static bool efuse_hal_is_coding_error_in_block(unsigned block) +{ + if (block > 0) { + if (esp_efuse_get_coding_scheme(block) == EFUSE_CODING_SCHEME_3_4) { + if (efuse_ll_get_dec_warnings(block)) { + return true; + } + } + } + return false; +} + #endif // ifndef CONFIG_EFUSE_VIRTUAL // Efuse read operation: copies data from physical efuses to efuse read registers. @@ -76,23 +113,7 @@ void esp_efuse_utility_burn_chip(void) { #ifdef CONFIG_EFUSE_VIRTUAL ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses"); - for (int num_block = EFUSE_BLK0; num_block < EFUSE_BLK_MAX; num_block++) { - esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block); - if (scheme == EFUSE_CODING_SCHEME_3_4) { - uint8_t buf[COUNT_EFUSE_REG_PER_BLOCK * 4] = { 0 }; - int i = 0; - for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4, ++i) { - *((uint32_t*)buf + i) = REG_READ(addr_wr_block); - } - int j = 0; - uint32_t out_buf[COUNT_EFUSE_REG_PER_BLOCK] = { 0 }; - for (int k = 0; k < 4; ++k, ++j) { - memcpy((uint8_t*)out_buf + j * 6, &buf[k * 8], 6); - } - for (int k = 0; k < COUNT_EFUSE_REG_PER_BLOCK; ++k) { - REG_WRITE(range_write_addr_blocks[num_block].start + k * 4, out_buf[k]); - } - } + for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { int subblock = 0; for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { virt_blocks[num_block][subblock++] |= REG_READ(addr_wr_block); @@ -102,14 +123,72 @@ void esp_efuse_utility_burn_chip(void) esp_efuse_utility_write_efuses_to_flash(); #endif #else - esp_efuse_set_timing(); - // Permanently update values written to the efuse write registers - REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_WRITE); - REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_PGM); - while (REG_READ(EFUSE_CMD_REG) != 0) {}; - REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ); - REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_READ); - while (REG_READ(EFUSE_CMD_REG) != 0) {}; + if (esp_efuse_set_timing() != ESP_OK) { + ESP_LOGE(TAG, "Efuse fields are not burnt"); + } else { + // Permanently update values written to the efuse write registers + // It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks. + for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { + esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block); + for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { + if (REG_READ(addr_wr_block) != 0) { + unsigned w_data_len; + unsigned r_data_len; + if (scheme == EFUSE_CODING_SCHEME_3_4) { + esp_efuse_utility_apply_34_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], 24); + r_data_len = 24; + w_data_len = 32; + } else if (scheme == EFUSE_CODING_SCHEME_REPEAT) { + apply_repeat_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], 16); + r_data_len = 16; + w_data_len = 32; + } else { + r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); + w_data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); + memcpy((void *)start_write_addr[num_block], (void *)range_write_addr_blocks[num_block].start, w_data_len); + } + + uint32_t backup_write_data[8]; + memcpy(backup_write_data, (void *)start_write_addr[num_block], w_data_len); + int repeat_burn_op = 1; + bool correct_written_data; + bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); + bool coding_error_occurred; + + do { + ESP_LOGI(TAG, "BURN BLOCK%d", num_block); + // BURN a block + REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_WRITE); + REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_PGM); + while (REG_READ(EFUSE_CMD_REG) != 0) {}; + REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ); + REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_READ); + while (REG_READ(EFUSE_CMD_REG) != 0) {}; + + bool coding_error_after = efuse_hal_is_coding_error_in_block(num_block); + coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; + if (coding_error_occurred) { + ESP_LOGE(TAG, "BLOCK%d has an error", num_block); + } + + correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); + if (!correct_written_data || coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d: next retry [%d/3]...", num_block, repeat_burn_op); + memcpy((void *)start_write_addr[num_block], (void *)backup_write_data, w_data_len); + } + + } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + } + if (coding_error_occurred) { + ESP_LOGE(TAG, "Coding error occurred in block"); + } + break; + } + } + } + } #endif // CONFIG_EFUSE_VIRTUAL esp_efuse_utility_reset(); } @@ -143,44 +222,33 @@ esp_err_t esp_efuse_utility_apply_34_encoding(const uint8_t *in_bytes, uint32_t return ESP_OK; } -static bool read_w_data_and_check_fill(esp_efuse_block_t num_block, uint32_t *buf_w_data) -{ - bool blk_is_filled = false; - int i = 0; - for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4, ++i) { - buf_w_data[i] = REG_READ(addr_wr_block); - if (buf_w_data[i] != 0) { - REG_WRITE(addr_wr_block, 0); - blk_is_filled = true; - } - } - return blk_is_filled; -} +#ifndef CONFIG_EFUSE_VIRTUAL -static void read_r_data(esp_efuse_block_t num_block, uint32_t* buf_r_data) +static void apply_repeat_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len) { - int i = 0; - for (uint32_t addr_rd_block = range_read_addr_blocks[num_block].start; addr_rd_block <= range_read_addr_blocks[num_block].end; addr_rd_block += 4, ++i) { - buf_r_data[i] = esp_efuse_utility_read_reg(num_block, i); + for (unsigned i = 0; i < 2; i++) { + memcpy(&out_words[i * 4], (uint32_t *)in_bytes, in_bytes_len); } } +#endif // CONFIG_EFUSE_VIRTUAL -// After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values. -// This function reads EFUSE_BLKx_WDATAx_REG registers, applies coding scheme and writes encoded values back to EFUSE_BLKx_WDATAx_REG. +// This function just checkes that given data for blocks will not rise a coding issue during the burn operation. +// Encoded data will be set during the burn operation. esp_err_t esp_efuse_utility_apply_new_coding_scheme() { - uint8_t buf_w_data[COUNT_EFUSE_REG_PER_BLOCK * 4]; - uint8_t buf_r_data[COUNT_EFUSE_REG_PER_BLOCK * 4]; - uint32_t reg[COUNT_EFUSE_REG_PER_BLOCK]; // start with EFUSE_BLK1. EFUSE_BLK0 - always uses EFUSE_CODING_SCHEME_NONE. for (int num_block = EFUSE_BLK1; num_block < EFUSE_BLK_MAX; num_block++) { esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block); - // check and apply a new coding scheme. if (scheme != EFUSE_CODING_SCHEME_NONE) { - memset(buf_w_data, 0, sizeof(buf_w_data)); - memset((uint8_t*)reg, 0, sizeof(reg)); - if (read_w_data_and_check_fill(num_block, (uint32_t*)buf_w_data) == true) { - read_r_data(num_block, (uint32_t*)buf_r_data); + bool is_write_data = false; + for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { + if (REG_READ(addr_wr_block)) { + is_write_data = true; + } + } + if (is_write_data) { + uint8_t* buf_w_data = (uint8_t*)range_write_addr_blocks[num_block].start; + uint8_t* buf_r_data = (uint8_t*)range_read_addr_blocks[num_block].start; if (scheme == EFUSE_CODING_SCHEME_3_4) { if (*((uint32_t*)buf_w_data + 6) != 0 || *((uint32_t*)buf_w_data + 7) != 0) { return ESP_ERR_CODING; @@ -195,32 +263,14 @@ esp_err_t esp_efuse_utility_apply_new_coding_scheme() return ESP_ERR_CODING; } } - - esp_err_t err = esp_efuse_utility_apply_34_encoding(&buf_w_data[st_offset_buf], reg, 6); - if (err != ESP_OK) { - return err; - } - - int num_reg = (st_offset_buf / 6) * 2; - for (int r = 0; r < 2; r++) { - REG_WRITE(range_write_addr_blocks[num_block].start + (num_reg + r) * 4, reg[r]); - } - i = st_offset_buf + 5; } } } else if (scheme == EFUSE_CODING_SCHEME_REPEAT) { - uint32_t* buf_32 = (uint32_t*)buf_w_data; for (int i = 4; i < 8; ++i) { - if (*(buf_32 + i) != 0) { + if (*((uint32_t*)buf_w_data + i) != 0) { return ESP_ERR_CODING; } } - for (int i = 0; i < 4; ++i) { - if (buf_32[i] != 0) { - REG_WRITE(range_write_addr_blocks[num_block].start + i * 4, buf_32[i]); - REG_WRITE(range_write_addr_blocks[num_block].start + (i + 4) * 4, buf_32[i]); - } - } } } } diff --git a/components/efuse/esp32c3/esp_efuse_utility.c b/components/efuse/esp32c3/esp_efuse_utility.c index 40eb064f12..037e571c29 100644 --- a/components/efuse/esp32c3/esp_efuse_utility.c +++ b/components/efuse/esp32c3/esp_efuse_utility.c @@ -83,6 +83,29 @@ static void efuse_program(esp_efuse_block_t block) ets_efuse_clear_program_registers(); efuse_read(); } + +static bool efuse_hal_is_coding_error_in_block(unsigned block) +{ + if (block == 0) { + for (unsigned i = 0; i < 5; i++) { + if (REG_READ(EFUSE_RD_REPEAT_ERR0_REG + i * 4)) { + return true; + } + } + } else if (block <= 10) { + // The order of error in these regs is different only for the C3 chip. + // EFUSE_RD_RS_ERR0_REG: (hi) BLOCK7, BLOCK6, BLOCK5, BLOCK4, BLOCK3, BLOCK2, BLOCK1, ------ (low) + // EFUSE_RD_RS_ERR1_REG: BLOCK9, BLOCK8 + // BLOCK10 is not presented in the error regs. + uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 8) * 4); + unsigned offset = (block >= 8) ? block - 8 : block; + if (((error_reg >> (4 * offset)) & 0x0F) != 0) { + return true; + } + } + return false; +} + #endif // ifndef CONFIG_EFUSE_VIRTUAL // Efuse read operation: copies data from physical efuses to efuse read registers. @@ -120,9 +143,47 @@ void esp_efuse_utility_burn_chip(void) ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); } - int data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); - efuse_program(num_block); + + uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data + memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); + int repeat_burn_op = 1; + bool correct_written_data; + bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); + bool coding_error_occurred; + + do { + ESP_LOGI(TAG, "BURN BLOCK%d", num_block); + efuse_program(num_block); // BURN a block + + bool coding_error_after; + for (unsigned i = 0; i < 5; i++) { + efuse_read(); + coding_error_after = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_after == true) { + break; + } + } + coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; + if (coding_error_occurred) { + ESP_LOGE(TAG, "BLOCK%d has an error", num_block); + } + + correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); + if (!correct_written_data || coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d: next retry [%d/3]...", num_block, repeat_burn_op); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); + } + + } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + } + if (coding_error_occurred) { + ESP_LOGE(TAG, "Coding error occurred in block"); + } break; } } diff --git a/components/efuse/esp32h2/esp_efuse_utility.c b/components/efuse/esp32h2/esp_efuse_utility.c index 1faca45802..c8c1fdde0f 100644 --- a/components/efuse/esp32h2/esp_efuse_utility.c +++ b/components/efuse/esp32h2/esp_efuse_utility.c @@ -65,6 +65,27 @@ static esp_err_t esp_efuse_set_timing(void) return ESP_OK; } + +static bool efuse_hal_is_coding_error_in_block(unsigned block) +{ + if (block == 0) { + for (unsigned i = 0; i < 5; i++) { + if (REG_READ(EFUSE_RD_REPEAT_ERR0_REG + i * 4)) { + return true; + } + } + } else if (block <= 10) { + // EFUSE_RD_RS_ERR0_REG: (hi) BLOCK8, BLOCK7, BLOCK6, BLOCK5, BLOCK4, BLOCK3, BLOCK2, BLOCK1 (low) + // EFUSE_RD_RS_ERR1_REG: BLOCK10, BLOCK9 + uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 9) * 4); + unsigned offset = (block >= 9) ? block - 9 : block - 1; + if (((error_reg >> (4 * offset)) & 0x0F) != 0) { + return true; + } + } + return false; +} + #endif // ifndef CONFIG_EFUSE_VIRTUAL // Efuse read operation: copies data from physical efuses to efuse read registers. @@ -102,9 +123,47 @@ void esp_efuse_utility_burn_chip(void) ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); } - int data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); - ets_efuse_program(num_block); + + uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data + memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); + int repeat_burn_op = 1; + bool correct_written_data; + bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); + bool coding_error_occurred; + + do { + ESP_LOGI(TAG, "BURN BLOCK%d", num_block); + ets_efuse_program(num_block); // BURN a block + + bool coding_error_after; + for (unsigned i = 0; i < 5; i++) { + ets_efuse_read(); + coding_error_after = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_after == true) { + break; + } + } + coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; + if (coding_error_occurred) { + ESP_LOGE(TAG, "BLOCK%d has an error", num_block); + } + + correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); + if (!correct_written_data || coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d: next retry [%d/3]...", num_block, repeat_burn_op); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); + } + + } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + } + if (coding_error_occurred) { + ESP_LOGE(TAG, "Coding error occurred in block"); + } break; } } diff --git a/components/efuse/esp32s2/esp_efuse_utility.c b/components/efuse/esp32s2/esp_efuse_utility.c index a5d5dc2867..cc54729038 100644 --- a/components/efuse/esp32s2/esp_efuse_utility.c +++ b/components/efuse/esp32s2/esp_efuse_utility.c @@ -58,6 +58,27 @@ static esp_err_t esp_efuse_set_timing(void) uint32_t clock_hz = esp_clk_apb_freq(); return ets_efuse_set_timing(clock_hz) ? ESP_FAIL : ESP_OK; } + +static bool efuse_hal_is_coding_error_in_block(unsigned block) +{ + if (block == 0) { + for (unsigned i = 0; i < 5; i++) { + if (REG_READ(EFUSE_RD_REPEAT_ERR0_REG + i * 4)) { + return true; + } + } + } else if (block <= 10) { + // EFUSE_RD_RS_ERR0_REG: (hi) BLOCK8, BLOCK7, BLOCK6, BLOCK5, BLOCK4, BLOCK3, BLOCK2, BLOCK1 (low) + // EFUSE_RD_RS_ERR1_REG: BLOCK10, BLOCK9 + uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 9) * 4); + unsigned offset = (block >= 9) ? block - 9 : block - 1; + if (((error_reg >> (4 * offset)) & 0x0F) != 0) { + return true; + } + } + return false; +} + #endif // ifndef CONFIG_EFUSE_VIRTUAL // Efuse read operation: copies data from physical efuses to efuse read registers. @@ -95,9 +116,47 @@ void esp_efuse_utility_burn_chip(void) ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); } - int data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); - ets_efuse_program(num_block); + + uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data + memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); + int repeat_burn_op = 1; + bool correct_written_data; + bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); + bool coding_error_occurred; + + do { + ESP_LOGI(TAG, "BURN BLOCK%d", num_block); + ets_efuse_program(num_block); // BURN a block + + bool coding_error_after; + for (unsigned i = 0; i < 5; i++) { + ets_efuse_read(); + coding_error_after = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_after == true) { + break; + } + } + coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; + if (coding_error_occurred) { + ESP_LOGE(TAG, "BLOCK%d has an error", num_block); + } + + correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); + if (!correct_written_data || coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d: next retry [%d/3]...", num_block, repeat_burn_op); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); + } + + } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + } + if (coding_error_occurred) { + ESP_LOGE(TAG, "Coding error occurred in block"); + } break; } } diff --git a/components/efuse/esp32s3/esp_efuse_utility.c b/components/efuse/esp32s3/esp_efuse_utility.c index 7dedd87987..8cd4bcecec 100644 --- a/components/efuse/esp32s3/esp_efuse_utility.c +++ b/components/efuse/esp32s3/esp_efuse_utility.c @@ -83,6 +83,27 @@ static void efuse_program(esp_efuse_block_t block) ets_efuse_clear_program_registers(); efuse_read(); } + +static bool efuse_hal_is_coding_error_in_block(unsigned block) +{ + if (block == 0) { + for (unsigned i = 0; i < 5; i++) { + if (REG_READ(EFUSE_RD_REPEAT_ERR0_REG + i * 4)) { + return true; + } + } + } else if (block <= 10) { + // EFUSE_RD_RS_ERR0_REG: (hi) BLOCK8, BLOCK7, BLOCK6, BLOCK5, BLOCK4, BLOCK3, BLOCK2, BLOCK1 (low) + // EFUSE_RD_RS_ERR1_REG: BLOCK10, BLOCK9 + uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 9) * 4); + unsigned offset = (block >= 9) ? block - 9 : block - 1; + if (((error_reg >> (4 * offset)) & 0x0F) != 0) { + return true; + } + } + return false; +} + #endif // ifndef CONFIG_EFUSE_VIRTUAL // Efuse read operation: copies data from physical efuses to efuse read registers. @@ -120,9 +141,47 @@ void esp_efuse_utility_burn_chip(void) ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); } - int data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); - efuse_program(num_block); + + uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data + memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); + int repeat_burn_op = 1; + bool correct_written_data; + bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); + bool coding_error_occurred; + + do { + ESP_LOGI(TAG, "BURN BLOCK%d", num_block); + efuse_program(num_block); // BURN a block + + bool coding_error_after; + for (unsigned i = 0; i < 5; i++) { + efuse_read(); + coding_error_after = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_after == true) { + break; + } + } + coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; + if (coding_error_occurred) { + ESP_LOGE(TAG, "BLOCK%d has an error", num_block); + } + + correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); + if (!correct_written_data || coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d: next retry [%d/3]...", num_block, repeat_burn_op); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); + } + + } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + } + if (coding_error_occurred) { + ESP_LOGE(TAG, "Coding error occurred in block"); + } break; } } diff --git a/components/efuse/private_include/esp_efuse_utility.h b/components/efuse/private_include/esp_efuse_utility.h index 3016d55dd2..710e1d618f 100644 --- a/components/efuse/private_include/esp_efuse_utility.h +++ b/components/efuse/private_include/esp_efuse_utility.h @@ -189,6 +189,19 @@ void esp_efuse_utility_erase_efuses_in_flash(void); */ uint32_t esp_efuse_utility_get_read_register_address(esp_efuse_block_t block); +/** + * @brief Checks the correctness of burned data in the given block. + * + * @note Internal use. Do not call it. + * + * @param[in] block Index of efuse block. + * @param[in] r_data_len Block length for reading data in bytes (multiple of 4). + * + * @return True - written data are correct. + * False - written data are incorrect. + */ +bool esp_efuse_utility_is_correct_written_data(esp_efuse_block_t block, unsigned r_data_len); + #ifdef __cplusplus } #endif diff --git a/components/efuse/src/esp_efuse_utility.c b/components/efuse/src/esp_efuse_utility.c index 319bebaa7b..903087ee28 100644 --- a/components/efuse/src/esp_efuse_utility.c +++ b/components/efuse/src/esp_efuse_utility.c @@ -474,3 +474,29 @@ void esp_efuse_utility_write_efuses_to_flash(void) } } #endif // CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH + +bool esp_efuse_utility_is_correct_written_data(esp_efuse_block_t block, unsigned r_data_len) +{ + uint32_t* w_data = (uint32_t*)range_write_addr_blocks[block].start; + uint32_t* r_data = (uint32_t*)range_read_addr_blocks[block].start; + + bool correct_written_data = memcmp(w_data, r_data, r_data_len) == 0; + if (correct_written_data) { + ESP_LOGI(TAG, "BURN BLOCK%d - OK (write block == read block)", block); + } else { + correct_written_data = true; + for (unsigned i = 0; i < r_data_len / 4; i++) { + if ((*(r_data + i) & *(w_data + i)) != *(w_data + i)) { + correct_written_data = false; + break; + } + } + if (correct_written_data) { + ESP_LOGI(TAG, "BURN BLOCK%d - OK (all write block bits are set)", block); + } + } + if (!correct_written_data) { + ESP_LOGE(TAG, "BURN BLOCK%d - was not successful", block); + } + return correct_written_data; +} From 24af86071d1111f30978ed6b468894000a5b4f48 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Wed, 6 Apr 2022 22:39:17 +0800 Subject: [PATCH 2/6] efuse: Burn func can return an error esp_efuse_utility_burn_chip() --- components/efuse/esp32/esp_efuse_utility.c | 29 +++++++++++++++---- components/efuse/esp32c3/esp_efuse_utility.c | 11 ++++--- components/efuse/esp32h2/esp_efuse_utility.c | 11 ++++--- components/efuse/esp32s2/esp_efuse_utility.c | 11 ++++--- components/efuse/esp32s3/esp_efuse_utility.c | 11 ++++--- .../efuse/private_include/esp_efuse_utility.h | 12 ++++++-- components/efuse/src/esp_efuse_api.c | 8 ++--- components/efuse/src/esp_efuse_utility.c | 5 ++-- 8 files changed, 69 insertions(+), 29 deletions(-) diff --git a/components/efuse/esp32/esp_efuse_utility.c b/components/efuse/esp32/esp_efuse_utility.c index ff32ea2486..3be5190d82 100644 --- a/components/efuse/esp32/esp_efuse_utility.c +++ b/components/efuse/esp32/esp_efuse_utility.c @@ -102,14 +102,30 @@ static bool efuse_hal_is_coding_error_in_block(unsigned block) #endif // ifndef CONFIG_EFUSE_VIRTUAL +static void efuse_hal_clear_program_registers(void) +{ + for (uint32_t r = EFUSE_BLK0_WDATA0_REG; r <= EFUSE_BLK0_WDATA6_REG; r += 4) { + REG_WRITE(r, 0); + } + for (uint32_t r = EFUSE_BLK1_WDATA0_REG; r <= EFUSE_BLK1_WDATA7_REG; r += 4) { + REG_WRITE(r, 0); + } + for (uint32_t r = EFUSE_BLK2_WDATA0_REG; r <= EFUSE_BLK2_WDATA7_REG; r += 4) { + REG_WRITE(r, 0); + } + for (uint32_t r = EFUSE_BLK3_WDATA0_REG; r <= EFUSE_BLK3_WDATA7_REG; r += 4) { + REG_WRITE(r, 0); + } +} + // Efuse read operation: copies data from physical efuses to efuse read registers. void esp_efuse_utility_clear_program_registers(void) { - REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ); + efuse_hal_clear_program_registers(); } // Burn values written to the efuse write registers -void esp_efuse_utility_burn_chip(void) +esp_err_t esp_efuse_utility_burn_chip(void) { #ifdef CONFIG_EFUSE_VIRTUAL ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses"); @@ -132,6 +148,7 @@ void esp_efuse_utility_burn_chip(void) esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block); for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { if (REG_READ(addr_wr_block) != 0) { + efuse_hal_clear_program_registers(); unsigned w_data_len; unsigned r_data_len; if (scheme == EFUSE_CODING_SCHEME_3_4) { @@ -178,12 +195,13 @@ void esp_efuse_utility_burn_chip(void) } } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); - if (!correct_written_data) { - ESP_LOGE(TAG, "Written data are incorrect"); - } if (coding_error_occurred) { ESP_LOGE(TAG, "Coding error occurred in block"); } + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + return ESP_FAIL; + } break; } } @@ -191,6 +209,7 @@ void esp_efuse_utility_burn_chip(void) } #endif // CONFIG_EFUSE_VIRTUAL esp_efuse_utility_reset(); + return ESP_OK; } esp_err_t esp_efuse_utility_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len) diff --git a/components/efuse/esp32c3/esp_efuse_utility.c b/components/efuse/esp32c3/esp_efuse_utility.c index 037e571c29..66c1e2af14 100644 --- a/components/efuse/esp32c3/esp_efuse_utility.c +++ b/components/efuse/esp32c3/esp_efuse_utility.c @@ -116,7 +116,7 @@ void esp_efuse_utility_clear_program_registers(void) } // Burn values written to the efuse write registers -void esp_efuse_utility_burn_chip(void) +esp_err_t esp_efuse_utility_burn_chip(void) { #ifdef CONFIG_EFUSE_VIRTUAL ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses"); @@ -138,6 +138,7 @@ void esp_efuse_utility_burn_chip(void) for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { if (REG_READ(addr_wr_block) != 0) { + ets_efuse_clear_program_registers(); if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { uint8_t block_rs[12]; ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); @@ -178,12 +179,13 @@ void esp_efuse_utility_burn_chip(void) } } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); - if (!correct_written_data) { - ESP_LOGE(TAG, "Written data are incorrect"); - } if (coding_error_occurred) { ESP_LOGE(TAG, "Coding error occurred in block"); } + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + return ESP_FAIL; + } break; } } @@ -191,6 +193,7 @@ void esp_efuse_utility_burn_chip(void) } #endif // CONFIG_EFUSE_VIRTUAL esp_efuse_utility_reset(); + return ESP_OK; } // After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values. diff --git a/components/efuse/esp32h2/esp_efuse_utility.c b/components/efuse/esp32h2/esp_efuse_utility.c index c8c1fdde0f..13f772a534 100644 --- a/components/efuse/esp32h2/esp_efuse_utility.c +++ b/components/efuse/esp32h2/esp_efuse_utility.c @@ -96,7 +96,7 @@ void esp_efuse_utility_clear_program_registers(void) } // Burn values written to the efuse write registers -void esp_efuse_utility_burn_chip(void) +esp_err_t esp_efuse_utility_burn_chip(void) { #ifdef CONFIG_EFUSE_VIRTUAL ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses"); @@ -118,6 +118,7 @@ void esp_efuse_utility_burn_chip(void) for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { if (REG_READ(addr_wr_block) != 0) { + ets_efuse_clear_program_registers(); if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { uint8_t block_rs[12]; ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); @@ -158,12 +159,13 @@ void esp_efuse_utility_burn_chip(void) } } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); - if (!correct_written_data) { - ESP_LOGE(TAG, "Written data are incorrect"); - } if (coding_error_occurred) { ESP_LOGE(TAG, "Coding error occurred in block"); } + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + return ESP_FAIL; + } break; } } @@ -171,6 +173,7 @@ void esp_efuse_utility_burn_chip(void) } #endif // CONFIG_EFUSE_VIRTUAL esp_efuse_utility_reset(); + return ESP_OK; } // After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values. diff --git a/components/efuse/esp32s2/esp_efuse_utility.c b/components/efuse/esp32s2/esp_efuse_utility.c index cc54729038..73477f46e8 100644 --- a/components/efuse/esp32s2/esp_efuse_utility.c +++ b/components/efuse/esp32s2/esp_efuse_utility.c @@ -89,7 +89,7 @@ void esp_efuse_utility_clear_program_registers(void) } // Burn values written to the efuse write registers -void esp_efuse_utility_burn_chip(void) +esp_err_t esp_efuse_utility_burn_chip(void) { #ifdef CONFIG_EFUSE_VIRTUAL ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses"); @@ -111,6 +111,7 @@ void esp_efuse_utility_burn_chip(void) for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { if (REG_READ(addr_wr_block) != 0) { + ets_efuse_clear_program_registers(); if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { uint8_t block_rs[12]; ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); @@ -151,12 +152,13 @@ void esp_efuse_utility_burn_chip(void) } } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); - if (!correct_written_data) { - ESP_LOGE(TAG, "Written data are incorrect"); - } if (coding_error_occurred) { ESP_LOGE(TAG, "Coding error occurred in block"); } + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + return ESP_FAIL; + } break; } } @@ -164,6 +166,7 @@ void esp_efuse_utility_burn_chip(void) } #endif // CONFIG_EFUSE_VIRTUAL esp_efuse_utility_reset(); + return ESP_OK; } // After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values. diff --git a/components/efuse/esp32s3/esp_efuse_utility.c b/components/efuse/esp32s3/esp_efuse_utility.c index 8cd4bcecec..ff5ac656c4 100644 --- a/components/efuse/esp32s3/esp_efuse_utility.c +++ b/components/efuse/esp32s3/esp_efuse_utility.c @@ -114,7 +114,7 @@ void esp_efuse_utility_clear_program_registers(void) } // Burn values written to the efuse write registers -void esp_efuse_utility_burn_chip(void) +esp_err_t esp_efuse_utility_burn_chip(void) { #ifdef CONFIG_EFUSE_VIRTUAL ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses"); @@ -136,6 +136,7 @@ void esp_efuse_utility_burn_chip(void) for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { if (REG_READ(addr_wr_block) != 0) { + ets_efuse_clear_program_registers(); if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { uint8_t block_rs[12]; ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); @@ -176,12 +177,13 @@ void esp_efuse_utility_burn_chip(void) } } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); - if (!correct_written_data) { - ESP_LOGE(TAG, "Written data are incorrect"); - } if (coding_error_occurred) { ESP_LOGE(TAG, "Coding error occurred in block"); } + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + return ESP_FAIL; + } break; } } @@ -189,6 +191,7 @@ void esp_efuse_utility_burn_chip(void) } #endif // CONFIG_EFUSE_VIRTUAL esp_efuse_utility_reset(); + return ESP_OK; } // After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values. diff --git a/components/efuse/private_include/esp_efuse_utility.h b/components/efuse/private_include/esp_efuse_utility.h index 710e1d618f..0fd026e3e7 100644 --- a/components/efuse/private_include/esp_efuse_utility.h +++ b/components/efuse/private_include/esp_efuse_utility.h @@ -93,8 +93,12 @@ esp_err_t esp_efuse_utility_fill_buff(unsigned int num_reg, esp_efuse_block_t ef * * If CONFIG_EFUSE_VIRTUAL is set, writing will not be performed. * After the function is completed, the writing registers are cleared. + * + * @return + * - ESP_OK: The operation was successfully completed. + * - ESP_FAIL: The operation was not successfully completed. */ -void esp_efuse_utility_burn_efuses(void); +esp_err_t esp_efuse_utility_burn_efuses(void); /** * @brief Chip specific operations to perform the burn of values written to the efuse write registers. @@ -103,8 +107,12 @@ void esp_efuse_utility_burn_efuses(void); * * If CONFIG_EFUSE_VIRTUAL is set, writing will not be performed. * After the function is completed, the writing registers are cleared. + * + * @return + * - ESP_OK: The operation was successfully completed. + * - ESP_FAIL: The operation was not successfully completed. */ -void esp_efuse_utility_burn_chip(void); +esp_err_t esp_efuse_utility_burn_chip(void); /** * @brief Returns the number of array elements for placing these "bits" in an array with the length of each element equal to "size_of_base". diff --git a/components/efuse/src/esp_efuse_api.c b/components/efuse/src/esp_efuse_api.c index a89205fc82..09c55bb50c 100644 --- a/components/efuse/src/esp_efuse_api.c +++ b/components/efuse/src/esp_efuse_api.c @@ -94,7 +94,7 @@ esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void if (err == ESP_OK) { err = esp_efuse_utility_apply_new_coding_scheme(); if (err == ESP_OK) { - esp_efuse_utility_burn_efuses(); + err = esp_efuse_utility_burn_efuses(); } } esp_efuse_utility_reset(); @@ -129,7 +129,7 @@ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt) if (err == ESP_OK) { err = esp_efuse_utility_apply_new_coding_scheme(); if (err == ESP_OK) { - esp_efuse_utility_burn_efuses(); + err = esp_efuse_utility_burn_efuses(); } } esp_efuse_utility_reset(); @@ -194,7 +194,7 @@ esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint3 if (err == ESP_OK) { err = esp_efuse_utility_apply_new_coding_scheme(); if (err == ESP_OK) { - esp_efuse_utility_burn_efuses(); + err = esp_efuse_utility_burn_efuses(); } } esp_efuse_utility_reset(); @@ -277,7 +277,7 @@ esp_err_t esp_efuse_batch_write_commit(void) if (--s_batch_writing_mode == 0) { esp_err_t err = esp_efuse_utility_apply_new_coding_scheme(); if (err == ESP_OK) { - esp_efuse_utility_burn_efuses(); + err = esp_efuse_utility_burn_efuses(); ESP_LOGI(TAG, "Batch mode. Prepared fields are committed"); } else { esp_efuse_utility_reset(); diff --git a/components/efuse/src/esp_efuse_utility.c b/components/efuse/src/esp_efuse_utility.c index 903087ee28..ea50eb0a69 100644 --- a/components/efuse/src/esp_efuse_utility.c +++ b/components/efuse/src/esp_efuse_utility.c @@ -165,11 +165,12 @@ void esp_efuse_utility_reset(void) } // Burn values written to the efuse write registers -void esp_efuse_utility_burn_efuses(void) +esp_err_t esp_efuse_utility_burn_efuses(void) { ++s_burn_counter; - esp_efuse_utility_burn_chip(); + esp_err_t err = esp_efuse_utility_burn_chip(); ++s_burn_counter; + return err; } // Erase the virt_blocks array. From ce148dd7b84a937d4c08678be0bbefc345a92bd2 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Thu, 7 Apr 2022 20:05:40 +0800 Subject: [PATCH 3/6] efuse: Improve messages during burn operation --- components/efuse/esp32/esp_efuse_utility.c | 127 +++++++++++-------- components/efuse/esp32c3/esp_efuse_utility.c | 118 ++++++++++------- components/efuse/esp32h2/esp_efuse_utility.c | 118 ++++++++++------- components/efuse/esp32s2/esp_efuse_utility.c | 118 ++++++++++------- components/efuse/esp32s3/esp_efuse_utility.c | 118 ++++++++++------- components/efuse/src/esp_efuse_utility.c | 2 +- 6 files changed, 349 insertions(+), 252 deletions(-) diff --git a/components/efuse/esp32/esp_efuse_utility.c b/components/efuse/esp32/esp_efuse_utility.c index 3be5190d82..497527458a 100644 --- a/components/efuse/esp32/esp_efuse_utility.c +++ b/components/efuse/esp32/esp_efuse_utility.c @@ -127,6 +127,7 @@ void esp_efuse_utility_clear_program_registers(void) // Burn values written to the efuse write registers esp_err_t esp_efuse_utility_burn_chip(void) { + esp_err_t error = ESP_OK; #ifdef CONFIG_EFUSE_VIRTUAL ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses"); for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { @@ -146,70 +147,85 @@ esp_err_t esp_efuse_utility_burn_chip(void) // It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks. for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block); + bool need_burn_block = false; for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { if (REG_READ(addr_wr_block) != 0) { - efuse_hal_clear_program_registers(); - unsigned w_data_len; - unsigned r_data_len; - if (scheme == EFUSE_CODING_SCHEME_3_4) { - esp_efuse_utility_apply_34_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], 24); - r_data_len = 24; - w_data_len = 32; - } else if (scheme == EFUSE_CODING_SCHEME_REPEAT) { - apply_repeat_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], 16); - r_data_len = 16; - w_data_len = 32; - } else { - r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); - w_data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); - memcpy((void *)start_write_addr[num_block], (void *)range_write_addr_blocks[num_block].start, w_data_len); - } - - uint32_t backup_write_data[8]; - memcpy(backup_write_data, (void *)start_write_addr[num_block], w_data_len); - int repeat_burn_op = 1; - bool correct_written_data; - bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); - bool coding_error_occurred; - - do { - ESP_LOGI(TAG, "BURN BLOCK%d", num_block); - // BURN a block - REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_WRITE); - REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_PGM); - while (REG_READ(EFUSE_CMD_REG) != 0) {}; - REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ); - REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_READ); - while (REG_READ(EFUSE_CMD_REG) != 0) {}; - - bool coding_error_after = efuse_hal_is_coding_error_in_block(num_block); - coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; - if (coding_error_occurred) { - ESP_LOGE(TAG, "BLOCK%d has an error", num_block); - } - - correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); - if (!correct_written_data || coding_error_occurred) { - ESP_LOGW(TAG, "BLOCK%d: next retry [%d/3]...", num_block, repeat_burn_op); - memcpy((void *)start_write_addr[num_block], (void *)backup_write_data, w_data_len); - } - - } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); - if (coding_error_occurred) { - ESP_LOGE(TAG, "Coding error occurred in block"); - } - if (!correct_written_data) { - ESP_LOGE(TAG, "Written data are incorrect"); - return ESP_FAIL; - } + need_burn_block = true; break; } } + if (!need_burn_block) { + continue; + } + if (error) { + // It is done for a use case: BLOCK2 (Flash encryption key) could have an error (incorrect written data) + // in this case we can not burn any data into BLOCK0 because it might set read/write protections of BLOCK2. + ESP_LOGE(TAG, "BLOCK%d can not be burned because a previous block got an error, skipped.", num_block); + continue; + } + efuse_hal_clear_program_registers(); + unsigned w_data_len; + unsigned r_data_len; + if (scheme == EFUSE_CODING_SCHEME_3_4) { + esp_efuse_utility_apply_34_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], 24); + r_data_len = 24; + w_data_len = 32; + } else if (scheme == EFUSE_CODING_SCHEME_REPEAT) { + apply_repeat_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], 16); + r_data_len = 16; + w_data_len = 32; + } else { + r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); + w_data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); + memcpy((void *)start_write_addr[num_block], (void *)range_write_addr_blocks[num_block].start, w_data_len); + } + + uint32_t backup_write_data[8]; + memcpy(backup_write_data, (void *)start_write_addr[num_block], w_data_len); + int repeat_burn_op = 1; + bool correct_written_data; + bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_before) { + ESP_LOGW(TAG, "BLOCK%d already has a coding error", num_block); + } + bool coding_error_occurred; + + do { + ESP_LOGI(TAG, "BURN BLOCK%d", num_block); + // BURN a block + REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_WRITE); + REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_PGM); + while (REG_READ(EFUSE_CMD_REG) != 0) {}; + REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ); + REG_WRITE(EFUSE_CMD_REG, EFUSE_CMD_READ); + while (REG_READ(EFUSE_CMD_REG) != 0) {}; + + bool coding_error_after = efuse_hal_is_coding_error_in_block(num_block); + coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; + if (coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d got a coding error", num_block); + } + + correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); + if (!correct_written_data || coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op); + memcpy((void *)start_write_addr[num_block], (void *)backup_write_data, w_data_len); + } + + } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); + + if (coding_error_occurred) { + ESP_LOGW(TAG, "Coding error was not fixed"); + } + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + error = ESP_FAIL; + } } } #endif // CONFIG_EFUSE_VIRTUAL esp_efuse_utility_reset(); - return ESP_OK; + return error; } esp_err_t esp_efuse_utility_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len) @@ -263,6 +279,7 @@ esp_err_t esp_efuse_utility_apply_new_coding_scheme() for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { if (REG_READ(addr_wr_block)) { is_write_data = true; + break; } } if (is_write_data) { diff --git a/components/efuse/esp32c3/esp_efuse_utility.c b/components/efuse/esp32c3/esp_efuse_utility.c index 66c1e2af14..06f21d4b56 100644 --- a/components/efuse/esp32c3/esp_efuse_utility.c +++ b/components/efuse/esp32c3/esp_efuse_utility.c @@ -118,6 +118,7 @@ void esp_efuse_utility_clear_program_registers(void) // Burn values written to the efuse write registers esp_err_t esp_efuse_utility_burn_chip(void) { + esp_err_t error = ESP_OK; #ifdef CONFIG_EFUSE_VIRTUAL ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses"); for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { @@ -136,64 +137,83 @@ esp_err_t esp_efuse_utility_burn_chip(void) // Permanently update values written to the efuse write registers // It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks. for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { + bool need_burn_block = false; for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { if (REG_READ(addr_wr_block) != 0) { - ets_efuse_clear_program_registers(); - if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { - uint8_t block_rs[12]; - ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); - memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); - } - unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); - unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); - memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); - - uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data - memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); - int repeat_burn_op = 1; - bool correct_written_data; - bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); - bool coding_error_occurred; - - do { - ESP_LOGI(TAG, "BURN BLOCK%d", num_block); - efuse_program(num_block); // BURN a block - - bool coding_error_after; - for (unsigned i = 0; i < 5; i++) { - efuse_read(); - coding_error_after = efuse_hal_is_coding_error_in_block(num_block); - if (coding_error_after == true) { - break; - } - } - coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; - if (coding_error_occurred) { - ESP_LOGE(TAG, "BLOCK%d has an error", num_block); - } - - correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); - if (!correct_written_data || coding_error_occurred) { - ESP_LOGW(TAG, "BLOCK%d: next retry [%d/3]...", num_block, repeat_burn_op); - memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); - } - - } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); - if (coding_error_occurred) { - ESP_LOGE(TAG, "Coding error occurred in block"); - } - if (!correct_written_data) { - ESP_LOGE(TAG, "Written data are incorrect"); - return ESP_FAIL; - } + need_burn_block = true; break; } } + if (!need_burn_block) { + continue; + } + if (error) { + // It is done for a use case: BLOCK2 (Flash encryption key) could have an error (incorrect written data) + // in this case we can not burn any data into BLOCK0 because it might set read/write protections of BLOCK2. + ESP_LOGE(TAG, "BLOCK%d can not be burned because a previous block got an error, skipped.", num_block); + continue; + } + ets_efuse_clear_program_registers(); + if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { + uint8_t block_rs[12]; + ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); + memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); + } + unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); + + uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data + memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); + int repeat_burn_op = 1; + bool correct_written_data; + bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_before) { + ESP_LOGW(TAG, "BLOCK%d already has a coding error", num_block); + } + bool coding_error_occurred; + + do { + ESP_LOGI(TAG, "BURN BLOCK%d", num_block); + efuse_program(num_block); // BURN a block + + bool coding_error_after; + for (unsigned i = 0; i < 5; i++) { + efuse_read(); + coding_error_after = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_after == true) { + break; + } + } + coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; + if (coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d got a coding error", num_block); + } + + correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); + if (!correct_written_data || coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); + } + + } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); + + if (coding_error_occurred) { + ESP_LOGW(TAG, "Coding error was not fixed"); + if (num_block == 0) { + ESP_LOGE(TAG, "BLOCK0 got a coding error, which might be critical for security"); + error = ESP_FAIL; + } + } + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + error = ESP_FAIL; + } } } #endif // CONFIG_EFUSE_VIRTUAL esp_efuse_utility_reset(); - return ESP_OK; + return error; } // After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values. diff --git a/components/efuse/esp32h2/esp_efuse_utility.c b/components/efuse/esp32h2/esp_efuse_utility.c index 13f772a534..0edb55e02e 100644 --- a/components/efuse/esp32h2/esp_efuse_utility.c +++ b/components/efuse/esp32h2/esp_efuse_utility.c @@ -98,6 +98,7 @@ void esp_efuse_utility_clear_program_registers(void) // Burn values written to the efuse write registers esp_err_t esp_efuse_utility_burn_chip(void) { + esp_err_t error = ESP_OK; #ifdef CONFIG_EFUSE_VIRTUAL ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses"); for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { @@ -116,64 +117,83 @@ esp_err_t esp_efuse_utility_burn_chip(void) // Permanently update values written to the efuse write registers // It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks. for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { + bool need_burn_block = false; for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { if (REG_READ(addr_wr_block) != 0) { - ets_efuse_clear_program_registers(); - if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { - uint8_t block_rs[12]; - ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); - memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); - } - unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); - unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); - memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); - - uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data - memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); - int repeat_burn_op = 1; - bool correct_written_data; - bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); - bool coding_error_occurred; - - do { - ESP_LOGI(TAG, "BURN BLOCK%d", num_block); - ets_efuse_program(num_block); // BURN a block - - bool coding_error_after; - for (unsigned i = 0; i < 5; i++) { - ets_efuse_read(); - coding_error_after = efuse_hal_is_coding_error_in_block(num_block); - if (coding_error_after == true) { - break; - } - } - coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; - if (coding_error_occurred) { - ESP_LOGE(TAG, "BLOCK%d has an error", num_block); - } - - correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); - if (!correct_written_data || coding_error_occurred) { - ESP_LOGW(TAG, "BLOCK%d: next retry [%d/3]...", num_block, repeat_burn_op); - memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); - } - - } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); - if (coding_error_occurred) { - ESP_LOGE(TAG, "Coding error occurred in block"); - } - if (!correct_written_data) { - ESP_LOGE(TAG, "Written data are incorrect"); - return ESP_FAIL; - } + need_burn_block = true; break; } } + if (!need_burn_block) { + continue; + } + if (error) { + // It is done for a use case: BLOCK2 (Flash encryption key) could have an error (incorrect written data) + // in this case we can not burn any data into BLOCK0 because it might set read/write protections of BLOCK2. + ESP_LOGE(TAG, "BLOCK%d can not be burned because a previous block got an error, skipped.", num_block); + continue; + } + ets_efuse_clear_program_registers(); + if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { + uint8_t block_rs[12]; + ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); + memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); + } + unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); + + uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data + memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); + int repeat_burn_op = 1; + bool correct_written_data; + bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_before) { + ESP_LOGW(TAG, "BLOCK%d already has a coding error", num_block); + } + bool coding_error_occurred; + + do { + ESP_LOGI(TAG, "BURN BLOCK%d", num_block); + ets_efuse_program(num_block); // BURN a block + + bool coding_error_after; + for (unsigned i = 0; i < 5; i++) { + ets_efuse_read(); + coding_error_after = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_after == true) { + break; + } + } + coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; + if (coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d got a coding error", num_block); + } + + correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); + if (!correct_written_data || coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); + } + + } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); + + if (coding_error_occurred) { + ESP_LOGW(TAG, "Coding error was not fixed"); + if (num_block == 0) { + ESP_LOGE(TAG, "BLOCK0 got a coding error, which might be critical for security"); + error = ESP_FAIL; + } + } + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + error = ESP_FAIL; + } } } #endif // CONFIG_EFUSE_VIRTUAL esp_efuse_utility_reset(); - return ESP_OK; + return error; } // After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values. diff --git a/components/efuse/esp32s2/esp_efuse_utility.c b/components/efuse/esp32s2/esp_efuse_utility.c index 73477f46e8..7cfb4281e4 100644 --- a/components/efuse/esp32s2/esp_efuse_utility.c +++ b/components/efuse/esp32s2/esp_efuse_utility.c @@ -91,6 +91,7 @@ void esp_efuse_utility_clear_program_registers(void) // Burn values written to the efuse write registers esp_err_t esp_efuse_utility_burn_chip(void) { + esp_err_t error = ESP_OK; #ifdef CONFIG_EFUSE_VIRTUAL ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses"); for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { @@ -109,64 +110,83 @@ esp_err_t esp_efuse_utility_burn_chip(void) // Permanently update values written to the efuse write registers // It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks. for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { + bool need_burn_block = false; for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { if (REG_READ(addr_wr_block) != 0) { - ets_efuse_clear_program_registers(); - if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { - uint8_t block_rs[12]; - ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); - memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); - } - unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); - unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); - memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); - - uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data - memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); - int repeat_burn_op = 1; - bool correct_written_data; - bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); - bool coding_error_occurred; - - do { - ESP_LOGI(TAG, "BURN BLOCK%d", num_block); - ets_efuse_program(num_block); // BURN a block - - bool coding_error_after; - for (unsigned i = 0; i < 5; i++) { - ets_efuse_read(); - coding_error_after = efuse_hal_is_coding_error_in_block(num_block); - if (coding_error_after == true) { - break; - } - } - coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; - if (coding_error_occurred) { - ESP_LOGE(TAG, "BLOCK%d has an error", num_block); - } - - correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); - if (!correct_written_data || coding_error_occurred) { - ESP_LOGW(TAG, "BLOCK%d: next retry [%d/3]...", num_block, repeat_burn_op); - memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); - } - - } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); - if (coding_error_occurred) { - ESP_LOGE(TAG, "Coding error occurred in block"); - } - if (!correct_written_data) { - ESP_LOGE(TAG, "Written data are incorrect"); - return ESP_FAIL; - } + need_burn_block = true; break; } } + if (!need_burn_block) { + continue; + } + if (error) { + // It is done for a use case: BLOCK2 (Flash encryption key) could have an error (incorrect written data) + // in this case we can not burn any data into BLOCK0 because it might set read/write protections of BLOCK2. + ESP_LOGE(TAG, "BLOCK%d can not be burned because a previous block got an error, skipped.", num_block); + continue; + } + ets_efuse_clear_program_registers(); + if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { + uint8_t block_rs[12]; + ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); + memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); + } + unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); + + uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data + memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); + int repeat_burn_op = 1; + bool correct_written_data; + bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_before) { + ESP_LOGW(TAG, "BLOCK%d already has a coding error", num_block); + } + bool coding_error_occurred; + + do { + ESP_LOGI(TAG, "BURN BLOCK%d", num_block); + ets_efuse_program(num_block); // BURN a block + + bool coding_error_after; + for (unsigned i = 0; i < 5; i++) { + ets_efuse_read(); + coding_error_after = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_after == true) { + break; + } + } + coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; + if (coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d got a coding error", num_block); + } + + correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); + if (!correct_written_data || coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); + } + + } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); + + if (coding_error_occurred) { + ESP_LOGW(TAG, "Coding error was not fixed"); + if (num_block == 0) { + ESP_LOGE(TAG, "BLOCK0 got a coding error, which might be critical for security"); + error = ESP_FAIL; + } + } + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + error = ESP_FAIL; + } } } #endif // CONFIG_EFUSE_VIRTUAL esp_efuse_utility_reset(); - return ESP_OK; + return error; } // After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values. diff --git a/components/efuse/esp32s3/esp_efuse_utility.c b/components/efuse/esp32s3/esp_efuse_utility.c index ff5ac656c4..3dc964ef05 100644 --- a/components/efuse/esp32s3/esp_efuse_utility.c +++ b/components/efuse/esp32s3/esp_efuse_utility.c @@ -116,6 +116,7 @@ void esp_efuse_utility_clear_program_registers(void) // Burn values written to the efuse write registers esp_err_t esp_efuse_utility_burn_chip(void) { + esp_err_t error = ESP_OK; #ifdef CONFIG_EFUSE_VIRTUAL ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses"); for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { @@ -134,64 +135,83 @@ esp_err_t esp_efuse_utility_burn_chip(void) // Permanently update values written to the efuse write registers // It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks. for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) { + bool need_burn_block = false; for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) { if (REG_READ(addr_wr_block) != 0) { - ets_efuse_clear_program_registers(); - if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { - uint8_t block_rs[12]; - ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); - memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); - } - unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); - unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); - memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); - - uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data - memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); - int repeat_burn_op = 1; - bool correct_written_data; - bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); - bool coding_error_occurred; - - do { - ESP_LOGI(TAG, "BURN BLOCK%d", num_block); - efuse_program(num_block); // BURN a block - - bool coding_error_after; - for (unsigned i = 0; i < 5; i++) { - efuse_read(); - coding_error_after = efuse_hal_is_coding_error_in_block(num_block); - if (coding_error_after == true) { - break; - } - } - coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; - if (coding_error_occurred) { - ESP_LOGE(TAG, "BLOCK%d has an error", num_block); - } - - correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); - if (!correct_written_data || coding_error_occurred) { - ESP_LOGW(TAG, "BLOCK%d: next retry [%d/3]...", num_block, repeat_burn_op); - memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); - } - - } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); - if (coding_error_occurred) { - ESP_LOGE(TAG, "Coding error occurred in block"); - } - if (!correct_written_data) { - ESP_LOGE(TAG, "Written data are incorrect"); - return ESP_FAIL; - } + need_burn_block = true; break; } } + if (!need_burn_block) { + continue; + } + if (error) { + // It is done for a use case: BLOCK2 (Flash encryption key) could have an error (incorrect written data) + // in this case we can not burn any data into BLOCK0 because it might set read/write protections of BLOCK2. + ESP_LOGE(TAG, "BLOCK%d can not be burned because a previous block got an error, skipped.", num_block); + continue; + } + ets_efuse_clear_program_registers(); + if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) { + uint8_t block_rs[12]; + ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); + memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); + } + unsigned r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); + unsigned data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len); + + uint32_t backup_write_data[8 + 3]; // 8 words are data and 3 words are RS coding data + memcpy(backup_write_data, (void *)EFUSE_PGM_DATA0_REG, sizeof(backup_write_data)); + int repeat_burn_op = 1; + bool correct_written_data; + bool coding_error_before = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_before) { + ESP_LOGW(TAG, "BLOCK%d already has a coding error", num_block); + } + bool coding_error_occurred; + + do { + ESP_LOGI(TAG, "BURN BLOCK%d", num_block); + efuse_program(num_block); // BURN a block + + bool coding_error_after; + for (unsigned i = 0; i < 5; i++) { + efuse_read(); + coding_error_after = efuse_hal_is_coding_error_in_block(num_block); + if (coding_error_after == true) { + break; + } + } + coding_error_occurred = (coding_error_before != coding_error_after) && coding_error_before == false; + if (coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d got a coding error", num_block); + } + + correct_written_data = esp_efuse_utility_is_correct_written_data(num_block, r_data_len); + if (!correct_written_data || coding_error_occurred) { + ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op); + memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); + } + + } while ((!correct_written_data || coding_error_occurred) && repeat_burn_op++ < 3); + + if (coding_error_occurred) { + ESP_LOGW(TAG, "Coding error was not fixed"); + if (num_block == 0) { + ESP_LOGE(TAG, "BLOCK0 got a coding error, which might be critical for security"); + error = ESP_FAIL; + } + } + if (!correct_written_data) { + ESP_LOGE(TAG, "Written data are incorrect"); + error = ESP_FAIL; + } } } #endif // CONFIG_EFUSE_VIRTUAL esp_efuse_utility_reset(); - return ESP_OK; + return error; } // After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values. diff --git a/components/efuse/src/esp_efuse_utility.c b/components/efuse/src/esp_efuse_utility.c index ea50eb0a69..0634191ec1 100644 --- a/components/efuse/src/esp_efuse_utility.c +++ b/components/efuse/src/esp_efuse_utility.c @@ -497,7 +497,7 @@ bool esp_efuse_utility_is_correct_written_data(esp_efuse_block_t block, unsigned } } if (!correct_written_data) { - ESP_LOGE(TAG, "BURN BLOCK%d - was not successful", block); + ESP_LOGE(TAG, "BURN BLOCK%d - ERROR (written bits != read bits)", block); } return correct_written_data; } From 8c063a326e20b49419b3879afe03a7bed7438f40 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Fri, 8 Apr 2022 16:27:46 +0800 Subject: [PATCH 4/6] efuse: Fix 3/4 coding scheme UTs --- components/efuse/esp32/esp_efuse_utility.c | 11 ++++++++++- components/efuse/test/test_efuse_coding_scheme.c | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/components/efuse/esp32/esp_efuse_utility.c b/components/efuse/esp32/esp_efuse_utility.c index 497527458a..4abe61a3cd 100644 --- a/components/efuse/esp32/esp_efuse_utility.c +++ b/components/efuse/esp32/esp_efuse_utility.c @@ -267,10 +267,19 @@ static void apply_repeat_encoding(const uint8_t *in_bytes, uint32_t *out_words, } #endif // CONFIG_EFUSE_VIRTUAL +static void read_r_data(esp_efuse_block_t num_block, uint32_t* buf_r_data) +{ + int i = 0; + for (uint32_t addr_rd_block = range_read_addr_blocks[num_block].start; addr_rd_block <= range_read_addr_blocks[num_block].end; addr_rd_block += 4, ++i) { + buf_r_data[i] = esp_efuse_utility_read_reg(num_block, i); + } +} + // This function just checkes that given data for blocks will not rise a coding issue during the burn operation. // Encoded data will be set during the burn operation. esp_err_t esp_efuse_utility_apply_new_coding_scheme() { + uint8_t buf_r_data[COUNT_EFUSE_REG_PER_BLOCK * 4]; // start with EFUSE_BLK1. EFUSE_BLK0 - always uses EFUSE_CODING_SCHEME_NONE. for (int num_block = EFUSE_BLK1; num_block < EFUSE_BLK_MAX; num_block++) { esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(num_block); @@ -283,8 +292,8 @@ esp_err_t esp_efuse_utility_apply_new_coding_scheme() } } if (is_write_data) { + read_r_data(num_block, (uint32_t*)buf_r_data); uint8_t* buf_w_data = (uint8_t*)range_write_addr_blocks[num_block].start; - uint8_t* buf_r_data = (uint8_t*)range_read_addr_blocks[num_block].start; if (scheme == EFUSE_CODING_SCHEME_3_4) { if (*((uint32_t*)buf_w_data + 6) != 0 || *((uint32_t*)buf_w_data + 7) != 0) { return ESP_ERR_CODING; diff --git a/components/efuse/test/test_efuse_coding_scheme.c b/components/efuse/test/test_efuse_coding_scheme.c index 753fe624d1..634221cc39 100644 --- a/components/efuse/test/test_efuse_coding_scheme.c +++ b/components/efuse/test/test_efuse_coding_scheme.c @@ -174,7 +174,7 @@ TEST_CASE("Test Coding Scheme for efuse manager", "[efuse]") } printf("\n"); #endif - TEST_ASSERT_EQUAL_HEX32_ARRAY(encoded, w_data_after_coding, 8); + TEST_ASSERT_EQUAL_HEX32_ARRAY(buf, w_data_after_coding, 8); } esp_efuse_utility_reset(); bootloader_random_disable(); @@ -198,7 +198,7 @@ TEST_CASE("Test data does not match the coding scheme", "[efuse]") esp_efuse_utility_reset(); for (int i = 0; i < count_useful_reg; ++i) { - REG_WRITE(EFUSE_BLK2_WDATA0_REG + i * 4, 0xABCDEF01 + i); + TEST_ESP_OK(esp_efuse_utility_write_reg(2, i, 0xABCDEF01 + i)); } if (coding_scheme == EFUSE_CODING_SCHEME_NONE) { From 06aeeff54e443bcf184b4f2bd57ffd2b3ff2773e Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Thu, 21 Apr 2022 00:44:24 +0800 Subject: [PATCH 5/6] efuse: fix --- components/efuse/esp32/esp_efuse_utility.c | 30 ++++++++----------- .../esp32/private_include/esp_efuse_utility.h | 3 ++ components/efuse/esp32c3/esp_efuse_utility.c | 9 +++--- components/efuse/esp32h2/esp_efuse_utility.c | 12 ++++---- components/efuse/esp32s2/esp_efuse_utility.c | 12 ++++---- components/efuse/esp32s3/esp_efuse_utility.c | 12 ++++---- components/efuse/src/esp_efuse_utility.c | 22 +++++++------- 7 files changed, 48 insertions(+), 52 deletions(-) diff --git a/components/efuse/esp32/esp_efuse_utility.c b/components/efuse/esp32/esp_efuse_utility.c index 4abe61a3cd..56eae3f73f 100644 --- a/components/efuse/esp32/esp_efuse_utility.c +++ b/components/efuse/esp32/esp_efuse_utility.c @@ -14,6 +14,8 @@ static const char *TAG = "efuse"; +#define ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block) ((error_reg) & (0x0F << (4 * (block)))) + #ifdef CONFIG_EFUSE_VIRTUAL extern uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK]; #endif // CONFIG_EFUSE_VIRTUAL @@ -82,22 +84,14 @@ __attribute__((always_inline)) static inline bool efuse_ll_get_dec_warnings(unsi return false; } uint32_t error_reg = REG_GET_FIELD(EFUSE_DEC_STATUS_REG, EFUSE_DEC_WARNINGS); - if (((error_reg >> (4 * (block - 1))) & 0x0F) != 0) { - return true; - } - return false; + return ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block - 1) != 0; } -static bool efuse_hal_is_coding_error_in_block(unsigned block) +bool efuse_hal_is_coding_error_in_block(unsigned block) { - if (block > 0) { - if (esp_efuse_get_coding_scheme(block) == EFUSE_CODING_SCHEME_3_4) { - if (efuse_ll_get_dec_warnings(block)) { - return true; - } - } - } - return false; + return block > 0 && + esp_efuse_get_coding_scheme(block) == EFUSE_CODING_SCHEME_3_4 && + efuse_ll_get_dec_warnings(block); } #endif // ifndef CONFIG_EFUSE_VIRTUAL @@ -139,7 +133,7 @@ esp_err_t esp_efuse_utility_burn_chip(void) #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH esp_efuse_utility_write_efuses_to_flash(); #endif -#else +#else // CONFIG_EFUSE_VIRTUAL if (esp_efuse_set_timing() != ESP_OK) { ESP_LOGE(TAG, "Efuse fields are not burnt"); } else { @@ -167,12 +161,12 @@ esp_err_t esp_efuse_utility_burn_chip(void) unsigned w_data_len; unsigned r_data_len; if (scheme == EFUSE_CODING_SCHEME_3_4) { - esp_efuse_utility_apply_34_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], 24); - r_data_len = 24; + esp_efuse_utility_apply_34_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES); + r_data_len = ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES; w_data_len = 32; } else if (scheme == EFUSE_CODING_SCHEME_REPEAT) { apply_repeat_encoding((void *)range_write_addr_blocks[num_block].start, (uint32_t *)start_write_addr[num_block], 16); - r_data_len = 16; + r_data_len = ESP_EFUSE_LEN_OF_REPEAT_BLOCK_IN_BYTES; w_data_len = 32; } else { r_data_len = (range_read_addr_blocks[num_block].end - range_read_addr_blocks[num_block].start) + sizeof(uint32_t); @@ -298,7 +292,7 @@ esp_err_t esp_efuse_utility_apply_new_coding_scheme() if (*((uint32_t*)buf_w_data + 6) != 0 || *((uint32_t*)buf_w_data + 7) != 0) { return ESP_ERR_CODING; } - for (int i = 0; i < 24; ++i) { + for (int i = 0; i < ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES; ++i) { if (buf_w_data[i] != 0) { int st_offset_buf = (i / 6) * 6; // check that place is free. diff --git a/components/efuse/esp32/private_include/esp_efuse_utility.h b/components/efuse/esp32/private_include/esp_efuse_utility.h index 7916223843..7b88cf7b94 100644 --- a/components/efuse/esp32/private_include/esp_efuse_utility.h +++ b/components/efuse/esp32/private_include/esp_efuse_utility.h @@ -10,6 +10,9 @@ extern "C" { #endif +#define ESP_EFUSE_LEN_OF_3_4_SCHEME_BLOCK_IN_BYTES (24) +#define ESP_EFUSE_LEN_OF_REPEAT_BLOCK_IN_BYTES (16) + #define COUNT_EFUSE_REG_PER_BLOCK 8 /* The number of registers per block. */ #define ESP_EFUSE_SECURE_VERSION_NUM_BLOCK EFUSE_BLK3 diff --git a/components/efuse/esp32c3/esp_efuse_utility.c b/components/efuse/esp32c3/esp_efuse_utility.c index 06f21d4b56..43d536eae4 100644 --- a/components/efuse/esp32c3/esp_efuse_utility.c +++ b/components/efuse/esp32c3/esp_efuse_utility.c @@ -15,6 +15,8 @@ static const char *TAG = "efuse"; +#define ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block) ((error_reg) & (0x0F << (4 * (block)))) + #ifdef CONFIG_EFUSE_VIRTUAL extern uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK]; #endif // CONFIG_EFUSE_VIRTUAL @@ -98,10 +100,7 @@ static bool efuse_hal_is_coding_error_in_block(unsigned block) // EFUSE_RD_RS_ERR1_REG: BLOCK9, BLOCK8 // BLOCK10 is not presented in the error regs. uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 8) * 4); - unsigned offset = (block >= 8) ? block - 8 : block; - if (((error_reg >> (4 * offset)) & 0x0F) != 0) { - return true; - } + return ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block % 8) != 0; } return false; } @@ -130,7 +129,7 @@ esp_err_t esp_efuse_utility_burn_chip(void) #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH esp_efuse_utility_write_efuses_to_flash(); #endif -#else +#else // CONFIG_EFUSE_VIRTUAL if (esp_efuse_set_timing() != ESP_OK) { ESP_LOGE(TAG, "Efuse fields are not burnt"); } else { diff --git a/components/efuse/esp32h2/esp_efuse_utility.c b/components/efuse/esp32h2/esp_efuse_utility.c index 0edb55e02e..aae6038e2f 100644 --- a/components/efuse/esp32h2/esp_efuse_utility.c +++ b/components/efuse/esp32h2/esp_efuse_utility.c @@ -15,6 +15,8 @@ static const char *TAG = "efuse"; +#define ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block) ((error_reg) & (0x0F << (4 * (block)))) + #ifdef CONFIG_EFUSE_VIRTUAL extern uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK]; #endif // CONFIG_EFUSE_VIRTUAL @@ -77,11 +79,9 @@ static bool efuse_hal_is_coding_error_in_block(unsigned block) } else if (block <= 10) { // EFUSE_RD_RS_ERR0_REG: (hi) BLOCK8, BLOCK7, BLOCK6, BLOCK5, BLOCK4, BLOCK3, BLOCK2, BLOCK1 (low) // EFUSE_RD_RS_ERR1_REG: BLOCK10, BLOCK9 - uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 9) * 4); - unsigned offset = (block >= 9) ? block - 9 : block - 1; - if (((error_reg >> (4 * offset)) & 0x0F) != 0) { - return true; - } + block--; + uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 8) * 4); + return ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block % 8) != 0; } return false; } @@ -110,7 +110,7 @@ esp_err_t esp_efuse_utility_burn_chip(void) #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH esp_efuse_utility_write_efuses_to_flash(); #endif -#else +#else // CONFIG_EFUSE_VIRTUAL if (esp_efuse_set_timing() != ESP_OK) { ESP_LOGE(TAG, "Efuse fields are not burnt"); } else { diff --git a/components/efuse/esp32s2/esp_efuse_utility.c b/components/efuse/esp32s2/esp_efuse_utility.c index 7cfb4281e4..79b963fab8 100644 --- a/components/efuse/esp32s2/esp_efuse_utility.c +++ b/components/efuse/esp32s2/esp_efuse_utility.c @@ -15,6 +15,8 @@ static const char *TAG = "efuse"; +#define ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block) ((error_reg) & (0x0F << (4 * (block)))) + #ifdef CONFIG_EFUSE_VIRTUAL extern uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK]; #endif // CONFIG_EFUSE_VIRTUAL @@ -70,11 +72,9 @@ static bool efuse_hal_is_coding_error_in_block(unsigned block) } else if (block <= 10) { // EFUSE_RD_RS_ERR0_REG: (hi) BLOCK8, BLOCK7, BLOCK6, BLOCK5, BLOCK4, BLOCK3, BLOCK2, BLOCK1 (low) // EFUSE_RD_RS_ERR1_REG: BLOCK10, BLOCK9 - uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 9) * 4); - unsigned offset = (block >= 9) ? block - 9 : block - 1; - if (((error_reg >> (4 * offset)) & 0x0F) != 0) { - return true; - } + block--; + uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 8) * 4); + return ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block % 8) != 0; } return false; } @@ -103,7 +103,7 @@ esp_err_t esp_efuse_utility_burn_chip(void) #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH esp_efuse_utility_write_efuses_to_flash(); #endif -#else +#else // CONFIG_EFUSE_VIRTUAL if (esp_efuse_set_timing() != ESP_OK) { ESP_LOGE(TAG, "Efuse fields are not burnt"); } else { diff --git a/components/efuse/esp32s3/esp_efuse_utility.c b/components/efuse/esp32s3/esp_efuse_utility.c index 3dc964ef05..f94efc8506 100644 --- a/components/efuse/esp32s3/esp_efuse_utility.c +++ b/components/efuse/esp32s3/esp_efuse_utility.c @@ -15,6 +15,8 @@ static const char *TAG = "efuse"; +#define ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block) ((error_reg) & (0x0F << (4 * (block)))) + #ifdef CONFIG_EFUSE_VIRTUAL extern uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK]; #endif // CONFIG_EFUSE_VIRTUAL @@ -95,11 +97,9 @@ static bool efuse_hal_is_coding_error_in_block(unsigned block) } else if (block <= 10) { // EFUSE_RD_RS_ERR0_REG: (hi) BLOCK8, BLOCK7, BLOCK6, BLOCK5, BLOCK4, BLOCK3, BLOCK2, BLOCK1 (low) // EFUSE_RD_RS_ERR1_REG: BLOCK10, BLOCK9 - uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 9) * 4); - unsigned offset = (block >= 9) ? block - 9 : block - 1; - if (((error_reg >> (4 * offset)) & 0x0F) != 0) { - return true; - } + block--; + uint32_t error_reg = REG_READ(EFUSE_RD_RS_ERR0_REG + (block / 8) * 4); + return ESP_EFUSE_BLOCK_ERROR_BITS(error_reg, block % 8) != 0; } return false; } @@ -128,7 +128,7 @@ esp_err_t esp_efuse_utility_burn_chip(void) #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH esp_efuse_utility_write_efuses_to_flash(); #endif -#else +#else // CONFIG_EFUSE_VIRTUAL if (esp_efuse_set_timing() != ESP_OK) { ESP_LOGE(TAG, "Efuse fields are not burnt"); } else { diff --git a/components/efuse/src/esp_efuse_utility.c b/components/efuse/src/esp_efuse_utility.c index 0634191ec1..db5b4a9af9 100644 --- a/components/efuse/src/esp_efuse_utility.c +++ b/components/efuse/src/esp_efuse_utility.c @@ -484,19 +484,19 @@ bool esp_efuse_utility_is_correct_written_data(esp_efuse_block_t block, unsigned bool correct_written_data = memcmp(w_data, r_data, r_data_len) == 0; if (correct_written_data) { ESP_LOGI(TAG, "BURN BLOCK%d - OK (write block == read block)", block); - } else { - correct_written_data = true; - for (unsigned i = 0; i < r_data_len / 4; i++) { - if ((*(r_data + i) & *(w_data + i)) != *(w_data + i)) { - correct_written_data = false; - break; - } - } - if (correct_written_data) { - ESP_LOGI(TAG, "BURN BLOCK%d - OK (all write block bits are set)", block); + return true; + } + + correct_written_data = true; + for (unsigned i = 0; i < r_data_len / 4; i++) { + if ((*(r_data + i) & *(w_data + i)) != *(w_data + i)) { + correct_written_data = false; + break; } } - if (!correct_written_data) { + if (correct_written_data) { + ESP_LOGI(TAG, "BURN BLOCK%d - OK (all write block bits are set)", block); + } else { ESP_LOGE(TAG, "BURN BLOCK%d - ERROR (written bits != read bits)", block); } return correct_written_data; From 18fb3d60b8a1dc923affa08b30735601e10a3857 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Tue, 10 May 2022 17:13:35 +0800 Subject: [PATCH 6/6] Apply 1 suggestion(s) to 1 file(s) --- components/efuse/esp32/esp_efuse_utility.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/efuse/esp32/esp_efuse_utility.c b/components/efuse/esp32/esp_efuse_utility.c index 56eae3f73f..c226936bdc 100644 --- a/components/efuse/esp32/esp_efuse_utility.c +++ b/components/efuse/esp32/esp_efuse_utility.c @@ -269,7 +269,7 @@ static void read_r_data(esp_efuse_block_t num_block, uint32_t* buf_r_data) } } -// This function just checkes that given data for blocks will not rise a coding issue during the burn operation. +// This function just checks that given data for blocks will not raise a coding issue during the burn operation. // Encoded data will be set during the burn operation. esp_err_t esp_efuse_utility_apply_new_coding_scheme() {