mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/efuse_reading_wo_locks' into 'master'
efuse: Burn operation does not block reading See merge request espressif/esp-idf!11683
This commit is contained in:
commit
298729b904
@ -474,6 +474,13 @@ UT_006:
|
||||
- UT_T1_SPIMODE
|
||||
- psram
|
||||
|
||||
UT_007:
|
||||
extends: .unit_test_esp32_template
|
||||
parallel: 2
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
|
||||
UT_008:
|
||||
extends: .unit_test_esp32_template
|
||||
tags:
|
||||
|
@ -72,7 +72,7 @@ void esp_efuse_utility_clear_program_registers(void)
|
||||
}
|
||||
|
||||
// Burn values written to the efuse write registers
|
||||
void esp_efuse_utility_burn_efuses(void)
|
||||
void esp_efuse_utility_burn_chip(void)
|
||||
{
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses");
|
||||
|
@ -75,7 +75,7 @@ void esp_efuse_utility_clear_program_registers(void)
|
||||
}
|
||||
|
||||
// Burn values written to the efuse write registers
|
||||
void esp_efuse_utility_burn_efuses(void)
|
||||
void esp_efuse_utility_burn_chip(void)
|
||||
{
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses");
|
||||
|
@ -68,7 +68,7 @@ void esp_efuse_utility_clear_program_registers(void)
|
||||
}
|
||||
|
||||
// Burn values written to the efuse write registers
|
||||
void esp_efuse_utility_burn_efuses(void)
|
||||
void esp_efuse_utility_burn_chip(void)
|
||||
{
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses");
|
||||
|
@ -68,7 +68,7 @@ void esp_efuse_utility_clear_program_registers(void)
|
||||
}
|
||||
|
||||
// Burn values written to the efuse write registers
|
||||
void esp_efuse_utility_burn_efuses(void)
|
||||
void esp_efuse_utility_burn_chip(void)
|
||||
{
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses");
|
||||
|
@ -33,6 +33,7 @@ extern "C" {
|
||||
#define ESP_ERR_EFUSE_REPEATED_PROG (ESP_ERR_EFUSE + 0x03) /*!< Error repeated programming of programmed bits is strictly forbidden. */
|
||||
#define ESP_ERR_CODING (ESP_ERR_EFUSE + 0x04) /*!< Error while a encoding operation. */
|
||||
#define ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS (ESP_ERR_EFUSE + 0x05) /*!< Error not enough unused key blocks available */
|
||||
#define ESP_ERR_DAMAGED_READING (ESP_ERR_EFUSE + 0x06) /*!< Error. Burn or reset was done during a reading operation leads to damage read data. This error is internal to the efuse component and not returned by any public API. */
|
||||
|
||||
/**
|
||||
* @brief Type definition for an eFuse field
|
||||
|
@ -96,6 +96,16 @@ esp_err_t esp_efuse_utility_fill_buff(unsigned int num_reg, esp_efuse_block_t ef
|
||||
*/
|
||||
void esp_efuse_utility_burn_efuses(void);
|
||||
|
||||
/**
|
||||
* @brief Chip specific operations to perform the burn of values written to the efuse write registers.
|
||||
*
|
||||
* @note Use esp_efuse_utility_burn_efuses() to burn efuses.
|
||||
*
|
||||
* If CONFIG_EFUSE_VIRTUAL is set, writing will not be performed.
|
||||
* After the function is completed, the writing registers are cleared.
|
||||
*/
|
||||
void 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".
|
||||
*/
|
||||
|
@ -17,6 +17,8 @@ const static char *TAG = "efuse";
|
||||
#define EFUSE_LOCK_ACQUIRE_RECURSIVE()
|
||||
#define EFUSE_LOCK_RELEASE_RECURSIVE()
|
||||
#else
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include <sys/lock.h>
|
||||
static _lock_t s_efuse_lock;
|
||||
#define EFUSE_LOCK_ACQUIRE_RECURSIVE() _lock_acquire_recursive(&s_efuse_lock)
|
||||
@ -30,15 +32,20 @@ static int s_batch_writing_mode = 0;
|
||||
// read value from EFUSE, writing it into an array
|
||||
esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst, size_t dst_size_bits)
|
||||
{
|
||||
EFUSE_LOCK_ACQUIRE_RECURSIVE();
|
||||
esp_err_t err = ESP_OK;
|
||||
if (field == NULL || dst == NULL || dst_size_bits == 0) {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
memset((uint8_t *)dst, 0, esp_efuse_utility_get_number_of_items(dst_size_bits, 8));
|
||||
err = esp_efuse_utility_process(field, dst, dst_size_bits, esp_efuse_utility_fill_buff);
|
||||
do {
|
||||
memset((uint8_t *)dst, 0, esp_efuse_utility_get_number_of_items(dst_size_bits, 8));
|
||||
err = esp_efuse_utility_process(field, dst, dst_size_bits, esp_efuse_utility_fill_buff);
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
if (err == ESP_ERR_DAMAGED_READING) {
|
||||
vTaskDelay(1);
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
} while (err == ESP_ERR_DAMAGED_READING);
|
||||
}
|
||||
EFUSE_LOCK_RELEASE_RECURSIVE();
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -53,15 +60,20 @@ bool esp_efuse_read_field_bit(const esp_efuse_desc_t *field[])
|
||||
// read number of bits programmed as "1" in the particular field
|
||||
esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_cnt)
|
||||
{
|
||||
EFUSE_LOCK_ACQUIRE_RECURSIVE();
|
||||
esp_err_t err = ESP_OK;
|
||||
if (field == NULL || out_cnt == NULL) {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
*out_cnt = 0;
|
||||
err = esp_efuse_utility_process(field, out_cnt, 0, esp_efuse_utility_count_once);
|
||||
do {
|
||||
*out_cnt = 0;
|
||||
err = esp_efuse_utility_process(field, out_cnt, 0, esp_efuse_utility_count_once);
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
if (err == ESP_ERR_DAMAGED_READING) {
|
||||
vTaskDelay(1);
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
} while (err == ESP_ERR_DAMAGED_READING);
|
||||
}
|
||||
EFUSE_LOCK_RELEASE_RECURSIVE();
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -163,9 +175,10 @@ int esp_efuse_get_field_size(const esp_efuse_desc_t* field[])
|
||||
// reading efuse register.
|
||||
uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg)
|
||||
{
|
||||
EFUSE_LOCK_ACQUIRE_RECURSIVE();
|
||||
uint32_t ret_val = esp_efuse_utility_read_reg(blk, num_reg);
|
||||
EFUSE_LOCK_RELEASE_RECURSIVE();
|
||||
uint32_t ret_val = 0;
|
||||
esp_err_t err = esp_efuse_read_block(blk, &ret_val, num_reg * 32, 32);
|
||||
assert(err == ESP_OK);
|
||||
(void)err;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,11 @@
|
||||
|
||||
static const char *TAG = "efuse";
|
||||
|
||||
// This counter is used to implement independent read access for efuses.
|
||||
// During the read operation, the counter should be unchanged and even.
|
||||
// If it is not so, we must repeat the read to make sure that the burn operation does not affect the read data.
|
||||
static volatile unsigned s_burn_counter = 0;
|
||||
|
||||
// Array for emulate efuse registers.
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK];
|
||||
@ -50,6 +55,7 @@ esp_err_t esp_efuse_utility_process(const esp_efuse_desc_t* field[], void* ptr,
|
||||
int req_size = (ptr_size_bits == 0) ? field_len : MIN(ptr_size_bits, field_len);
|
||||
|
||||
int i = 0;
|
||||
unsigned count_before = s_burn_counter;
|
||||
while (err == ESP_OK && req_size > bits_counter && field[i] != NULL) {
|
||||
if (check_range_of_bits(field[i]->efuse_block, field[i]->bit_start, field[i]->bit_count) == false) {
|
||||
ESP_EARLY_LOGE(TAG, "Range of data does not match the coding scheme");
|
||||
@ -72,6 +78,12 @@ esp_err_t esp_efuse_utility_process(const esp_efuse_desc_t* field[], void* ptr,
|
||||
}
|
||||
i++;
|
||||
}
|
||||
unsigned count_after = s_burn_counter;
|
||||
if (err == ESP_OK &&
|
||||
(func_proc == esp_efuse_utility_fill_buff || func_proc == esp_efuse_utility_count_once) && // these functions are used for read APIs: read_field_blob and read_field_cnt
|
||||
(count_before != count_after || (count_after & 1) == 1)) {
|
||||
err = ESP_ERR_DAMAGED_READING;
|
||||
}
|
||||
assert(bits_counter <= req_size);
|
||||
return err;
|
||||
}
|
||||
@ -141,7 +153,9 @@ esp_err_t esp_efuse_utility_write_cnt(unsigned int num_reg, esp_efuse_block_t ef
|
||||
// Reset efuse write registers
|
||||
void esp_efuse_utility_reset(void)
|
||||
{
|
||||
++s_burn_counter;
|
||||
esp_efuse_utility_clear_program_registers();
|
||||
++s_burn_counter;
|
||||
for (int num_block = EFUSE_BLK0; num_block < EFUSE_BLK_MAX; 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) {
|
||||
REG_WRITE(addr_wr_block, 0);
|
||||
@ -149,6 +163,14 @@ void esp_efuse_utility_reset(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Burn values written to the efuse write registers
|
||||
void esp_efuse_utility_burn_efuses(void)
|
||||
{
|
||||
++s_burn_counter;
|
||||
esp_efuse_utility_burn_chip();
|
||||
++s_burn_counter;
|
||||
}
|
||||
|
||||
// Erase the virt_blocks array.
|
||||
void esp_efuse_utility_erase_virt_blocks(void)
|
||||
{
|
||||
|
@ -669,7 +669,7 @@ static void task2(void* arg)
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &mac, sizeof(mac) * 8));
|
||||
int64_t t2 = esp_timer_get_time();
|
||||
int diff_ms = (t2 - t1) / 1000;
|
||||
TEST_ASSERT_GREATER_THAN(delay_ms, diff_ms);
|
||||
TEST_ASSERT_GREATER_THAN(diff_ms, delay_ms);
|
||||
ESP_LOGI(TAG, "read MAC address: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
xSemaphoreGive(sema);
|
||||
|
||||
@ -788,8 +788,100 @@ TEST_CASE("Test a write/read protection", "[efuse]")
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
}
|
||||
|
||||
static volatile bool cmd_stop_reset_task1;
|
||||
static void efuse_burn_task(void* arg)
|
||||
{
|
||||
SemaphoreHandle_t sema = (SemaphoreHandle_t) arg;
|
||||
ESP_LOGI(TAG, "Start burn task");
|
||||
size_t test3_len_6 = 2;
|
||||
while (!cmd_stop_reset_task1) {
|
||||
esp_efuse_utility_update_virt_blocks();
|
||||
esp_efuse_utility_reset();
|
||||
TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, test3_len_6));
|
||||
}
|
||||
xSemaphoreGive(sema);
|
||||
ESP_LOGI(TAG, "Stop burn task");
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void efuse_read_task(void* arg)
|
||||
{
|
||||
SemaphoreHandle_t sema = (SemaphoreHandle_t) arg;
|
||||
ESP_LOGI(TAG, "Start read task");
|
||||
size_t test3_len_6 = 0;
|
||||
while (!cmd_stop_reset_task1) {
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST3_LEN_6, &test3_len_6, 6));
|
||||
}
|
||||
xSemaphoreGive(sema);
|
||||
ESP_LOGI(TAG, "Stop read task");
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Check a case when ESP_ERR_DAMAGED_READING occurs and read and burn are not blocked", "[efuse]")
|
||||
{
|
||||
cmd_stop_reset_task1 = false;
|
||||
TaskHandle_t read_task_hdl;
|
||||
xSemaphoreHandle sema[2];
|
||||
sema[0] = xSemaphoreCreateBinary();
|
||||
sema[1] = xSemaphoreCreateBinary();
|
||||
|
||||
esp_efuse_utility_update_virt_blocks();
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
xTaskCreatePinnedToCore(efuse_burn_task, "efuse_burn_task", 3072, sema[0], 2, NULL, 0);
|
||||
xTaskCreatePinnedToCore(efuse_read_task, "efuse_read_task", 3072, sema[1], 2, &read_task_hdl, 0);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
for (unsigned i = 1; i < 30; ++i) {
|
||||
vTaskPrioritySet(read_task_hdl, 2 + i % 2);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
cmd_stop_reset_task1 = true;
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
TEST_ASSERT_EQUAL(pdPASS, xSemaphoreTake(sema[0], 1000 / portTICK_PERIOD_MS));
|
||||
TEST_ASSERT_EQUAL(pdPASS, xSemaphoreTake(sema[1], 1000 / portTICK_PERIOD_MS));
|
||||
|
||||
vSemaphoreDelete(sema[0]);
|
||||
vSemaphoreDelete(sema[1]);
|
||||
}
|
||||
#endif // #ifdef CONFIG_EFUSE_VIRTUAL
|
||||
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
static volatile bool cmd_stop_reset_task;
|
||||
static void reset_task(void* arg)
|
||||
{
|
||||
ESP_LOGI(TAG, "Start reset task");
|
||||
while (!cmd_stop_reset_task) {
|
||||
esp_efuse_utility_reset();
|
||||
vTaskDelay(1);
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Check a case when ESP_ERR_DAMAGED_READING occurs during reading efuses", "[efuse]")
|
||||
{
|
||||
cmd_stop_reset_task = false;
|
||||
esp_efuse_utility_update_virt_blocks();
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
uint8_t mac[6];
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &mac, sizeof(mac) * 8));
|
||||
ESP_LOGI(TAG, "read MAC address: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
xTaskCreatePinnedToCore(reset_task, "reset_task", 3072, NULL, UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
|
||||
|
||||
uint8_t new_mac[6];
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &new_mac, sizeof(new_mac) * 8));
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(mac, new_mac, sizeof(mac));
|
||||
}
|
||||
cmd_stop_reset_task = true;
|
||||
ESP_LOGI(TAG, "read new MAC address: %02x:%02x:%02x:%02x:%02x:%02x", new_mac[0], new_mac[1], new_mac[2], new_mac[3], new_mac[4], new_mac[5]);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
#endif // if not CONFIG_FREERTOS_UNICORE
|
||||
|
||||
#ifdef CONFIG_IDF_ENV_FPGA
|
||||
TEST_CASE("Test a real write (FPGA)", "[efuse]")
|
||||
{
|
||||
|
@ -296,6 +296,13 @@ static const esp_err_msg_t esp_err_msg_table[] = {
|
||||
# endif
|
||||
# ifdef ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS
|
||||
ERR_TBL_IT(ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS), /* 5637 0x1605 Error not enough unused key blocks available */
|
||||
# endif
|
||||
# ifdef ESP_ERR_DAMAGED_READING
|
||||
ERR_TBL_IT(ESP_ERR_DAMAGED_READING), /* 5638 0x1606 Error. Burn or reset was done during a
|
||||
reading operation leads to damage read
|
||||
data. This error is internal to the
|
||||
efuse component and not returned by any
|
||||
public API. */
|
||||
# endif
|
||||
// components/bootloader_support/include/esp_image_format.h
|
||||
# ifdef ESP_ERR_IMAGE_BASE
|
||||
|
@ -3,3 +3,4 @@ CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0x9000
|
||||
|
5
tools/test_apps/system/startup/sdkconfig.ci.verbose_log
Normal file
5
tools/test_apps/system/startup/sdkconfig.ci.verbose_log
Normal file
@ -0,0 +1,5 @@
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE=y
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL=5
|
||||
CONFIG_LOG_DEFAULT_LEVEL_VERBOSE=y
|
||||
CONFIG_LOG_DEFAULT_LEVEL=5
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0x9000
|
Loading…
x
Reference in New Issue
Block a user