efuse: Fix make/cmake build systems and docs

This commit is contained in:
Konstantin Kondrashov 2018-12-06 17:49:02 +08:00 committed by bot
parent 9822055851
commit b8141f3ad8
12 changed files with 325 additions and 303 deletions

View File

@ -18,43 +18,24 @@ register_component()
set(GEN_EFUSE_TABLE_ARG --coding_scheme ${CONFIG_EFUSE_CODE_SCHEME})
if(CONFIG_EFUSE_CUSTOM_TABLE_USE_BLK1)
list(APPEND GEN_EFUSE_TABLE_ARG --custom_table_use_BLK1)
endif()
if(CONFIG_EFUSE_CUSTOM_TABLE_USE_BLK2)
list(APPEND GEN_EFUSE_TABLE_ARG --custom_table_use_BLK2)
endif()
if(CONFIG_EFUSE_COMMON_TABLE_FIX_SIZE_BLK1_BLK2_DEP_ON_CODE_SCHEME)
list(APPEND GEN_EFUSE_TABLE_ARG --common_table_fix_size_secure_key_and_encrypt_key)
endif()
###################
# Make common files esp_efuse_table.c and include/esp_efuse_table.h files.
set(EFUSE_COMMON_TABLE_CSV_PATH "${COMPONENT_PATH}/${SOC_NAME}/esp_efuse_table.csv")
set(EFUSE_COMMON_TABLE_OUT_PATH "${COMPONENT_PATH}/${SOC_NAME}/esp_efuse_table.c")
add_custom_target(efuse_common_table COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/efuse_table_gen.py" ${EFUSE_COMMON_TABLE_CSV_PATH} ${GEN_EFUSE_TABLE_ARG})
###################
# Make custom files project/main/esp_efuse_custom_table.c and project/main/include/esp_efuse_custom_table.h files.
# Path to CSV file is relative to project path for custom CSV files.
if(${CONFIG_EFUSE_CUSTOM_TABLE})
# Custom filename expands any path relative to the project
get_filename_component(EFUSE_CUSTOM_TABLE_CSV_PATH "${CONFIG_EFUSE_CUSTOM_TABLE_FILENAME}" ABSOLUTE BASE_DIR "${PROJECT_PATH}")
string(REPLACE ".csv" ".c" EFUSE_CUSTOM_TABLE_OUT_PATH ${EFUSE_CUSTOM_TABLE_CSV_PATH})
get_filename_component(EFUSE_CUSTOM_TABLE_CSV_PATH "${CONFIG_EFUSE_CUSTOM_TABLE_FILENAME}" ABSOLUTE BASE_DIR "${IDF_PROJECT_PATH}")
add_custom_target(efuse_custom_table COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/efuse_table_gen.py" ${EFUSE_COMMON_TABLE_CSV_PATH} ${EFUSE_CUSTOM_TABLE_CSV_PATH} ${GEN_EFUSE_TABLE_ARG})
else()
add_custom_target(efuse_custom_table COMMAND)
endif()#if(${CONFIG_EFUSE_CUSTOM_TABLE})
set(GENERATED_SRC ${EFUSE_COMMON_TABLE_OUT_PATH} ${EFUSE_CUSTOM_TABLE_OUT_PATH})
set_source_files_properties(GENERATED_SRC PROPERTIES SYMBOLIC true)
add_custom_command(
OUTPUT GENERATED_OUTPUT
BYPRODUCTS ${GENERATED_SRC}
COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/efuse_table_gen.py"
${EFUSE_COMMON_TABLE_CSV_PATH} ${EFUSE_CUSTOM_TABLE_CSV_PATH} ${GEN_EFUSE_TABLE_ARG}
DEPENDS "${EFUSE_COMMON_TABLE_CSV_PATH}" "${EFUSE_CUSTOM_TABLE_CSV_PATH}" "${SDKCONFIG_CMAKE}"
VERBATIM)
add_custom_target(GENERATED_SRC DEPENDS GENERATED_OUTPUT ${GENERATED_SRC})
add_custom_target(show_efuse_table COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/efuse_table_gen.py" ${EFUSE_COMMON_TABLE_CSV_PATH} ${EFUSE_CUSTOM_TABLE_CSV_PATH} ${GEN_EFUSE_TABLE_ARG} "--info")
###################
# Generates files for unit test. This command is run manually.

View File

@ -40,24 +40,4 @@ config EFUSE_CODE_SCHEME
default 1 if EFUSE_CODE_SCHEME_STATE_3_4
default 2 if EFUSE_CODE_SCHEME_STATE_REPEAT
config EFUSE_CUSTOM_TABLE_USE_BLK1
bool "Use EFUSE_BLK1 for custom purpose"
default n
help
If this option is set then ENCRYPT_FLASH_KEY field from EFUSE_BLK1 [0..192/255] can not be used anymore.
ENCRYPT_FLASH_KEY field will contain 0 bits.
config EFUSE_CUSTOM_TABLE_USE_BLK2
bool "Use EFUSE_BLK2 for custom purpose"
default n
help
If this option is set then SECURE_BOOT_KEY field from EFUSE_BLK2 [0..192/255] can not be used anymore.
SECURE_BOOT_KEY field will contain 0 bits.
config EFUSE_COMMON_TABLE_FIX_SIZE_BLK1_BLK2_DEP_ON_CODE_SCHEME
bool "Limit size BLK1 and BLK2 if coding scheme is changed"
default y
help
efuse_table_gen.py tool will change size two fields: SECURE_BOOT_KEY and ENCRYPT_FLASH_KEY if they have not much coding scheme with a description in csv file.
endmenu

View File

@ -1,57 +1,47 @@
#
# eFuse Manager ganeretes header file.
#
# .PHONY: efuse_table efuse_test_table show_efuse_table
.PHONY: efuse_custom_table efuse_common_table efuse_test_table show_efuse_table
GEN_TOOL := $(COMPONENT_PATH)/efuse_table_gen.py
GEN_EFUSE_TABLE := $(PYTHON) $(GEN_TOOL)
GEN_EFUSE_TABLE := $(PYTHON) $(COMPONENT_PATH)/efuse_table_gen.py
GEN_EFUSE_TABLE_ARG := --coding_scheme $(CONFIG_EFUSE_CODE_SCHEME)
ifdef CONFIG_EFUSE_CUSTOM_TABLE_USE_BLK1
GEN_EFUSE_TABLE_ARG += --custom_table_use_BLK1
endif
ifdef CONFIG_EFUSE_CUSTOM_TABLE_USE_BLK2
GEN_EFUSE_TABLE_ARG += --custom_table_use_BLK2
endif
ifdef CONFIG_EFUSE_COMMON_TABLE_FIX_SIZE_BLK1_BLK2_DEP_ON_CODE_SCHEME
GEN_EFUSE_TABLE_ARG += --common_table_fix_size_secure_key_and_encrypt_key
endif
###################
# Make common files esp_efuse_table.c and include/esp_efuse_table.h files.
SOC_NAME := $(IDF_TARGET)
EFUSE_COMMON_TABLE_CSV_PATH := $(COMPONENT_PATH)/$(SOC_NAME)/esp_efuse_table.csv
EFUSE_COMMON_TABLE_OUT_PATH := $(COMPONENT_PATH)/$(SOC_NAME)/esp_efuse_table.c
efuse_common_table:
@echo "COMMON_TABLE_CSV: $(EFUSE_COMMON_TABLE_CSV_PATH)"
$(GEN_EFUSE_TABLE) $(EFUSE_COMMON_TABLE_CSV_PATH) $(GEN_EFUSE_TABLE_ARG)
###################
# Make custom files project/main/esp_efuse_custom_table.c and project/main/include/esp_efuse_custom_table.h files.
ifdef CONFIG_EFUSE_CUSTOM_TABLE
# Path to CSV file is relative to project path for custom CSV files.
EFUSE_CUSTOM_TABLE_CSV_PATH := $(call dequote,$(abspath $(call dequote, $(PROJECT_PATH))/$(call dequote,$(CONFIG_EFUSE_CUSTOM_TABLE_FILENAME))))
EFUSE_CUSTOM_TABLE_OUT_PATH_CSV := $(call dequote,$(abspath $(call dequote, $(PROJECT_PATH))/$(call dequote,$(CONFIG_EFUSE_CUSTOM_TABLE_FILENAME))))
EFUSE_CUSTOM_TABLE_OUT_PATH := $(EFUSE_CUSTOM_TABLE_OUT_PATH_CSV:.csv=.c)
efuse_custom_table:
@echo "COMMON_TABLE_CSV: $(EFUSE_COMMON_TABLE_CSV_PATH)"
@echo "CUSTOM_TABLE_CSV: $(EFUSE_CUSTOM_TABLE_CSV_PATH)"
$(GEN_EFUSE_TABLE) $(EFUSE_COMMON_TABLE_CSV_PATH) $(EFUSE_CUSTOM_TABLE_CSV_PATH) $(GEN_EFUSE_TABLE_ARG)
else
efuse_custom_table:
EFUSE_CUSTOM_TABLE_CSV_PATH :=
EFUSE_CUSTOM_TABLE_OUT_PATH :=
endif # ifdef CONFIG_EFUSE_CUSTOM_TABLE
efuse_table: $(EFUSE_COMMON_TABLE_OUT_PATH) $(EFUSE_CUSTOM_TABLE_OUT_PATH)
$(EFUSE_COMMON_TABLE_OUT_PATH): $(EFUSE_COMMON_TABLE_CSV_PATH) $(SDKCONFIG_MAKEFILE)
@echo "COMMON_TABLE_CSV: $(EFUSE_COMMON_TABLE_CSV_PATH)"
$(GEN_EFUSE_TABLE) $(EFUSE_COMMON_TABLE_CSV_PATH) $(GEN_EFUSE_TABLE_ARG)
$(EFUSE_CUSTOM_TABLE_OUT_PATH): $(EFUSE_CUSTOM_TABLE_CSV_PATH) $(SDKCONFIG_MAKEFILE)
@echo "CUSTOM_TABLE_CSV: $(EFUSE_CUSTOM_TABLE_CSV_PATH)"
$(GEN_EFUSE_TABLE) $(EFUSE_COMMON_TABLE_CSV_PATH) $(EFUSE_CUSTOM_TABLE_CSV_PATH) $(GEN_EFUSE_TABLE_ARG)
###################
# print to console efuse table
show_efuse_table:
$(GEN_EFUSE_TABLE) $(EFUSE_COMMON_TABLE_CSV_PATH) $(EFUSE_CUSTOM_TABLE_CSV_PATH) $(GEN_EFUSE_TABLE_ARG) --info
###################
# Generates files for unit test. This command is run manually.
EFUSE_TEST_TABLE_CSV_PATH := $(COMPONENT_PATH)/test/esp_efuse_test_table.csv

View File

@ -31,14 +31,11 @@ __version__ = '1.0'
quiet = False
coding_scheme = 0
custom_table_use_BLK1 = False
custom_table_use_BLK2 = False
common_table_fix_size = False
CODE_SCHEME = {
"NONE" : 0,
"3/4" : 1,
"REPEAT" : 2,
"NONE" : 0,
"3/4" : 1,
"REPEAT" : 2,
}
copyright = '''// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
@ -61,25 +58,27 @@ def status(msg):
if not quiet:
critical(msg)
def critical(msg):
""" Print critical message to stderr """
sys.stderr.write(msg)
sys.stderr.write('\n')
class FuseTable(list):
def __init__(self):
super(FuseTable, self).__init__(self)
self.md5_digest_table = ""
@classmethod
def from_csv(cls, csv_contents, type_table):
def from_csv(cls, csv_contents):
res = FuseTable()
lines = csv_contents.splitlines()
def expand_vars(f):
f = os.path.expandvars(f)
m = re.match(r'(?<!\\)\$([A-Za-z_][A-Za-z0-9_]*)', f)
if m:
raise InputError("unknown variable '%s'" % m.group(1))
raise InputError("unknown variable '%s'" % (m.group(1)))
return f
for line_no in range(len(lines)):
@ -89,9 +88,9 @@ class FuseTable(list):
try:
res.append(FuseDefinition.from_csv(line))
except InputError as e:
raise InputError("Error at line %d: %s" % (line_no+1, e))
raise InputError("Error at line %d: %s" % (line_no + 1, e))
except Exception:
critical("Unexpected error parsing line %d: %s" % (line_no+1, line))
critical("Unexpected error parsing line %d: %s" % (line_no + 1, line))
raise
# fix up missing bit_start
@ -111,14 +110,14 @@ class FuseTable(list):
last_field = None
for e in res:
if e.field_name == "" and last_field is None:
raise InputError("Error at line %d: %s missing field name" % (line_no+1, e))
raise InputError("Error at line %d: %s missing field name" % (line_no + 1, e))
elif e.field_name == "" and last_field is not None:
e.field_name = last_field.field_name
last_field = e
# fill group
names = [ p.field_name for p in res ]
duplicates = set( n for n in names if names.count(n) > 1 )
names = [p.field_name for p in res]
duplicates = set(n for n in names if names.count(n) > 1)
if len(duplicates) != 0:
i_count = 0
for p in res:
@ -129,13 +128,6 @@ class FuseTable(list):
i_count = 0
res.verify_duplicate_name()
# fix size due to coding scheme
if type_table == "common_table":
if common_table_fix_size == True and (custom_table_use_BLK1 == False or custom_table_use_BLK2 == False):
res.fix_size_fields_from_blk1_blk2();
if custom_table_use_BLK1 == True or custom_table_use_BLK2 == True:
res.keys_from_blk1_blk2_make_empty();
# clac md5 for table
res.calc_md5()
@ -143,8 +135,8 @@ class FuseTable(list):
def verify_duplicate_name(self):
# check on duplicate name
names = [ p.field_name for p in self ]
duplicates = set( n for n in names if names.count(n) > 1 )
names = [p.field_name for p in self]
duplicates = set(n for n in names if names.count(n) > 1)
# print sorted duplicate partitions by name
if len(duplicates) != 0:
@ -153,8 +145,8 @@ class FuseTable(list):
field_name = p.field_name + p.group
if field_name != "" and len(duplicates.intersection([field_name])) != 0:
fl_error = True
print ("Field at %s, %s, %s, %s have dublicate field_name"
% ( p.field_name, p.efuse_block, p.bit_start, p.bit_count))
print ("Field at %s, %s, %s, %s have dublicate field_name" %
(p.field_name, p.efuse_block, p.bit_start, p.bit_count))
if fl_error == True:
raise InputError("Field names must be unique")
@ -168,9 +160,9 @@ class FuseTable(list):
last = None
for p in sorted(self, key=lambda x:(x.efuse_block, x.bit_start)):
if last is not None and last.efuse_block == p.efuse_block and p.bit_start < last.bit_start + last.bit_count:
raise InputError("Field at %s, %s, %s, %s overlaps %s, %s, %s, %s"
% ( p.field_name, p.efuse_block, p.bit_start, p.bit_count,
last.field_name, last.efuse_block, last.bit_start, last.bit_count))
raise InputError("Field at %s, %s, %s, %s overlaps %s, %s, %s, %s" %
(p.field_name, p.efuse_block, p.bit_start, p.bit_count,
last.field_name, last.efuse_block, last.bit_start, last.bit_count))
last = p
def fix_size_fields_from_blk1_blk2(self):
@ -178,14 +170,14 @@ class FuseTable(list):
if (p.efuse_block == "EFUSE_BLK1" and custom_table_use_BLK1 == False) or (p.efuse_block == "EFUSE_BLK2" and custom_table_use_BLK2 == False):
max_bits = p.get_max_bits_of_block()
if p.bit_start == 0 and p.bit_count > max_bits:
print("Fix size `%s` field from %d to %d" %(p.field_name, p.bit_count, max_bits))
print("Fix size `%s` field from %d to %d" % (p.field_name, p.bit_count, max_bits))
p.bit_count = max_bits
def keys_from_blk1_blk2_make_empty(self):
for p in self:
if (p.efuse_block == "EFUSE_BLK1" and custom_table_use_BLK1 == True) or (p.efuse_block == "EFUSE_BLK2" and custom_table_use_BLK2 == True):
p.bit_count = 0
print("efuse: `%s` field was changed from %d to 0" %(p.field_name, p.bit_count))
print("efuse: `%s` field was changed from %d to 0" % (p.field_name, p.bit_count))
def calc_md5(self):
txt_table = ''
@ -198,8 +190,9 @@ class FuseTable(list):
rows = ''
rows += 'Sorted efuse table:\n'
num = 1
rows = "{0} \t{1:<30} \t{2} \t{3} \t{4}".format("#", "field_name", "efuse_block", "bit_start", "bit_count") + "\n"
for p in sorted(self, key=lambda x:(x.efuse_block, x.bit_start)):
rows += "#%d \t%s \t\t%s \t\t%d \t\t%d" % (num, p.field_name, p.efuse_block, p.bit_start, p.bit_count) + "\n"
rows += "{0} \t{1:<30} \t{2} \t{3:^8} \t{4:^8}".format(num, p.field_name, p.efuse_block, p.bit_start, p.bit_count) + "\n"
num += 1
rows += '\nUsed bits in efuse table:\n'
@ -214,12 +207,12 @@ class FuseTable(list):
rows += '%d] [%d ' % (last.bit_start + last.bit_count - 1, p.bit_start)
last = p
rows += '%d] \n' % (last.bit_start + last.bit_count - 1)
rows += '\nNote: Not printed ranges are free for using.\n'
rows += '\nNote: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)\n'
return rows
def to_header(self, file_name):
rows = [ copyright ]
rows += [ "#ifdef __cplusplus",
rows = [copyright]
rows += ["#ifdef __cplusplus",
'extern "C" {',
"#endif",
"",
@ -234,19 +227,19 @@ class FuseTable(list):
last_field_name = ''
for p in self:
if (p.field_name != last_field_name):
rows += [ "extern const esp_efuse_desc_t* " + "ESP_EFUSE_" + p.field_name + "[];" ]
rows += ["extern const esp_efuse_desc_t* " + "ESP_EFUSE_" + p.field_name + "[];"]
last_field_name = p.field_name
rows += [ "",
"#ifdef __cplusplus",
"}",
"#endif",
""]
rows += ["",
"#ifdef __cplusplus",
"}",
"#endif",
""]
return '\n'.join(rows) + "\n"
def to_c_file(self, file_name, debug):
rows = [ copyright ]
rows += [ '#include "esp_efuse.h"',
rows = [copyright]
rows += ['#include "esp_efuse.h"',
'#include "' + file_name + '.h"',
"",
"// md5_digest_table " + self.md5_digest_table,
@ -260,11 +253,11 @@ class FuseTable(list):
for p in self:
if (p.field_name != last_name):
if last_name != '':
rows += [ "};\n"]
rows += [ "static const esp_efuse_desc_t " + p.field_name + "[] = {" ]
rows += ["};\n"]
rows += ["static const esp_efuse_desc_t " + p.field_name + "[] = {"]
last_name = p.field_name
rows += [ p.to_struct(debug) + "," ]
rows += [ "};\n" ]
rows += [p.to_struct(debug) + ","]
rows += ["};\n"]
rows += ["\n\n\n"]
@ -273,18 +266,18 @@ class FuseTable(list):
if (p.field_name != last_name):
if last_name != '':
rows += [" NULL",
"};\n" ]
rows += [ "const esp_efuse_desc_t* " + "ESP_EFUSE_" + p.field_name + "[] = {" ]
"};\n"]
rows += ["const esp_efuse_desc_t* " + "ESP_EFUSE_" + p.field_name + "[] = {"]
last_name = p.field_name
index = str(0) if str(p.group) == "" else str(p.group)
rows += [ " &" + p.field_name + "[" + index + "], \t\t// " + p.comment ]
rows += [" &" + p.field_name + "[" + index + "], \t\t// " + p.comment]
rows += [" NULL",
"};\n" ]
return '\n'.join(rows) + "\n"
class FuseDefinition(object):
class FuseDefinition(object):
def __init__(self):
self.field_name = ""
self.group = ""
@ -297,7 +290,7 @@ class FuseDefinition(object):
def from_csv(cls, line):
""" Parse a line from the CSV """
line_w_defaults = line + ",,,," # lazy way to support default fields
fields = [ f.strip() for f in line_w_defaults.split(",") ]
fields = [f.strip() for f in line_w_defaults.split(",")]
res = FuseDefinition()
res.field_name = fields[0]
@ -339,7 +332,7 @@ class FuseDefinition(object):
elif coding_scheme == CODE_SCHEME["REPEAT"]:
max_bits = 128
else:
ValidationError(self, "Unknown coding scheme")
raise ValidationError(self, "Unknown coding scheme")
return max_bits
def verify(self, type_table):
@ -351,13 +344,12 @@ class FuseDefinition(object):
if type_table is not None:
if type_table == "custom_table":
if self.efuse_block != "EFUSE_BLK3":
ValidationError(self, "custom_table should use only EFUSE_BLK3")
raise ValidationError(self, "custom_table should use only EFUSE_BLK3")
max_bits = self.get_max_bits_of_block()
if self.bit_start + self.bit_count > max_bits:
print("(%d + %d) > %d" % (self.bit_start, self.bit_count, max_bits))
raise ValidationError(self, "The field is outside the boundaries of the %s block" % (self.efuse_block))
raise ValidationError(self, "The field is outside the boundaries(max_bits = %d) of the %s block" % (max_bits, self.efuse_block))
def get_full_name(self):
def get_postfix(group):
@ -376,26 +368,25 @@ class FuseDefinition(object):
str(self.bit_start),
str(self.bit_count) + "}, \t // " + self.comment])
def process_input_file(file, type_table):
status("Parsing efuse CSV input file " + file.name + " ...")
input = file.read()
table = FuseTable.from_csv(input, type_table)
table = FuseTable.from_csv(input)
status("Verifying efuse table...")
table.verify(type_table)
return table
def ckeck_md5_in_file(md5, filename):
if os.path.exists(filename):
with open(filename,'r') as f:
with open(filename, 'r') as f:
for line in f:
if md5 in line:
return True
return False
def touch(fname, times=None):
with open(fname, 'a'):
os.utime(fname, times)
def create_output_files(name, output_table, debug):
file_name = os.path.splitext(os.path.basename(name))[0]
gen_dir = os.path.dirname(name)
@ -423,25 +414,19 @@ def create_output_files(name, output_table, debug):
f.write(output)
f.close()
else:
print("touch: %s.c" % (file_name))
touch(file_c_path)
print("Source files do not require updating correspond to csv file.")
def main():
global quiet
global coding_scheme
global custom_table_use_BLK1
global custom_table_use_BLK2
global common_table_fix_size
parser = argparse.ArgumentParser(description='ESP32 eFuse Manager')
parser.add_argument('--quiet', '-q', help="Don't print non-critical status messages to stderr", action='store_true')
parser.add_argument('--debug', help='Create header file with debug info', default=False, action="store_false")
parser.add_argument('--info', help='Print info about range of used bits', default=False, action="store_true")
parser.add_argument('--custom_table_use_BLK1', help='BLK1 is used for custom purpose', default=False, action="store_true")
parser.add_argument('--custom_table_use_BLK2', help='BLK2 is used for custom purpose', default=False, action="store_true")
parser.add_argument('--common_table_fix_size_secure_key_and_encrypt_key', help='Size of secure_key and encrypt_key will limit to coding scheme', default=False, action="store_true")
parser.add_argument('--coding_scheme', help='Coding scheme', type=int, default=None)
parser.add_argument('--coding_scheme', help='Coding scheme', type=int, default=0)
parser.add_argument('common_input', help='Path to common CSV file to parse.', type=argparse.FileType('rb'))
parser.add_argument('custom_input', help='Path to custom CSV file to parse.', type=argparse.FileType('rb'), nargs='?', default=None)
@ -454,10 +439,9 @@ def main():
print("eFuse coding scheme: 3/4")
elif CODE_SCHEME["REPEAT"] == coding_scheme:
print("eFuse coding scheme: REPEAT")
custom_table_use_BLK1 = args.custom_table_use_BLK1
custom_table_use_BLK2 = args.custom_table_use_BLK2
common_table_fix_size = args.common_table_fix_size_secure_key_and_encrypt_key
else:
raise InputError("unknown CODE_SCHEME = %s" % (coding_scheme))
quiet = args.quiet
debug = args.debug
info = args.info
@ -486,8 +470,7 @@ class InputError(RuntimeError):
class ValidationError(InputError):
def __init__(self, p, message):
super(ValidationError, self).__init__(
"Entry %s invalid: %s" % (p.field_name, message))
super(ValidationError, self).__init__("Entry %s invalid: %s" % (p.field_name, message))
if __name__ == '__main__':
try:

View File

@ -161,10 +161,12 @@ uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg);
esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t val);
/**
* @brief Return efuse coding_scheme for blocks.
* @brief Return efuse coding scheme for blocks.
*
* Note: The coding scheme is applicable only to 1, 2 and 3 blocks. For 0 block, the coding scheme is always ``NONE``.
*
* @param[in] blk Block number of eFuse.
* @return Return efuse coding_scheme for blocks
* @return Return efuse coding scheme for blocks
*/
esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk);

View File

@ -15,7 +15,7 @@
#include "esp_efuse.h"
#include "esp_efuse_test_table.h"
// md5_digest dac4d84347dab29412b8b8713b4b0065
// md5_digest_table 7d587827a6f6134241dce7d3713b3edc
// This file was generated automatically from the file esp_efuse_test_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
// If you want to change some fields, you need to change esp_efuse_test_table.csv file then build system will generate this header file
// To show efuse_table run the command 'make show_efuse_table'.

View File

@ -17,7 +17,7 @@ extern "C" {
#endif
// md5_digest dac4d84347dab29412b8b8713b4b0065
// md5_digest_table 7d587827a6f6134241dce7d3713b3edc
// This file was generated automatically from the file esp_efuse_test_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
// If you want to change some fields, you need to change esp_efuse_test_table.csv file then build system will generate this header file
// To show efuse_table run the command 'make show_efuse_table'.

View File

@ -8,8 +8,13 @@ import subprocess
import tempfile
import os
import StringIO
sys.path.append("..")
from efuse import *
try:
import efuse_table_gen
except ImportError:
sys.path.append("..")
import efuse_table_gen
'''
To run the test on local PC:
@ -26,20 +31,20 @@ class CSVParserTests(unittest.TestCase):
name1, EFUSE_BLK3, 0, 5, Use for test name 1
name2, EFUSE_BLK3, 5, 4, Use for test name 2
"""
t = FuseTable.from_csv(csv)
t = efuse_table_gen.FuseTable.from_csv(csv)
t.verify()
self.assertEqual(t[0].field_name, 'name1')
self.assertEqual(t[0].efuse_block, 'EFUSE_BLK3')
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[0].comment, 'Use for test name 1')
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[0].comment, 'Use for test name 1')
self.assertEqual(t[1].field_name, 'name2')
self.assertEqual(t[1].efuse_block, 'EFUSE_BLK3')
self.assertEqual(t[1].bit_start, 5)
self.assertEqual(t[1].bit_count, 4)
self.assertEqual(t[1].comment, 'Use for test name 2')
self.assertEqual(t[1].bit_start, 5)
self.assertEqual(t[1].bit_count, 4)
self.assertEqual(t[1].comment, 'Use for test name 2')
def test_seq_bit_start1_fill(self):
csv = """
@ -47,16 +52,16 @@ name2, EFUSE_BLK3, 5,
name1, EFUSE_BLK3, , 5,
name2, EFUSE_BLK3, , 4,
"""
t = FuseTable.from_csv(csv)
t = efuse_table_gen.FuseTable.from_csv(csv)
t.verify()
self.assertEqual(t[0].field_name, 'name1')
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[1].field_name, 'name2')
self.assertEqual(t[1].bit_start, 5)
self.assertEqual(t[1].bit_count, 4)
self.assertEqual(t[1].bit_start, 5)
self.assertEqual(t[1].bit_count, 4)
def test_seq_bit_start2_fill(self):
csv = """
@ -64,16 +69,16 @@ name2, EFUSE_BLK3, ,
name1, EFUSE_BLK3, , 5,
name2, EFUSE_BLK2, , 4,
"""
t = FuseTable.from_csv(csv)
t = efuse_table_gen.FuseTable.from_csv(csv)
t.verify()
self.assertEqual(t[0].field_name, 'name1')
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[1].field_name, 'name2')
self.assertEqual(t[1].bit_start, 0)
self.assertEqual(t[1].bit_count, 4)
self.assertEqual(t[1].bit_start, 0)
self.assertEqual(t[1].bit_count, 4)
def test_seq_bit_start3_fill(self):
csv = """
@ -83,20 +88,20 @@ name2, EFUSE_BLK2, ,
name3, EFUSE_BLK2, 5, 4,
"""
t = FuseTable.from_csv(csv)
t = efuse_table_gen.FuseTable.from_csv(csv)
t.verify()
self.assertEqual(t[0].field_name, 'name1')
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[1].field_name, 'name2')
self.assertEqual(t[1].bit_start, 0)
self.assertEqual(t[1].bit_count, 4)
self.assertEqual(t[1].bit_start, 0)
self.assertEqual(t[1].bit_count, 4)
self.assertEqual(t[2].field_name, 'name3')
self.assertEqual(t[2].bit_start, 5)
self.assertEqual(t[2].bit_count, 4)
self.assertEqual(t[2].bit_start, 5)
self.assertEqual(t[2].bit_count, 4)
def test_seq_bit_start4_fill(self):
csv = """
@ -106,9 +111,8 @@ name2, EFUSE_BLK2, ,
, EFUSE_BLK2, , 4,
name1, EFUSE_BLK3, , 5,
"""
with self.assertRaisesRegexp(InputError, "Field names must be unique"):
t = FuseTable.from_csv(csv)
with self.assertRaisesRegexp(efuse_table_gen.InputError, "Field names must be unique"):
t = efuse_table_gen.FuseTable.from_csv(csv)
def test_seq_bit_start5_fill(self):
csv = """
@ -118,33 +122,33 @@ name2, EFUSE_BLK2, ,
, EFUSE_BLK2, , 4,
name3, EFUSE_BLK3, 5, 5,
"""
t = FuseTable.from_csv(csv)
t = efuse_table_gen.FuseTable.from_csv(csv)
t.verify()
self.assertEqual(t[0].field_name, 'name1')
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[1].field_name, 'name2')
self.assertEqual(t[1].bit_start, 0)
self.assertEqual(t[1].bit_count, 4)
self.assertEqual(t[1].bit_start, 0)
self.assertEqual(t[1].bit_count, 4)
self.assertEqual(t[2].field_name, 'name2')
self.assertEqual(t[2].bit_start, 4)
self.assertEqual(t[2].bit_count, 4)
self.assertEqual(t[2].bit_start, 4)
self.assertEqual(t[2].bit_count, 4)
self.assertEqual(t[3].field_name, 'name3')
self.assertEqual(t[3].bit_start, 5)
self.assertEqual(t[3].bit_count, 5)
self.assertEqual(t[3].bit_start, 5)
self.assertEqual(t[3].bit_count, 5)
def test_overlapping_bit_start_fail(self):
csv = """
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
name1, EFUSE_BLK3, 1, 5, Use for test name 1
name2, EFUSE_BLK3, 5, 4, Use for test name 2
"""
t = FuseTable.from_csv(csv)
with self.assertRaisesRegexp(InputError, "overlap"):
t = efuse_table_gen.FuseTable.from_csv(csv)
with self.assertRaisesRegexp(efuse_table_gen.InputError, "overlap"):
t.verify()
def test_empty_field_name_fail(self):
@ -153,26 +157,26 @@ name2, EFUSE_BLK3, 5,
, EFUSE_BLK3, , 5,
name2, EFUSE_BLK2, , 4,
"""
with self.assertRaisesRegexp(InputError, "missing field name"):
t = FuseTable.from_csv(csv)
with self.assertRaisesRegexp(efuse_table_gen.InputError, "missing field name"):
t = efuse_table_gen.FuseTable.from_csv(csv)
def test_unique_field_name_fail(self):
csv = """
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
name1, EFUSE_BLK3, 0, 5, Use for test name 1
name1, EFUSE_BLK3, 5, 4, Use for test name 2
"""
with self.assertRaisesRegexp(InputError, "Field names must be unique"):
t = FuseTable.from_csv(csv)
with self.assertRaisesRegexp(efuse_table_gen.InputError, "Field names must be unique"):
t = efuse_table_gen.FuseTable.from_csv(csv)
def test_bit_count_empty_fail(self):
csv = """
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
name1, EFUSE_BLK3, 0, , Use for test name 1
name2, EFUSE_BLK3, 5, 4, Use for test name 2
"""
with self.assertRaisesRegexp(InputError, "empty"):
t = FuseTable.from_csv(csv)
with self.assertRaisesRegexp(efuse_table_gen.InputError, "empty"):
t = efuse_table_gen.FuseTable.from_csv(csv)
def test_bit_start_num_fail(self):
csv = """
@ -180,10 +184,10 @@ name2, EFUSE_BLK3, 5,
name1, EFUSE_BLK3, k, 5, Use for test name 1
name2, EFUSE_BLK3, 5, 4, Use for test name 2
"""
with self.assertRaisesRegexp(InputError, "Invalid field value"):
t = FuseTable.from_csv(csv)
with self.assertRaisesRegexp(efuse_table_gen.InputError, "Invalid field value"):
t = efuse_table_gen.FuseTable.from_csv(csv)
def test_join_entry(self):
def test_join_entry(self):
csv = """
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
name1, EFUSE_BLK2, 0, 6, Use for test name 1
@ -192,33 +196,33 @@ name3, EFUSE_BLK3, 20,
, EFUSE_BLK3, 30, 5, Use for test name 3
name4, EFUSE_BLK2, 30, 5, Use for test name 4
"""
t = FuseTable.from_csv(csv)
t = efuse_table_gen.FuseTable.from_csv(csv)
t.verify()
self.assertEqual(t[0].field_name, 'name1')
self.assertEqual(t[0].efuse_block, 'EFUSE_BLK2')
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 6)
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 6)
self.assertEqual(t[1].field_name, 'name2')
self.assertEqual(t[1].efuse_block, 'EFUSE_BLK2')
self.assertEqual(t[1].bit_start, 6)
self.assertEqual(t[1].bit_count, 5)
self.assertEqual(t[1].bit_start, 6)
self.assertEqual(t[1].bit_count, 5)
self.assertEqual(t[2].field_name, 'name3')
self.assertEqual(t[2].efuse_block, 'EFUSE_BLK3')
self.assertEqual(t[2].bit_start, 20)
self.assertEqual(t[2].bit_count, 5)
self.assertEqual(t[2].bit_start, 20)
self.assertEqual(t[2].bit_count, 5)
self.assertEqual(t[3].field_name, 'name3')
self.assertEqual(t[3].efuse_block, 'EFUSE_BLK3')
self.assertEqual(t[3].bit_start, 30)
self.assertEqual(t[3].bit_count, 5)
self.assertEqual(t[3].bit_start, 30)
self.assertEqual(t[3].bit_count, 5)
self.assertEqual(t[4].field_name, 'name4')
self.assertEqual(t[4].efuse_block, 'EFUSE_BLK2')
self.assertEqual(t[4].bit_start, 30)
self.assertEqual(t[4].bit_count, 5)
self.assertEqual(t[4].bit_start, 30)
self.assertEqual(t[4].bit_count, 5)
def test_block_fail(self):
csv = """
@ -226,8 +230,8 @@ name4, EFUSE_BLK2, 30,
name1, EFUSE_BLK5, 0, 5, Use for test name 1
name2, EFUSE_BLK3, 5, 4, Use for test name 2
"""
with self.assertRaisesRegexp(InputError, "'efuse_block' should consist from EFUSE_BLK0..EFUSE_BLK3"):
t = FuseTable.from_csv(csv)
with self.assertRaisesRegexp(efuse_table_gen.InputError, "'efuse_block' should consist from EFUSE_BLK0..EFUSE_BLK3"):
t = efuse_table_gen.FuseTable.from_csv(csv)
def test_field_size_is_ok(self):
csv = """
@ -235,17 +239,19 @@ name2, EFUSE_BLK3, 5,
name1, EFUSE_BLK0, 0, 224, Use for test name 1
name2, EFUSE_BLK1, 0, 256, Use for test name 2
"""
t = FuseTable.from_csv(csv)
efuse_table_gen.coding_scheme = 0 # NONE
t = efuse_table_gen.FuseTable.from_csv(csv)
t.verify()
def test_field_blk0_size_is_more(self):
def test_field_blk3_size_is_more(self):
csv = """
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
name1, EFUSE_BLK0, 1, 224, Use for test name 1
name2, EFUSE_BLK1, 0, 256, Use for test name 2
name1, EFUSE_BLK3, 190, 1, Use for test name 1
name2, EFUSE_BLK3, 191, 5, Use for test name 2
"""
t = FuseTable.from_csv(csv)
with self.assertRaisesRegexp(InputError, "The field is outside the boundaries"):
efuse_table_gen.coding_scheme = 1 #3/4 coding
t = efuse_table_gen.FuseTable.from_csv(csv)
with self.assertRaisesRegexp(efuse_table_gen.InputError, "The field is outside the boundaries"):
t.verify()
def test_field_blk1_size_is_more(self):
@ -254,13 +260,14 @@ name2, EFUSE_BLK1, 0,
name1, EFUSE_BLK0, 0, 224, Use for test name 1
name2, EFUSE_BLK1, 1, 256, Use for test name 2
"""
t = FuseTable.from_csv(csv)
with self.assertRaisesRegexp(InputError, "The field is outside the boundaries"):
t = efuse_table_gen.FuseTable.from_csv(csv)
with self.assertRaisesRegexp(efuse_table_gen.InputError, "The field is outside the boundaries"):
t.verify()
class VerificationTests(unittest.TestCase):
def test_bit_start_num_fail(self):
def test_general(self):
csv = """
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
name1, EFUSE_BLK3, 0, 5, Use for test name 1
@ -268,28 +275,60 @@ name2, EFUSE_BLK3, 5,
name1_1, EFUSE_BLK2, 0, 5, Use for test name 1_1
name2_1, EFUSE_BLK2, 5, 4, Use for test name 2_1
"""
t = FuseTable.from_csv(csv)
t = efuse_table_gen.FuseTable.from_csv(csv)
t.verify()
self.assertEqual(t[0].field_name, 'name1')
self.assertEqual(t[0].efuse_block, 'EFUSE_BLK3')
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[0].bit_start, 0)
self.assertEqual(t[0].bit_count, 5)
self.assertEqual(t[1].field_name, 'name2')
self.assertEqual(t[1].efuse_block, 'EFUSE_BLK3')
self.assertEqual(t[1].bit_start, 5)
self.assertEqual(t[1].bit_count, 4)
self.assertEqual(t[1].bit_start, 5)
self.assertEqual(t[1].bit_count, 4)
self.assertEqual(t[2].field_name, 'name1_1')
self.assertEqual(t[2].efuse_block, 'EFUSE_BLK2')
self.assertEqual(t[2].bit_start, 0)
self.assertEqual(t[2].bit_count, 5)
self.assertEqual(t[2].bit_start, 0)
self.assertEqual(t[2].bit_count, 5)
self.assertEqual(t[3].field_name, 'name2_1')
self.assertEqual(t[3].efuse_block, 'EFUSE_BLK2')
self.assertEqual(t[3].bit_start, 5)
self.assertEqual(t[3].bit_count, 4)
if __name__ =="__main__":
self.assertEqual(t[3].bit_start, 5)
self.assertEqual(t[3].bit_count, 4)
def test_custom_use_only_BLK3(self):
csv = """
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
name1, EFUSE_BLK3, 0, 5, Use for test name 1
name2, EFUSE_BLK2, 5, 4, Use for test name 2
"""
t = efuse_table_gen.FuseTable.from_csv(csv)
with self.assertRaisesRegexp(efuse_table_gen.ValidationError, "custom_table should use only EFUSE_BLK3"):
t.verify("custom_table")
def test_common_and_custom_table_use_the_same_bits(self):
csv_common = """
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
name1, EFUSE_BLK3, 0, 5, Use for test name 1
name2, EFUSE_BLK2, 5, 4, Use for test name 2
"""
common_table = efuse_table_gen.FuseTable.from_csv(csv_common)
common_table.verify("common_table")
two_tables = common_table
csv_custom = """
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
name3, EFUSE_BLK3, 20, 5, Use for test name 1
name4, EFUSE_BLK3, 4, 1, Use for test name 2
"""
custom_table = efuse_table_gen.FuseTable.from_csv(csv_custom)
custom_table.verify("custom_table")
two_tables += custom_table
with self.assertRaisesRegexp(efuse_table_gen.InputError, "overlaps"):
two_tables.verify()
if __name__ == "__main__":
unittest.main()

View File

@ -13,4 +13,6 @@ list(APPEND COMPONENT_SRCS "src/memory_layout_utils.c")
set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
set(COMPONENT_REQUIRES)
register_component()

View File

@ -32,7 +32,7 @@ The component has API functions for reading and writing fields. Access to the fi
CSV files:
* common (`esp_efuse_table.csv`) - contains efuse fields are used inside the IDF field. C-source generation should be done manually when changing this file (run command 'make efuse_common_table' or `idf.py efuse_common_table`). Note that changes to this file can lead to incorrect IDF operation. Changes are not desirable!
* custom - (may be absent, selected through :envvar:`CONFIG_EFUSE_CUSTOM_TABLE`) contains efuse fields that are used by the user in their application. C-source generation will be done automatically when changing this file.
* custom - (may be absent, selected through :envvar:`CONFIG_EFUSE_CUSTOM_TABLE`) contains efuse fields that are used by the user in their application. C-source generation should be done manually when changing this file (run command 'make efuse_custom_table' or `idf.py efuse_custom_table`).
Description CSV file
@ -49,7 +49,7 @@ Table header:
Individual params in csv file the following meanings:
field_name
Name of field. The prefix `ESP_EFUSE_` will be added to the name, and this field name will be available in the code. This name will be used to access the fields. The name must be unique for all fields. If the line has an empty name, then this line is combined with the previous field. This allows you to set an arbitrary order of bits in the field, and expand the field as well.
Name of field. The prefix `ESP_EFUSE_` will be added to the name, and this field name will be available in the code. This name will be used to access the fields. The name must be unique for all fields. If the line has an empty name, then this line is combined with the previous field. This allows you to set an arbitrary order of bits in the field, and expand the field as well (see ``MAC_FACTORY`` field in the common table).
efuse_block
Block number. It determines where the efuse bits will be placed for this field. Available EFUSE_BLK0..EFUSE_BLK3.
@ -87,7 +87,8 @@ The tool is designed to generate C-source files from CSV file and validate field
To generate a `common` files, use the following command 'make efuse_common_table' or `idf.py efuse_common_table` or:
::
cd ~/esp/esp-idf/components/efuse/
./efuse_table_gen.py esp32/esp_efuse_table.csv
After generation in the folder `esp32` create:
@ -95,10 +96,11 @@ After generation in the folder `esp32` create:
* `esp_efuse_table.c` file.
* In `include` folder `esp_efuse_table.c` file.
To generate custom files, you need to build the project, the build system tracks changes in the csv file and starts the regeneration of the C-source files itself. In this case, the tool will be called with the following parameters:
To generate a `custom` files, use the following command 'make efuse_custom_table' or `idf.py efuse_custom_table` or:
::
cd ~/esp/esp-idf/components/efuse/
./efuse_table_gen.py esp32/esp_efuse_table.csv PROJECT_PATH/main/esp_efuse_custom_table.csv
After generation in the folder PROJECT_PATH/main create:
@ -113,6 +115,37 @@ To use the generated fields, you need to include two files:
#include "esp_efuse.h"
#include "esp_efuse_table.h" or "esp_efuse_custom_table.h"
Support coding scheme
---------------------
eFuse have three coding schemes:
* ``None`` (value 0).
* ``3/4`` (value 1).
* ``Repeat`` (value 2).
The coding scheme affects only EFUSE_BLK1, EFUSE_BLK2 and EFUSE_BLK3 blocks. EUSE_BLK0 block always has a coding scheme ``None``.
Coding changes the number of bits that can be written into a block, the block length is constant 256, some of these bits are used for encoding and are not used.
When using a coding scheme, the length of the payload that can be written is limited (for more detailes ``20.3.1.3 System Parameter coding_scheme``):
* None 256 bits.
* 3/4 192 bits.
* Repeat 128 bits.
You can find out the coding scheme of your chip:
* run a ``espefuse.py -p COM4 summary`` command.
* from ``esptool`` utility logs (during flashing).
* calling the function in the code :cpp:func:`esp_efuse_get_coding_scheme` for the EFUSE_BLK3 block.
eFuse tables must always comply with the coding scheme in the chip. There is an :envvar:`EFUSE_CODE_SCHEME_SELECTOR` option to select the coding type for tables in a Kconfig. When generating source files, if your tables do not follow the coding scheme, an error message will be displayed. Adjust the length or offset fields.
If your program was compiled with ``None`` encoding and ``3/4`` is used in the chip, then the ``ESP_ERR_CODING`` error may occur when calling the efuse API (the field is outside the block boundaries). If the field matches the new block boundaries, then the API will work without errors.
Also, 3/4 coding scheme imposes restrictions on writing bits belonging to one coding unit. The whole block with a length of 256 bits is divided into 4 coding units, and in each coding unit there are 6 bytes of useful data and 2 service bytes. These 2 service bytes contain the checksum of the previous 6 data bytes.
It turns out that only one field can be written into one coding unit. Repeated rewriting in one coding unit is prohibited. But if the record was made in advance or through a :cpp:func:`esp_efuse_write_block` function, then reading the fields belonging to one coding unit is possible.
eFuse API
---------
@ -124,6 +157,10 @@ Access to the fields is via a pointer to the description structure. API function
* :cpp:func:`esp_efuse_write_field_cnt` - writes a required count of bits as "1".
* :cpp:func:`esp_efuse_get_field_size` - returns the number of bits by the field name.
* :cpp:func:`esp_efuse_read_reg` - returns value of efuse register.
* :cpp:func:`esp_efuse_write_reg` - writes value to efuse register.
* :cpp:func:`esp_efuse_get_coding_scheme` - returns efuse coding scheme for blocks.
* :cpp:func:`esp_efuse_read_block` - reads key to efuse block starting at the offset and the required size.
* :cpp:func:`esp_efuse_write_block` - writes key to efuse block starting at the offset and the required size.
For frequently used fields, special functions are made, like this :cpp:func:`esp_efuse_get_chip_ver`, :cpp:func:`esp_efuse_get_pkg_ver`.
@ -131,53 +168,55 @@ For frequently used fields, special functions are made, like this :cpp:func:`esp
How add a new field
-------------------
1. Find a free bits for field. Show `efuse_table.csv` file or run the next command:
1. Find a free bits for field. Show `esp_efuse_table.csv` file or run ``make show_efuse_table`` or ``idf.py show_efuse_table`` or the next command:
::
$ ./efuse_table_gen.py --info esp32/esp_efuse_table.csv
Sorted efuse table:
#1 WR_DIS_FLASH_CRYPT_CNT EFUSE_BLK0 2 1
#2 WR_DIS_BLK1 EFUSE_BLK0 7 1
#3 WR_DIS_BLK2 EFUSE_BLK0 8 1
#4 WR_DIS_BLK3 EFUSE_BLK0 9 1
#5 RD_DIS_BLK1 EFUSE_BLK0 16 1
#6 RD_DIS_BLK2 EFUSE_BLK0 17 1
#7 RD_DIS_BLK3 EFUSE_BLK0 18 1
#8 FLASH_CRYPT_CNT EFUSE_BLK0 20 8
#9 MAC_FACTORY EFUSE_BLK0 32 8
#10 MAC_FACTORY EFUSE_BLK0 40 8
#11 MAC_FACTORY EFUSE_BLK0 48 8
#12 MAC_FACTORY EFUSE_BLK0 56 8
#13 MAC_FACTORY EFUSE_BLK0 64 8
#14 MAC_FACTORY EFUSE_BLK0 72 8
#15 MAC_FACTORY_CRC EFUSE_BLK0 80 8
#16 CHIP_VER_DIS_APP_CPU EFUSE_BLK0 96 1
#17 CHIP_VER_DIS_BT EFUSE_BLK0 97 1
#18 CHIP_VER_PKG EFUSE_BLK0 105 3
#19 CHIP_CPU_FREQ_LOW EFUSE_BLK0 108 1
#20 CHIP_CPU_FREQ_RATED EFUSE_BLK0 109 1
#21 CHIP_VER_REV1 EFUSE_BLK0 111 1
#22 ADC_VREF_AND_SDIO_DREF EFUSE_BLK0 136 6
#23 XPD_SDIO_REG EFUSE_BLK0 142 1
#24 SDIO_TIEH EFUSE_BLK0 143 1
#25 SDIO_FORCE EFUSE_BLK0 144 1
#26 ENCRYPT_CONFIG EFUSE_BLK0 188 4
#27 CONSOLE_DEBUG_DISABLE EFUSE_BLK0 194 1
#28 ABS_DONE_0 EFUSE_BLK0 196 1
#29 DISABLE_JTAG EFUSE_BLK0 198 1
#30 DISABLE_DL_ENCRYPT EFUSE_BLK0 199 1
#31 DISABLE_DL_DECRYPT EFUSE_BLK0 200 1
#32 DISABLE_DL_CACHE EFUSE_BLK0 201 1
#33 ENCRYPT_FLASH_KEY EFUSE_BLK1 0 256
#34 SECURE_BOOT_KEY EFUSE_BLK2 0 256
#35 MAC_CUSTOM_CRC EFUSE_BLK3 0 8
#36 MAC_CUSTOM EFUSE_BLK3 8 48
#37 ADC1_TP_LOW EFUSE_BLK3 96 7
#38 ADC1_TP_HIGH EFUSE_BLK3 103 9
#39 ADC2_TP_LOW EFUSE_BLK3 112 7
#40 ADC2_TP_HIGH EFUSE_BLK3 119 9
#41 MAC_CUSTOM_VER EFUSE_BLK3 184 8
eFuse coding scheme: NONE
# field_name efuse_block bit_start bit_count
1 WR_DIS_FLASH_CRYPT_CNT EFUSE_BLK0 2 1
2 WR_DIS_BLK1 EFUSE_BLK0 7 1
3 WR_DIS_BLK2 EFUSE_BLK0 8 1
4 WR_DIS_BLK3 EFUSE_BLK0 9 1
5 RD_DIS_BLK1 EFUSE_BLK0 16 1
6 RD_DIS_BLK2 EFUSE_BLK0 17 1
7 RD_DIS_BLK3 EFUSE_BLK0 18 1
8 FLASH_CRYPT_CNT EFUSE_BLK0 20 8
9 MAC_FACTORY EFUSE_BLK0 32 8
10 MAC_FACTORY EFUSE_BLK0 40 8
11 MAC_FACTORY EFUSE_BLK0 48 8
12 MAC_FACTORY EFUSE_BLK0 56 8
13 MAC_FACTORY EFUSE_BLK0 64 8
14 MAC_FACTORY EFUSE_BLK0 72 8
15 MAC_FACTORY_CRC EFUSE_BLK0 80 8
16 CHIP_VER_DIS_APP_CPU EFUSE_BLK0 96 1
17 CHIP_VER_DIS_BT EFUSE_BLK0 97 1
18 CHIP_VER_PKG EFUSE_BLK0 105 3
19 CHIP_CPU_FREQ_LOW EFUSE_BLK0 108 1
20 CHIP_CPU_FREQ_RATED EFUSE_BLK0 109 1
21 CHIP_VER_REV1 EFUSE_BLK0 111 1
22 ADC_VREF_AND_SDIO_DREF EFUSE_BLK0 136 6
23 XPD_SDIO_REG EFUSE_BLK0 142 1
24 SDIO_TIEH EFUSE_BLK0 143 1
25 SDIO_FORCE EFUSE_BLK0 144 1
26 ENCRYPT_CONFIG EFUSE_BLK0 188 4
27 CONSOLE_DEBUG_DISABLE EFUSE_BLK0 194 1
28 ABS_DONE_0 EFUSE_BLK0 196 1
29 DISABLE_JTAG EFUSE_BLK0 198 1
30 DISABLE_DL_ENCRYPT EFUSE_BLK0 199 1
31 DISABLE_DL_DECRYPT EFUSE_BLK0 200 1
32 DISABLE_DL_CACHE EFUSE_BLK0 201 1
33 ENCRYPT_FLASH_KEY EFUSE_BLK1 0 256
34 SECURE_BOOT_KEY EFUSE_BLK2 0 256
35 MAC_CUSTOM_CRC EFUSE_BLK3 0 8
36 MAC_CUSTOM EFUSE_BLK3 8 48
37 ADC1_TP_LOW EFUSE_BLK3 96 7
38 ADC1_TP_HIGH EFUSE_BLK3 103 9
39 ADC2_TP_LOW EFUSE_BLK3 112 7
40 ADC2_TP_HIGH EFUSE_BLK3 119 9
41 SECURE_VERSION EFUSE_BLK3 128 32
42 MAC_CUSTOM_VER EFUSE_BLK3 184 8
Used bits in efuse table:
EFUSE_BLK0
@ -190,18 +229,19 @@ How add a new field
[0 255]
EFUSE_BLK3
[0 55] [96 127] [184 191]
[0 55] [96 159] [184 191]
Note: Not printed ranges are free for using.
Note: Not printed ranges are free for using. (bits in EFUSE_BLK0 are reserved for Espressif)
Parsing efuse CSV input file esp32/esp_efuse_table.csv ...
Parsing efuse CSV input file C:/msys32/home/virtpc/esp/esp-idf/components/efuse/esp32/esp_efuse_table.csv ...
Verifying efuse table...
The number of bits not included in square brackets is free. All fields are checked for overlapping.
The number of bits not included in square brackets is free (bits in EFUSE_BLK0 are reserved for Espressif). All fields are checked for overlapping.
2. Fill a line for field: field_name, efuse_block, bit_start, bit_count, comment.
3. Run a command `make show_efuse_table` to check and generate header file.
3. Run a ``show_efuse_table`` command to check efuse table. To generate source files run ``efuse_common_table`` or ``efuse_custom_table`` command.
Debug efuse & Unit tests
------------------------
@ -213,13 +253,13 @@ esptool have an useful tool for reading/writing ESP32 efuse bits - `espefuse.py
::
espefuse.py -p COM4 summary
espefuse.py v2.3.1
Connecting........_
Security fuses:
FLASH_CRYPT_CNT Flash encryption mode counter = 0 R/W (0x4)
FLASH_CRYPT_CNT Flash encryption mode counter = 0 R/W (0x0)
FLASH_CRYPT_CONFIG Flash encryption config (key tweak bits) = 0 R/W (0x0)
CONSOLE_DEBUG_DISABLE Disable ROM BASIC interpreter fallback = 0 R/W (0x0)
CONSOLE_DEBUG_DISABLE Disable ROM BASIC interpreter fallback = 1 R/W (0x1)
ABS_DONE_0 secure boot enabled for bootloader = 0 R/W (0x0)
ABS_DONE_1 secure boot abstract 1 locked = 0 R/W (0x0)
JTAG_DISABLE Disable JTAG = 0 R/W (0x0)
@ -231,12 +271,12 @@ esptool have an useful tool for reading/writing ESP32 efuse bits - `espefuse.py
BLK2 Secure boot key
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
BLK3 Variable Block 3
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa 87 02 91 00 00 00 00 00 00 00 00 00 00 00 00 R/W
Efuse fuses:
WR_DIS Efuse write disable mask = 0 R/W (0x0)
RD_DIS Efuse read disablemask = 0 R/W (0x0)
CODING_SCHEME Efuse variable block length scheme = 0 R/W (0x0)
CODING_SCHEME Efuse variable block length scheme = 1 R/W (0x1) (3/4)
KEY_STATUS Usage of efuse block 3 (reserved) = 0 R/W (0x0)
Config fuses:
@ -252,14 +292,18 @@ esptool have an useful tool for reading/writing ESP32 efuse bits - `espefuse.py
Identity fuses:
MAC MAC Address
= 24:0a:c4:03:bb:68 (CRC 82 OK) R/W
CHIP_VER_REV1 Silicon Revision 1 = 0 R/W (0x0)
CHIP_VERSION Reserved for future chip versions = 0 R/W (0x0)
= 84:0d:8e:18:8e:44 (CRC ad OK) R/W
CHIP_VER_REV1 Silicon Revision 1 = 1 R/W (0x1)
CHIP_VERSION Reserved for future chip versions = 2 R/W (0x2)
CHIP_PACKAGE Chip package identifier = 0 R/W (0x0)
Calibration fuses:
BLK3_PART_RESERVE BLOCK3 partially served for ADC calibration data = 0 R/W (0x0)
ADC_VREF Voltage reference calibration = 1100 R/W (0x0)
BLK3_PART_RESERVE BLOCK3 partially served for ADC calibration data = 1 R/W (0x1)
ADC_VREF Voltage reference calibration = 1114 R/W (0x2)
ADC1_TP_LOW ADC1 150mV reading = 346 R/W (0x11)
ADC1_TP_HIGH ADC1 850mV reading = 3285 R/W (0x5)
ADC2_TP_LOW ADC2 150mV reading = 449 R/W (0x7)
ADC2_TP_HIGH ADC2 850mV reading = 3362 R/W (0x1f5)
Flash voltage (VDD_SDIO) determined by GPIO12 on reset (High for 1.8V, Low/NC for 3.3V).

View File

@ -13,7 +13,7 @@
.PHONY: build-components menuconfig defconfig all build clean all_binaries check-submodules size size-components size-files size-symbols list-components
MAKECMDGOALS ?= all
all: efuse_table all_binaries | check_python_dependencies
all: all_binaries | check_python_dependencies
# see below for recipe of 'all' target
#
# # other components will add dependencies to 'all_binaries'. The
@ -481,7 +481,7 @@ $(APP_ELF): $(foreach libcomp,$(COMPONENT_LIBRARIES),$(BUILD_DIR_BASE)/$(libcomp
$(summary) LD $(patsubst $(PWD)/%,%,$@)
$(CC) $(LDFLAGS) -o $@ -Wl,-Map=$(APP_MAP)
app: efuse_table $(APP_BIN) partition_table_get_info
app: $(APP_BIN) partition_table_get_info
ifeq ("$(CONFIG_SECURE_BOOT_ENABLED)$(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)","y") # secure boot enabled, but remote sign app image
@echo "App built but not signed. Signing step via espsecure.py:"
@echo "espsecure.py sign_data --keyfile KEYFILE $(APP_BIN)"

View File

@ -424,6 +424,7 @@ ACTIONS = {
"app-flash": (flash, ["app"], ["erase_flash"]),
"efuse_common_table": (build_target, [], ["reconfigure"]),
"efuse_custom_table": (build_target, [], ["reconfigure"]),
"show_efuse_table": (build_target, [], ["reconfigure"]),
"partition_table": (build_target, [], ["reconfigure"]),
"partition_table-flash": (flash, ["partition_table"], ["erase_flash"]),
"flash": (flash, ["all"], ["erase_flash"]),