Skip to content

Commit 4cc2182

Browse files
author
Naveen Kaje
committed
tools: support cases where bootloader is in chunks
Support the requirement where bootloader can be in chunks and enable placing the application at a particular offset specified by config. With FEATURE_BOOTLOADER support, the bootloader can be placed at a high address. Add support to the tools so that application can be placed in the available space before the beginning of the bootloader.
1 parent 2ecb0a5 commit 4cc2182

File tree

3 files changed

+62
-21
lines changed

3 files changed

+62
-21
lines changed

tools/build_api.py

100644100755
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,10 @@ def merge_region_list(region_list, destination, notify, config, padding=b'\xFF')
423423
merged = IntelHex()
424424
_, format = splitext(destination)
425425
notify.info("Merging Regions")
426+
# Merged file list: Keep track of binary/hex files that we have already
427+
# merged. e.g In some cases, bootloader may be split into multiple parts, but
428+
# all internally referring to the same bootloader file.
429+
merged_list = []
426430

427431
for region in region_list:
428432
if region.active and not region.filename:
@@ -432,7 +436,7 @@ def merge_region_list(region_list, destination, notify, config, padding=b'\xFF')
432436
header_filename = header_basename + "_header.hex"
433437
_fill_header(region_list, region).tofile(header_filename, format='hex')
434438
region = region._replace(filename=header_filename)
435-
if region.filename:
439+
if region.filename and (region.filename not in merged_list):
436440
notify.info(" Filling region %s with %s" % (region.name, region.filename))
437441
part = intelhex_offset(region.filename, offset=region.start)
438442
part.start_addr = None
@@ -443,7 +447,10 @@ def merge_region_list(region_list, destination, notify, config, padding=b'\xFF')
443447
if part_size > region.size:
444448
raise ToolException("Contents of region %s does not fit"
445449
% region.name)
450+
merged_list.append(region.filename)
446451
merged.merge(part)
452+
elif region.filename in merged_list:
453+
notify.info(" Skipping %s as it is merged previously" % (region.name))
447454

448455
# Hex file can have gaps, so no padding needed. While other formats may
449456
# need padding. Iterate through segments and pad the gaps.

tools/config/__init__.py

100644100755
Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -780,13 +780,29 @@ def _make_header_region(self, start, header_format, offset=None):
780780
return (start, region)
781781

782782
@staticmethod
783-
def _assign_new_offset(rom_start, start, new_offset, region_name):
783+
def _assign_new_offset(rom_start, new_offset, region_name, regions):
784784
newstart = rom_start + integer(new_offset, 0)
785-
if newstart < start:
786-
raise ConfigException(
787-
"Can not place %r region inside previous region" % region_name)
785+
786+
for s, e in regions:
787+
if newstart > s and newstart < e:
788+
raise ConfigException(
789+
"Can not place %r region inside previous region" % region_name)
788790
return newstart
789791

792+
@staticmethod
793+
def _get_end_address(region_list, start_address, rom_end):
794+
"""Given a start address and set of regions, sort the
795+
regions and then compute the end address.
796+
The end address is either rom_end or beginning of the
797+
next section, whichever is smaller
798+
"""
799+
# Sort the list by starting address
800+
region_list = sorted(region_list, key=lambda x:x[0])
801+
for s, e in region_list:
802+
if start_address < s:
803+
return s
804+
return rom_end
805+
790806
def _generate_bootloader_build(self, rom_memories):
791807
rom_start, rom_size = rom_memories.get('ROM')
792808
start = rom_start
@@ -803,26 +819,41 @@ def _generate_bootloader_build(self, rom_memories):
803819
if part.minaddr() != rom_start:
804820
raise ConfigException("bootloader executable does not "
805821
"start at 0x%x" % rom_start)
822+
regions = part.segments()
806823

807824
# find the last valid address that's within rom_end and use that
808825
# to compute the bootloader size
809-
end_address = None
810-
for start, stop in part.segments():
811-
if (stop < rom_end):
812-
end_address = stop
813-
else:
814-
break
815-
if end_address == None:
816-
raise ConfigException("bootloader segments don't fit within rom region")
817-
part_size = Config._align_ceiling(end_address, self.sectors) - rom_start
818826

819-
yield Region("bootloader", rom_start, part_size, False,
820-
filename)
827+
# we have multiple parts in bootloader. Treat each of them as
828+
# a different region (BLP1, BLP2 ...)
829+
if len(part.segments()) > 1:
830+
end_address = None
831+
part_count = 0
832+
for start, stop in part.segments():
833+
part_count += 1
834+
if (stop < rom_end):
835+
end_address = stop
836+
else:
837+
break
838+
if end_address == None:
839+
raise ConfigException("bootloader segments don't fit within rom")
840+
part_size = Config._align_ceiling(end_address, self.sectors) - rom_start
841+
# Generate the region in the loop (bootloader0, bootloader1, ...)
842+
yield Region("bootloader"+str(part_count), start, part_size, False, filename)
843+
else:
844+
# Number of segments is 1
845+
_, end_address = part.segments()[0]
846+
if (end_address > rom_end):
847+
raise ConfigException("bootloader segments don't fit within rom")
848+
part_size = Config._align_ceiling(end_address, self.sectors) - rom_start
849+
yield Region("bootloader", rom_start, part_size, False,
850+
filename)
851+
821852
start = rom_start + part_size
822853
if self.target.header_format:
823854
if self.target.header_offset:
824855
start = self._assign_new_offset(
825-
rom_start, start, self.target.header_offset, "header")
856+
rom_start, self.target.header_offset, "header", regions)
826857
start, region = self._make_header_region(
827858
start, self.target.header_format)
828859
yield region._replace(filename=self.target.header_format)
@@ -832,14 +863,14 @@ def _generate_bootloader_build(self, rom_memories):
832863
new_size = Config._align_floor(start + new_size, self.sectors) - start
833864

834865
if self.target.app_offset:
835-
start = self._assign_new_offset(rom_start, start, self.target.app_offset, "application")
866+
start = self._assign_new_offset(rom_start, self.target.app_offset, "application", regions)
836867

837868
yield Region("application", start, new_size, True, None)
838869
start += new_size
839870
if self.target.header_format and not self.target.bootloader_img:
840871
if self.target.header_offset:
841872
start = self._assign_new_offset(
842-
rom_start, start, self.target.header_offset, "header")
873+
rom_start, self.target.header_offset, "header", regions)
843874
start, region = self._make_header_region(
844875
start, self.target.header_format)
845876
yield region
@@ -849,8 +880,10 @@ def _generate_bootloader_build(self, rom_memories):
849880
else:
850881
if self.target.app_offset:
851882
start = self._assign_new_offset(
852-
rom_start, start, self.target.app_offset, "application")
853-
yield Region("application", start, rom_end - start,
883+
rom_start, self.target.app_offset, "application", regions)
884+
# compute the end address of the application region based on existing segments
885+
end = self._get_end_address(regions, start, rom_end)
886+
yield Region("application", start, end - start,
854887
True, None)
855888
if start > rom_end:
856889
raise ConfigException("Not enough memory on device to fit all "

tools/toolchains/__init__.py

100644100755
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,7 @@ def add_regions(self):
742742
if self.config.has_regions:
743743
try:
744744
regions = list(self.config.regions)
745+
regions.sort(key=lambda x:x.start)
745746
self.notify.info("Using ROM region%s %s in this build." % (
746747
"s" if len(regions) > 1 else "",
747748
", ".join(r.name for r in regions)

0 commit comments

Comments
 (0)