Skip to content

Commit 115f981

Browse files
committed
Dynamically configure partition offsets for ESP-IDF
1 parent cd0af53 commit 115f981

File tree

3 files changed

+132
-14
lines changed

3 files changed

+132
-14
lines changed

builder/frameworks/espidf.py

Lines changed: 122 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,9 @@ def generate_project_ld_script(sdk_config, ignore_targets=None):
499499
"env_file": os.path.join("$BUILD_DIR", "config.env"),
500500
"libraries_list": libraries_list,
501501
"objdump": os.path.join(
502-
TOOLCHAIN_DIR, "bin", env.subst("$CC").replace("-gcc", "-objdump"),
502+
TOOLCHAIN_DIR,
503+
"bin",
504+
env.subst("$CC").replace("-gcc", "-objdump"),
503505
),
504506
}
505507

@@ -803,19 +805,90 @@ def find_default_component(target_configs):
803805
return ""
804806

805807

806-
def create_verion_file():
808+
def create_version_file():
807809
version_file = os.path.join(FRAMEWORK_DIR, "version.txt")
808810
if not os.path.isfile(version_file):
809811
with open(version_file, "w") as fp:
810812
fp.write(platform.get_package_version("framework-espidf"))
811813

812814

813-
#
815+
def generate_empty_partition_image(binary_path, image_size):
816+
empty_partition = env.Command(
817+
binary_path,
818+
None,
819+
env.VerboseAction(
820+
'"$PYTHONEXE" "%s" %s $TARGET'
821+
% (
822+
os.path.join(
823+
FRAMEWORK_DIR,
824+
"components",
825+
"partition_table",
826+
"gen_empty_partition.py",
827+
),
828+
image_size,
829+
),
830+
"Generating an empty partition $TARGET",
831+
),
832+
)
833+
834+
env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", empty_partition)
835+
836+
837+
def get_partition_info(pt_path, pt_offset, pt_params):
838+
assert os.path.isfile(pt_path)
839+
cmd = [
840+
env.subst("$PYTHONEXE"),
841+
os.path.join(FRAMEWORK_DIR, "components", "partition_table", "parttool.py"),
842+
"-q",
843+
"--partition-table-offset",
844+
hex(pt_offset),
845+
"--partition-table-file",
846+
pt_path,
847+
"get_partition_info",
848+
"--info",
849+
"size",
850+
"offset",
851+
]
852+
853+
if pt_params["name"] == "boot":
854+
cmd.append("--partition-boot-default")
855+
else:
856+
cmd.extend(
857+
[
858+
"--partition-type",
859+
pt_params["type"],
860+
"--partition-subtype",
861+
pt_params["subtype"],
862+
]
863+
)
864+
865+
result = exec_command(cmd)
866+
if result["returncode"] != 0:
867+
sys.stderr.write(
868+
"Couldn't extract information for %s/%s from the partition table\n"
869+
% (pt_params["type"], pt_params["subtype"])
870+
)
871+
sys.stderr.write(result["out"] + "\n")
872+
sys.stderr.write(result["err"] + "\n")
873+
env.Exit(1)
874+
875+
size = offset = 0
876+
if result["out"].strip():
877+
size, offset = result["out"].strip().split(" ", 1)
878+
879+
return {"size": size, "offset": offset}
880+
881+
882+
def get_app_partition_offset(pt_table, pt_offset):
883+
# Get the default boot partition offset
884+
app_params = get_partition_info(pt_table, pt_offset, {"name": "boot"})
885+
return app_params.get("offset", "0x10000")
886+
887+
814888
# ESP-IDF package doesn't contain .git folder, instead package version is specified
815889
# in a special file "version.h" in the root folder of the package
816-
#
817890

818-
create_verion_file()
891+
create_version_file()
819892

820893
#
821894
# Generate final linker script
@@ -845,6 +918,7 @@ def create_verion_file():
845918

846919
fwpartitions_dir = os.path.join(FRAMEWORK_DIR, "components", "partition_table")
847920
partitions_csv = board.get("build.partitions", "partitions_singleapp.csv")
921+
848922
env.Replace(
849923
PARTITIONS_TABLE_CSV=os.path.abspath(
850924
os.path.join(fwpartitions_dir, partitions_csv)
@@ -1058,6 +1132,7 @@ def _skip_prj_source_files(node):
10581132
)
10591133
)
10601134

