1# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, 2# Espressif Systems (Shanghai) CO LTD, other contributors as noted. 3# 4# SPDX-License-Identifier: GPL-2.0-or-later 5 6import struct 7import time 8from typing import Dict 9 10from .esp32c3 import ESP32C3ROM 11from ..loader import ESPLoader 12from ..util import FatalError 13 14 15class ESP32C2ROM(ESP32C3ROM): 16 CHIP_NAME = "ESP32-C2" 17 IMAGE_CHIP_ID = 12 18 19 IROM_MAP_START = 0x42000000 20 IROM_MAP_END = 0x42400000 21 DROM_MAP_START = 0x3C000000 22 DROM_MAP_END = 0x3C400000 23 24 # Magic value for ESP32C2 ECO0 , ECO1 and ECO4 respectively 25 CHIP_DETECT_MAGIC_VALUE = [0x6F51306F, 0x7C41A06F, 0x0C21E06F] 26 27 EFUSE_BASE = 0x60008800 28 EFUSE_BLOCK2_ADDR = EFUSE_BASE + 0x040 29 MAC_EFUSE_REG = EFUSE_BASE + 0x040 30 31 EFUSE_SECURE_BOOT_EN_REG = EFUSE_BASE + 0x30 32 EFUSE_SECURE_BOOT_EN_MASK = 1 << 21 33 34 EFUSE_SPI_BOOT_CRYPT_CNT_REG = EFUSE_BASE + 0x30 35 EFUSE_SPI_BOOT_CRYPT_CNT_MASK = 0x7 << 18 36 37 EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = EFUSE_BASE + 0x30 38 EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = 1 << 6 39 40 EFUSE_XTS_KEY_LENGTH_256_REG = EFUSE_BASE + 0x30 41 EFUSE_XTS_KEY_LENGTH_256 = 1 << 10 42 43 EFUSE_BLOCK_KEY0_REG = EFUSE_BASE + 0x60 44 45 EFUSE_RD_DIS_REG = EFUSE_BASE + 0x30 46 EFUSE_RD_DIS = 3 47 48 FLASH_FREQUENCY = { 49 "60m": 0xF, 50 "30m": 0x0, 51 "20m": 0x1, 52 "15m": 0x2, 53 } 54 55 MEMORY_MAP = [ 56 [0x00000000, 0x00010000, "PADDING"], 57 [0x3C000000, 0x3C400000, "DROM"], 58 [0x3FCA0000, 0x3FCE0000, "DRAM"], 59 [0x3FC88000, 0x3FD00000, "BYTE_ACCESSIBLE"], 60 [0x3FF00000, 0x3FF50000, "DROM_MASK"], 61 [0x40000000, 0x40090000, "IROM_MASK"], 62 [0x42000000, 0x42400000, "IROM"], 63 [0x4037C000, 0x403C0000, "IRAM"], 64 ] 65 66 UF2_FAMILY_ID = 0x2B88D29C 67 68 KEY_PURPOSES: Dict[int, str] = {} 69 70 def get_pkg_version(self): 71 num_word = 1 72 return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 22) & 0x07 73 74 def get_chip_description(self): 75 chip_name = { 76 0: "ESP32-C2", 77 1: "ESP32-C2", 78 }.get(self.get_pkg_version(), "unknown ESP32-C2") 79 major_rev = self.get_major_chip_version() 80 minor_rev = self.get_minor_chip_version() 81 return f"{chip_name} (revision v{major_rev}.{minor_rev})" 82 83 def get_minor_chip_version(self): 84 num_word = 1 85 return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 16) & 0xF 86 87 def get_major_chip_version(self): 88 num_word = 1 89 return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 20) & 0x3 90 91 def get_flash_cap(self): 92 # ESP32-C2 doesn't have eFuse field FLASH_CAP. 93 # Can't get info about the flash chip. 94 return 0 95 96 def get_flash_vendor(self): 97 # ESP32-C2 doesn't have eFuse field FLASH_VENDOR. 98 # Can't get info about the flash chip. 99 return "" 100 101 def get_crystal_freq(self): 102 # The crystal detection algorithm of ESP32/ESP8266 works for ESP32-C2 as well. 103 return ESPLoader.get_crystal_freq(self) 104 105 def change_baud(self, baud): 106 rom_with_26M_XTAL = not self.IS_STUB and self.get_crystal_freq() == 26 107 if rom_with_26M_XTAL: 108 # The code is copied over from ESPLoader.change_baud(). 109 # Probably this is just a temporary solution until the next chip revision. 110 111 # The ROM code thinks it uses a 40 MHz XTAL. Recompute the baud rate 112 # in order to trick the ROM code to set the correct baud rate for 113 # a 26 MHz XTAL. 114 false_rom_baud = baud * 40 // 26 115 116 print(f"Changing baud rate to {baud}") 117 self.command( 118 self.ESP_CHANGE_BAUDRATE, struct.pack("<II", false_rom_baud, 0) 119 ) 120 print("Changed.") 121 self._set_port_baudrate(baud) 122 time.sleep(0.05) # get rid of garbage sent during baud rate change 123 self.flush_input() 124 else: 125 ESPLoader.change_baud(self, baud) 126 127 def _post_connect(self): 128 # ESP32C2 ECO0 is no longer supported by the flasher stub 129 if not self.secure_download_mode and self.get_chip_revision() == 0: 130 self.stub_is_disabled = True 131 self.IS_STUB = False 132 133 """ Try to read (encryption key) and check if it is valid """ 134 135 def is_flash_encryption_key_valid(self): 136 key_len_256 = ( 137 self.read_reg(self.EFUSE_XTS_KEY_LENGTH_256_REG) 138 & self.EFUSE_XTS_KEY_LENGTH_256 139 ) 140 141 word0 = self.read_reg(self.EFUSE_RD_DIS_REG) & self.EFUSE_RD_DIS 142 rd_disable = word0 == 3 if key_len_256 else word0 == 1 143 144 # reading of BLOCK3 is NOT ALLOWED so we assume valid key is programmed 145 if rd_disable: 146 return True 147 else: 148 # reading of BLOCK3 is ALLOWED so we will read and verify for non-zero. 149 # When chip has not generated AES/encryption key in BLOCK3, 150 # the contents will be readable and 0. 151 # If the flash encryption is enabled it is expected to have a valid 152 # non-zero key. We break out on first occurrence of non-zero value 153 key_word = [0] * 7 if key_len_256 else [0] * 3 154 for i in range(len(key_word)): 155 key_word[i] = self.read_reg(self.EFUSE_BLOCK_KEY0_REG + i * 4) 156 # key is non-zero so break & return 157 if key_word[i] != 0: 158 return True 159 return False 160 161 def check_spi_connection(self, spi_connection): 162 if not set(spi_connection).issubset(set(range(0, 21))): 163 raise FatalError("SPI Pin numbers must be in the range 0-20.") 164 165 166class ESP32C2StubLoader(ESP32C2ROM): 167 """Access class for ESP32C2 stub loader, runs on top of ROM. 168 169 (Basically the same as ESP32StubLoader, but different base class. 170 Can possibly be made into a mixin.) 171 """ 172 173 FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c 174 STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM 175 IS_STUB = True 176 177 def __init__(self, rom_loader): 178 self.secure_download_mode = rom_loader.secure_download_mode 179 self._port = rom_loader._port 180 self._trace_enabled = rom_loader._trace_enabled 181 self.cache = rom_loader.cache 182 self.flush_input() # resets _slip_reader 183 184 185ESP32C2ROM.STUB_CLASS = ESP32C2StubLoader 186