PlatformIO自动生成ESP32S3全量固件(单独烧录的bin文件)

24次阅读
没有评论

共计3459个字符,预计需要花费9分钟才能阅读完成。

ESP32S3 固件烧录地址

在我们用 PlatformIO 的 Upload 自动上传固件的时候,实际上是上传了以下四个文件,每个文件的地址如下:

PlatformIO 自动生成 ESP32S3 全量固件 (单独烧录的 bin 文件)

其中地址为 0x0 的是 bootloader.bin 文件 (引导程序);0x8000 的是 partitions.bin 文件 (分区文件);0x10000 的才是我们的应用程序文件 firmware.bin 文件。最后的 0xe000 文件本身可以不用上传,是用于区分 OTA 分区的,可以参考 ESP32S3 官方文档 - 引导加载 ESP32S3 官方文档 -OTA 分区

并且以上的这些文件都存在于项目文件夹下的 .pio\build\env (env 为你的环境名) 里面,我们可以用这些文件当做固件进行上传,但是很麻烦,因为有四个 (也可以只上传三个) 文件:

PlatformIO 自动生成 ESP32S3 全量固件 (单独烧录的 bin 文件)

(而且每次编译完成,都要到这些文件夹里面去找)

那有没有简单的方法呢?有的,有的,往下看。

合并多个 BIN 文件

ESP32 官方提供的 ESPTool 提供了 merge-bin 命令,用于合并多个分区文件,最终变成全量固件,这样就只用在 0x0 地址烧录一个 BIN 文件就行了。官方介绍如下, 点我

也就是说,我们只需要用命令 esptool --chip ESP32-S3 merge-bin -o merged-flash.bin 0x0 bootloader.bin 0x8000 partitions.bin 0x10000 firmware.bin 就能把三个不同文件合在一起了,变成 merged-flash.bin

但是每次都执行这个命令实在是太麻烦了,而且 PlatformIO 下无法直接运行这个命令。

PlatformIO 执行自定义命令

官方文档点我

主要意思是,在 platformio.ini 文件中加入:

[env:pre_and_post_hooks]
extra_scripts = post:extra_script.py

并且创建 extra_script.py 文件:

Import("env")

print("Current CLI targets", COMMAND_LINE_TARGETS)
print("Current Build targets", BUILD_TARGETS)

def post_program_action(source, target, env):
    print("Program has been built!")
    program_path = target[0].get_abspath()
    print("Program path", program_path)
    # Use case: sign a firmware, do any manipulations with ELF, etc
    # env.Execute(f"sign --elf {program_path}")

env.AddPostAction("$PROGPATH", post_program_action)

#
# Upload actions
#

def before_upload(source, target, env):
    print("before_upload")
    # do some actions

    # call Node.JS or other script
    env.Execute("node --version")

def after_upload(source, target, env):
    print("after_upload")
    # do some actions

env.AddPreAction("upload", before_upload)
env.AddPostAction("upload", after_upload)

#
# Custom actions when building program/firmware
#

env.AddPreAction("buildprog", callback...)
env.AddPostAction("buildprog", callback...)

#
# Custom actions for specific files/objects
#

env.AddPreAction("$PROGPATH", callback...)
env.AddPreAction("$BUILD_DIR/${PROGNAME}.elf", [callback1, callback2,...])
env.AddPostAction("$BUILD_DIR/${PROGNAME}.hex", callback...)

# custom action before building SPIFFS image. For example, compress HTML, etc.
env.AddPreAction("$BUILD_DIR/spiffs.bin", callback...)

# custom action for project's main.cpp
env.AddPostAction("$BUILD_DIR/src/main.cpp.o", callback...)

# Custom HEX from ELF
env.AddPostAction("$BUILD_DIR/${PROGNAME}.elf",
    env.VerboseAction(" ".join([
        "$OBJCOPY", "-O", "ihex", "-R", ".eeprom",
        "$BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex"
    ]), "Building $BUILD_DIR/${PROGNAME}.hex")
)

可以运行自定义的 python 脚本,当然也可以运行我们刚才提到的 merge-bin 命令。

也就是说,env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", callback...) 能够在生成 firmware.bin 后,执行 callback... 函数。

PlatformIO 自动生成全量固件方法

在项目文件夹下的 platformio.ini 的 PIO 配置文件中加上 (可以在 [env] 或者 [env:xxx] 下面加上 ):

extra_scripts = post:build/build_script.py

其中 build/build_script.py 对应我们想要执行的额外脚本文件。

根据刚才的配置,我们在项目文件夹下创建 build 目录,并创建以下自动合并固件的脚本 build/build_script.py (这个对应刚才的配置):

Import("env")
import os

OUTPUT_DIR = f"build{os.path.sep}firmware.bin"

def merge_bins(source, target, env):
  # source 为 ELF 文件路径
  # target 为 BIN 文件路径

  # 获取除了 APP_BIN 之外的其他需要烧录的 bin 文件列表
  flash_images = env.Flatten(env.get("FLASH_EXTRA_IMAGES", []))
  # 添加主程序 bin 文件及其偏移地址
  flash_images += [env.get("ESP32_APP_OFFSET"),
    f"$BUILD_DIR{os.path.sep}${{PROGNAME}}.bin",
  ]

  # 执行合并 bin 文件命令
  cmd = " ".join(
    [
      "$PYTHONEXE",
      "$OBJCOPY",
      "--chip",
      env.get("BOARD_MCU"),
      "merge-bin",
      "--output",
      f"$PROJECT_DIR{os.path.sep}{OUTPUT_DIR}",
      # "--flash-mode",
      # env.get("BOARD_FLASH_MODE"),
      # "--flash-size",
      # flash_size,
      # "--flash-freq",
      # str(int(env.get("BOARD_F_FLASH").replace("L", "")) // 1000000) + "m",
    ]
    + flash_images
  )
  env.Execute(cmd)

env.AddPostAction(f"$BUILD_DIR{os.path.sep}${{PROGNAME}}.bin", [merge_bins])

代码里的 OUTPUT_DIR 表示合并好后的输出文件路径,可以修改。其他内容代码里都有注释,应该很好理解。

此时,执行 build 后,在 build/firmware.bin 可以看到我们的全量固件:

PlatformIO 自动生成 ESP32S3 全量固件 (单独烧录的 bin 文件)

PlatformIO 自动生成 ESP32S3 全量固件 (单独烧录的 bin 文件)

这时候我们烧录只用烧录一个文件即可,即烧录到 0x0

PlatformIO 自动生成 ESP32S3 全量固件 (单独烧录的 bin 文件)

正文完
 0
评论(没有评论)
验证码
zh_CN简体中文
文章目录