1135+
partition_table_offset = sdk_config.get("PARTITION_TABLE_OFFSET", 0x8000)
10611136
project_flags.update(link_args)
10621137
env.MergeFlags(project_flags)
10631138
env.Prepend(
@@ -1068,12 +1143,11 @@ def _skip_prj_source_files(node):
10681143
FLASH_EXTRA_IMAGES=[
10691144
(
10701145
board.get("upload.bootloader_offset", "0x1000"),
1071-
os.path.join("$BUILD_DIR", "bootloader.bin")
1146+
os.path.join("$BUILD_DIR", "bootloader.bin"),
10721147
),
10731148
(
1074-
board.get("upload.partition_table_offset", hex(
1075-
sdk_config.get("PARTITION_TABLE_OFFSET", 0x8000))),
1076-
os.path.join("$BUILD_DIR", "partitions.bin")
1149+
board.get("upload.partition_table_offset", hex(partition_table_offset)),
1150+
os.path.join("$BUILD_DIR", "partitions.bin"),
10771151
),
10781152
],
10791153
)
@@ -1095,3 +1169,42 @@ def _skip_prj_source_files(node):
10951169
ulp_dir = os.path.join(env.subst("$PROJECT_DIR"), "ulp")
10961170
if os.path.isdir(ulp_dir) and os.listdir(ulp_dir):
10971171
env.SConscript("ulp.py", exports="env project_config idf_variant")
1172+
1173+
#
1174+
# Process OTA partition and image
1175+
#
1176+
1177+
ota_partition_params = get_partition_info(
1178+
env.subst("$PARTITIONS_TABLE_CSV"),
1179+
partition_table_offset,
1180+
{"name": "ota", "type": "data", "subtype": "ota"},
1181+
)
1182+
1183+
if ota_partition_params["size"] and ota_partition_params["offset"]:
1184+
# Generate an empty image if OTA is enabled in partition table
1185+
ota_partition_image = os.path.join("$BUILD_DIR", "ota_data_initial.bin")
1186+
generate_empty_partition_image(ota_partition_image, ota_partition_params["size"])
1187+
1188+
env.Append(
1189+
FLASH_EXTRA_IMAGES=[
1190+
(
1191+
board.get(
1192+
"upload.ota_partition_offset", ota_partition_params["offset"]
1193+
),
1194+
ota_partition_image,
1195+
)
1196+
]
1197+
)
1198+
1199+
#
1200+
# Configure application partition offset
1201+
#
1202+
1203+
env.Replace(
1204+
ESP32_APP_OFFSET=get_app_partition_offset(
1205+
env.subst("$PARTITIONS_TABLE_CSV"), partition_table_offset
1206+
)
1207+
)
1208+
1209+
# Propagate application offset to debug configurations
1210+
env["IDE_EXTRA_DATA"].update({"application_offset": env.subst("$ESP32_APP_OFFSET")})

builder/main.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ def __fetch_spiffs_size(target, source, env):
163163
MKSPIFFSTOOL="mkspiffs_${PIOPLATFORM}_" + ("espidf" if "espidf" in env.subst(
164164
"$PIOFRAMEWORK") else "${PIOFRAMEWORK}"),
165165
ESP32_SPIFFS_IMAGE_NAME=env.get("ESP32_SPIFFS_IMAGE_NAME", "spiffs"),
166+
ESP32_APP_OFFSET="0x10000",
166167

167168
PROGSUFFIX=".elf"
168169
)
@@ -310,7 +311,7 @@ def __fetch_spiffs_size(target, source, env):
310311
"--flash_freq", "${__get_board_f_flash(__env__)}",
311312
"--flash_size", "detect"
312313
],
313-
UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS 0x10000 $SOURCE'
314+
UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $ESP32_APP_OFFSET $SOURCE'
314315
)
315316
for image in env.get("FLASH_EXTRA_IMAGES", []):
316317
env.Append(UPLOADERFLAGS=[image[0], env.subst(image[1])])
@@ -372,7 +373,7 @@ def __fetch_spiffs_size(target, source, env):
372373
openocd_args.extend([
373374
"-c",
374375
"program_esp {{$SOURCE}} %s verify" %
375-
board.get("upload.offset_address", "0x10000")
376+
board.get("upload.offset_address", "$ESP32_APP_OFFSET")
376377
])
377378
for image in env.get("FLASH_EXTRA_IMAGES", []):
378379
openocd_args.extend([

platform.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ def _add_dynamic_options(self, board):
157157
return board
158158

159159
def configure_debug_options(self, initial_debug_options, ide_data):
160-
flash_images = ide_data.get("extra", {}).get("flash_images")
160+
ide_extra_data = ide_data.get("extra", {})
161+
flash_images = ide_extra_data.get("flash_images", [])
161162
ignore_conds = [
162163
initial_debug_options["load_cmds"] != ["load"],
163164
not flash_images,
@@ -174,8 +175,11 @@ def configure_debug_options(self, initial_debug_options, ide_data):
174175
for item in flash_images
175176
]
176177
load_cmds.append(
177-
'monitor program_esp "{%s.bin}" 0x10000 verify'
178-
% fs.to_unix_path(ide_data["prog_path"][:-4])
178+
'monitor program_esp "{%s.bin}" %s verify'
179+
% (
180+
fs.to_unix_path(ide_data["prog_path"][:-4]),
181+
ide_extra_data.get("application_offset", "0x10000"),
182+
)
179183
)
180184
debug_options["load_cmds"] = load_cmds
181185
return debug_options

0 commit comments

Comments
 (0)