1# This file describes eFuses controller for ESP32 chip 2# 3# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD 4# 5# SPDX-License-Identifier: GPL-2.0-or-later 6 7import time 8 9from .mem_definition import EfuseDefineBlocks, EfuseDefineFields, EfuseDefineRegisters 10from ..emulate_efuse_controller_base import EmulateEfuseControllerBase, FatalError 11 12 13class EmulateEfuseController(EmulateEfuseControllerBase): 14 """The class for virtual efuse operations. Using for HOST_TEST.""" 15 16 CHIP_NAME = "ESP32" 17 mem = None 18 debug = False 19 20 def __init__(self, efuse_file=None, debug=False): 21 self.Blocks = EfuseDefineBlocks 22 self.Fields = EfuseDefineFields(None) 23 self.REGS = EfuseDefineRegisters 24 super(EmulateEfuseController, self).__init__(efuse_file, debug) 25 26 """ esptool method start >> """ 27 28 def get_major_chip_version(self): 29 return 3 30 31 def get_minor_chip_version(self): 32 return 0 33 34 def get_crystal_freq(self): 35 return 40 # MHz (common for all chips) 36 37 def read_reg(self, addr): 38 if addr == self.REGS.APB_CTL_DATE_ADDR: 39 return self.REGS.APB_CTL_DATE_V << self.REGS.APB_CTL_DATE_S 40 else: 41 return super(EmulateEfuseController, self).read_reg(addr) 42 43 """ << esptool method end """ 44 45 def send_burn_cmd(self): 46 def wait_idle(): 47 deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT 48 while time.time() < deadline: 49 if self.read_reg(self.REGS.EFUSE_REG_CMD) == 0: 50 return 51 raise FatalError( 52 "Timed out waiting for Efuse controller command to complete" 53 ) 54 55 self.write_reg(self.REGS.EFUSE_REG_CMD, self.REGS.EFUSE_CMD_WRITE) 56 wait_idle() 57 self.write_reg(self.REGS.EFUSE_REG_CONF, self.REGS.EFUSE_CONF_READ) 58 self.write_reg(self.REGS.EFUSE_REG_CMD, self.REGS.EFUSE_CMD_READ) 59 wait_idle() 60 61 def handle_writing_event(self, addr, value): 62 if addr == self.REGS.EFUSE_REG_CMD: 63 if value == self.REGS.EFUSE_CMD_WRITE: 64 self.write_reg(addr, 0) 65 elif value == self.REGS.EFUSE_CMD_READ: 66 self.copy_blocks_wr_regs_to_rd_regs() 67 self.clean_blocks_wr_regs() 68 self.check_rd_protection_area() 69 self.write_reg(addr, 0) 70 self.save_to_file() 71 72 def read_raw_coding_scheme(self): 73 coding_scheme = ( 74 self.read_efuse(self.REGS.EFUSE_CODING_SCHEME_WORD) 75 & self.REGS.EFUSE_CODING_SCHEME_MASK 76 ) 77 if coding_scheme == self.REGS.CODING_SCHEME_NONE_RECOVERY: 78 return self.REGS.CODING_SCHEME_NONE 79 else: 80 return coding_scheme 81 82 def write_raw_coding_scheme(self, value): 83 self.write_efuse( 84 self.REGS.EFUSE_CODING_SCHEME_WORD, 85 value & self.REGS.EFUSE_CODING_SCHEME_MASK, 86 ) 87 self.send_burn_cmd() 88 if value != self.read_raw_coding_scheme(): 89 raise FatalError( 90 "Error during a burning process to set the new coding scheme" 91 ) 92 print("Set coding scheme = %d" % self.read_raw_coding_scheme()) 93 94 def get_bitlen_of_block(self, blk, wr=False): 95 if blk.id == 0: 96 return 32 * blk.len 97 else: 98 coding_scheme = self.read_raw_coding_scheme() 99 if coding_scheme == self.REGS.CODING_SCHEME_NONE: 100 return 32 * blk.len 101 elif coding_scheme == self.REGS.CODING_SCHEME_34: 102 if wr: 103 return 32 * 8 104 else: 105 return 32 * blk.len * 3 // 4 106 else: 107 raise FatalError( 108 "The {} coding scheme is not supported".format(coding_scheme) 109 ) 110 111 def handle_coding_scheme(self, blk, data): 112 # it verifies the coding scheme part of data and returns just data 113 if blk.id != 0 and self.read_raw_coding_scheme() == self.REGS.CODING_SCHEME_34: 114 # CODING_SCHEME 3/4 applied only for BLK1..3 115 # Takes 24 byte sequence to be represented in 3/4 encoding, 116 # returns 8 words suitable for writing "encoded" to an efuse block 117 data.pos = 0 118 for _ in range(0, 4): 119 xor_res = 0 120 mul_res = 0 121 chunk_data = data.readlist("8*uint:8") 122 chunk_data = chunk_data[::-1] 123 for i in range(0, 6): 124 byte_data = chunk_data[i] 125 xor_res ^= byte_data 126 mul_res += (i + 1) * bin(byte_data).count("1") 127 if xor_res != chunk_data[6] or mul_res != chunk_data[7]: 128 print( 129 "xor_res ", 130 xor_res, 131 chunk_data[6], 132 "mul_res", 133 mul_res, 134 chunk_data[7], 135 ) 136 raise FatalError("Error in coding scheme data") 137 # cut the coded data 138 for i in range(0, 4): 139 del data[i * 6 * 8 : (i * 6 * 8) + 16] 140 return data 141