Skip to content

Commit 074f315

Browse files
authored
Update PlatformIO build scripts (#7200)
This update includes the following: - Implemented an additional build step that produces an adjusted bootloader image with updated headers according to selected flash mode and size values. This step is only executed for debugging or uploading via debug probes. - Implemented a basic mechanism to dynamically add an extra UF2 bootloader image if corresponding partition is selected (e.g. for Adafruit targets) - Minor code formatting
1 parent 77065bf commit 074f315

File tree

1 file changed

+147
-50
lines changed

1 file changed

+147
-50
lines changed

Diff for: tools/platformio-build.py

+147-50
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@
2424

2525
# Extends: https://github.com/platformio/platform-espressif32/blob/develop/builder/main.py
2626

27-
from os.path import abspath, isdir, isfile, join
27+
from os.path import abspath, basename, isdir, isfile, join
2828

2929
from SCons.Script import DefaultEnvironment, SConscript
3030

3131
env = DefaultEnvironment()
3232
platform = env.PioPlatform()
3333
board_config = env.BoardConfig()
3434
build_mcu = board_config.get("build.mcu", "").lower()
35+
partitions_name = board_config.get(
36+
"build.partitions", board_config.get("build.arduino.partitions", "")
37+
)
3538

3639
FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32")
3740
assert isdir(FRAMEWORK_DIR)
@@ -41,25 +44,23 @@
4144
# Helpers
4245
#
4346

47+
4448
def get_partition_table_csv(variants_dir):
4549
fwpartitions_dir = join(FRAMEWORK_DIR, "tools", "partitions")
50+
variant_partitions_dir = join(variants_dir, board_config.get("build.variant", ""))
4651

47-
custom_partition = board_config.get(
48-
"build.partitions", board_config.get("build.arduino.partitions", "")
49-
)
52+
if partitions_name:
53+
# A custom partitions file is selected
54+
if isfile(join(variant_partitions_dir, partitions_name)):
55+
return join(variant_partitions_dir, partitions_name)
5056

51-
if custom_partition:
52-
partitions_csv = board_config.get("build.partitions", board_config.get(
53-
"build.arduino.partitions", "default.csv"))
5457
return abspath(
55-
join(fwpartitions_dir, partitions_csv)
56-
if isfile(join(fwpartitions_dir, partitions_csv))
57-
else partitions_csv
58+
join(fwpartitions_dir, partitions_name)
59+
if isfile(join(fwpartitions_dir, partitions_name))
60+
else partitions_name
5861
)
5962

60-
variant_partitions = join(
61-
variants_dir, board_config.get("build.variant", ""), "partitions.csv"
62-
)
63+
variant_partitions = join(variant_partitions_dir, "partitions.csv")
6364
return (
6465
variant_partitions
6566
if isfile(variant_partitions)
@@ -68,9 +69,16 @@ def get_partition_table_csv(variants_dir):
6869

6970

7071
def get_bootloader_image(variants_dir):
72+
bootloader_image_file = "bootloader.bin"
73+
if partitions_name.endswith("tinyuf2.csv"):
74+
bootloader_image_file = "bootloader-tinyuf2.bin"
75+
7176
variant_bootloader = join(
72-
variants_dir, board_config.get("build.variant", ""), "bootloader.bin"
77+
variants_dir,
78+
board_config.get("build.variant", ""),
79+
board_config.get("build.arduino.custom_bootloader", bootloader_image_file),
7380
)
81+
7482
return (
7583
variant_bootloader
7684
if isfile(variant_bootloader)
@@ -85,6 +93,76 @@ def get_bootloader_image(variants_dir):
8593
)
8694

8795

96+
def get_patched_bootloader_image(original_bootloader_image, bootloader_offset):
97+
patched_bootloader_image = join(env.subst("$BUILD_DIR"), "patched_bootloader.bin")
98+
bootloader_cmd = env.Command(
99+
patched_bootloader_image,
100+
original_bootloader_image,
101+
env.VerboseAction(
102+
" ".join(
103+
[
104+
'"$PYTHONEXE"',
105+
join(
106+
platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"
107+
),
108+
"--chip",
109+
build_mcu,
110+
"merge_bin",
111+
"-o",
112+
"$TARGET",
113+
"--flash_mode",
114+
"${__get_board_flash_mode(__env__)}",
115+
"--flash_size",
116+
board_config.get("upload.flash_size", "4MB"),
117+
"--target-offset",
118+
bootloader_offset,
119+
bootloader_offset,
120+
"$SOURCE",
121+
]
122+
),
123+
"Updating bootloader headers",
124+
),
125+
)
126+
env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", bootloader_cmd)
127+
128+
return patched_bootloader_image
129+
130+
131+
def add_tinyuf2_extra_image():
132+
tinuf2_image = board_config.get(
133+
"upload.arduino.tinyuf2_image",
134+
join(variants_dir, board_config.get("build.variant", ""), "tinyuf2.bin"),
135+
)
136+
137+
# Add the UF2 image only if it exists and it's not already added
138+
if not isfile(tinuf2_image):
139+
print("Warning! The `%s` UF2 bootloader image doesn't exist" % tinuf2_image)
140+
return
141+
142+
if any(
143+
"tinyuf2.bin" == basename(extra_image[1])
144+
for extra_image in env.get("FLASH_EXTRA_IMAGES", [])
145+
):
146+
print("Warning! An extra UF2 bootloader image is already added!")
147+
return
148+
149+
env.Append(
150+
FLASH_EXTRA_IMAGES=[
151+
(
152+
board_config.get(
153+
"upload.arduino.uf2_bootloader_offset",
154+
(
155+
"0x2d0000"
156+
if env.subst("$BOARD").startswith("adafruit")
157+
else "0x410000"
158+
),
159+
),
160+
tinuf2_image,
161+
),
162+
]
163+
)
164+
165+
88166
#
89167
# Run target-specific script to populate the environment with proper build flags
90168
#
@@ -99,32 +177,6 @@ def get_bootloader_image(variants_dir):
99177
)
100178
)
101179

