mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
efuse: Add API efuse
Added support 3/4 coding scheme
This commit is contained in:
parent
91676b8620
commit
693a5c209b
54
components/efuse/CMakeLists.txt
Normal file
54
components/efuse/CMakeLists.txt
Normal file
@ -0,0 +1,54 @@
|
||||
set(SOC_NAME ${IDF_TARGET})
|
||||
|
||||
if(EXISTS "${COMPONENT_PATH}/${SOC_NAME}")
|
||||
include(${COMPONENT_PATH}/${SOC_NAME}/sources.cmake)
|
||||
spaces2list(EFUSE_SOC_SRCS)
|
||||
add_prefix(COMPONENT_SRCS "${SOC_NAME}/" ${EFUSE_SOC_SRCS})
|
||||
set(COMPONENT_ADD_INCLUDEDIRS include
|
||||
${SOC_NAME}/include)
|
||||
endif()
|
||||
|
||||
list(APPEND COMPONENT_SRCS "src/esp_efuse_api.c"
|
||||
"src/esp_efuse_fields.c"
|
||||
"src/esp_efuse_utility.c")
|
||||
|
||||
set(COMPONENT_REQUIRES)
|
||||
set(COMPONENT_PRIV_REQUIRES bootloader_support)
|
||||
register_component()
|
||||
|
||||
|
||||
###################
|
||||
# Make common files esp_efuse_table.c and include/esp_efuse_table.h files.
|
||||
# The generated files are used in the bootloader and application space.
|
||||
# To generate new *.c/*.h files run the command manually "make efuse_common_table".
|
||||
set(EFUSE_COMMON_TABLE_CSV_PATH "${COMPONENT_PATH}/${SOC_NAME}/esp_efuse_table.csv")
|
||||
add_custom_target(efuse_common_table COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/efuse_table_gen.py" ${EFUSE_COMMON_TABLE_CSV_PATH})
|
||||
|
||||
|
||||
# custom gen header 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}")
|
||||
|
||||
add_custom_target(efuse_custom_table ALL
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Efuse CSV ${EFUSE_CUSTOM_TABLE_CSV_PATH} does not exist. Either change efuse table file in menuconfig or create this input file."
|
||||
COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/CMakeCache.txt"
|
||||
COMMAND ${CMAKE_COMMAND} -P ${IDF_PATH}/tools/cmake/scripts/fail.cmake)
|
||||
|
||||
string(REPLACE ".csv" ".c" HEADER_CUSTOM ${EFUSE_CUSTOM_TABLE_CSV_PATH})
|
||||
add_custom_command(OUTPUT ${HEADER_CUSTOM}
|
||||
COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/efuse_table_gen.py"
|
||||
${EFUSE_COMMON_TABLE_CSV_PATH} ${EFUSE_CUSTOM_TABLE_CSV_PATH}
|
||||
DEPENDS ${EFUSE_CUSTOM_TABLE_CSV_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/efuse_table_gen.py"
|
||||
VERBATIM)
|
||||
|
||||
if(EXISTS ${EFUSE_CUSTOM_TABLE_CSV_PATH})
|
||||
add_custom_target(efuse_custom_table ALL DEPENDS ${HEADER_CUSTOM} ${EFUSE_CUSTOM_TABLE_CSV_PATH})
|
||||
endif()
|
||||
|
||||
endif()#if(${CONFIG_EFUSE_CUSTOM_TABLE})
|
||||
|
||||
###################
|
||||
# Generates files for unit test. This command is run manually.
|
||||
set(EFUSE_TEST_TABLE_CSV_PATH "${COMPONENT_PATH}/test/esp_efuse_test_table.csv")
|
||||
add_custom_target(efuse_test_table COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/efuse_table_gen.py" ${EFUSE_TEST_TABLE_CSV_PATH})
|
37
components/efuse/Kconfig
Normal file
37
components/efuse/Kconfig
Normal file
@ -0,0 +1,37 @@
|
||||
menu "eFuse bit Manager"
|
||||
|
||||
config EFUSE_CUSTOM_TABLE
|
||||
bool "Use custom eFuse table"
|
||||
default n
|
||||
help
|
||||
Allows to generate a structure for eFuse from the CSV file.
|
||||
|
||||
config EFUSE_CUSTOM_TABLE_FILENAME
|
||||
string "Custom eFuse CSV file" if EFUSE_CUSTOM_TABLE
|
||||
default main/esp_efuse_custom_table.csv
|
||||
help
|
||||
Name of the custom eFuse CSV filename. This path is evaluated
|
||||
relative to the project root directory.
|
||||
|
||||
config EFUSE_VIRTUAL
|
||||
bool "Emulate eFuse work"
|
||||
default n
|
||||
help
|
||||
If this option is set, all permanent changes (via eFuse) are disabled.
|
||||
Log output will state changes which would be applied, but they will not be.
|
||||
|
||||
choice EFUSE_CODE_SCHEME
|
||||
prompt "eFuse Code Scheme"
|
||||
default EFUSE_CODE_SCHEME_NONE
|
||||
help
|
||||
Selector eFuse code scheme.
|
||||
|
||||
config EFUSE_CODE_SCHEME_NONE
|
||||
bool "None"
|
||||
config EFUSE_CODE_SCHEME_3_4
|
||||
bool "3/4"
|
||||
config EFUSE_CODE_SCHEME_REPEAT
|
||||
bool "Repeat"
|
||||
endchoice
|
||||
|
||||
endmenu
|
48
components/efuse/Makefile.projbuild
Normal file
48
components/efuse/Makefile.projbuild
Normal file
@ -0,0 +1,48 @@
|
||||
#
|
||||
# eFuse Manager ganeretes header file.
|
||||
#
|
||||
# .PHONY: efuse_table efuse_custom_table efuse_common_table efuse_test_table show_efuse_table
|
||||
|
||||
GEN_EFUSE_TABLE := $(PYTHON) $(COMPONENT_PATH)/efuse_table_gen.py
|
||||
|
||||
efuse_table: efuse_custom_table
|
||||
|
||||
###################
|
||||
# Make common files esp_efuse_table.c and include/esp_efuse_table.h files.
|
||||
# The generated files are used in the bootloader and application space.
|
||||
# To generate new *.c/*.h files run the command manually "make efuse_common_table".
|
||||
SOC_NAME := $(IDF_TARGET)
|
||||
EFUSE_COMMON_TABLE_CSV_PATH := $(COMPONENT_PATH)/$(SOC_NAME)/esp_efuse_table.csv
|
||||
efuse_common_table:
|
||||
$(GEN_EFUSE_TABLE) $(EFUSE_COMMON_TABLE_CSV_PATH)
|
||||
|
||||
###################
|
||||
# Make custom files
|
||||
# Changes in esp_efuse_custom_table.csv file lead to regeneration of esp_efuse_custom_table.c and include/esp_efuse_custom_table.h files.
|
||||
# The generated files are used only in the application.
|
||||
ifdef IS_BOOTLOADER_BUILD
|
||||
efuse_custom_table:
|
||||
else
|
||||
|
||||
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 := $(call dequote,$(abspath $(call dequote, $(BUILD_DIR_BASE))/$(call dequote,$(CONFIG_EFUSE_CUSTOM_TABLE_FILENAME))))
|
||||
efuse_custom_table: $(EFUSE_CUSTOM_TABLE_OUT_PATH:.csv=.o)
|
||||
|
||||
$(EFUSE_CUSTOM_TABLE_OUT_PATH:.csv=.o): $(EFUSE_CUSTOM_TABLE_CSV_PATH)
|
||||
@echo "$(EFUSE_CUSTOM_TABLE_OUT_PATH)"
|
||||
@echo "$(EFUSE_CUSTOM_TABLE_CSV_PATH)"
|
||||
$(GEN_EFUSE_TABLE) $(EFUSE_COMMON_TABLE_CSV_PATH) $(EFUSE_CUSTOM_TABLE_CSV_PATH)
|
||||
|
||||
else
|
||||
efuse_custom_table:
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
###################
|
||||
# Generates files for unit test. This command is run manually.
|
||||
EFUSE_TEST_TABLE_CSV_PATH := $(COMPONENT_PATH)/test/esp_efuse_test_table.csv
|
||||
efuse_test_table:
|
||||
$(GEN_EFUSE_TABLE) $(EFUSE_TEST_TABLE_CSV_PATH)
|
10
components/efuse/component.mk
Normal file
10
components/efuse/component.mk
Normal file
@ -0,0 +1,10 @@
|
||||
#
|
||||
# Component Makefile
|
||||
# currently the only SoC supported; to be moved into Kconfig
|
||||
SOC_NAME := $(IDF_TARGET)
|
||||
|
||||
COMPONENT_SRCDIRS := $(SOC_NAME) src
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := $(SOC_NAME)/include include
|
||||
|
||||
-include $(COMPONENT_PATH)/$(SOC_NAME)/component.mk
|
415
components/efuse/efuse_table_gen.py
Normal file
415
components/efuse/efuse_table_gen.py
Normal file
@ -0,0 +1,415 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# ESP32 efuse table generation tool
|
||||
#
|
||||
# Converts efuse table to header file efuse_table.h.
|
||||
#
|
||||
# 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.
|
||||
from __future__ import print_function, division
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
import sys
|
||||
import hashlib
|
||||
import binascii
|
||||
import ntpath
|
||||
|
||||
__version__ = '1.0'
|
||||
|
||||
quiet = False
|
||||
|
||||
copyright = '''// 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
|
||||
'''
|
||||
|
||||
def status(msg):
|
||||
""" Print status message to stderr """
|
||||
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 = ""
|
||||
|
||||
@classmethod
|
||||
def from_csv(cls, csv_contents):
|
||||
res = FuseTable()
|
||||
res.md5_digest = res.calc_md5(csv_contents)
|
||||
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))
|
||||
return f
|
||||
|
||||
for line_no in range(len(lines)):
|
||||
line = expand_vars(lines[line_no]).strip()
|
||||
if line.startswith("#") or len(line) == 0:
|
||||
continue
|
||||
try:
|
||||
res.append(FuseDefinition.from_csv(line))
|
||||
except InputError as 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))
|
||||
raise
|
||||
|
||||
# fix up missing bit_start
|
||||
last_enfl_error = 0
|
||||
last_efuse_block = None
|
||||
for e in res:
|
||||
if last_efuse_block != e.efuse_block:
|
||||
last_end = 0
|
||||
if e.bit_start is None:
|
||||
e.bit_start = last_end
|
||||
last_end = e.bit_start + e.bit_count
|
||||
last_efuse_block = e.efuse_block
|
||||
|
||||
res.verify_duplicate_name()
|
||||
|
||||
# fix up missing field_name
|
||||
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))
|
||||
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 )
|
||||
if len(duplicates) != 0:
|
||||
i_count = 0
|
||||
for p in res:
|
||||
if len(duplicates.intersection([p.field_name])) != 0:
|
||||
p.group = str(i_count)
|
||||
i_count += 1
|
||||
else:
|
||||
i_count = 0
|
||||
res.verify_duplicate_name()
|
||||
|
||||
return res
|
||||
|
||||
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 )
|
||||
|
||||
# print sorted duplicate partitions by name
|
||||
if len(duplicates) != 0:
|
||||
fl_error = False
|
||||
for p in self:
|
||||
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))
|
||||
if fl_error == True:
|
||||
raise InputError("Field names must be unique")
|
||||
|
||||
def verify(self):
|
||||
|
||||
'''list_field_names = []'''
|
||||
for p in self:
|
||||
p.verify()
|
||||
|
||||
self.verify_duplicate_name()
|
||||
|
||||
# check for overlaps
|
||||
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))
|
||||
last = p
|
||||
|
||||
def calc_md5(self, csv_contents):
|
||||
return hashlib.md5(csv_contents).hexdigest()
|
||||
|
||||
def show_range_used_bits(self):
|
||||
# print used and free bits
|
||||
rows = ''
|
||||
rows += 'Sorted efuse table:\n'
|
||||
num = 1
|
||||
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"
|
||||
num += 1
|
||||
|
||||
rows += '\nUsed bits in efuse table:\n'
|
||||
last = None
|
||||
for p in sorted(self, key=lambda x:(x.efuse_block, x.bit_start)):
|
||||
if last is None:
|
||||
rows += '%s \n[%d ' % (p.efuse_block, p.bit_start)
|
||||
if last is not None:
|
||||
if last.efuse_block != p.efuse_block:
|
||||
rows += '%d] \n\n%s \n[%d ' % (last.bit_start + last.bit_count - 1, p.efuse_block, p.bit_start)
|
||||
elif last.bit_start + last.bit_count != p.bit_start:
|
||||
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'
|
||||
return rows
|
||||
|
||||
def to_header(self, file_name):
|
||||
rows = [ copyright ]
|
||||
rows += [ "#ifdef __cplusplus",
|
||||
'extern "C" {',
|
||||
"#endif",
|
||||
"",
|
||||
"",
|
||||
"// md5_digest " + self.md5_digest,
|
||||
"// This file was generated automatically from the file " + file_name + ".csv. DO NOT CHANGE THIS FILE MANUALLY.",
|
||||
"// If you want to change some fields, you need to change " + file_name + ".csv file then build system will generate this header file",
|
||||
"// To show efuse_table run the command 'make show_efuse_table'.",
|
||||
"",
|
||||
""]
|
||||
|
||||
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 + "[];" ]
|
||||
last_field_name = p.field_name
|
||||
|
||||
rows += [ "",
|
||||
"#ifdef __cplusplus",
|
||||
"}",
|
||||
"#endif",
|
||||
""]
|
||||
return '\n'.join(rows) + "\n"
|
||||
|
||||
def to_c_file(self, file_name, debug):
|
||||
rows = [ copyright ]
|
||||
rows += [ '#include "esp_efuse.h"',
|
||||
'#include "' + file_name + '.h"',
|
||||
"",
|
||||
"// md5_digest " + self.md5_digest,
|
||||
"// This file was generated automatically from the file " + file_name + ".csv. DO NOT CHANGE THIS FILE MANUALLY.",
|
||||
"// If you want to change some fields, you need to change " + file_name + ".csv file then build system will generate this header file",
|
||||
"// To show efuse_table run the command 'make show_efuse_table'.",
|
||||
"",
|
||||
""]
|
||||
|
||||
last_name = ''
|
||||
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 + "[] = {" ]
|
||||
last_name = p.field_name
|
||||
rows += [ p.to_struct(debug) + "," ]
|
||||
rows += [ "};\n" ]
|
||||
|
||||
rows += ["\n\n\n"]
|
||||
|
||||
last_name = ''
|
||||
for p in self:
|
||||
if (p.field_name != last_name):
|
||||
if last_name != '':
|
||||
rows += [" NULL",
|
||||
"};\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 += [" NULL",
|
||||
"};\n" ]
|
||||
|
||||
return '\n'.join(rows) + "\n"
|
||||
|
||||
class FuseDefinition(object):
|
||||
|
||||
def __init__(self):
|
||||
self.field_name = ""
|
||||
self.group = ""
|
||||
self.efuse_block = ""
|
||||
self.bit_start = None
|
||||
self.bit_count = None
|
||||
self.comment = ""
|
||||
|
||||
@classmethod
|
||||
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(",") ]
|
||||
|
||||
res = FuseDefinition()
|
||||
res.field_name = fields[0]
|
||||
res.efuse_block = res.parse_block(fields[1])
|
||||
res.bit_start = res.parse_num(fields[2])
|
||||
res.bit_count = res.parse_num(fields[3])
|
||||
if res.bit_count is None or res.bit_count == 0:
|
||||
raise InputError("Field bit_count can't be empty")
|
||||
res.comment = fields[4]
|
||||
return res
|
||||
|
||||
def parse_num(self, strval):
|
||||
if strval == "":
|
||||
return None # Field will fill in default
|
||||
return self.parse_int(strval)
|
||||
|
||||
def parse_int(self, v):
|
||||
try:
|
||||
return int(v, 0)
|
||||
except ValueError:
|
||||
raise InputError("Invalid field value %s" % v)
|
||||
|
||||
def parse_block(self, strval):
|
||||
if strval == "":
|
||||
raise InputError("Field 'efuse_block' can't be left empty.")
|
||||
if strval != "EFUSE_BLK0" and strval != "EFUSE_BLK1" and strval != "EFUSE_BLK2" and strval != "EFUSE_BLK3":
|
||||
raise InputError("Field 'efuse_block' should consist from EFUSE_BLK0..EFUSE_BLK3")
|
||||
return strval
|
||||
|
||||
def verify(self):
|
||||
'''if self.field_name is None:
|
||||
raise ValidationError(self, "field_name field is not set")'''
|
||||
if self.efuse_block is None:
|
||||
raise ValidationError(self, "efuse_block field is not set")
|
||||
if self.bit_count is None:
|
||||
raise ValidationError(self, "bit_count field is not set")
|
||||
|
||||
max_bits = 256
|
||||
if self.efuse_block == "EFUSE_BLK0":
|
||||
max_bits = 224
|
||||
if self.bit_start + self.bit_count > max_bits:
|
||||
raise ValidationError(self, "The field is outside the boundaries of the %s block" % (self.efuse_block))
|
||||
|
||||
def get_full_name(self):
|
||||
def get_postfix(group):
|
||||
postfix = ""
|
||||
if group != "":
|
||||
postfix = "_PART_" + group
|
||||
return postfix
|
||||
|
||||
return self.field_name + get_postfix(self.group)
|
||||
|
||||
def to_struct(self, debug):
|
||||
start = " {"
|
||||
if (debug == True):
|
||||
start = " {" + '"' + self.field_name + '" ,'
|
||||
return ", ".join([start + self.efuse_block,
|
||||
str(self.bit_start),
|
||||
str(self.bit_count) + "}, \t // " + self.comment])
|
||||
|
||||
def process_input_file(file):
|
||||
status("Parsing efuse CSV input file " + file.name + " ...")
|
||||
input = file.read()
|
||||
table = FuseTable.from_csv(input)
|
||||
|
||||
status("Verifying efuse table...")
|
||||
table.verify()
|
||||
return table
|
||||
|
||||
def create_output_files(name, output_table, debug):
|
||||
file_name = os.path.splitext(os.path.basename(name))[0]
|
||||
gen_dir = os.path.dirname(name)
|
||||
|
||||
dir_for_file_h = gen_dir + "/include"
|
||||
try:
|
||||
os.stat(dir_for_file_h)
|
||||
except:
|
||||
os.mkdir(dir_for_file_h)
|
||||
|
||||
file_h_path = os.path.join(dir_for_file_h, file_name + ".h")
|
||||
file_c_path = os.path.join(gen_dir, file_name + ".c")
|
||||
|
||||
status("Creating efuse *.h file " + file_h_path + " ...")
|
||||
output = output_table.to_header(file_name)
|
||||
with open(file_h_path, 'w') as f:
|
||||
f.write(output)
|
||||
f.close()
|
||||
|
||||
status("Creating efuse *.c file " + file_c_path + " ...")
|
||||
output = output_table.to_c_file(file_name, debug)
|
||||
with open(file_c_path, 'w') as f:
|
||||
f.write(output)
|
||||
f.close()
|
||||
|
||||
def main():
|
||||
global quiet
|
||||
|
||||
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('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)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
quiet = args.quiet
|
||||
debug = args.debug
|
||||
info = args.info
|
||||
|
||||
common_table = process_input_file(args.common_input)
|
||||
if args.custom_input is not None:
|
||||
custom_table = process_input_file(args.custom_input)
|
||||
common_table += custom_table
|
||||
common_table.verify()
|
||||
if info == True:
|
||||
output_table = common_table
|
||||
else:
|
||||
output_table = custom_table
|
||||
name = args.custom_input.name
|
||||
else:
|
||||
output_table = common_table
|
||||
name = args.common_input.name
|
||||
output_table.verify()
|
||||
|
||||
# save files.
|
||||
if info == False:
|
||||
create_output_files(name, output_table, debug)
|
||||
else:
|
||||
print(output_table.show_range_used_bits())
|
||||
|
||||
return 0
|
||||
|
||||
class InputError(RuntimeError):
|
||||
def __init__(self, e):
|
||||
super(InputError, self).__init__(e)
|
||||
|
||||
class ValidationError(InputError):
|
||||
def __init__(self, p, message):
|
||||
super(ValidationError, self).__init__(
|
||||
"Entry %s invalid: %s" % (p.field_name, message))
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except InputError as e:
|
||||
print(e, file=sys.stderr)
|
||||
sys.exit(2)
|
0
components/efuse/esp32/component.mk
Normal file
0
components/efuse/esp32/component.mk
Normal file
362
components/efuse/esp32/esp_efuse_table.c
Normal file
362
components/efuse/esp32/esp_efuse_table.c
Normal file
@ -0,0 +1,362 @@
|
||||
// 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_table.h"
|
||||
|
||||
|
||||
// md5_digest 963d6d14dc4bd997fd5d4b9de351745d
|
||||
// This file was generated automatically from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
// If you want to change some fields, you need to change esp_efuse_table.csv file then build system will generate this header file
|
||||
// To show efuse_table run the command 'make show_efuse_table'.
|
||||
|
||||
|
||||
static const esp_efuse_desc_t MAC_FACTORY[] = {
|
||||
{EFUSE_BLK0, 72, 8}, // Factory MAC addr [0],
|
||||
{EFUSE_BLK0, 64, 8}, // Factory MAC addr [1],
|
||||
{EFUSE_BLK0, 56, 8}, // Factory MAC addr [2],
|
||||
{EFUSE_BLK0, 48, 8}, // Factory MAC addr [3],
|
||||
{EFUSE_BLK0, 40, 8}, // Factory MAC addr [4],
|
||||
{EFUSE_BLK0, 32, 8}, // Factory MAC addr [5],
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t MAC_FACTORY_CRC[] = {
|
||||
{EFUSE_BLK0, 80, 8}, // CRC8 for factory MAC address,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t MAC_CUSTOM_CRC[] = {
|
||||
{EFUSE_BLK3, 0, 8}, // CRC8 for custom MAC address.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t MAC_CUSTOM[] = {
|
||||
{EFUSE_BLK3, 8, 48}, // Custom MAC,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t MAC_CUSTOM_VER[] = {
|
||||
{EFUSE_BLK3, 184, 8}, // Custom MAC version,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t SECURE_BOOT_KEY[] = {
|
||||
{EFUSE_BLK2, 0, 256}, // Security boot. Key.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t ABS_DONE_0[] = {
|
||||
{EFUSE_BLK0, 196, 1}, // Secure boot is enabled for bootloader image. EFUSE_RD_ABS_DONE_0,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t ENCRYPT_FLASH_KEY[] = {
|
||||
{EFUSE_BLK1, 0, 256}, // Flash encrypt. Key.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t ENCRYPT_CONFIG[] = {
|
||||
{EFUSE_BLK0, 188, 4}, // Flash encrypt. EFUSE_FLASH_CRYPT_CONFIG_M,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t DISABLE_DL_ENCRYPT[] = {
|
||||
{EFUSE_BLK0, 199, 1}, // Flash encrypt. Disable UART bootloader encryption. EFUSE_DISABLE_DL_ENCRYPT.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t DISABLE_DL_DECRYPT[] = {
|
||||
{EFUSE_BLK0, 200, 1}, // Flash encrypt. Disable UART bootloader decryption. EFUSE_DISABLE_DL_DECRYPT.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t DISABLE_DL_CACHE[] = {
|
||||
{EFUSE_BLK0, 201, 1}, // Flash encrypt. Disable UART bootloader MMU cache. EFUSE_DISABLE_DL_CACHE.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t DISABLE_JTAG[] = {
|
||||
{EFUSE_BLK0, 198, 1}, // Flash encrypt. Disable JTAG. EFUSE_RD_DISABLE_JTAG.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t CONSOLE_DEBUG_DISABLE[] = {
|
||||
{EFUSE_BLK0, 194, 1}, // Flash encrypt. Disable ROM BASIC interpreter fallback. EFUSE_RD_CONSOLE_DEBUG_DISABLE.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t FLASH_CRYPT_CNT[] = {
|
||||
{EFUSE_BLK0, 20, 8}, // Flash encrypt. Flash encryption is enabled if this field has an odd number of bits set. EFUSE_FLASH_CRYPT_CNT.,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t WR_DIS_FLASH_CRYPT_CNT[] = {
|
||||
{EFUSE_BLK0, 2, 1}, // Flash encrypt. Write protection FLASH_CRYPT_CNT. EFUSE_WR_DIS_FLASH_CRYPT_CNT,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t WR_DIS_BLK1[] = {
|
||||
{EFUSE_BLK0, 7, 1}, // Flash encrypt. Write protection encryption key. EFUSE_WR_DIS_BLK1,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t WR_DIS_BLK2[] = {
|
||||
{EFUSE_BLK0, 8, 1}, // Security boot. Write protection security key. EFUSE_WR_DIS_BLK2,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t WR_DIS_BLK3[] = {
|
||||
{EFUSE_BLK0, 9, 1}, // Write protection for EFUSE_BLK3. EFUSE_WR_DIS_BLK3,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t RD_DIS_BLK1[] = {
|
||||
{EFUSE_BLK0, 16, 1}, // Flash encrypt. efuse_key_read_protected. EFUSE_RD_DIS_BLK1,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t RD_DIS_BLK2[] = {
|
||||
{EFUSE_BLK0, 17, 1}, // Security boot. efuse_key_read_protected. EFUSE_RD_DIS_BLK2,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t RD_DIS_BLK3[] = {
|
||||
{EFUSE_BLK0, 18, 1}, // Read protection for EFUSE_BLK3. EFUSE_RD_DIS_BLK3,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t CHIP_VER_DIS_APP_CPU[] = {
|
||||
{EFUSE_BLK0, 96, 1}, // EFUSE_RD_CHIP_VER_DIS_APP_CPU,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t CHIP_VER_DIS_BT[] = {
|
||||
{EFUSE_BLK0, 97, 1}, // EFUSE_RD_CHIP_VER_DIS_BT,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t CHIP_VER_PKG[] = {
|
||||
{EFUSE_BLK0, 105, 3}, // EFUSE_RD_CHIP_VER_PKG,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t CHIP_CPU_FREQ_LOW[] = {
|
||||
{EFUSE_BLK0, 108, 1}, // EFUSE_RD_CHIP_CPU_FREQ_LOW,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t CHIP_CPU_FREQ_RATED[] = {
|
||||
{EFUSE_BLK0, 109, 1}, // EFUSE_RD_CHIP_CPU_FREQ_RATED,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t CHIP_VER_REV1[] = {
|
||||
{EFUSE_BLK0, 111, 1}, // EFUSE_RD_CHIP_VER_REV1,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t XPD_SDIO_REG[] = {
|
||||
{EFUSE_BLK0, 142, 1}, // EFUSE_RD_XPD_SDIO_REG,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t SDIO_TIEH[] = {
|
||||
{EFUSE_BLK0, 143, 1}, // EFUSE_RD_SDIO_TIEH,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t SDIO_FORCE[] = {
|
||||
{EFUSE_BLK0, 144, 1}, // EFUSE_RD_SDIO_FORCE,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t ADC_VREF_AND_SDIO_DREF[] = {
|
||||
{EFUSE_BLK0, 136, 6}, // EFUSE_RD_ADC_VREF[0..4] or ( SDIO_DREFH[0 1],
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t ADC1_TP_LOW[] = {
|
||||
{EFUSE_BLK3, 96, 7}, // TP_REG EFUSE_RD_ADC1_TP_LOW,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t ADC2_TP_LOW[] = {
|
||||
{EFUSE_BLK3, 112, 7}, // TP_REG EFUSE_RD_ADC2_TP_LOW,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t ADC1_TP_HIGH[] = {
|
||||
{EFUSE_BLK3, 103, 9}, // TP_REG EFUSE_RD_ADC1_TP_HIGH,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t ADC2_TP_HIGH[] = {
|
||||
{EFUSE_BLK3, 119, 9}, // TP_REG EFUSE_RD_ADC2_TP_HIGH,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY[] = {
|
||||
&MAC_FACTORY[0], // Factory MAC addr [0]
|
||||
&MAC_FACTORY[1], // Factory MAC addr [1]
|
||||
&MAC_FACTORY[2], // Factory MAC addr [2]
|
||||
&MAC_FACTORY[3], // Factory MAC addr [3]
|
||||
&MAC_FACTORY[4], // Factory MAC addr [4]
|
||||
&MAC_FACTORY[5], // Factory MAC addr [5]
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY_CRC[] = {
|
||||
&MAC_FACTORY_CRC[0], // CRC8 for factory MAC address
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_MAC_CUSTOM_CRC[] = {
|
||||
&MAC_CUSTOM_CRC[0], // CRC8 for custom MAC address.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_MAC_CUSTOM[] = {
|
||||
&MAC_CUSTOM[0], // Custom MAC
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_MAC_CUSTOM_VER[] = {
|
||||
&MAC_CUSTOM_VER[0], // Custom MAC version
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY[] = {
|
||||
&SECURE_BOOT_KEY[0], // Security boot. Key.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_ABS_DONE_0[] = {
|
||||
&ABS_DONE_0[0], // Secure boot is enabled for bootloader image. EFUSE_RD_ABS_DONE_0
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_ENCRYPT_FLASH_KEY[] = {
|
||||
&ENCRYPT_FLASH_KEY[0], // Flash encrypt. Key.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_ENCRYPT_CONFIG[] = {
|
||||
&ENCRYPT_CONFIG[0], // Flash encrypt. EFUSE_FLASH_CRYPT_CONFIG_M
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_ENCRYPT[] = {
|
||||
&DISABLE_DL_ENCRYPT[0], // Flash encrypt. Disable UART bootloader encryption. EFUSE_DISABLE_DL_ENCRYPT.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_DECRYPT[] = {
|
||||
&DISABLE_DL_DECRYPT[0], // Flash encrypt. Disable UART bootloader decryption. EFUSE_DISABLE_DL_DECRYPT.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_CACHE[] = {
|
||||
&DISABLE_DL_CACHE[0], // Flash encrypt. Disable UART bootloader MMU cache. EFUSE_DISABLE_DL_CACHE.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_DISABLE_JTAG[] = {
|
||||
&DISABLE_JTAG[0], // Flash encrypt. Disable JTAG. EFUSE_RD_DISABLE_JTAG.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_CONSOLE_DEBUG_DISABLE[] = {
|
||||
&CONSOLE_DEBUG_DISABLE[0], // Flash encrypt. Disable ROM BASIC interpreter fallback. EFUSE_RD_CONSOLE_DEBUG_DISABLE.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_FLASH_CRYPT_CNT[] = {
|
||||
&FLASH_CRYPT_CNT[0], // Flash encrypt. Flash encryption is enabled if this field has an odd number of bits set. EFUSE_FLASH_CRYPT_CNT.
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT[] = {
|
||||
&WR_DIS_FLASH_CRYPT_CNT[0], // Flash encrypt. Write protection FLASH_CRYPT_CNT. EFUSE_WR_DIS_FLASH_CRYPT_CNT
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK1[] = {
|
||||
&WR_DIS_BLK1[0], // Flash encrypt. Write protection encryption key. EFUSE_WR_DIS_BLK1
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK2[] = {
|
||||
&WR_DIS_BLK2[0], // Security boot. Write protection security key. EFUSE_WR_DIS_BLK2
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK3[] = {
|
||||
&WR_DIS_BLK3[0], // Write protection for EFUSE_BLK3. EFUSE_WR_DIS_BLK3
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_BLK1[] = {
|
||||
&RD_DIS_BLK1[0], // Flash encrypt. efuse_key_read_protected. EFUSE_RD_DIS_BLK1
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_BLK2[] = {
|
||||
&RD_DIS_BLK2[0], // Security boot. efuse_key_read_protected. EFUSE_RD_DIS_BLK2
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_BLK3[] = {
|
||||
&RD_DIS_BLK3[0], // Read protection for EFUSE_BLK3. EFUSE_RD_DIS_BLK3
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_DIS_APP_CPU[] = {
|
||||
&CHIP_VER_DIS_APP_CPU[0], // EFUSE_RD_CHIP_VER_DIS_APP_CPU
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_DIS_BT[] = {
|
||||
&CHIP_VER_DIS_BT[0], // EFUSE_RD_CHIP_VER_DIS_BT
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_PKG[] = {
|
||||
&CHIP_VER_PKG[0], // EFUSE_RD_CHIP_VER_PKG
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_CHIP_CPU_FREQ_LOW[] = {
|
||||
&CHIP_CPU_FREQ_LOW[0], // EFUSE_RD_CHIP_CPU_FREQ_LOW
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_CHIP_CPU_FREQ_RATED[] = {
|
||||
&CHIP_CPU_FREQ_RATED[0], // EFUSE_RD_CHIP_CPU_FREQ_RATED
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_REV1[] = {
|
||||
&CHIP_VER_REV1[0], // EFUSE_RD_CHIP_VER_REV1
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_XPD_SDIO_REG[] = {
|
||||
&XPD_SDIO_REG[0], // EFUSE_RD_XPD_SDIO_REG
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_SDIO_TIEH[] = {
|
||||
&SDIO_TIEH[0], // EFUSE_RD_SDIO_TIEH
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_SDIO_FORCE[] = {
|
||||
&SDIO_FORCE[0], // EFUSE_RD_SDIO_FORCE
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_ADC_VREF_AND_SDIO_DREF[] = {
|
||||
&ADC_VREF_AND_SDIO_DREF[0], // EFUSE_RD_ADC_VREF[0..4] or ( SDIO_DREFH[0 1]
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_ADC1_TP_LOW[] = {
|
||||
&ADC1_TP_LOW[0], // TP_REG EFUSE_RD_ADC1_TP_LOW
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_ADC2_TP_LOW[] = {
|
||||
&ADC2_TP_LOW[0], // TP_REG EFUSE_RD_ADC2_TP_LOW
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_ADC1_TP_HIGH[] = {
|
||||
&ADC1_TP_HIGH[0], // TP_REG EFUSE_RD_ADC1_TP_HIGH
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_ADC2_TP_HIGH[] = {
|
||||
&ADC2_TP_HIGH[0], // TP_REG EFUSE_RD_ADC2_TP_HIGH
|
||||
NULL
|
||||
};
|
||||
|
80
components/efuse/esp32/esp_efuse_table.csv
Normal file
80
components/efuse/esp32/esp_efuse_table.csv
Normal file
@ -0,0 +1,80 @@
|
||||
# field_name, | efuse_block, | bit_start, | bit_count, |comment #
|
||||
# | (EFUSE_BLK0 | (0..255) | (1..256) | #
|
||||
# | EFUSE_BLK1 | | | #
|
||||
# | EFUSE_BLK2 | | | #
|
||||
# | EFUSE_BLK3) | | | #
|
||||
##########################################################################
|
||||
# !!!!!!!!!!! #
|
||||
# After editing this file, run the command manually "make efuse_common_table" or "idf.py efuse_common_table"
|
||||
# this will generate new source files, next rebuild all the sources.
|
||||
# !!!!!!!!!!! #
|
||||
|
||||
# Factory MAC address #
|
||||
#######################
|
||||
MAC_FACTORY, EFUSE_BLK0, 72, 8, Factory MAC addr [0]
|
||||
, EFUSE_BLK0, 64, 8, Factory MAC addr [1]
|
||||
, EFUSE_BLK0, 56, 8, Factory MAC addr [2]
|
||||
, EFUSE_BLK0, 48, 8, Factory MAC addr [3]
|
||||
, EFUSE_BLK0, 40, 8, Factory MAC addr [4]
|
||||
, EFUSE_BLK0, 32, 8, Factory MAC addr [5]
|
||||
MAC_FACTORY_CRC, EFUSE_BLK0, 80, 8, CRC8 for factory MAC address
|
||||
|
||||
# Custom MAC address #
|
||||
######################
|
||||
MAC_CUSTOM_CRC, EFUSE_BLK3, 0, 8, CRC8 for custom MAC address.
|
||||
MAC_CUSTOM, EFUSE_BLK3, 8, 48, Custom MAC
|
||||
MAC_CUSTOM_VER, EFUSE_BLK3, 184, 8, Custom MAC version
|
||||
|
||||
# Security boot #
|
||||
#################
|
||||
SECURE_BOOT_KEY, EFUSE_BLK2, 0, 256, Security boot. Key.
|
||||
ABS_DONE_0, EFUSE_BLK0, 196, 1, Secure boot is enabled for bootloader image. EFUSE_RD_ABS_DONE_0
|
||||
|
||||
# Flash encrypt #
|
||||
#################
|
||||
ENCRYPT_FLASH_KEY, EFUSE_BLK1, 0, 256, Flash encrypt. Key.
|
||||
ENCRYPT_CONFIG, EFUSE_BLK0, 188, 4, Flash encrypt. EFUSE_FLASH_CRYPT_CONFIG_M
|
||||
|
||||
DISABLE_DL_ENCRYPT, EFUSE_BLK0, 199, 1, Flash encrypt. Disable UART bootloader encryption. EFUSE_DISABLE_DL_ENCRYPT.
|
||||
DISABLE_DL_DECRYPT, EFUSE_BLK0, 200, 1, Flash encrypt. Disable UART bootloader decryption. EFUSE_DISABLE_DL_DECRYPT.
|
||||
DISABLE_DL_CACHE, EFUSE_BLK0, 201, 1, Flash encrypt. Disable UART bootloader MMU cache. EFUSE_DISABLE_DL_CACHE.
|
||||
DISABLE_JTAG, EFUSE_BLK0, 198, 1, Flash encrypt. Disable JTAG. EFUSE_RD_DISABLE_JTAG.
|
||||
CONSOLE_DEBUG_DISABLE, EFUSE_BLK0, 194, 1, Flash encrypt. Disable ROM BASIC interpreter fallback. EFUSE_RD_CONSOLE_DEBUG_DISABLE.
|
||||
FLASH_CRYPT_CNT, EFUSE_BLK0, 20, 8, Flash encrypt. Flash encryption is enabled if this field has an odd number of bits set. EFUSE_FLASH_CRYPT_CNT.
|
||||
|
||||
# Write protection #
|
||||
####################
|
||||
WR_DIS_FLASH_CRYPT_CNT, EFUSE_BLK0, 2, 1, Flash encrypt. Write protection FLASH_CRYPT_CNT. EFUSE_WR_DIS_FLASH_CRYPT_CNT
|
||||
WR_DIS_BLK1, EFUSE_BLK0, 7, 1, Flash encrypt. Write protection encryption key. EFUSE_WR_DIS_BLK1
|
||||
WR_DIS_BLK2, EFUSE_BLK0, 8, 1, Security boot. Write protection security key. EFUSE_WR_DIS_BLK2
|
||||
WR_DIS_BLK3, EFUSE_BLK0, 9, 1, Write protection for EFUSE_BLK3. EFUSE_WR_DIS_BLK3
|
||||
|
||||
# Read protection #
|
||||
###################
|
||||
RD_DIS_BLK1, EFUSE_BLK0, 16, 1, Flash encrypt. efuse_key_read_protected. EFUSE_RD_DIS_BLK1
|
||||
RD_DIS_BLK2, EFUSE_BLK0, 17, 1, Security boot. efuse_key_read_protected. EFUSE_RD_DIS_BLK2
|
||||
RD_DIS_BLK3, EFUSE_BLK0, 18, 1, Read protection for EFUSE_BLK3. EFUSE_RD_DIS_BLK3
|
||||
|
||||
# Chip info #
|
||||
#############
|
||||
CHIP_VER_DIS_APP_CPU, EFUSE_BLK0, 96, 1, EFUSE_RD_CHIP_VER_DIS_APP_CPU
|
||||
CHIP_VER_DIS_BT, EFUSE_BLK0, 97, 1, EFUSE_RD_CHIP_VER_DIS_BT
|
||||
CHIP_VER_PKG, EFUSE_BLK0, 105, 3, EFUSE_RD_CHIP_VER_PKG
|
||||
CHIP_CPU_FREQ_LOW, EFUSE_BLK0, 108, 1, EFUSE_RD_CHIP_CPU_FREQ_LOW
|
||||
CHIP_CPU_FREQ_RATED, EFUSE_BLK0, 109, 1, EFUSE_RD_CHIP_CPU_FREQ_RATED
|
||||
CHIP_VER_REV1, EFUSE_BLK0, 111, 1, EFUSE_RD_CHIP_VER_REV1
|
||||
XPD_SDIO_REG, EFUSE_BLK0, 142, 1, EFUSE_RD_XPD_SDIO_REG
|
||||
SDIO_TIEH, EFUSE_BLK0, 143, 1, EFUSE_RD_SDIO_TIEH
|
||||
SDIO_FORCE, EFUSE_BLK0, 144, 1, EFUSE_RD_SDIO_FORCE
|
||||
|
||||
#SDIO_DREFH, EFUSE_BLK0, 136, 2, EFUSE_RD_SDIO_DREFH
|
||||
#SDIO_DREFM, EFUSE_BLK0, 138, 2, EFUSE_RD_SDIO_DREFM
|
||||
#SDIO_DREFL, EFUSE_BLK0, 140, 2, EFUSE_RD_SDIO_DREFL
|
||||
|
||||
# esp_adc_cal #
|
||||
###############
|
||||
ADC_VREF_AND_SDIO_DREF, EFUSE_BLK0, 136, 6, EFUSE_RD_ADC_VREF[0..4] or ( SDIO_DREFH[0 1], SDIO_DREFM[2 3], SDIO_DREFL[4 5] )
|
||||
ADC1_TP_LOW, EFUSE_BLK3, 96, 7, TP_REG EFUSE_RD_ADC1_TP_LOW
|
||||
ADC2_TP_LOW, EFUSE_BLK3, 112, 7, TP_REG EFUSE_RD_ADC2_TP_LOW
|
||||
ADC1_TP_HIGH, EFUSE_BLK3, 103, 9, TP_REG EFUSE_RD_ADC1_TP_HIGH
|
||||
ADC2_TP_HIGH, EFUSE_BLK3, 119, 9, TP_REG EFUSE_RD_ADC2_TP_HIGH
|
Can't render this file because it contains an unexpected character in line 8 and column 53.
|
66
components/efuse/esp32/include/esp_efuse_table.h
Normal file
66
components/efuse/esp32/include/esp_efuse_table.h
Normal file
@ -0,0 +1,66 @@
|
||||
// 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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// md5_digest 963d6d14dc4bd997fd5d4b9de351745d
|
||||
// This file was generated automatically from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
// If you want to change some fields, you need to change esp_efuse_table.csv file then build system will generate this header file
|
||||
// To show efuse_table run the command 'make show_efuse_table'.
|
||||
|
||||
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY_CRC[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_MAC_CUSTOM_CRC[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_MAC_CUSTOM[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_MAC_CUSTOM_VER[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_ABS_DONE_0[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_ENCRYPT_FLASH_KEY[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_ENCRYPT_CONFIG[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_ENCRYPT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_DECRYPT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_DL_CACHE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DISABLE_JTAG[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CONSOLE_DEBUG_DISABLE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_CRYPT_CNT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK3[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_BLK1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_BLK2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_BLK3[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_DIS_APP_CPU[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_DIS_BT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_PKG[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_CPU_FREQ_LOW[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_CPU_FREQ_RATED[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_REV1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_XPD_SDIO_REG[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SDIO_TIEH[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SDIO_FORCE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_ADC_VREF_AND_SDIO_DREF[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_TP_LOW[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_TP_LOW[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_TP_HIGH[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_TP_HIGH[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
1
components/efuse/esp32/sources.cmake
Normal file
1
components/efuse/esp32/sources.cmake
Normal file
@ -0,0 +1 @@
|
||||
set(EFUSE_SOC_SRCS "esp_efuse_table.c")
|
294
components/efuse/include/esp_efuse.h
Normal file
294
components/efuse/include/esp_efuse.h
Normal file
@ -0,0 +1,294 @@
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP_EFUSE_MANAGER_H_
|
||||
#define _ESP_EFUSE_MANAGER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define ESP_ERR_EFUSE 0x1600 /*!< Base error code for efuse api. */
|
||||
#define ESP_OK_EFUSE_CNT (ESP_ERR_EFUSE + 0x01) /*!< OK the required number of bits is set. */
|
||||
#define ESP_ERR_EFUSE_CNT_IS_FULL (ESP_ERR_EFUSE + 0x02) /*!< Error field is full. */
|
||||
#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. */
|
||||
|
||||
/**
|
||||
* @brief Type of eFuse blocks
|
||||
*/
|
||||
typedef enum {
|
||||
EFUSE_BLK0 = 0, /**< Number of eFuse block. Reserved. */
|
||||
EFUSE_BLK1 = 1, /**< Number of eFuse block. Used for Flash Encryption. If not using that Flash Encryption feature, they can be used for another purpose. */
|
||||
EFUSE_BLK2 = 2, /**< Number of eFuse block. Used for Secure Boot. If not using that Secure Boot feature, they can be used for another purpose. */
|
||||
EFUSE_BLK3 = 3 /**< Number of eFuse block. Uses for the purpose of the user. */
|
||||
} esp_efuse_block_t;
|
||||
|
||||
/**
|
||||
* @brief Type of coding scheme
|
||||
*/
|
||||
typedef enum {
|
||||
EFUSE_CODING_SCHEME_NONE = 0, /**< None */
|
||||
EFUSE_CODING_SCHEME_3_4 = 1, /**< 3/4 coding */
|
||||
EFUSE_CODING_SCHEME_REPEAT = 2, /**< Repeat coding */
|
||||
} esp_efuse_coding_scheme_t;
|
||||
|
||||
/**
|
||||
* @brief Structure eFuse field
|
||||
*/
|
||||
typedef struct {
|
||||
esp_efuse_block_t efuse_block; /**< Block of eFuse */
|
||||
uint16_t bit_start; /**< Start bit [0..255] */
|
||||
uint16_t bit_count; /**< Length of bit field [1..256]*/
|
||||
} esp_efuse_desc_t;
|
||||
|
||||
/**
|
||||
* @brief Reads bits from EFUSE field and writes it into an array.
|
||||
*
|
||||
* The number of read bits will be limited to the minimum value
|
||||
* from the description of the bits in "field" structure or "dst_size_bits" required size.
|
||||
* Use "esp_efuse_get_field_size()" function to determine the length of the field.
|
||||
* @param[in] field A pointer to the structure describing the fields of efuse.
|
||||
* @param[out] dst A pointer to array that will contain the result of reading.
|
||||
* @param[in] dst_size_bits The number of bits required to read.
|
||||
* If the requested number of bits is greater than the field,
|
||||
* the number will be limited to the field size.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed.
|
||||
* - ESP_ERR_INVALID_ARG: Error in the passed arguments.
|
||||
*/
|
||||
esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst, size_t dst_size_bits);
|
||||
|
||||
/**
|
||||
* @brief Reads bits from EFUSE field and returns number of bits programmed as "1".
|
||||
*
|
||||
* If the bits are set not sequentially, they will still be counted.
|
||||
* @param[in] field A pointer to the structure describing the fields of efuse.
|
||||
* @param[out] out_cnt A pointer that will contain the number of programmed as "1" bits.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed.
|
||||
* - ESP_ERR_INVALID_ARG: Error in the passed arguments.
|
||||
*/
|
||||
esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_cnt);
|
||||
|
||||
/**
|
||||
* @brief Writes array to EFUSE field.
|
||||
*
|
||||
* The number of write bits will be limited to the minimum value
|
||||
* from the description of the bits in "field" structure or "src_size_bits" required size.
|
||||
* Use "esp_efuse_get_field_size()" function to determine the length of the field.
|
||||
* After the function is completed, the writing registers are cleared.
|
||||
* @param[in] field A pointer to the structure describing the fields of efuse.
|
||||
* @param[in] src A pointer to array that contains the data for writing.
|
||||
* @param[in] src_size_bits The number of bits required to write.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed.
|
||||
* - ESP_ERR_INVALID_ARG: Error in the passed arguments.
|
||||
* - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden.
|
||||
* - ESP_ERR_CODING: Error range of data does not match the coding scheme.
|
||||
*/
|
||||
esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void* src, size_t src_size_bits);
|
||||
|
||||
/**
|
||||
* @brief Writes a required count of bits as "1" to EFUSE field.
|
||||
*
|
||||
* If there are no free bits in the field to set the required number of bits to "1",
|
||||
* ESP_ERR_EFUSE_CNT_IS_FULL error is returned, the field will not be partially recorded.
|
||||
* After the function is completed, the writing registers are cleared.
|
||||
* @param[in] field A pointer to the structure describing the fields of efuse.
|
||||
* @param[in] cnt Required number of programmed as "1" bits.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed.
|
||||
* - ESP_ERR_INVALID_ARG: Error in the passed arguments.
|
||||
* - ESP_ERR_EFUSE_CNT_IS_FULL: Not all requested cnt bits is set.
|
||||
*/
|
||||
esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of bits used by field.
|
||||
*
|
||||
* @param[in] field A pointer to the structure describing the fields of efuse.
|
||||
*
|
||||
* @return Returns the number of bits used by field.
|
||||
*/
|
||||
esp_err_t esp_efuse_get_field_size(const esp_efuse_desc_t* field[]);
|
||||
|
||||
/**
|
||||
* @brief Returns value of efuse register.
|
||||
*
|
||||
* This is a thread-safe implementation.
|
||||
* Example: EFUSE_BLK2_RDATA3_REG where (blk=2, num_reg=3)
|
||||
* @param[in] blk Block number of eFuse.
|
||||
* @param[in] num_reg The register number in the block.
|
||||
*
|
||||
* @return Value of register
|
||||
*/
|
||||
uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg);
|
||||
|
||||
/**
|
||||
* @brief Write value to efuse register.
|
||||
*
|
||||
* Apply a coding scheme if necessary.
|
||||
* This is a thread-safe implementation.
|
||||
* Example: EFUSE_BLK3_WDATA0_REG where (blk=3, num_reg=0)
|
||||
* @param[in] blk Block number of eFuse.
|
||||
* @param[in] num_reg The register number in the block.
|
||||
* @param[in] val Value to write.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed.
|
||||
* - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param[in] blk Block number of eFuse.
|
||||
* @return Return efuse coding_scheme for blocks
|
||||
*/
|
||||
esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk);
|
||||
|
||||
/**
|
||||
* @brief Read key to efuse block starting at the offset and the required size.
|
||||
*
|
||||
* @param[in] blk Block number of eFuse.
|
||||
* @param[in] dst_key A pointer to array that will contain the result of reading.
|
||||
* @param[in] offset_in_bits Start bit in block.
|
||||
* @param[in] size_bits The number of bits required to read.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed.
|
||||
* - ESP_ERR_INVALID_ARG: Error in the passed arguments.
|
||||
* - ESP_ERR_CODING: Error range of data does not match the coding scheme.
|
||||
*/
|
||||
esp_err_t esp_efuse_read_block(esp_efuse_block_t blk, void* dst_key, size_t offset_in_bits, size_t size_bits);
|
||||
|
||||
/**
|
||||
* @brief Write key to efuse block starting at the offset and the required size.
|
||||
*
|
||||
* @param[in] blk Block number of eFuse.
|
||||
* @param[in] src_key A pointer to array that contains the key for writing.
|
||||
* @param[in] offset_in_bits Start bit in block.
|
||||
* @param[in] size_bits The number of bits required to write.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed.
|
||||
* - ESP_ERR_INVALID_ARG: Error in the passed arguments.
|
||||
* - ESP_ERR_CODING: Error range of data does not match the coding scheme.
|
||||
* - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief Returns chip version from efuse
|
||||
*
|
||||
* @return chip version
|
||||
*/
|
||||
uint8_t esp_efuse_get_chip_ver(void);
|
||||
|
||||
/**
|
||||
* @brief Returns chip package from efuse
|
||||
*
|
||||
* @return chip package
|
||||
*/
|
||||
uint32_t esp_efuse_get_pkg_ver(void);
|
||||
|
||||
/* @brief Permanently update values written to the efuse write registers
|
||||
*
|
||||
* After updating EFUSE_BLKx_WDATAx_REG registers with new values to
|
||||
* write, call this function to permanently write them to efuse.
|
||||
*
|
||||
* @note Setting bits in efuse is permanent, they cannot be unset.
|
||||
*
|
||||
* @note Due to this restriction you don't need to copy values to
|
||||
* Efuse write registers from the matching read registers, bits which
|
||||
* are set in the read register but unset in the matching write
|
||||
* register will be unchanged when new values are burned.
|
||||
*
|
||||
* @note This function is not threadsafe, if calling code updates
|
||||
* efuse values from multiple tasks then this is caller's
|
||||
* responsibility to serialise.
|
||||
*
|
||||
* After burning new efuses, the read registers are updated to match
|
||||
* the new efuse values.
|
||||
*/
|
||||
void esp_efuse_burn_new_values(void);
|
||||
|
||||
/* @brief Reset efuse write registers
|
||||
*
|
||||
* Efuse write registers are written to zero, to negate
|
||||
* any changes that have been staged here.
|
||||
*
|
||||
* @note This function is not threadsafe, if calling code updates
|
||||
* efuse values from multiple tasks then this is caller's
|
||||
* responsibility to serialise.
|
||||
*/
|
||||
void esp_efuse_reset(void);
|
||||
|
||||
/* @brief Disable BASIC ROM Console via efuse
|
||||
*
|
||||
* By default, if booting from flash fails the ESP32 will boot a
|
||||
* BASIC console in ROM.
|
||||
*
|
||||
* Call this function (from bootloader or app) to permanently
|
||||
* disable the console on this chip.
|
||||
*/
|
||||
void esp_efuse_disable_basic_rom_console(void);
|
||||
|
||||
/* @brief Encode one or more sets of 6 byte sequences into
|
||||
* 8 bytes suitable for 3/4 Coding Scheme.
|
||||
*
|
||||
* This function is only useful if the CODING_SCHEME efuse
|
||||
* is set to value 1 for 3/4 Coding Scheme.
|
||||
*
|
||||
* @param[in] in_bytes Pointer to a sequence of bytes to encode for 3/4 Coding Scheme. Must have length in_bytes_len. After being written to hardware, these bytes will read back as little-endian words.
|
||||
* @param[out] out_words Pointer to array of words suitable for writing to efuse write registers. Array must contain 2 words (8 bytes) for every 6 bytes in in_bytes_len. Can be a pointer to efuse write registers.
|
||||
* @param in_bytes_len. Length of array pointed to by in_bytes, in bytes. Must be a multiple of 6.
|
||||
*
|
||||
* @return ESP_ERR_INVALID_ARG if either pointer is null or in_bytes_len is not a multiple of 6. ESP_OK otherwise.
|
||||
*/
|
||||
esp_err_t esp_efuse_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len);
|
||||
|
||||
/* @brief Write random data to efuse key block write registers
|
||||
*
|
||||
* @note Caller is responsible for ensuring efuse
|
||||
* block is empty and not write protected, before calling.
|
||||
*
|
||||
* @note Behaviour depends on coding scheme: a 256-bit key is
|
||||
* generated and written for Coding Scheme "None", a 192-bit key
|
||||
* is generated, extended to 256-bits by the Coding Scheme,
|
||||
* and then writtten for 3/4 Coding Scheme.
|
||||
*
|
||||
* @note This function does not burn the new values, caller should
|
||||
* call esp_efuse_burn_new_values() when ready to do this.
|
||||
*
|
||||
* @param blk_wdata0_reg Address of the first data write register
|
||||
* in the block
|
||||
*/
|
||||
void esp_efuse_write_random_key(uint32_t blk_wdata0_reg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _ESP_EFUSE_MANAGER_H_
|
214
components/efuse/src/esp_efuse_api.c
Normal file
214
components/efuse/src/esp_efuse_api.c
Normal file
@ -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;
|
||||
}
|
117
components/efuse/src/esp_efuse_fields.c
Normal file
117
components/efuse/src/esp_efuse_fields.c
Normal file
@ -0,0 +1,117 @@
|
||||
// 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 "esp_efuse_table.h"
|
||||
#include "stdlib.h"
|
||||
#include "esp_types.h"
|
||||
#include "rom/efuse.h"
|
||||
#include "assert.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "bootloader_random.h"
|
||||
|
||||
const static char *TAG = "efuse";
|
||||
|
||||
// Contains functions that provide access to efuse fields which are often used in IDF.
|
||||
|
||||
// Returns chip version from efuse
|
||||
uint8_t esp_efuse_get_chip_ver(void)
|
||||
{
|
||||
uint8_t chip_ver;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_CHIP_VER_REV1, &chip_ver, 1);
|
||||
return chip_ver;
|
||||
}
|
||||
|
||||
// Returns chip package from efuse
|
||||
uint32_t esp_efuse_get_pkg_ver(void)
|
||||
{
|
||||
uint32_t pkg_ver;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_CHIP_VER_PKG, &pkg_ver, 3);
|
||||
return pkg_ver;
|
||||
}
|
||||
|
||||
// Permanently update values written to the efuse write registers
|
||||
void esp_efuse_burn_new_values(void)
|
||||
{
|
||||
esp_efuse_utility_burn_efuses();
|
||||
}
|
||||
|
||||
// Reset efuse write registers
|
||||
void esp_efuse_reset(void)
|
||||
{
|
||||
esp_efuse_utility_reset();
|
||||
}
|
||||
|
||||
// Disable BASIC ROM Console via efuse
|
||||
void esp_efuse_disable_basic_rom_console(void)
|
||||
{
|
||||
if (esp_efuse_write_field_cnt(ESP_EFUSE_CONSOLE_DEBUG_DISABLE, 1) == ESP_OK) {
|
||||
ESP_EARLY_LOGI(TAG, "Disable BASIC ROM Console fallback via efuse...");
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_apply_34_encoding(const uint8_t *in_bytes, uint32_t *out_words, size_t in_bytes_len)
|
||||
{
|
||||
if (in_bytes == NULL || out_words == NULL || in_bytes_len % 6 != 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
while (in_bytes_len > 0) {
|
||||
uint8_t out[8];
|
||||
uint8_t xor = 0;
|
||||
uint8_t mul = 0;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
xor ^= in_bytes[i];
|
||||
mul += (i + 1) * __builtin_popcount(in_bytes[i]);
|
||||
}
|
||||
|
||||
memcpy(out, in_bytes, 6); // Data bytes
|
||||
out[6] = xor;
|
||||
out[7] = mul;
|
||||
|
||||
memcpy(out_words, out, 8);
|
||||
|
||||
in_bytes_len -= 6;
|
||||
in_bytes += 6;
|
||||
out_words += 2;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void esp_efuse_write_random_key(uint32_t blk_wdata0_reg)
|
||||
{
|
||||
uint32_t buf[8];
|
||||
uint8_t raw[24];
|
||||
uint32_t coding_scheme = REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_CODING_SCHEME_M;
|
||||
|
||||
if (coding_scheme == EFUSE_CODING_SCHEME_VAL_NONE) {
|
||||
bootloader_fill_random(buf, sizeof(buf));
|
||||
} else { // 3/4 Coding Scheme
|
||||
bootloader_fill_random(raw, sizeof(raw));
|
||||
esp_err_t r = esp_efuse_apply_34_encoding(raw, buf, sizeof(raw));
|
||||
assert(r == ESP_OK);
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Writing random values to address 0x%08x", blk_wdata0_reg);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ESP_LOGV(TAG, "EFUSE_BLKx_WDATA%d_REG = 0x%08x", i, buf[i]);
|
||||
REG_WRITE(blk_wdata0_reg + 4*i, buf[i]);
|
||||
}
|
||||
bzero(buf, sizeof(buf));
|
||||
bzero(raw, sizeof(raw));
|
||||
}
|
512
components/efuse/src/esp_efuse_utility.c
Normal file
512
components/efuse/src/esp_efuse_utility.c
Normal file
@ -0,0 +1,512 @@
|
||||
// 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_utility.h"
|
||||
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "esp_log.h"
|
||||
#include "assert.h"
|
||||
#include "sdkconfig.h"
|
||||
#include <sys/param.h>
|
||||
|
||||
static const char *TAG = "efuse";
|
||||
|
||||
#define COUNT_EFUSE_BLOCKS 4 /* The number of blocks. */
|
||||
#define COUNT_EFUSE_REG_PER_BLOCK 8 /* The number of registers per block. */
|
||||
#define EFUSE_CONF_WRITE 0x5A5A /* eFuse_pgm_op_ena, force no rd/wr disable. */
|
||||
#define EFUSE_CONF_READ 0x5AA5 /* eFuse_read_op_ena, release force. */
|
||||
#define EFUSE_CMD_PGM 0x02 /* Command to program. */
|
||||
#define EFUSE_CMD_READ 0x01 /* Command to read. */
|
||||
|
||||
// Array for emulate efuse registers.
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
static uint32_t virt_blocks[COUNT_EFUSE_BLOCKS][COUNT_EFUSE_REG_PER_BLOCK];
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Structure range address by blocks
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
} esp_efuse_range_addr_t;
|
||||
|
||||
/*Range addresses to read blocks*/
|
||||
static const esp_efuse_range_addr_t range_read_addr_blocks[] = {
|
||||
{EFUSE_BLK0_RDATA0_REG, EFUSE_BLK0_RDATA6_REG}, // range address of EFUSE_BLK0
|
||||
{EFUSE_BLK1_RDATA0_REG, EFUSE_BLK1_RDATA7_REG}, // range address of EFUSE_BLK1
|
||||
{EFUSE_BLK2_RDATA0_REG, EFUSE_BLK2_RDATA7_REG}, // range address of EFUSE_BLK2
|
||||
{EFUSE_BLK3_RDATA0_REG, EFUSE_BLK3_RDATA7_REG} // range address of EFUSE_BLK3
|
||||
};
|
||||
|
||||
/*Range addresses to write blocks*/
|
||||
static 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
|
||||
};
|
||||
|
||||
static int get_reg_num(int bit_start, int bit_count, int i_reg);
|
||||
static int get_starting_bit_num_in_reg(int bit_start, int i_reg);
|
||||
static uint32_t get_mask(unsigned int bit_count, unsigned int shift);
|
||||
static int get_count_bits_in_reg(int bit_start, int bit_count, int i_reg);
|
||||
static void write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t value);
|
||||
static uint32_t fill_reg(int bit_start_in_reg, int bit_count_in_reg, uint8_t* blob, int* filled_bits_blob);
|
||||
static uint32_t set_cnt_in_reg(int bit_start_in_reg, int bit_count_used_in_reg, uint32_t reg_masked, size_t* cnt);
|
||||
static bool check_range_of_bits(esp_efuse_block_t blk, int offset_in_bits, int size_bits);
|
||||
|
||||
// This function processes the field by calling the passed function.
|
||||
esp_err_t esp_efuse_utility_process(const esp_efuse_desc_t* field[], void* ptr, size_t ptr_size_bits, efuse_func_proc_t func_proc)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
int bits_counter = 0;
|
||||
|
||||
// get and check size.
|
||||
int field_len = esp_efuse_get_field_size(field);
|
||||
int req_size = (ptr_size_bits == 0) ? field_len : MIN(ptr_size_bits, field_len);
|
||||
|
||||
int i = 0;
|
||||
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_LOGE(TAG, "Range of data does not match the coding scheme");
|
||||
err = ESP_ERR_CODING;
|
||||
}
|
||||
int i_reg = 0;
|
||||
int num_reg;
|
||||
while (err == ESP_OK && req_size > bits_counter &&
|
||||
(num_reg = get_reg_num(field[i]->bit_start, field[i]->bit_count, i_reg)) != -1) {
|
||||
|
||||
int start_bit = get_starting_bit_num_in_reg(field[i]->bit_start, i_reg);
|
||||
int num_bits = get_count_bits_in_reg(field[i]->bit_start, field[i]->bit_count, i_reg);
|
||||
if ((bits_counter + num_bits) > req_size) { // Limits the length of the field.
|
||||
num_bits = req_size - bits_counter;
|
||||
}
|
||||
ESP_LOGD(TAG, "In EFUSE_BLK%d__DATA%d_REG is used %d bits starting with %d bit",
|
||||
(int)field[i]->efuse_block, num_reg, num_bits, start_bit);
|
||||
err = func_proc(num_reg, field[i]->efuse_block, start_bit, num_bits, ptr, &bits_counter);
|
||||
++i_reg;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(bits_counter <= req_size);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
// Read efuse register and write this value to array.
|
||||
esp_err_t esp_efuse_utility_fill_buff(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* arr_out, int* bits_counter)
|
||||
{
|
||||
uint8_t* blob = (uint8_t *) arr_out;
|
||||
uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
|
||||
uint64_t reg_of_aligned_bits = (reg >> bit_start) & get_mask(bit_count, 0);
|
||||
|
||||
int shift_bit = (*bits_counter) % 8;
|
||||
if (shift_bit != 0) {
|
||||
blob[(*bits_counter) / 8] |= (uint8_t)(reg_of_aligned_bits << shift_bit);
|
||||
shift_bit = ((8 - shift_bit) < bit_count) ? (8 - shift_bit) : bit_count;
|
||||
(*bits_counter) += shift_bit;
|
||||
bit_count -= shift_bit;
|
||||
}
|
||||
|
||||
int sum_shift = 0;
|
||||
while (bit_count > 0) {
|
||||
sum_shift += shift_bit;
|
||||
blob[(*bits_counter) / 8] |= (uint8_t)(reg_of_aligned_bits >> sum_shift);
|
||||
shift_bit = (bit_count > 8) ? 8 : bit_count;
|
||||
(*bits_counter) += shift_bit;
|
||||
bit_count -= shift_bit;
|
||||
};
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Count a set bits.
|
||||
esp_err_t esp_efuse_utility_count_once(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* out_cnt, int* bits_counter)
|
||||
{
|
||||
uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
|
||||
*((size_t *)out_cnt) += __builtin_popcount(reg & get_mask(bit_count, bit_start)); // Returns the number of 1-bits in reg.
|
||||
*bits_counter += bit_count;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Fill registers from array for writing.
|
||||
esp_err_t esp_efuse_utility_write_blob(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* arr_in, int* bits_counter)
|
||||
{
|
||||
uint32_t reg_to_write = fill_reg(bit_start, bit_count, (uint8_t *)arr_in, bits_counter);
|
||||
return esp_efuse_utility_write_reg(efuse_block, num_reg, reg_to_write);
|
||||
}
|
||||
|
||||
// fill registers with the required number of bits for writing.
|
||||
esp_err_t esp_efuse_utility_write_cnt(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* cnt, int* bits_counter)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
|
||||
size_t* set_bits = (size_t*)cnt;
|
||||
uint32_t mask = get_mask(bit_count, bit_start);
|
||||
uint32_t reg_masked_bits = reg & mask;
|
||||
if ((reg_masked_bits ^ mask) != 0) {// register has free bits to set them to 1?
|
||||
uint32_t reg_to_write = set_cnt_in_reg(bit_start, bit_count, reg_masked_bits, set_bits);
|
||||
write_reg(efuse_block, num_reg, reg_to_write);
|
||||
}
|
||||
*bits_counter += bit_count;
|
||||
if ((*set_bits) == 0) {
|
||||
err = ESP_OK_EFUSE_CNT;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// Reset efuse write registers
|
||||
void esp_efuse_utility_reset(void)
|
||||
{
|
||||
REG_WRITE(EFUSE_CONF_REG, EFUSE_CONF_READ);
|
||||
for (int num_block = 0; num_block < COUNT_EFUSE_BLOCKS; 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Burn values written to the efuse write registers
|
||||
void esp_efuse_utility_burn_efuses(void)
|
||||
{
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
ESP_LOGE(TAG, "Not really burning any efuses!");
|
||||
for (int num_block = 0; num_block < COUNT_EFUSE_BLOCKS; 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]);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// 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) {};
|
||||
#endif
|
||||
esp_efuse_utility_reset();
|
||||
}
|
||||
|
||||
|
||||
// Erase the virt_blocks array.
|
||||
void esp_efuse_utility_erase_virt_blocks()
|
||||
{
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
memset(virt_blocks, 0, sizeof(virt_blocks));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Fills the virt_blocks array by values from efuse_Rdata.
|
||||
void esp_efuse_utility_update_virt_blocks()
|
||||
{
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
ESP_LOGI(TAG, "Emulate efuse is enabled");
|
||||
for (int num_block = 0; num_block < COUNT_EFUSE_BLOCKS; num_block++) {
|
||||
int subblock = 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) {
|
||||
virt_blocks[num_block][subblock++] = REG_READ(addr_rd_block);
|
||||
}
|
||||
ESP_LOGD(TAG, "virt_blocks[%d] is filled by EFUSE_BLOCK%d", num_block, num_block);
|
||||
}
|
||||
#else
|
||||
ESP_LOGI(TAG, "Emulate efuse is disabled");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Prints efuse values for all registers.
|
||||
void esp_efuse_utility_debug_dump_blocks()
|
||||
{
|
||||
printf("EFUSE_BLKx:\n");
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
for (int num_block = 0; num_block < COUNT_EFUSE_BLOCKS; num_block++) {
|
||||
int num_reg = 0;
|
||||
printf("%d) ", num_block);
|
||||
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, num_reg++) {
|
||||
printf("0x%08x ", virt_blocks[num_block][num_reg]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#else
|
||||
for (int num_block = 0; num_block < COUNT_EFUSE_BLOCKS; num_block++) {
|
||||
printf("%d) ", num_block);
|
||||
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) {
|
||||
printf("0x%08x ", REG_READ(addr_rd_block));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// returns the number of array elements for placing these bits in an array with the length of each element equal to size_of_base.
|
||||
int esp_efuse_utility_get_number_of_items(int bits, int size_of_base)
|
||||
{
|
||||
return bits / size_of_base + (bits % size_of_base > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
// Writing efuse register with checking of repeated programming of programmed bits.
|
||||
esp_err_t esp_efuse_utility_write_reg(esp_efuse_block_t efuse_block, unsigned int num_reg, uint32_t reg_to_write)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
|
||||
if (reg & reg_to_write) {
|
||||
ESP_LOGE(TAG, "Repeated programming of programmed bits is strictly forbidden 0x%08x", reg & reg_to_write);
|
||||
err = ESP_ERR_EFUSE_REPEATED_PROG;
|
||||
} else {
|
||||
write_reg(efuse_block, num_reg, reg_to_write);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// Reading efuse register.
|
||||
uint32_t esp_efuse_utility_read_reg(esp_efuse_block_t blk, unsigned int num_reg)
|
||||
{
|
||||
assert(blk >= 0 && blk <= 3);
|
||||
if (blk == 0) {
|
||||
assert(num_reg <= 6);
|
||||
} else {
|
||||
assert(num_reg <= 7);
|
||||
}
|
||||
|
||||
uint32_t value;
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
value = virt_blocks[blk][num_reg];
|
||||
#else
|
||||
value = REG_READ(range_read_addr_blocks[blk].start + num_reg * 4);
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
// Private functions
|
||||
|
||||
// writing efuse register.
|
||||
static void write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t value)
|
||||
{
|
||||
assert(blk >= 0 && blk <= 3);
|
||||
if (blk == 0) {
|
||||
assert(num_reg <= 6);
|
||||
} else {
|
||||
assert(num_reg <= 7);
|
||||
}
|
||||
uint32_t addr_wr_reg = range_write_addr_blocks[blk].start + num_reg * 4;
|
||||
uint32_t reg_to_write = REG_READ(addr_wr_reg) | value;
|
||||
// The register can be written in parts so we combine the new value with the one already available.
|
||||
REG_WRITE(addr_wr_reg, reg_to_write);
|
||||
}
|
||||
|
||||
// return mask with required the number of ones with shift.
|
||||
static uint32_t get_mask(unsigned int bit_count, unsigned int shift)
|
||||
{
|
||||
uint32_t mask;
|
||||
if (bit_count != 32) {
|
||||
mask = (1 << bit_count) - 1;
|
||||
} else {
|
||||
mask = 0xFFFFFFFF;
|
||||
}
|
||||
return mask << shift;
|
||||
}
|
||||
|
||||
// return the register number in the array. return -1 if all registers for field was selected.
|
||||
static int get_reg_num(int bit_start, int bit_count, int i_reg)
|
||||
{
|
||||
int num_reg = i_reg + bit_start / 32;
|
||||
|
||||
if (num_reg > (bit_start + bit_count - 1) / 32) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return num_reg;
|
||||
}
|
||||
|
||||
// returns the starting bit number in the register.
|
||||
static int get_starting_bit_num_in_reg(int bit_start, int i_reg)
|
||||
{
|
||||
return (i_reg == 0) ? bit_start % 32 : 0;
|
||||
}
|
||||
|
||||
// Returns the number of bits in the register.
|
||||
static int get_count_bits_in_reg(int bit_start, int bit_count, int i_reg)
|
||||
{
|
||||
int ret_count = 0;
|
||||
int num_reg = 0;
|
||||
int last_used_bit = (bit_start + bit_count - 1);
|
||||
for (int num_bit = bit_start; num_bit <= last_used_bit; ++num_bit) {
|
||||
++ret_count;
|
||||
if ((((num_bit + 1) % 32) == 0) || (num_bit == last_used_bit)) {
|
||||
if (i_reg == num_reg++) {
|
||||
return ret_count;
|
||||
}
|
||||
ret_count = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fill efuse register from array.
|
||||
static uint32_t fill_reg(int bit_start_in_reg, int bit_count_in_reg, uint8_t* blob, int* filled_bits_blob)
|
||||
{
|
||||
uint32_t reg_to_write = 0;
|
||||
uint32_t temp_blob_32;
|
||||
int shift_bit = (*filled_bits_blob) % 8;
|
||||
if (shift_bit != 0) {
|
||||
temp_blob_32 = blob[(*filled_bits_blob) / 8] >> shift_bit;
|
||||
shift_bit = ((8 - shift_bit) < bit_count_in_reg) ? (8 - shift_bit) : bit_count_in_reg;
|
||||
reg_to_write = temp_blob_32 & get_mask(shift_bit, 0);
|
||||
(*filled_bits_blob) += shift_bit;
|
||||
bit_count_in_reg -= shift_bit;
|
||||
}
|
||||
|
||||
int shift_reg = shift_bit;
|
||||
while (bit_count_in_reg > 0) {
|
||||
temp_blob_32 = blob[(*filled_bits_blob) / 8];
|
||||
shift_bit = (bit_count_in_reg > 8) ? 8 : bit_count_in_reg;
|
||||
reg_to_write |= (temp_blob_32 & get_mask(shift_bit, 0)) << shift_reg;
|
||||
(*filled_bits_blob) += shift_bit;
|
||||
bit_count_in_reg -= shift_bit;
|
||||
shift_reg += 8;
|
||||
};
|
||||
return reg_to_write << bit_start_in_reg;
|
||||
}
|
||||
|
||||
// sets a required count of bits as "1".
|
||||
static uint32_t set_cnt_in_reg(int bit_start_in_reg, int bit_count_used_in_reg, uint32_t reg_masked, size_t* cnt)
|
||||
{
|
||||
assert((bit_start_in_reg + bit_count_used_in_reg) <= 32);
|
||||
uint32_t reg_to_write = 0;
|
||||
for (int i = bit_start_in_reg; i < bit_start_in_reg + bit_count_used_in_reg; ++i) {
|
||||
if ((reg_masked & (1 << i)) == 0) {
|
||||
reg_to_write |= (1 << i);
|
||||
if (--(*cnt) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return reg_to_write;
|
||||
}
|
||||
|
||||
// check range of bits for any coding scheme.
|
||||
static bool check_range_of_bits(esp_efuse_block_t blk, int offset_in_bits, int size_bits)
|
||||
{
|
||||
esp_efuse_coding_scheme_t scheme = esp_efuse_get_coding_scheme(blk);
|
||||
int max_num_bit = offset_in_bits + size_bits;
|
||||
if ((scheme == EFUSE_CODING_SCHEME_NONE && max_num_bit > 256) ||
|
||||
(scheme == EFUSE_CODING_SCHEME_3_4 && max_num_bit > 192) ||
|
||||
(scheme == EFUSE_CODING_SCHEME_REPEAT && max_num_bit > 128)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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] = REG_READ(addr_rd_block);
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
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 = 1; num_block < COUNT_EFUSE_BLOCKS; 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);
|
||||
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;
|
||||
}
|
||||
for (int i = 0; i < 24; ++i) {
|
||||
if (buf_w_data[i] != 0) {
|
||||
int st_offset_buf = (i / 6) * 6;
|
||||
// check that place is free.
|
||||
for (int n = st_offset_buf; n < st_offset_buf + 6; ++n) {
|
||||
if (buf_r_data[n] != 0) {
|
||||
ESP_LOGE(TAG, "Bits are not empty. Write operation is forbidden.");
|
||||
return ESP_ERR_CODING;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t err = esp_efuse_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) {
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
140
components/efuse/src/esp_efuse_utility.h
Normal file
140
components/efuse/src/esp_efuse_utility.h
Normal file
@ -0,0 +1,140 @@
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP_EFUSE_UTILITY_H_
|
||||
#define _ESP_EFUSE_UTILITY_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_types.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_efuse.h"
|
||||
|
||||
/**
|
||||
* @brief This is type of function that will handle the efuse field register.
|
||||
*
|
||||
* @param[in] num_reg The register number in the block.
|
||||
* @param[in] efuse_block Block number.
|
||||
* @param[in] bit_start Start bit in the register.
|
||||
* @param[in] bit_count The number of bits used in the register.
|
||||
* @param[in/out] arr A pointer to an array or variable.
|
||||
* @param[in/out] bits_counter Counter bits.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed.
|
||||
* - other efuse component errors.
|
||||
*/
|
||||
typedef esp_err_t (*efuse_func_proc_t) (unsigned int num_reg, esp_efuse_block_t efuse_block, int starting_bit_num_in_reg, int num_bits_used_in_reg, void* arr, int* bits_counter);
|
||||
|
||||
/**
|
||||
* @brief This function processes the field by calling the passed function.
|
||||
*
|
||||
* This function selects the field, checks the length, and calls the register processing function.
|
||||
* @param[in] field A pointer to the structure describing the fields of efuse.
|
||||
* @param[in/out] ptr A pointer to an array that is used to read / write from / to the efuse field.
|
||||
* @param[in] ptr_size_bits The size of the data in bits for the efuse field. if = 0 then read all field bits.
|
||||
* @param[in] func_proc This is the function that will handle the efuse fields.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed.
|
||||
* - other efuse component errors.
|
||||
*/
|
||||
esp_err_t esp_efuse_utility_process(const esp_efuse_desc_t* field[], void* ptr, size_t ptr_size_bits, efuse_func_proc_t func_proc);
|
||||
|
||||
/**
|
||||
* @brief Write register with the required number of "1" bits.
|
||||
* @param[in/out] cnt The number of bits you need to set in the field.
|
||||
*/
|
||||
esp_err_t esp_efuse_utility_write_cnt(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* cnt, int* bits_counter);
|
||||
|
||||
/**
|
||||
* @brief Fill registers from array for writing.
|
||||
* @param[in] arr_in A pointer to an array in which the data for the writing.
|
||||
*/
|
||||
esp_err_t esp_efuse_utility_write_blob(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* arr_in, int* bits_counter);
|
||||
|
||||
/**
|
||||
* @brief Count a set bits in register.
|
||||
* @param[in/out] out_cnt A pointer to size_t variable which will contain the number of "1" bits.
|
||||
*/
|
||||
esp_err_t esp_efuse_utility_count_once(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* out_cnt, int* bits_counter);
|
||||
|
||||
/**
|
||||
* @brief Read efuse register and write this value to array.
|
||||
* @param[out] arr_out A pointer to array that will contain the result of reading.
|
||||
*/
|
||||
esp_err_t esp_efuse_utility_fill_buff(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* arr_out, int* bits_counter);
|
||||
|
||||
/**
|
||||
* @brief Burn values written to the efuse write registers.
|
||||
*
|
||||
* 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_efuses(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".
|
||||
*/
|
||||
int esp_efuse_utility_get_number_of_items(int bits, int size_of_base);
|
||||
|
||||
/**
|
||||
* @brief Reading efuse register.
|
||||
*/
|
||||
uint32_t esp_efuse_utility_read_reg(esp_efuse_block_t blk, unsigned int num_reg);
|
||||
|
||||
/**
|
||||
* @brief Writing efuse register with checking of repeated programming of programmed bits.
|
||||
*/
|
||||
esp_err_t esp_efuse_utility_write_reg(unsigned int num_reg, esp_efuse_block_t efuse_block, uint32_t reg_to_write);
|
||||
|
||||
/* @brief Reset efuse write registers
|
||||
*
|
||||
* Efuse write registers are written to zero, to negate
|
||||
* any changes that have been staged here.
|
||||
*/
|
||||
void esp_efuse_utility_reset(void);
|
||||
|
||||
/**
|
||||
* @brief Fills the virt_blocks array by values from efuse_Rdata.
|
||||
*/
|
||||
void esp_efuse_utility_update_virt_blocks();
|
||||
|
||||
/**
|
||||
* @brief Prints efuse values for all registers.
|
||||
*/
|
||||
void esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
/**
|
||||
* @brief Erase the virt_blocks array.
|
||||
*/
|
||||
void esp_efuse_utility_erase_virt_blocks();
|
||||
|
||||
/**
|
||||
* @brief Apply coding_scheme to write registers.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: The operation was successfully completed.
|
||||
* - ESP_ERR_CODING: Error range of data does not match the coding scheme.
|
||||
*/
|
||||
esp_err_t esp_efuse_utility_apply_new_coding_scheme();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _ESP_EFUSE_UTILITY_H_
|
6
components/efuse/test/CMakeLists.txt
Normal file
6
components/efuse/test/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
set(COMPONENT_SRCDIRS ".")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "." "include")
|
||||
|
||||
set(COMPONENT_REQUIRES unity test_utils efuse bootloader_support)
|
||||
|
||||
register_component()
|
6
components/efuse/test/component.mk
Normal file
6
components/efuse/test/component.mk
Normal file
@ -0,0 +1,6 @@
|
||||
#
|
||||
#Component Makefile
|
||||
#
|
||||
COMPONENT_ADD_INCLUDEDIRS := include
|
||||
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
103
components/efuse/test/esp_efuse_test_table.c
Normal file
103
components/efuse/test/esp_efuse_test_table.c
Normal file
@ -0,0 +1,103 @@
|
||||
// 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_test_table.h"
|
||||
|
||||
// md5_digest dac4d84347dab29412b8b8713b4b0065
|
||||
// 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'.
|
||||
|
||||
|
||||
static const esp_efuse_desc_t TEST1_LEN_8[] = {
|
||||
{EFUSE_BLK3, 0, 8}, // TEST field,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t TEST2_LEN_16[] = {
|
||||
{EFUSE_BLK3, 10, 8}, // TEST field,
|
||||
{EFUSE_BLK3, 80, 8}, // TEST field,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t TEST3_LEN_6[] = {
|
||||
{EFUSE_BLK3, 22, 6}, // TEST field,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t TEST4_LEN_182[] = {
|
||||
{EFUSE_BLK1, 22, 49}, // TEST field,
|
||||
{EFUSE_BLK1, 89, 39}, // TEST field,
|
||||
{EFUSE_BLK1, 71, 18}, // TEST field,
|
||||
{EFUSE_BLK1, 0, 16}, // TEST field,
|
||||
{EFUSE_BLK2, 0, 17}, // TEST field,
|
||||
{EFUSE_BLK2, 60, 43}, // TEST field,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t TEST5_LEN_1[] = {
|
||||
{EFUSE_BLK1, 16, 1}, // TEST field,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t TEST6_LEN_17[] = {
|
||||
{EFUSE_BLK1, 17, 1}, // TEST field,
|
||||
{EFUSE_BLK2, 17, 2}, // TEST field,
|
||||
{EFUSE_BLK3, 29, 4}, // TEST field,
|
||||
{EFUSE_BLK2, 31, 3}, // TEST field,
|
||||
{EFUSE_BLK3, 60, 6}, // TEST field,
|
||||
{EFUSE_BLK2, 127, 1}, // TEST field,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_TEST1_LEN_8[] = {
|
||||
&TEST1_LEN_8[0], // TEST field
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_TEST2_LEN_16[] = {
|
||||
&TEST2_LEN_16[0], // TEST field
|
||||
&TEST2_LEN_16[1], // TEST field
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_TEST3_LEN_6[] = {
|
||||
&TEST3_LEN_6[0], // TEST field
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_TEST4_LEN_182[] = {
|
||||
&TEST4_LEN_182[0], // TEST field
|
||||
&TEST4_LEN_182[1], // TEST field
|
||||
&TEST4_LEN_182[2], // TEST field
|
||||
&TEST4_LEN_182[3], // TEST field
|
||||
&TEST4_LEN_182[4], // TEST field
|
||||
&TEST4_LEN_182[5], // TEST field
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_TEST5_LEN_1[] = {
|
||||
&TEST5_LEN_1[0], // TEST field
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_TEST6_LEN_17[] = {
|
||||
&TEST6_LEN_17[0], // TEST field
|
||||
&TEST6_LEN_17[1], // TEST field
|
||||
&TEST6_LEN_17[2], // TEST field
|
||||
&TEST6_LEN_17[3], // TEST field
|
||||
&TEST6_LEN_17[4], // TEST field
|
||||
&TEST6_LEN_17[5], // TEST field
|
||||
NULL
|
||||
};
|
||||
|
33
components/efuse/test/esp_efuse_test_table.csv
Normal file
33
components/efuse/test/esp_efuse_test_table.csv
Normal file
@ -0,0 +1,33 @@
|
||||
# field_name, | efuse_block, | bit_start, | bit_count, |comment #
|
||||
# | (EFUSE_BLK0 | (0..255) | (1..256) | #
|
||||
# | EFUSE_BLK1 | | | #
|
||||
# | EFUSE_BLK2 | | | #
|
||||
# | EFUSE_BLK3) | | | #
|
||||
##########################################################################
|
||||
|
||||
# To generate a new source files. Run two commands:
|
||||
# cd ~/esp/esp-idf/components/efuse/
|
||||
# ./efuse_table_gen.py test/esp_efuse_test_table.csv
|
||||
|
||||
TEST1_LEN_8, EFUSE_BLK3, 0, 8, TEST field
|
||||
|
||||
TEST2_LEN_16, EFUSE_BLK3, 10, 8, TEST field
|
||||
, EFUSE_BLK3, 80, 8, TEST field
|
||||
|
||||
TEST3_LEN_6, EFUSE_BLK3, 22, 6, TEST field
|
||||
|
||||
TEST4_LEN_182, EFUSE_BLK1, 22, 49, TEST field
|
||||
, EFUSE_BLK1, 89, 39, TEST field
|
||||
, EFUSE_BLK1, 71, 18, TEST field
|
||||
, EFUSE_BLK1, 0, 16, TEST field
|
||||
, EFUSE_BLK2, 0, 17, TEST field
|
||||
, EFUSE_BLK2, 60, 43, TEST field
|
||||
|
||||
TEST5_LEN_1, EFUSE_BLK1, 16, 1, TEST field
|
||||
|
||||
TEST6_LEN_17, EFUSE_BLK1, 17, 1, TEST field
|
||||
, EFUSE_BLK2, 17, 2, TEST field
|
||||
, EFUSE_BLK3, 29, 4, TEST field
|
||||
, EFUSE_BLK2, 31, 3, TEST field
|
||||
, EFUSE_BLK3, 60, 6, TEST field
|
||||
, EFUSE_BLK2, 127, 1, TEST field
|
|
36
components/efuse/test/include/esp_efuse_test_table.h
Normal file
36
components/efuse/test/include/esp_efuse_test_table.h
Normal file
@ -0,0 +1,36 @@
|
||||
// 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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// md5_digest dac4d84347dab29412b8b8713b4b0065
|
||||
// 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'.
|
||||
|
||||
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_TEST1_LEN_8[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_TEST2_LEN_16[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_TEST3_LEN_6[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_TEST4_LEN_182[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_TEST5_LEN_1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_TEST6_LEN_17[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
546
components/efuse/test/test_efuse.c
Normal file
546
components/efuse/test/test_efuse.c
Normal file
@ -0,0 +1,546 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "unity.h"
|
||||
#include "esp_log.h"
|
||||
#include <string.h>
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_table.h"
|
||||
#include "../src/esp_efuse_utility.h"
|
||||
#include "esp_efuse_test_table.h"
|
||||
#include "rom/efuse.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static const char* TAG = "efuse_test";
|
||||
|
||||
static void test_read_blob(void)
|
||||
{
|
||||
esp_efuse_utility_update_virt_blocks();
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
uint8_t mac[6];
|
||||
|
||||
ESP_LOGI(TAG, "1. Read MAC address");
|
||||
memset(mac, 0, sizeof(mac));
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &mac, sizeof(mac) * 8));
|
||||
TEST_ASSERT_EQUAL_INT(sizeof(mac) * 8, esp_efuse_get_field_size(ESP_EFUSE_MAC_FACTORY));
|
||||
ESP_LOGI(TAG, "MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
ESP_LOGI(TAG, "2. Check CRC by MAC");
|
||||
uint8_t crc;
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY_CRC, &crc, 8));
|
||||
TEST_ASSERT_EQUAL_HEX8(crc, esp_crc8(mac, sizeof(mac)));
|
||||
|
||||
ESP_LOGI(TAG, "3. Test check args");
|
||||
uint32_t test_var;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, NULL, 1));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &test_var, 0));
|
||||
|
||||
uint8_t half_byte;
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &half_byte, 4));
|
||||
TEST_ASSERT_EQUAL_HEX8(mac[0]&0x0F, half_byte);
|
||||
|
||||
uint8_t buff[7] = {0x59};
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &buff, sizeof(buff) * 8));
|
||||
TEST_ASSERT_TRUE_MESSAGE(memcmp(mac, buff, sizeof(mac)) == 0, "Operation read blob is not success");
|
||||
TEST_ASSERT_EQUAL_HEX8(0, buff[6]);
|
||||
}
|
||||
|
||||
TEST_CASE("efuse test read_field_blob", "[efuse]")
|
||||
{
|
||||
test_read_blob();
|
||||
}
|
||||
|
||||
static void test_read_cnt(void)
|
||||
{
|
||||
esp_efuse_utility_update_virt_blocks();
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
ESP_LOGI(TAG, "1. Test check args");
|
||||
size_t cnt;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_read_field_cnt(ESP_EFUSE_MAC_FACTORY, NULL));
|
||||
|
||||
ESP_LOGI(TAG, "2. Read MAC address");
|
||||
uint8_t mac[6];
|
||||
memset(mac, 0, sizeof(mac));
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, &mac, 48));
|
||||
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_MAC_FACTORY, &cnt));
|
||||
size_t cnt_summ = 0;
|
||||
for (int i = 0; i < sizeof(mac); ++i) {
|
||||
cnt_summ += __builtin_popcount(mac[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL_INT(cnt_summ, cnt);
|
||||
}
|
||||
|
||||
TEST_CASE("efuse test read_field_cnt", "[efuse]")
|
||||
{
|
||||
test_read_cnt();
|
||||
}
|
||||
|
||||
// If using efuse is real, then turn off writing tests.
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
static void test_write_blob(void)
|
||||
{
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
ESP_LOGI(TAG, "1. Test check args");
|
||||
uint16_t test1_len_8 = 0x5FAA;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_field_blob(ESP_EFUSE_MAC_FACTORY, &test1_len_8, 0));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_field_blob(ESP_EFUSE_TEST1_LEN_8, NULL, 8));
|
||||
TEST_ASSERT_EQUAL_HEX16(0x5FAA, test1_len_8);
|
||||
|
||||
ESP_LOGI(TAG, "2. Test write operation");
|
||||
|
||||
TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_TEST1_LEN_8, &test1_len_8, 7));
|
||||
TEST_ESP_ERR(ESP_ERR_EFUSE_REPEATED_PROG, esp_efuse_write_field_blob(ESP_EFUSE_TEST1_LEN_8, &test1_len_8, 9));
|
||||
uint16_t val_read1 = 0;
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST1_LEN_8, &val_read1, 8));
|
||||
TEST_ASSERT_EQUAL_HEX16(test1_len_8&((1 << 7) - 1), val_read1);
|
||||
|
||||
uint16_t test1_len_8_hi = test1_len_8 & ~((1 << 7) - 1);
|
||||
TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_TEST1_LEN_8, &test1_len_8_hi, 8));
|
||||
TEST_ESP_ERR(ESP_ERR_EFUSE_REPEATED_PROG, esp_efuse_write_field_blob(ESP_EFUSE_TEST1_LEN_8, &test1_len_8, 8));
|
||||
val_read1 = 0;
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST1_LEN_8, &val_read1, 16));
|
||||
TEST_ASSERT_EQUAL_HEX16(test1_len_8&0x00FF, val_read1);
|
||||
|
||||
uint16_t test2_len_16 = 0xAA55;
|
||||
uint32_t val_32 = test2_len_16;
|
||||
TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_TEST2_LEN_16, &val_32, 17));
|
||||
TEST_ESP_ERR(ESP_ERR_EFUSE_REPEATED_PROG, esp_efuse_write_field_blob(ESP_EFUSE_TEST2_LEN_16, &test2_len_16, 16));
|
||||
uint16_t test_16 = 0;
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST2_LEN_16, &test_16, 16));
|
||||
TEST_ASSERT_EQUAL_HEX16(test2_len_16, test_16);
|
||||
|
||||
ESP_LOGI(TAG, "3. Test field with one bit");
|
||||
uint8_t test5_len_1;
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
|
||||
TEST_ASSERT_EQUAL_HEX8(0, test5_len_1);
|
||||
|
||||
test5_len_1 = 0;
|
||||
TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
|
||||
TEST_ASSERT_EQUAL_HEX8(0, test5_len_1);
|
||||
|
||||
test5_len_1 = 1;
|
||||
TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
|
||||
TEST_ASSERT_EQUAL_HEX8(1, test5_len_1);
|
||||
|
||||
test5_len_1 = 1;
|
||||
TEST_ESP_ERR(ESP_ERR_EFUSE_REPEATED_PROG, esp_efuse_write_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
|
||||
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
}
|
||||
|
||||
TEST_CASE("efuse test write_field_blob", "[efuse]")
|
||||
{
|
||||
test_write_blob();
|
||||
}
|
||||
|
||||
static void test_write_cnt(void)
|
||||
{
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
ESP_LOGI(TAG, "1. Test check args");
|
||||
size_t test3_len_6 = 5;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_field_cnt(ESP_EFUSE_MAC_FACTORY, 0));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_field_cnt(NULL, 5));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, 0));
|
||||
|
||||
ESP_LOGI(TAG, "2. Test write operation");
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST3_LEN_6, &test3_len_6));
|
||||
TEST_ASSERT_EQUAL_INT(0, test3_len_6);
|
||||
|
||||
TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, 1));
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST3_LEN_6, &test3_len_6));
|
||||
TEST_ASSERT_EQUAL_INT(1, test3_len_6);
|
||||
|
||||
TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, 1));
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST3_LEN_6, &test3_len_6));
|
||||
TEST_ASSERT_EQUAL_INT(2, test3_len_6);
|
||||
|
||||
TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST3_LEN_6, 3));
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST3_LEN_6, &test3_len_6));
|
||||
TEST_ASSERT_EQUAL_INT(5, test3_len_6);
|
||||
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
ESP_LOGI(TAG, "3. Test field is full set");
|
||||
int max_bits = esp_efuse_get_field_size(ESP_EFUSE_TEST4_LEN_182);
|
||||
size_t test4_len_182;
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
for (int i = 0; i < max_bits / 26; ++i) {
|
||||
ESP_LOGD(TAG, "# %d", i);
|
||||
TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST4_LEN_182, 26));
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST4_LEN_182, &test4_len_182));
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
TEST_ASSERT_EQUAL_INT((i + 1) * 26, test4_len_182);
|
||||
}
|
||||
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
ESP_LOGI(TAG, "4. Test field ESP_EFUSE_TEST4_LEN_182 is full");
|
||||
TEST_ESP_ERR(ESP_ERR_EFUSE_CNT_IS_FULL, esp_efuse_write_field_cnt(ESP_EFUSE_TEST4_LEN_182, 1));
|
||||
|
||||
ESP_LOGI(TAG, "3. Test field with one bit");
|
||||
size_t test5_len_1;
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST5_LEN_1, &test5_len_1));
|
||||
TEST_ASSERT_EQUAL_HEX8(0, test5_len_1);
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
|
||||
TEST_ASSERT_EQUAL_HEX8(0, test5_len_1);
|
||||
|
||||
test5_len_1 = 1;
|
||||
TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST5_LEN_1, test5_len_1));
|
||||
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST5_LEN_1, &test5_len_1));
|
||||
TEST_ASSERT_EQUAL_HEX8(1, test5_len_1);
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST5_LEN_1, &test5_len_1, 1));
|
||||
TEST_ASSERT_EQUAL_HEX8(1, test5_len_1);
|
||||
|
||||
test5_len_1 = 1;
|
||||
TEST_ESP_ERR(ESP_ERR_EFUSE_CNT_IS_FULL, esp_efuse_write_field_cnt(ESP_EFUSE_TEST5_LEN_1, test5_len_1));
|
||||
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
ESP_LOGI(TAG, "4. Test field test2_len_16");
|
||||
size_t test2_len_16 = 11;
|
||||
TEST_ESP_OK(esp_efuse_write_field_cnt(ESP_EFUSE_TEST2_LEN_16, test2_len_16));
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(ESP_EFUSE_TEST2_LEN_16, &test2_len_16));
|
||||
TEST_ASSERT_EQUAL_HEX16(11, test2_len_16);
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_TEST2_LEN_16, &test2_len_16, 16));
|
||||
TEST_ASSERT_EQUAL_HEX16(0x07FF, test2_len_16);
|
||||
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
}
|
||||
|
||||
TEST_CASE("efuse test write_field_cnt", "[efuse]")
|
||||
{
|
||||
test_write_cnt();
|
||||
}
|
||||
|
||||
void cut_tail_arr(uint8_t *arr, int num_used_bits, size_t count_bits)
|
||||
{
|
||||
if ((num_used_bits + count_bits) % 8) {
|
||||
int start_used_item = (num_used_bits - 1) / 8;
|
||||
int last_used_item = ((num_used_bits + count_bits) - 1) / 8;
|
||||
int shift = 0;
|
||||
int mask = num_used_bits + count_bits;
|
||||
if (last_used_item == start_used_item) {
|
||||
shift = (num_used_bits) % 8;
|
||||
mask = count_bits;
|
||||
}
|
||||
arr[last_used_item] &= ((1 << (mask % 8)) - 1) << shift;
|
||||
}
|
||||
}
|
||||
|
||||
void cut_start_arr(uint8_t *arr, size_t num_used_bits)
|
||||
{
|
||||
if (num_used_bits % 8) {
|
||||
int start_used_item = (num_used_bits - 1) / 8;
|
||||
arr[start_used_item] &= ~((1 << (num_used_bits % 8)) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void get_part_arr(uint8_t *arr_in, uint8_t *arr_out, int num_used_bits, int count_bits)
|
||||
{
|
||||
int num_items = esp_efuse_utility_get_number_of_items(num_used_bits + count_bits, 8);
|
||||
memcpy(arr_out, arr_in, num_items);
|
||||
memset(arr_out, 0, num_used_bits / 8);
|
||||
cut_start_arr(arr_out, num_used_bits);
|
||||
cut_tail_arr(arr_out, num_used_bits, count_bits);
|
||||
}
|
||||
|
||||
void fill_part_arr(uint8_t *arr_in, uint8_t *arr_out, int count_bits)
|
||||
{
|
||||
int num_items = esp_efuse_utility_get_number_of_items(count_bits, 8);
|
||||
memcpy(arr_out, arr_in, num_items);
|
||||
cut_tail_arr(arr_out, 0, count_bits);
|
||||
}
|
||||
|
||||
// Writes a random array to efuse, then reads and compares it.
|
||||
void test_blob(const esp_efuse_desc_t* field[], uint8_t *arr_w, uint8_t *arr_r, uint8_t *arr_temp, int arr_size, size_t field_size)
|
||||
{
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_w, arr_size, ESP_LOG_INFO);
|
||||
TEST_ESP_OK(esp_efuse_write_field_blob(field, arr_w, field_size));
|
||||
memset(arr_r, 0, arr_size);
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(field, arr_r, field_size));
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_r, arr_size, ESP_LOG_INFO);
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(memcmp(arr_w, arr_r, arr_size) == 0, "Operation write/read blob is not success");
|
||||
|
||||
int count_once = 0;
|
||||
for (int i = 0; i < arr_size; ++i) {
|
||||
count_once += __builtin_popcount(arr_w[i]);
|
||||
}
|
||||
|
||||
size_t num_bits_r = 0;
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(field, &num_bits_r));
|
||||
TEST_ASSERT_EQUAL_INT(count_once, num_bits_r);
|
||||
|
||||
size_t num_bits_w = field_size - count_once;
|
||||
if (num_bits_w == 0) {
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
num_bits_w = field_size;
|
||||
}
|
||||
|
||||
TEST_ESP_OK(esp_efuse_write_field_cnt(field, num_bits_w));
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(field, &num_bits_r));
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
TEST_ASSERT_EQUAL_INT(field_size, num_bits_r);
|
||||
|
||||
memset(arr_r, 0, arr_size);
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(field, arr_r, field_size));
|
||||
memset(arr_temp, 0xFF, arr_size);
|
||||
cut_tail_arr(arr_temp, 0, field_size);
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
TEST_ASSERT_TRUE_MESSAGE(memcmp(arr_temp, arr_r, arr_size) == 0, "Operation write/read blob is not success");
|
||||
}
|
||||
|
||||
// Records a random number of bits (as "1") in the efuse field, then reads and compares.
|
||||
void test_cnt_part(const esp_efuse_desc_t* field[], uint8_t *arr_r, int arr_size, size_t field_size)
|
||||
{
|
||||
size_t num_bits_r = 0;
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(field, &num_bits_r));
|
||||
TEST_ASSERT_EQUAL_INT(0, num_bits_r);
|
||||
|
||||
TEST_ESP_OK(esp_efuse_write_field_cnt(field, field_size));
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(field, &num_bits_r));
|
||||
TEST_ASSERT_EQUAL_INT(field_size, num_bits_r);
|
||||
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
|
||||
int num_bits_summ_r = 0;
|
||||
int num_bits_w = 0;
|
||||
while(field_size > num_bits_summ_r) {
|
||||
num_bits_w = 0;
|
||||
while(num_bits_w == 0 || (num_bits_summ_r + num_bits_w) > field_size) {
|
||||
bootloader_random_enable();
|
||||
bootloader_fill_random(&num_bits_w, 1);
|
||||
bootloader_random_disable();
|
||||
num_bits_w = num_bits_w * field_size / 255;
|
||||
if (num_bits_w != 0 && (num_bits_summ_r + num_bits_w) <= field_size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_ESP_OK(esp_efuse_write_field_cnt(field, num_bits_w));
|
||||
TEST_ESP_OK(esp_efuse_read_field_cnt(field, &num_bits_r));
|
||||
num_bits_summ_r += num_bits_w;
|
||||
TEST_ASSERT_EQUAL_INT(num_bits_summ_r, num_bits_r);
|
||||
|
||||
memset(arr_r, 0, arr_size);
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(field, arr_r, field_size));
|
||||
int count_once = 0;
|
||||
for (int i = 0; i < arr_size; ++i) {
|
||||
count_once += __builtin_popcount(arr_r[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL_INT(num_bits_summ_r, count_once);
|
||||
|
||||
ESP_LOGI(TAG, "Once bits=%d, step=%d", num_bits_summ_r, num_bits_w);
|
||||
}
|
||||
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
}
|
||||
|
||||
// From a random array takes a random number of bits and write to efuse, it repeats until the entire length of the field is written down.
|
||||
void test_blob_part(const esp_efuse_desc_t* field[], uint8_t *arr_w, uint8_t *arr_r, uint8_t *arr_temp, int arr_size, size_t field_size)
|
||||
{
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
int num_bits_summ_r = 0;
|
||||
int num_bits_w = 0;
|
||||
memset(arr_w, 0, arr_size);
|
||||
bootloader_random_enable();
|
||||
bootloader_fill_random(arr_w, arr_size);
|
||||
bootloader_random_disable();
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_w, arr_size, ESP_LOG_INFO);
|
||||
while(field_size > num_bits_summ_r) {
|
||||
num_bits_w = 0;
|
||||
while(num_bits_w == 0 || (num_bits_summ_r + num_bits_w) > field_size) {
|
||||
bootloader_random_enable();
|
||||
bootloader_fill_random(&num_bits_w, 1);
|
||||
bootloader_random_disable();
|
||||
num_bits_w = num_bits_w * field_size / 255;
|
||||
if (num_bits_w != 0 && (num_bits_summ_r + num_bits_w) <= field_size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ESP_LOGI(TAG, "Summ bits=%d, step=%d", num_bits_summ_r, num_bits_w);
|
||||
memset(arr_temp, 0, arr_size);
|
||||
get_part_arr(arr_w, arr_temp, num_bits_summ_r, num_bits_w);
|
||||
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_temp, arr_size, ESP_LOG_INFO);
|
||||
TEST_ESP_OK(esp_efuse_write_field_blob(field, arr_temp, field_size));
|
||||
memset(arr_r, 0, arr_size);
|
||||
TEST_ESP_OK(esp_efuse_read_field_blob(field, arr_r, field_size));
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_r, arr_size, ESP_LOG_INFO);
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
num_bits_summ_r += num_bits_w;
|
||||
memset(arr_temp, 0, arr_size);
|
||||
fill_part_arr(arr_w, arr_temp, num_bits_summ_r);
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, arr_temp, arr_size, ESP_LOG_INFO);
|
||||
TEST_ASSERT_TRUE_MESSAGE(memcmp(arr_temp, arr_r, arr_size) == 0, "Operation write/read blob is not success");
|
||||
}
|
||||
}
|
||||
|
||||
void check_efuse_table_test(int cycle)
|
||||
{
|
||||
int num_test = 0;
|
||||
while(1) {
|
||||
const esp_efuse_desc_t** field;
|
||||
switch (num_test++) {
|
||||
case 0: field = ESP_EFUSE_TEST1_LEN_8; break;
|
||||
case 1: field = ESP_EFUSE_TEST2_LEN_16; break;
|
||||
case 2: field = ESP_EFUSE_TEST3_LEN_6; break;
|
||||
case 3: field = ESP_EFUSE_TEST4_LEN_182; break;
|
||||
case 4: field = ESP_EFUSE_TEST5_LEN_1; break;
|
||||
case 5: field = ESP_EFUSE_TEST6_LEN_17; break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
size_t field_size = esp_efuse_get_field_size(field);
|
||||
int arr_size = esp_efuse_utility_get_number_of_items(field_size, 8);
|
||||
uint8_t *arr_w = (uint8_t *) malloc(arr_size);
|
||||
uint8_t *arr_r = (uint8_t *) malloc(arr_size);
|
||||
uint8_t *arr_temp = (uint8_t *) malloc(arr_size);
|
||||
ESP_LOGI(TAG, "Test#%d", num_test);
|
||||
for (int c = 1; c <= cycle; ++c) {
|
||||
ESP_LOGI(TAG, "Cycle#%d/%d", c, cycle);
|
||||
|
||||
memset(arr_w, 0, arr_size);
|
||||
bootloader_random_enable();
|
||||
bootloader_fill_random(arr_w, arr_size);
|
||||
bootloader_random_disable();
|
||||
cut_tail_arr(arr_w, 0, field_size);
|
||||
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
ESP_LOGI(TAG, "1) blob write/read");
|
||||
test_blob(field, arr_w, arr_r, arr_temp, arr_size, field_size);
|
||||
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
ESP_LOGI(TAG, "2) cnt part write/read");
|
||||
test_cnt_part(field, arr_r, arr_size, field_size);
|
||||
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
ESP_LOGI(TAG, "3) blob part write/read");
|
||||
test_blob_part(field, arr_w, arr_r, arr_temp, arr_size, field_size);
|
||||
}
|
||||
free(arr_temp);
|
||||
free(arr_r);
|
||||
free(arr_w);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("efuse esp_efuse_table_test", "[efuse]")
|
||||
{
|
||||
check_efuse_table_test(2);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Test esp_efuse_read_block esp_efuse_write_block functions", "[efuse]")
|
||||
{
|
||||
int count_useful_reg = 0;
|
||||
esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme(EFUSE_BLK2);
|
||||
if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {
|
||||
printf("EFUSE_CODING_SCHEME_NONE\n");
|
||||
count_useful_reg = 8;
|
||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_3_4) {
|
||||
printf("EFUSE_CODING_SCHEME_3_4\n");
|
||||
count_useful_reg = 6;
|
||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_REPEAT) {
|
||||
printf("EFUSE_CODING_SCHEME_REPEAT\n");
|
||||
count_useful_reg = 4;
|
||||
}
|
||||
|
||||
esp_efuse_utility_reset();
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
|
||||
uint8_t src_key[32] = { 0 };
|
||||
uint8_t dst_key[32] = { 0 };
|
||||
int offset_in_bits = 0;
|
||||
for (int i = 0; i < count_useful_reg * 4; ++i) {
|
||||
src_key[i] = 0xAB + i;
|
||||
}
|
||||
|
||||
TEST_ESP_OK(esp_efuse_write_block(EFUSE_BLK2, src_key, offset_in_bits, count_useful_reg * 32));
|
||||
TEST_ESP_OK(esp_efuse_read_block(EFUSE_BLK2, dst_key, offset_in_bits, count_useful_reg * 32));
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(src_key, dst_key, sizeof(src_key));
|
||||
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
|
||||
memset(src_key, 0, sizeof(src_key));
|
||||
memset(dst_key, 0, sizeof(dst_key));
|
||||
offset_in_bits = count_useful_reg * 32 / 2;
|
||||
for (int i = 0; i < count_useful_reg * 4 / 2; ++i) {
|
||||
src_key[i] = 0xCD + i;
|
||||
}
|
||||
TEST_ESP_OK(esp_efuse_write_block(EFUSE_BLK2, src_key, offset_in_bits, count_useful_reg * 32 / 2));
|
||||
TEST_ESP_OK(esp_efuse_read_block(EFUSE_BLK2, dst_key, offset_in_bits, count_useful_reg * 32 / 2));
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(src_key, dst_key, count_useful_reg * 4 / 2);
|
||||
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
}
|
||||
|
||||
TEST_CASE("Test Bits are not empty. Write operation is forbidden", "[efuse]")
|
||||
{
|
||||
esp_efuse_utility_update_virt_blocks();
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
|
||||
int count_useful_reg = 0;
|
||||
uint8_t r_buff[32];
|
||||
int st_offset = -1;
|
||||
int num_block;
|
||||
for (num_block = EFUSE_BLK1; num_block < 4; ++num_block) {
|
||||
memset(r_buff, 0, sizeof(r_buff));
|
||||
esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme(num_block);
|
||||
if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {
|
||||
printf("EFUSE_CODING_SCHEME_NONE. The test is not applicable.\n");
|
||||
count_useful_reg = 8;
|
||||
return;
|
||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_3_4) {
|
||||
printf("EFUSE_CODING_SCHEME_3_4\n");
|
||||
count_useful_reg = 6;
|
||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_REPEAT) {
|
||||
printf("EFUSE_CODING_SCHEME_REPEAT\n");
|
||||
count_useful_reg = 4;
|
||||
}
|
||||
TEST_ESP_OK(esp_efuse_read_block(num_block, r_buff, 0, count_useful_reg * 32));
|
||||
for (int i = 0; i < count_useful_reg * 4; ++i) {
|
||||
if (r_buff[i] != 0) {
|
||||
// found used byte
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
if ((r_buff[i] & (1 << j)) == 0) {
|
||||
// found empty bit into this byte
|
||||
st_offset = i * 8 + j;
|
||||
printf("Byte = 0x%02x. offset is = %d\n", r_buff[i], st_offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (st_offset != -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (st_offset != -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (st_offset != -1) {
|
||||
// write 1 bit to empty place.
|
||||
uint8_t val = 1;
|
||||
TEST_ESP_ERR(ESP_ERR_CODING, esp_efuse_write_block(num_block, &val, st_offset, 1));
|
||||
} else {
|
||||
printf("Test skipped. It is not applicable, the device has no written bits.");
|
||||
}
|
||||
}
|
||||
#endif // #ifdef CONFIG_EFUSE_VIRTUAL
|
204
components/efuse/test/test_efuse_coding_scheme.c
Normal file
204
components/efuse/test/test_efuse_coding_scheme.c
Normal file
@ -0,0 +1,204 @@
|
||||
#include <stdint.h>
|
||||
#include <strings.h>
|
||||
#include "esp_efuse.h"
|
||||
#include "../src/esp_efuse_utility.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "unity.h"
|
||||
#include "bootloader_random.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t unencoded[24];
|
||||
uint32_t encoded[8];
|
||||
} coding_scheme_test_t;
|
||||
|
||||
/* Randomly generated byte strings, encoded and written to ESP32
|
||||
using espefuse algorithm, then verified to have no encoding errors
|
||||
and correct readback.
|
||||
*/
|
||||
static const coding_scheme_test_t coding_scheme_data[] = {
|
||||
{
|
||||
.unencoded = { 0x96, 0xa9, 0xab, 0xb2, 0xda, 0xdd, 0x21, 0xd2, 0x35, 0x22, 0xd3, 0x30, 0x3b, 0xf8, 0xcb, 0x77, 0x8d, 0x8d, 0xf4, 0x96, 0x25, 0xc4, 0xb9, 0x94 },
|
||||
.encoded = { 0xb2aba996, 0x6821ddda, 0x2235d221, 0x430730d3, 0x77cbf83b, 0x627f8d8d, 0xc42596f4, 0x4dae94b9 },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0x0e, 0x6b, 0x1a, 0x1d, 0xa5, 0x9f, 0x24, 0xcf, 0x91, 0x5b, 0xe7, 0xe1, 0x7c, 0x0a, 0x6e, 0xdc, 0x5e, 0x8e, 0xb1, 0xec, 0xd1, 0xf3, 0x75, 0x48 },
|
||||
.encoded = { 0x1d1a6b0e, 0x5e589fa5, 0x5b91cf24, 0x6127e1e7, 0xdc6e0a7c, 0x5d148e5e, 0xf3d1ecb1, 0x57424875 },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0x0a, 0x79, 0x5a, 0x1c, 0xb1, 0x45, 0x71, 0x2c, 0xb3, 0xda, 0x9e, 0xdc, 0x76, 0x27, 0xf5, 0xca, 0xe7, 0x00, 0x39, 0x95, 0x6c, 0x53, 0xc2, 0x07 },
|
||||
.encoded = { 0x1c5a790a, 0x4ac145b1, 0xdab32c71, 0x6476dc9e, 0xcaf52776, 0x4d8900e7, 0x536c9539, 0x495607c2 },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0x76, 0x46, 0x88, 0x2d, 0x4c, 0xe1, 0x50, 0x5d, 0xd6, 0x7c, 0x41, 0x15, 0xc6, 0x1f, 0xd4, 0x60, 0x10, 0x15, 0x2a, 0x72, 0x2d, 0x89, 0x93, 0x13 },
|
||||
.encoded = { 0x2d884676, 0x4838e14c, 0x7cd65d50, 0x4bf31541, 0x60d41fc6, 0x39681510, 0x892d722a, 0x497c1393 },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0x32, 0xbc, 0x40, 0x92, 0x13, 0x37, 0x1a, 0xae, 0xb6, 0x00, 0xed, 0x30, 0xb8, 0x82, 0xee, 0xfc, 0xcf, 0x6d, 0x7f, 0xc5, 0xfa, 0x0e, 0xdd, 0x84 },
|
||||
.encoded = { 0x9240bc32, 0x49783713, 0x00b6ae1a, 0x46df30ed, 0xfcee82b8, 0x6e8a6dcf, 0x0efac57f, 0x571784dd },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0x29, 0xb3, 0x04, 0x95, 0xf2, 0x3c, 0x81, 0xe6, 0x5a, 0xf3, 0x42, 0x82, 0xd1, 0x79, 0xe2, 0x12, 0xbe, 0xc3, 0xd4, 0x10, 0x63, 0x66, 0x9f, 0xe3 },
|
||||
.encoded = { 0x9504b329, 0x51c53cf2, 0xf35ae681, 0x460e8242, 0x12e279d1, 0x5825c3be, 0x666310d4, 0x5ebde39f },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0xda, 0xda, 0x71, 0x4a, 0x62, 0x33, 0xdd, 0x31, 0x87, 0xf3, 0x70, 0x12, 0x33, 0x3b, 0x3b, 0xe9, 0xed, 0xc4, 0x6e, 0x6a, 0xc7, 0xd5, 0x85, 0xfc },
|
||||
.encoded = { 0x4a71dada, 0x4e6a3362, 0xf38731dd, 0x4bfa1270, 0xe93b3b33, 0x61f3c4ed, 0xd5c76a6e, 0x636ffc85 },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0x45, 0x64, 0x51, 0x34, 0x1c, 0x82, 0x81, 0x77, 0xf8, 0x89, 0xb1, 0x15, 0x82, 0x94, 0xdd, 0x64, 0xa2, 0x46, 0x0e, 0xfb, 0x1a, 0x70, 0x4b, 0x9f },
|
||||
.encoded = { 0x34516445, 0x39da821c, 0x89f87781, 0x4f2315b1, 0x64dd9482, 0x474b46a2, 0x701afb0e, 0x5e4b9f4b },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0x89, 0x87, 0x15, 0xb6, 0x66, 0x34, 0x49, 0x18, 0x8b, 0x7b, 0xb2, 0xf6, 0x96, 0x1e, 0x2e, 0xf1, 0x03, 0x9d, 0x4e, 0x16, 0x32, 0xd6, 0x23, 0x22 },
|
||||
.encoded = { 0xb6158789, 0x4eff3466, 0x7b8b1849, 0x63e5f6b2, 0xf12e1e96, 0x54c99d03, 0xd632164e, 0x42bd2223 },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0xa7, 0xa0, 0xb5, 0x21, 0xd2, 0xa3, 0x9f, 0x65, 0xa9, 0xeb, 0x72, 0xa2, 0x2e, 0xa6, 0xfb, 0x9c, 0x48, 0x7e, 0x68, 0x08, 0x7a, 0xb1, 0x4f, 0xbc },
|
||||
.encoded = { 0x21b5a0a7, 0x4ce2a3d2, 0xeba9659f, 0x5868a272, 0x9cfba62e, 0x5fd97e48, 0xb17a0868, 0x5b58bc4f },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0xf7, 0x05, 0xe3, 0x6c, 0xb1, 0x55, 0xcb, 0x2f, 0x8d, 0x3e, 0x0b, 0x2e, 0x3e, 0xb7, 0x02, 0xf5, 0x91, 0xb1, 0xfe, 0x8b, 0x58, 0x50, 0xb2, 0x40 },
|
||||
.encoded = { 0x6ce305f7, 0x569955b1, 0x3e8d2fcb, 0x56722e0b, 0xf502b73e, 0x535eb191, 0x50588bfe, 0x3a8f40b2 },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0x0f, 0x93, 0xb0, 0xd5, 0x60, 0xba, 0x40, 0x2a, 0x62, 0xa6, 0x92, 0x82, 0xb8, 0x91, 0x2c, 0xd7, 0x23, 0xdc, 0x6f, 0x7f, 0x2f, 0xbe, 0x41, 0xf5 },
|
||||
.encoded = { 0xd5b0930f, 0x5123ba60, 0xa6622a40, 0x3bbe8292, 0xd72c91b8, 0x582ddc23, 0xbe2f7f6f, 0x6935f541 },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0x7f, 0x0c, 0x99, 0xde, 0xff, 0x2e, 0xd2, 0x1c, 0x48, 0x98, 0x70, 0x85, 0x15, 0x01, 0x2a, 0xfb, 0xcd, 0xf2, 0xa0, 0xf9, 0x0e, 0xbc, 0x9f, 0x0c },
|
||||
.encoded = { 0xde990c7f, 0x6fe52eff, 0x98481cd2, 0x3deb8570, 0xfb2a0115, 0x61faf2cd, 0xbc0ef9a0, 0x55780c9f },
|
||||
},
|
||||
{
|
||||
.unencoded = { 0x9a, 0x10, 0x92, 0x03, 0x81, 0xfe, 0x41, 0x57, 0x77, 0x02, 0xcb, 0x20, 0x67, 0xa4, 0x97, 0xf3, 0xf8, 0xc7, 0x0d, 0x65, 0xcd, 0xfc, 0x15, 0xef },
|
||||
.encoded = { 0x0392109a, 0x4b64fe81, 0x02775741, 0x418820cb, 0xf397a467, 0x6998c7f8, 0xfccd650d, 0x6ba3ef15 },
|
||||
},
|
||||
};
|
||||
|
||||
TEST_CASE("Test 3/4 Coding Scheme Algorithm", "[efuse]")
|
||||
{
|
||||
const int num_tests = sizeof(coding_scheme_data)/sizeof(coding_scheme_test_t);
|
||||
for (int i = 0; i < num_tests; i++) {
|
||||
uint32_t result[8];
|
||||
const coding_scheme_test_t *t = &coding_scheme_data[i];
|
||||
|
||||
printf("Test case %d...\n", i);
|
||||
esp_err_t r = esp_efuse_apply_34_encoding(t->unencoded, result, sizeof(t->unencoded));
|
||||
TEST_ASSERT_EQUAL_HEX(ESP_OK, r);
|
||||
TEST_ASSERT_EQUAL_HEX32_ARRAY(t->encoded, result, 8);
|
||||
|
||||
// Do the same, 6 bytes at a time
|
||||
for (int offs = 0; offs < sizeof(t->unencoded); offs += 6) {
|
||||
bzero(result, sizeof(result));
|
||||
r = esp_efuse_apply_34_encoding(t->unencoded + offs, result, 6);
|
||||
TEST_ASSERT_EQUAL_HEX(ESP_OK, r);
|
||||
TEST_ASSERT_EQUAL_HEX32_ARRAY(t->encoded + (offs / 6 * 2), result, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test Coding Scheme for efuse manager", "[efuse]")
|
||||
{
|
||||
int count_useful_reg = 0;
|
||||
int useful_data_in_byte;
|
||||
uint8_t buf[32];
|
||||
uint32_t encoded[8];
|
||||
bootloader_random_enable();
|
||||
esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme(EFUSE_BLK2);
|
||||
if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {
|
||||
printf("EFUSE_CODING_SCHEME_NONE\n");
|
||||
count_useful_reg = 8;
|
||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_3_4) {
|
||||
printf("EFUSE_CODING_SCHEME_3_4\n");
|
||||
count_useful_reg = 6;
|
||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_REPEAT) {
|
||||
printf("EFUSE_CODING_SCHEME_REPEAT\n");
|
||||
count_useful_reg = 4;
|
||||
}
|
||||
useful_data_in_byte = count_useful_reg * 4;
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
printf("Test case %d...\n", i);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memset(encoded, 0, sizeof(encoded));
|
||||
// get test data
|
||||
bootloader_fill_random(buf, useful_data_in_byte);
|
||||
memset(buf, 0, i);
|
||||
|
||||
esp_efuse_utility_reset();
|
||||
|
||||
for (int j = 0; j < count_useful_reg; ++j) {
|
||||
REG_WRITE(EFUSE_BLK2_WDATA0_REG + j * 4, *((uint32_t*)buf + j));
|
||||
}
|
||||
|
||||
TEST_ESP_OK(esp_efuse_utility_apply_new_coding_scheme());
|
||||
|
||||
uint32_t w_data_after_coding[8] = { 0 };
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
w_data_after_coding[j] = REG_READ(EFUSE_BLK2_WDATA0_REG + j * 4);
|
||||
}
|
||||
|
||||
if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {
|
||||
memcpy((uint8_t*)encoded, buf, sizeof(buf));
|
||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_3_4) {
|
||||
TEST_ESP_OK(esp_efuse_apply_34_encoding(buf, encoded, useful_data_in_byte));
|
||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_REPEAT) {
|
||||
for (int j = 0; j < count_useful_reg; ++j) {
|
||||
encoded[j] = *((uint32_t*)buf + j);
|
||||
encoded[j + 4] = encoded[j];
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||
printf("Data from W reg\n");
|
||||
esp_efuse_utility_erase_virt_blocks();
|
||||
esp_efuse_utility_burn_efuses();
|
||||
esp_efuse_utility_debug_dump_blocks();
|
||||
printf("Data from encoded\n");
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
printf("0x%08x ", encoded[j]);
|
||||
}
|
||||
printf("\nData from w_data_after_coding\n");
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
printf("0x%08x ", w_data_after_coding[j]);
|
||||
}
|
||||
|
||||
printf("\nData from buf\n");
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
printf("0x%08x ", *((uint32_t*)buf + j));
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
TEST_ASSERT_EQUAL_HEX32_ARRAY(encoded, w_data_after_coding, 8);
|
||||
}
|
||||
esp_efuse_utility_reset();
|
||||
bootloader_random_disable();
|
||||
}
|
||||
|
||||
TEST_CASE("Test data does not match the coding scheme", "[efuse]")
|
||||
{
|
||||
int count_useful_reg = 0;
|
||||
esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme(EFUSE_BLK2);
|
||||
if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {
|
||||
printf("EFUSE_CODING_SCHEME_NONE\n");
|
||||
count_useful_reg = 8;
|
||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_3_4) {
|
||||
printf("EFUSE_CODING_SCHEME_3_4\n");
|
||||
count_useful_reg = 6 + 1;
|
||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_REPEAT) {
|
||||
printf("EFUSE_CODING_SCHEME_REPEAT\n");
|
||||
count_useful_reg = 4 + 1;
|
||||
}
|
||||
|
||||
esp_efuse_utility_reset();
|
||||
|
||||
for (int i = 0; i < count_useful_reg; ++i) {
|
||||
REG_WRITE(EFUSE_BLK2_WDATA0_REG + i * 4, 0xABCDEF01 + i);
|
||||
}
|
||||
|
||||
if (coding_scheme == EFUSE_CODING_SCHEME_NONE) {
|
||||
TEST_ESP_OK(esp_efuse_utility_apply_new_coding_scheme());
|
||||
} else {
|
||||
TEST_ESP_ERR(ESP_ERR_CODING, esp_efuse_utility_apply_new_coding_scheme());
|
||||
}
|
||||
|
||||
esp_efuse_utility_reset();
|
||||
}
|
295
components/efuse/test_efuse_host/efuse_tests.py
Normal file
295
components/efuse/test_efuse_host/efuse_tests.py
Normal file
@ -0,0 +1,295 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function, division
|
||||
import unittest
|
||||
import struct
|
||||
import csv
|
||||
import sys
|
||||
import subprocess
|
||||
import tempfile
|
||||
import os
|
||||
import StringIO
|
||||
sys.path.append("..")
|
||||
from efuse import *
|
||||
|
||||
'''
|
||||
To run the test on local PC:
|
||||
cd ~/esp/esp-idf/components/efuse/test_efuse_host/
|
||||
./efuse_tests.py
|
||||
'''
|
||||
|
||||
|
||||
class CSVParserTests(unittest.TestCase):
|
||||
|
||||
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
|
||||
name2, EFUSE_BLK3, 5, 4, Use for test name 2
|
||||
"""
|
||||
t = 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[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')
|
||||
|
||||
def test_seq_bit_start1_fill(self):
|
||||
csv = """
|
||||
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
|
||||
name1, EFUSE_BLK3, , 5,
|
||||
name2, EFUSE_BLK3, , 4,
|
||||
"""
|
||||
t = 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[1].field_name, 'name2')
|
||||
self.assertEqual(t[1].bit_start, 5)
|
||||
self.assertEqual(t[1].bit_count, 4)
|
||||
|
||||
def test_seq_bit_start2_fill(self):
|
||||
csv = """
|
||||
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
|
||||
name1, EFUSE_BLK3, , 5,
|
||||
name2, EFUSE_BLK2, , 4,
|
||||
"""
|
||||
t = 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[1].field_name, 'name2')
|
||||
self.assertEqual(t[1].bit_start, 0)
|
||||
self.assertEqual(t[1].bit_count, 4)
|
||||
|
||||
def test_seq_bit_start3_fill(self):
|
||||
csv = """
|
||||
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
|
||||
name1, EFUSE_BLK3, , 5,
|
||||
name2, EFUSE_BLK2, , 4,
|
||||
|
||||
name3, EFUSE_BLK2, 5, 4,
|
||||
"""
|
||||
t = 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[1].field_name, 'name2')
|
||||
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)
|
||||
|
||||
def test_seq_bit_start4_fill(self):
|
||||
csv = """
|
||||
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
|
||||
name1, EFUSE_BLK3, , 5,
|
||||
name2, EFUSE_BLK2, , 4,
|
||||
, EFUSE_BLK2, , 4,
|
||||
name1, EFUSE_BLK3, , 5,
|
||||
"""
|
||||
with self.assertRaisesRegexp(InputError, "Field names must be unique"):
|
||||
t = FuseTable.from_csv(csv)
|
||||
|
||||
|
||||
def test_seq_bit_start5_fill(self):
|
||||
csv = """
|
||||
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
|
||||
name1, EFUSE_BLK3, , 5,
|
||||
name2, EFUSE_BLK2, , 4,
|
||||
, EFUSE_BLK2, , 4,
|
||||
name3, EFUSE_BLK3, 5, 5,
|
||||
"""
|
||||
t = 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[1].field_name, 'name2')
|
||||
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[3].field_name, 'name3')
|
||||
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.verify()
|
||||
|
||||
def test_empty_field_name_fail(self):
|
||||
csv = """
|
||||
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
|
||||
, EFUSE_BLK3, , 5,
|
||||
name2, EFUSE_BLK2, , 4,
|
||||
"""
|
||||
with self.assertRaisesRegexp(InputError, "missing field name"):
|
||||
t = 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)
|
||||
|
||||
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)
|
||||
|
||||
def test_bit_start_num_fail(self):
|
||||
csv = """
|
||||
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
|
||||
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)
|
||||
|
||||
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
|
||||
name2, EFUSE_BLK2, 6, 5, Use for test name 2
|
||||
name3, EFUSE_BLK3, 20, 5, Use for test name 3
|
||||
, 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.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[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[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[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[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)
|
||||
|
||||
def test_block_fail(self):
|
||||
csv = """
|
||||
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
|
||||
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)
|
||||
|
||||
def test_field_size_is_ok(self):
|
||||
csv = """
|
||||
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
|
||||
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)
|
||||
t.verify()
|
||||
|
||||
def test_field_blk0_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
|
||||
"""
|
||||
t = FuseTable.from_csv(csv)
|
||||
with self.assertRaisesRegexp(InputError, "The field is outside the boundaries"):
|
||||
t.verify()
|
||||
|
||||
def test_field_blk1_size_is_more(self):
|
||||
csv = """
|
||||
# field_name, efuse_block(EFUSE_BLK0..EFUSE_BLK3), bit_start(0..255), bit_count, comment
|
||||
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.verify()
|
||||
|
||||
class VerificationTests(unittest.TestCase):
|
||||
|
||||
def test_bit_start_num_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
|
||||
name2, EFUSE_BLK3, 5, 4, Use for test name 2
|
||||
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.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[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[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[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__":
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user