前言
9.9元入手了一块ESP32-C3板子, 用来取代手上引脚不足的ESP8266. 但是编译时候总是失败,从Log上看是这一步出了错误.
prepare_file([".pio\build\esp32c3\lite.ttf.txt.o"], ["src\lite.ttf"])
Converting .pio\build\esp32c3\lite.ttf.txt.o
'xtensa-esp32-elf-objcopy' \xb2\xbb\xca\xc7\xc4ڲ\xbf\xbb\xf2\xcdⲿ\xc3\xfc\xc1Ҳ\xb2\xbb\xcaǿ\xc9\xd4\xcb\xd0еij\xcc\xd0\xf2
\xbb\xf2\xc5\xfa\xb4\xa6\xc0\xed\xceļ\xfe\xa1\xa3
*** [.pio\build\esp32c3\lite.ttf.txt.o] Error 1
此外并没有任何提示了.
错误分析
lite.ttf是我的一个放在src目录下的文件,
为其在platformio.ini配置”board_build.embed_txtfiles = src/lite.ttf”,就可以让这个文件嵌入固件中. 从日志里看到是转化的时候出了问题, xtensa-esp32-elf-objcopy
xtensa是ESP32,ESP32-S2,ESP32-S3的处理器结构,而ESP32-C3是RISC-V的,所以这里出错应该是结构不匹配. 去ESP-IDF的文件夹搜索”elf-objcopy”后发现的确有不同很多类似关键字.
for dir in esp32 esp32s2 esp32c3 esp32s3; do
if [ $dir = esp32 ]; then
TOOLCHAIN="xtensa-esp32-elf"
elif [ $dir = esp32s2 ]; then
TOOLCHAIN="xtensa-esp32s2-elf"
elif [ $dir = esp32c3 ]; then
TOOLCHAIN="riscv32-esp-elf"
elif [ $dir = esp32s3 ]; then
TOOLCHAIN="xtensa-esp32s3-elf"
else
echo "$dir does not exist"
fi
if [ -d "$dir" ]; then
cd $dir
git status libphy.a | grep "modified" >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo $dir/libphy.a fixed
$TOOLCHAIN-objcopy --redefine-sym ets_printf=phy_printf libphy.a
fi
所以应该是PlatformIO在转化的时候调用了错误的程序导致的.
解决问题
去PlatformIO的工作目录(.platformio)下搜索xtensa-esp32-elf-objcopy
[
"xtensa-esp32-elf-objcopy",
"--input-target",
"binary",
"--output-target",
"elf32-xtensa-le",
"--binary-architecture",
"xtensa",
"--rename-section",
".data=.rodata.embedded",
"$SOURCE",
"$TARGET",
]
确实搜索到了多个包含这个关键字的文件_embed_files.py (platforms\espressif32\builder\frameworks_embed_files.py) 其中platforms下有好几个文件夹
├── .platformio
│ └── platforms
│ └── espressif32
│ └── espressif32@src-ba2d3999402da5eaf2c9d5863ef113c7
│ └── espressif32@src-ebefb4289db63a9f0ca5ee29fa328eef
│ └── espressif8266
│ └── raspberrypi
这应该是不同项目所需的platform,凑巧这次C3项目的platform是专门下载的,所以从文件夹修改日期上来看,我这次C3使用的应该是espressif32@src-ebefb4289db63a9f0ca5ee29fa328eef 打开espressif32@src-ebefb4289db63a9f0ca5ee29fa328eef下的_embed_files.py 里面果然还在使用xtensa-esp32-elf-objcopy 按照ESP-IDF里面的描述,应该使用riscv32-esp-elf-objcopy,并且要把xtensa相关的都修改为riscv.
所以最后修改成了
[
"riscv32-esp-elf-objcopy",
"--input-target",
"binary",
"--output-target",
"elf32-littleriscv",
"--binary-architecture",
"riscv",
"--rename-section",
".data=.rodata.embedded",
"$SOURCE",
"$TARGET",
]
重新执行编译,这一次终于通过了.
Building in release mode
prepare_file([".pio\build\esp32c3\lite.ttf.txt.o"], ["src\lite.ttf"])
Converting .pio\build\esp32c3\lite.ttf.txt.o
revert_original_file([".pio\build\esp32c3\lite.ttf.txt.o"], ["src\lite.ttf"])
Linking .pio\build\esp32c3\firmware.elf
Retrieving maximum program size .pio\build\esp32c3\firmware.elf
Checking size .pio\build\esp32c3\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM: [ ] 4.7% (used 15480 bytes from 327680 bytes)
Flash: [= ] 14.1% (used 443870 bytes from 3145728 bytes)
Building .pio\build\esp32c3\firmware.bin
esptool.py v3.1
Merged 2 ELF sections
附
_embed_files.py
## Copyright 2014-present PlatformIO <contact@platformio.org>
##
## 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.
import shutil
from os import SEEK_CUR, SEEK_END
from os.path import basename, isfile, join
from SCons.Script import Builder
Import("env")
board = env.BoardConfig()
##
## Embedded files helpers
##
def extract_files(cppdefines, files_type):
files = []
if "build." + files_type in board:
files.extend(
[
join("$PROJECT_DIR", f)
for f in board.get("build." + files_type, "").split()
if f
]
)
else:
files_define = "COMPONENT_" + files_type.upper()
for define in cppdefines:
if files_define not in define:
continue
value = define[1]
if not isinstance(define, tuple):
print("Warning! %s macro cannot be empty!" % files_define)
return []
if not isinstance(value, str):
print(
"Warning! %s macro must contain "
"a list of files separated by ':'" % files_define
)
return []
for f in value.split(":"):
if not f:
continue
files.append(join("$PROJECT_DIR", f))
for f in files:
if not isfile(env.subst(f)):
print('Warning! Could not find file "%s"' % basename(f))
return files
def remove_config_define(cppdefines, files_type):
for define in cppdefines:
if files_type in define:
env.ProcessUnFlags("-D%s" % "=".join(str(d) for d in define))
return
def prepare_file(source, target, env):
filepath = source[0].get_abspath()
shutil.copy(filepath, filepath + ".piobkp")
with open(filepath, "rb+") as fp:
fp.seek(-1, SEEK_END)
if fp.read(1) != "\0":
fp.seek(0, SEEK_CUR)
fp.write(b"\0")
def revert_original_file(source, target, env):
filepath = source[0].get_abspath()
if isfile(filepath + ".piobkp"):
shutil.move(filepath + ".piobkp", filepath)
def embed_files(files, files_type):
for f in files:
filename = basename(f) + ".txt.o"
file_target = env.TxtToBin(join("$BUILD_DIR", filename), f)
env.Depends("$PIOMAINPROG", file_target)
if files_type == "embed_txtfiles":
env.AddPreAction(file_target, prepare_file)
env.AddPostAction(file_target, revert_original_file)
env.AppendUnique(PIOBUILDFILES=[env.File(join("$BUILD_DIR", filename))])
def transform_to_asm(target, source, env):
files = [join("$BUILD_DIR", s.name + ".S") for s in source]
return files, source
env.Append(
BUILDERS=dict(
TxtToBin=Builder(
action=env.VerboseAction(
" ".join(
[
"riscv32-esp-elf-objcopy",
"--input-target",
"binary",
"--output-target",
"elf32-littleriscv",
"--binary-architecture",
"riscv",
"--rename-section",
".data=.rodata.embedded",
"$SOURCE",
"$TARGET",
]
),
"Converting $TARGET",
),
suffix=".txt.o",
),
TxtToAsm=Builder(
action=env.VerboseAction(
" ".join(
[
join(
env.PioPlatform().get_package_dir("tool-cmake") or "",
"bin",
"cmake",
),
"-DDATA_FILE=$SOURCE",
"-DSOURCE_FILE=$TARGET",
"-DFILE_TYPE=TEXT",
"-P",
join(
env.PioPlatform().get_package_dir("framework-espidf") or "",
"tools",
"cmake",
"scripts",
"data_file_embed_asm.cmake",
),
]
),
"Generating assembly for $TARGET",
),
emitter=transform_to_asm,
single_source=True,
),
)
)
flags = env.get("CPPDEFINES")
for files_type in ("embed_txtfiles", "embed_files"):
if (
"COMPONENT_" + files_type.upper() not in env.Flatten(flags)
and "build." + files_type not in board
):
continue
files = extract_files(flags, files_type)
if "espidf" in env.subst("$PIOFRAMEWORK"):
env.Requires(join("$BUILD_DIR", "${PROGNAME}.elf"), env.TxtToAsm(files))
else:
embed_files(files, files_type)
remove_config_define(flags, files_type)
环境:
PLATFORM: Espressif 32 (3.3.0+sha.3b5de56) > Espressif ESP32 Dev Module
- framework-arduinoespressif32 0.0.0+sha.68daea4
- tool-esptoolpy 1.30100.210531 (3.1.0)
- toolchain-riscv-esp 1.80400.0 (8.4.0)
- toolchain-riscv32-esp 8.4.0+2021r1