102-
#
103-
# Process framework extra images
104-
#
105-
106-
env.Append(
107-
LIBSOURCE_DIRS=[
108-
join(FRAMEWORK_DIR, "libraries")
109-
],
110-
111-
FLASH_EXTRA_IMAGES=[
112-
(
113-
"0x1000" if build_mcu in ("esp32", "esp32s2") else "0x0000",
114-
get_bootloader_image(board_config.get(
115-
"build.variants_dir", join(FRAMEWORK_DIR, "variants")))
116-
),
117-
("0x8000", join(env.subst("$BUILD_DIR"), "partitions.bin")),
118-
("0xe000", join(FRAMEWORK_DIR, "tools", "partitions", "boot_app0.bin"))
119-
]
120-
+ [
121-
(offset, join(FRAMEWORK_DIR, img))
122-
for offset, img in board_config.get(
123-
"upload.arduino.flash_extra_images", []
124-
)
125-
],
126-
)
127-
128180
#
129181
# Target: Build Core Library
130182
#
@@ -137,23 +189,68 @@ def get_bootloader_image(variants_dir):
137189
variants_dir = join("$PROJECT_DIR", board_config.get("build.variants_dir"))
138190

139191
if "build.variant" in board_config:
140-
env.Append(
141-
CPPPATH=[
142-
join(variants_dir, board_config.get("build.variant"))
143-
]
144-
)
192+
env.Append(CPPPATH=[join(variants_dir, board_config.get("build.variant"))])
145193
env.BuildSources(
146194
join("$BUILD_DIR", "FrameworkArduinoVariant"),
147-
join(variants_dir, board_config.get("build.variant"))
195+
join(variants_dir, board_config.get("build.variant")),
148196
)
149197

150-
libs.append(env.BuildLibrary(
151-
join("$BUILD_DIR", "FrameworkArduino"),
152-
join(FRAMEWORK_DIR, "cores", board_config.get("build.core"))
153-
))
198+
libs.append(
199+
env.BuildLibrary(
200+
join("$BUILD_DIR", "FrameworkArduino"),
201+
join(FRAMEWORK_DIR, "cores", board_config.get("build.core")),
202+
)
203+
)
154204

155205
env.Prepend(LIBS=libs)
156206

207+
#
208+
# Process framework extra images
209+
#
210+
211+
# Starting with v2.0.4 the Arduino core contains updated bootloader images that have
212+
# innacurate default headers. This results in bootloops if firmware is flashed via
213+
# OpenOCD (e.g. debugging or uploading via debug tools). For this reason, before
214+
# uploading or debugging we need to adjust the bootloader binary according to
215+
# the values of the --flash-size and --flash-mode arguments.
216+
# Note: This behavior doesn't occur if uploading is done via esptoolpy, as esptoolpy
217+
# overrides the binary image headers before flashing.
218+
219+
bootloader_patch_required = bool(
220+
env.get("PIOFRAMEWORK", []) == ["arduino"]
221+
and (
222+
"debug" in env.GetBuildType()
223+
or env.subst("$UPLOAD_PROTOCOL") in board_config.get("debug.tools", {})
224+
or env.IsIntegrationDump()
225+
)
226+
)
227+
228+
bootloader_image_path = get_bootloader_image(variants_dir)
229+
bootloader_offset = "0x1000" if build_mcu in ("esp32", "esp32s2") else "0x0000"
230+
if bootloader_patch_required:
231+
bootloader_image_path = get_patched_bootloader_image(
232+
bootloader_image_path, bootloader_offset
233+
)
234+
235+
env.Append(
236+
LIBSOURCE_DIRS=[join(FRAMEWORK_DIR, "libraries")],
237+
FLASH_EXTRA_IMAGES=[
238+
(bootloader_offset, bootloader_image_path),
239+
("0x8000", join(env.subst("$BUILD_DIR"), "partitions.bin")),
240+
("0xe000", join(FRAMEWORK_DIR, "tools", "partitions", "boot_app0.bin")),
241+
]
242+
+ [
243+
(offset, join(FRAMEWORK_DIR, img))
244+
for offset, img in board_config.get("upload.arduino.flash_extra_images", [])
245+
],
246+
)
247+
248+
# Add an extra UF2 image if the 'TinyUF2' partition is selected
249+
if partitions_name.endswith("tinyuf2.csv") or board_config.get(
250+
"upload.arduino.tinyuf2_image", ""
251+
):
252+
add_tinyuf2_extra_image()
253+
157254
#
158255
# Generate partition table
159256
#

0 commit comments

Comments
 (0)