mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 05:08:41 +08:00
5e2fc181c2
Nxdiag examples scripts modified to print system information without building and flashing nxdiag application to get report about system without reflash or reconfigure.
424 lines
13 KiB
Python
424 lines
13 KiB
Python
############################################################################
|
|
# tools/espressif/chip_info.py
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
# contributor license agreements. See the NOTICE file distributed with
|
|
# this work for additional information regarding copyright ownership. The
|
|
# ASF licenses this file to you 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.
|
|
#
|
|
############################################################################
|
|
import os
|
|
import platform
|
|
import re
|
|
import subprocess
|
|
|
|
TOPDIR = "."
|
|
ARCH_ESP_HALDIR = "{TOPDIR}/arch/{ARCH_DIR}/src/chip/esp-hal-3rdparty"
|
|
|
|
|
|
def get_python_modules():
|
|
"""
|
|
Gets the list of python modules installed on the host system.
|
|
|
|
Args:
|
|
None.
|
|
|
|
Returns:
|
|
list: Python modules (with version) installed on the host system.
|
|
"""
|
|
|
|
modules = []
|
|
|
|
output = subprocess.check_output(
|
|
["pip", "list", "--format=freeze"], universal_newlines=True
|
|
)
|
|
for line in output.splitlines():
|
|
if line.startswith("#"):
|
|
continue
|
|
package_info = line.split("==")
|
|
if len(package_info) > 1:
|
|
modules.append("{}-{}".format(package_info[0], package_info[1]))
|
|
else:
|
|
modules.append(package_info[0])
|
|
return modules
|
|
|
|
|
|
def run_espressif_tool(cmd):
|
|
tool = "esptool.py"
|
|
strings_out = ""
|
|
command = "{} {}".format(tool, cmd)
|
|
|
|
strings_out = subprocess.run(
|
|
command, universal_newlines=True, shell=True, capture_output=True
|
|
)
|
|
|
|
return strings_out.stdout
|
|
|
|
|
|
def get_espressif_chip_id():
|
|
output = run_espressif_tool("chip_id")
|
|
string_out = next((s for s in output.split("\n") if "Chip ID" in s), "Not found")
|
|
if string_out != "Not found":
|
|
string_out = string_out.split("Warning: ")[-1]
|
|
return string_out
|
|
|
|
|
|
def get_espressif_flash_id():
|
|
strings_out = []
|
|
output = run_espressif_tool("flash_id")
|
|
|
|
strings_out.append(
|
|
next(
|
|
(s for s in output.split("\n") if "Manufacturer" in s),
|
|
"Manufacturer: Not found",
|
|
)
|
|
)
|
|
strings_out.append(
|
|
next((s for s in output.split("\n") if "Device" in s), "Device: Not found")
|
|
)
|
|
|
|
return strings_out
|
|
|
|
|
|
def get_espressif_security_info():
|
|
output = run_espressif_tool("get_security_info")
|
|
|
|
start_string = "====================="
|
|
stop_string = "Hard resetting via RTS pin..."
|
|
output = output.split("\n")
|
|
strings_out = []
|
|
|
|
str_out = next((s for s in output if start_string in s), "Not found")
|
|
if str_out != "Not found":
|
|
start_index = output.index(start_string) + 1
|
|
stop_index = output.index(stop_string)
|
|
strings_out = output[start_index:stop_index]
|
|
else:
|
|
strings_out.append(str_out)
|
|
|
|
return strings_out
|
|
|
|
|
|
def get_espressif_flash_status():
|
|
output = run_espressif_tool("read_flash_status")
|
|
|
|
string_out = next(
|
|
(s for s in output.split("\n") if "Status value" in s), "Not found"
|
|
)
|
|
if string_out != "Not found":
|
|
string_out = string_out.split("Status value: ")[-1]
|
|
return string_out
|
|
|
|
|
|
def get_espressif_mac_address():
|
|
output = run_espressif_tool("read_mac")
|
|
|
|
string_out = next((s for s in output.split("\n") if "MAC" in s), "Not found")
|
|
if string_out != "Not found":
|
|
string_out = string_out.split("MAC: ")[-1]
|
|
return string_out
|
|
|
|
|
|
def get_espressif_bootloader_version(bindir):
|
|
"""
|
|
Get the bootloader version for Espressif chips from the bootloader binary. This
|
|
function works on Linux, Windows, and macOS.
|
|
|
|
Args:
|
|
bindir (str): The path to the bootloader binary directory.
|
|
|
|
Returns:
|
|
dict: A dictionary containing the bootloader version for each chip.
|
|
"""
|
|
|
|
regex = r"^(?=.*\bv\d+(\.\d+){1,2}\b).+$"
|
|
bootloader_chips = [
|
|
"esp32",
|
|
"esp32s2",
|
|
"esp32s3",
|
|
"esp32c2",
|
|
"esp32c3",
|
|
"esp32c6",
|
|
"esp32h2",
|
|
]
|
|
bootloader_version = {}
|
|
|
|
for chip in bootloader_chips:
|
|
file = "bootloader-{}.bin".format(chip)
|
|
path = os.path.join(bindir, file)
|
|
|
|
if os.path.isfile(path):
|
|
if platform.system() == "Linux":
|
|
process = subprocess.Popen(["strings", path], stdout=subprocess.PIPE)
|
|
elif platform.system() == "Windows":
|
|
process = subprocess.Popen(
|
|
[
|
|
"powershell",
|
|
"Get-Content -Raw -Encoding Byte {} |".format(path)
|
|
+ " % { [char[]]$_ -join \"\" } | Select-String -Pattern '[\\x20-\\x7E]+'"
|
|
+ " -AllMatches | % { $_.Matches } | % { $_.Value }",
|
|
],
|
|
stdout=subprocess.PIPE,
|
|
)
|
|
elif platform.system() == "Darwin":
|
|
process = subprocess.Popen(
|
|
["strings", "-", path], stdout=subprocess.PIPE
|
|
)
|
|
else:
|
|
bootloader_version[chip] = "Not supported on host OS"
|
|
break
|
|
|
|
output, error = process.communicate()
|
|
strings_out = output.decode("utf-8", errors="ignore")
|
|
matches = re.finditer(regex, strings_out, re.MULTILINE)
|
|
|
|
try:
|
|
bootloader_version[chip] = next(matches).group(0)
|
|
except StopIteration:
|
|
bootloader_version[chip] = "Unknown"
|
|
|
|
else:
|
|
bootloader_version[chip] = "Bootloader image not found"
|
|
|
|
return bootloader_version
|
|
|
|
|
|
def get_espressif_toolchain_version():
|
|
"""
|
|
Get the version of different toolchains used by Espressif chips.
|
|
|
|
Args:
|
|
None.
|
|
|
|
Returns:
|
|
dict: A dictionary containing the toolchain version for each toolchain.
|
|
"""
|
|
|
|
toolchain_version = {}
|
|
toolchain_bins = [
|
|
"clang",
|
|
"gcc",
|
|
"xtensa-esp32-elf-gcc",
|
|
"xtensa-esp32s2-elf-gcc",
|
|
"xtensa-esp32s3-elf-gcc",
|
|
"riscv32-esp-elf-gcc",
|
|
"riscv64-unknown-elf-gcc",
|
|
]
|
|
|
|
for binary in toolchain_bins:
|
|
try:
|
|
version_output = subprocess.check_output(
|
|
[binary, "--version"], stderr=subprocess.STDOUT, universal_newlines=True
|
|
)
|
|
version_lines = version_output.split("\n")
|
|
version = version_lines[0].strip()
|
|
toolchain_version[binary] = version
|
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
toolchain_version[binary] = "Not found"
|
|
|
|
return toolchain_version
|
|
|
|
|
|
def get_espressif_hal_version(hal_dir):
|
|
"""
|
|
Get the version of the ESP HAL used by Espressif chips.
|
|
|
|
Args:
|
|
None.
|
|
|
|
Returns:
|
|
str: The ESP HAL version.
|
|
"""
|
|
|
|
hal_version = "Not found"
|
|
|
|
try:
|
|
if os.path.isdir(os.path.join(hal_dir, ".git")):
|
|
hal_version_output = subprocess.check_output(
|
|
["git", "describe", "--tags", "--always"],
|
|
cwd=hal_dir,
|
|
stderr=subprocess.STDOUT,
|
|
universal_newlines=True,
|
|
)
|
|
hal_version = hal_version_output.strip()
|
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
pass
|
|
|
|
return hal_version
|
|
|
|
|
|
def get_arch(config):
|
|
"""
|
|
Get the architecture type.
|
|
|
|
Args:
|
|
config (list): Listed version of .config file.
|
|
|
|
Returns:
|
|
str: Architecture name (xtensa or risc-v).
|
|
"""
|
|
|
|
arch_key = "CONFIG_ARCH="
|
|
arch = [s for s in config if arch_key in s][0].replace(arch_key, "")
|
|
if "risc" in arch:
|
|
return "risc-v"
|
|
return "xtensa"
|
|
|
|
|
|
def check_chip_info(config):
|
|
"""
|
|
Get chip info flag to fetch data.
|
|
|
|
Args:
|
|
config (list): Listed version of .config file.
|
|
|
|
Returns:
|
|
bool: Indication of getting chip information
|
|
bool: Indication of getting chip information on runtime
|
|
"""
|
|
|
|
chip_info_key = "CONFIG_SYSTEM_NXDIAG_ESPRESSIF_CHIP="
|
|
chip_info_runtime_key = "CONFIG_SYSTEM_NXDIAG_ESPRESSIF_CHIP_WO_TOOL="
|
|
nxdiag_key = "CONFIG_SYSTEM_NXDIAG="
|
|
|
|
chip_info = [s for s in config if chip_info_key in s]
|
|
chip_info_runtime = [s for s in config if chip_info_runtime_key in s]
|
|
nxdiag = [s for s in config if nxdiag_key in s]
|
|
|
|
if nxdiag == []:
|
|
return True, False
|
|
|
|
return chip_info != [], chip_info_runtime != []
|
|
|
|
|
|
def get_vendor_info(config):
|
|
"""
|
|
Get vendor specific information.
|
|
|
|
Args:
|
|
config (list): Listed version of .config file.
|
|
|
|
Returns:
|
|
str: Parsed vendor specific information for sysinfo.h,
|
|
str: Parsed vendor specific information for print during build
|
|
"""
|
|
|
|
info = {}
|
|
output = ""
|
|
build_output = ""
|
|
|
|
# Espressif bootloader version
|
|
|
|
info["ESPRESSIF_BOOTLOADER"] = get_espressif_bootloader_version(TOPDIR)
|
|
output += "#define ESPRESSIF_BOOTLOADER_ARRAY_SIZE {}\n".format(
|
|
len(info["ESPRESSIF_BOOTLOADER"])
|
|
)
|
|
output += "static const char *ESPRESSIF_BOOTLOADER[ESPRESSIF_BOOTLOADER_ARRAY_SIZE] =\n{\n"
|
|
build_output = "Bootloader version:\n"
|
|
for key, value in info["ESPRESSIF_BOOTLOADER"].items():
|
|
output += ' "{}: {}",\n'.format(key, value)
|
|
build_output += " {}: {},\n".format(key, value)
|
|
output += "};\n\n"
|
|
build_output += "\n\n"
|
|
|
|
# Espressif toolchain version
|
|
|
|
info["ESPRESSIF_TOOLCHAIN"] = get_espressif_toolchain_version()
|
|
output += "#define ESPRESSIF_TOOLCHAIN_ARRAY_SIZE {}\n".format(
|
|
len(info["ESPRESSIF_TOOLCHAIN"])
|
|
)
|
|
output += (
|
|
"static const char *ESPRESSIF_TOOLCHAIN[ESPRESSIF_TOOLCHAIN_ARRAY_SIZE] =\n{\n"
|
|
)
|
|
build_output += "Toolchain version:\n"
|
|
for key, value in info["ESPRESSIF_TOOLCHAIN"].items():
|
|
output += ' "{}: {}",\n'.format(key, value)
|
|
build_output += " {}: {},\n".format(key, value)
|
|
output += "};\n\n"
|
|
build_output += "\n\n"
|
|
|
|
# Espressif esptool version
|
|
|
|
info["ESPRESSIF_ESPTOOL"] = next(
|
|
(s for s in get_python_modules() if "esptool" in s), "Not found"
|
|
)
|
|
output += 'static const char ESPRESSIF_ESPTOOL[] = "{}";\n\n'.format(
|
|
info["ESPRESSIF_ESPTOOL"].split("-")[1]
|
|
)
|
|
build_output += "Esptool version: {}\n\n".format(
|
|
info["ESPRESSIF_ESPTOOL"].split("-")[1]
|
|
)
|
|
|
|
# Espressif HAL version
|
|
|
|
arch = get_arch(config)
|
|
hal_path = ARCH_ESP_HALDIR.format(TOPDIR=TOPDIR, ARCH_DIR=arch)
|
|
info["ESPRESSIF_HAL"] = get_espressif_hal_version(hal_path)
|
|
output += 'static const char ESPRESSIF_HAL[] = "{}";\n\n'.format(
|
|
info["ESPRESSIF_HAL"]
|
|
)
|
|
build_output += "HAL version: {}\n\n".format(info["ESPRESSIF_HAL"])
|
|
|
|
chip_info, chip_runtime = check_chip_info(config)
|
|
if (chip_info and not chip_runtime) and info[
|
|
"ESPRESSIF_ESPTOOL"
|
|
] not in "Not found":
|
|
info["ESPRESSIF_CHIP_ID"] = get_espressif_chip_id()
|
|
output += 'static const char ESPRESSIF_CHIP_ID[] = "{}";\n\n'.format(
|
|
info["ESPRESSIF_CHIP_ID"]
|
|
)
|
|
build_output += "CHIP ID: = {}\n\n".format(info["ESPRESSIF_CHIP_ID"])
|
|
|
|
info["ESPRESSIF_FLASH_ID"] = get_espressif_flash_id()
|
|
output += "#define ESPRESSIF_FLASH_ID_ARRAY_SIZE {}\n".format(
|
|
len(info["ESPRESSIF_FLASH_ID"])
|
|
)
|
|
output += "static const char *ESPRESSIF_FLASH_ID[ESPRESSIF_FLASH_ID_ARRAY_SIZE] =\n{\n"
|
|
build_output += "Flash ID:\n"
|
|
for each_item in info["ESPRESSIF_FLASH_ID"]:
|
|
output += ' "{}",\n'.format(each_item)
|
|
build_output += " {}\n".format(each_item)
|
|
output += "};\n\n"
|
|
build_output += "\n\n"
|
|
|
|
info["ESPRESSIF_SECURITY_INFO"] = get_espressif_security_info()
|
|
output += "#define ESPRESSIF_SECURITY_INFO_ARRAY_SIZE {}\n".format(
|
|
len(info["ESPRESSIF_SECURITY_INFO"])
|
|
)
|
|
output += "static const char *ESPRESSIF_SECURITY_INFO[ESPRESSIF_SECURITY_INFO_ARRAY_SIZE] =\n{\n"
|
|
build_output += "Security information: \n"
|
|
for each_item in info["ESPRESSIF_SECURITY_INFO"]:
|
|
output += ' "{}",\n'.format(each_item)
|
|
build_output += " {}\n".format(each_item)
|
|
output += "};\n\n"
|
|
build_output += "\n\n"
|
|
|
|
info["ESPRESSIF_FLASH_STAT"] = get_espressif_flash_status()
|
|
output += 'static const char ESPRESSIF_FLASH_STAT[] = "{}";\n\n'.format(
|
|
info["ESPRESSIF_FLASH_STAT"]
|
|
)
|
|
build_output += "Flash status: {}\n\n".format(info["ESPRESSIF_FLASH_STAT"])
|
|
|
|
info["ESPRESSIF_MAC_ADDR"] = get_espressif_mac_address()
|
|
output += 'static const char ESPRESSIF_MAC_ADDR[] = "{}";\n\n'.format(
|
|
info["ESPRESSIF_MAC_ADDR"]
|
|
)
|
|
build_output += "MAC address: {}\n\n".format(info["ESPRESSIF_MAC_ADDR"])
|
|
|
|
elif chip_runtime:
|
|
output += "#define ESPRESSIF_INFO_SIZE 384\n"
|
|
output += "static char ESPRESSIF_INFO[ESPRESSIF_TOOLCHAIN_ARRAY_SIZE] =\n{\n 0\n};\n\n"
|
|
|
|
return output, build_output
|