efuse: Add API efuse
Added support 3/4 coding scheme
This commit is contained in:
committed by
bot
parent
91676b8620
commit
693a5c209b
@@ -0,0 +1,214 @@
|
||||
// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_utility.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "assert.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
const static char *TAG = "efuse";
|
||||
|
||||
#if defined(BOOTLOADER_BUILD)
|
||||
#define EFUSE_LOCK_ACQUIRE()
|
||||
#define EFUSE_LOCK_RELEASE()
|
||||
#else
|
||||
#include <sys/lock.h>
|
||||
static _lock_t s_efuse_lock;
|
||||
#define EFUSE_LOCK_ACQUIRE() _lock_acquire(&s_efuse_lock)
|
||||
#define EFUSE_LOCK_RELEASE() _lock_release(&s_efuse_lock)
|
||||
#endif
|
||||
|
||||
// Public API functions
|
||||
|
||||
// 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();
|
||||
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);
|
||||
}
|
||||
EFUSE_LOCK_RELEASE();
|
||||
return err;
|
||||
}
|
||||
|
||||
// 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();
|
||||
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);
|
||||
}
|
||||
EFUSE_LOCK_RELEASE();
|
||||
return err;
|
||||
}
|
||||
|
||||
// write array to EFUSE
|
||||
esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void* src, size_t src_size_bits)
|
||||
{
|
||||
EFUSE_LOCK_ACQUIRE();
|
||||
esp_err_t err = ESP_OK;
|
||||
if (field == NULL || src == NULL || src_size_bits == 0) {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
esp_efuse_utility_reset();
|
||||
err = esp_efuse_utility_process(field, (void*)src, src_size_bits, esp_efuse_utility_write_blob);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
err = esp_efuse_utility_apply_new_coding_scheme();
|
||||
if (err == ESP_OK) {
|
||||
esp_efuse_utility_burn_efuses();
|
||||
}
|
||||
}
|
||||
esp_efuse_utility_reset();
|
||||
}
|
||||
EFUSE_LOCK_RELEASE();
|
||||
return err;
|
||||
}
|
||||
|
||||
// program cnt bits to "1"
|
||||
esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt)
|
||||
{
|
||||
EFUSE_LOCK_ACQUIRE();
|
||||
esp_err_t err = ESP_OK;
|
||||
if (field == NULL || cnt == 0) {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
esp_efuse_utility_reset();
|
||||
err = esp_efuse_utility_process(field, &cnt, 0, esp_efuse_utility_write_cnt);
|
||||
|
||||
if (cnt != 0) {
|
||||
ESP_LOGE(TAG, "The required number of bits can not be set. [Not set %d]", cnt);
|
||||
err = ESP_ERR_EFUSE_CNT_IS_FULL;
|
||||
}
|
||||
|
||||
if (err == ESP_OK_EFUSE_CNT || err == ESP_OK) {
|
||||
err = esp_efuse_utility_apply_new_coding_scheme();
|
||||
if (err == ESP_OK) {
|
||||
esp_efuse_utility_burn_efuses();
|
||||
}
|
||||
}
|
||||
esp_efuse_utility_reset();
|
||||
}
|
||||
EFUSE_LOCK_RELEASE();
|
||||
return err;
|
||||
}
|
||||
|
||||
// get the length of the field in bits
|
||||
int esp_efuse_get_field_size(const esp_efuse_desc_t* field[])
|
||||
{
|
||||
assert(field != NULL);
|
||||
int bits_counter = 0;
|
||||
int i = 0;
|
||||
while (field[i] != NULL) {
|
||||
bits_counter += field[i]->bit_count;
|
||||
++i;
|
||||
}
|
||||
return bits_counter;
|
||||
}
|
||||
|
||||
// reading efuse register.
|
||||
uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg)
|
||||
{
|
||||
EFUSE_LOCK_ACQUIRE();
|
||||
uint32_t ret_val = esp_efuse_utility_read_reg(blk, num_reg);
|
||||
EFUSE_LOCK_RELEASE();
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
// writing efuse register.
|
||||
esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t val)
|
||||
{
|
||||
EFUSE_LOCK_ACQUIRE();
|
||||
esp_efuse_utility_reset();
|
||||
esp_err_t err = esp_efuse_utility_write_reg(blk, num_reg, val);
|
||||
if (err == ESP_OK) {
|
||||
err = esp_efuse_utility_apply_new_coding_scheme();
|
||||
if (err == ESP_OK) {
|
||||
esp_efuse_utility_burn_efuses();
|
||||
}
|
||||
}
|
||||
esp_efuse_utility_reset();
|
||||
EFUSE_LOCK_RELEASE();
|
||||
return err;
|
||||
}
|
||||
|
||||
// get efuse coding_scheme.
|
||||
esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk)
|
||||
{
|
||||
esp_efuse_coding_scheme_t scheme;
|
||||
if (blk == EFUSE_BLK0) {
|
||||
scheme = EFUSE_CODING_SCHEME_NONE;
|
||||
} else {
|
||||
uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME);
|
||||
if (coding_scheme == EFUSE_CODING_SCHEME_VAL_NONE ||
|
||||
coding_scheme == (EFUSE_CODING_SCHEME_VAL_34 | EFUSE_CODING_SCHEME_VAL_REPEAT)) {
|
||||
scheme = EFUSE_CODING_SCHEME_NONE;
|
||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_VAL_34) {
|
||||
scheme = EFUSE_CODING_SCHEME_3_4;
|
||||
} else {
|
||||
scheme = EFUSE_CODING_SCHEME_REPEAT;
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "coding scheme %d", scheme);
|
||||
return scheme;
|
||||
}
|
||||
|
||||
// This function reads the key from the efuse block, starting at the offset and the required size.
|
||||
esp_err_t esp_efuse_read_block(esp_efuse_block_t blk, void* dst_key, size_t offset_in_bits, size_t size_bits)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
if (blk == EFUSE_BLK0 || blk > EFUSE_BLK3 || dst_key == NULL || size_bits == 0) {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
const esp_efuse_desc_t field_desc[] = {
|
||||
{blk, offset_in_bits, size_bits},
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* field[] = {
|
||||
&field_desc[0],
|
||||
NULL
|
||||
};
|
||||
err = esp_efuse_read_field_blob(field, dst_key, size_bits);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// This function writes the key from the efuse block, starting at the offset and the required size.
|
||||
esp_err_t esp_efuse_write_block(esp_efuse_block_t blk, const void* src_key, size_t offset_in_bits, size_t size_bits)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
if (blk == EFUSE_BLK0 || blk > EFUSE_BLK3 || src_key == NULL || size_bits == 0) {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
const esp_efuse_desc_t field_desc[] = {
|
||||
{blk, offset_in_bits, size_bits},
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* field[] = {
|
||||
&field_desc[0],
|
||||
NULL
|
||||
};
|
||||
err = esp_efuse_write_field_blob(field, src_key, size_bits);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
Reference in New Issue
Block a user