mirror of
https://github.com/apache/nuttx.git
synced 2025-12-11 21:20:26 +08:00
Add xpack risc-v compiler info on diagnostic tool Signed-off-by: Eren Terzioglu <eren.terzioglu@espressif.com>
426 lines
13 KiB
Python
426 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",
|
|
"riscv-none-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
|