waf: create separate image sections for internal and external flash

This commit is contained in:
Siddharth Purohit 2021-06-13 17:24:36 +05:30 committed by Andrew Tridgell
parent 4ba2835de1
commit f15f5e9334
2 changed files with 91 additions and 8 deletions

View File

@ -322,6 +322,7 @@ class Board:
] ]
else: else:
env.LINKFLAGS += [ env.LINKFLAGS += [
'-fno-exceptions',
'-Wl,--gc-sections', '-Wl,--gc-sections',
] ]

View File

@ -5,7 +5,7 @@
Waf tool for ChibiOS build Waf tool for ChibiOS build
""" """
from waflib import Errors, Logs, Task, Utils from waflib import Errors, Logs, Task, Utils, Context
from waflib.TaskGen import after_method, before_method, feature from waflib.TaskGen import after_method, before_method, feature
import os import os
@ -91,10 +91,80 @@ class set_default_parameters(Task.Task):
class generate_bin(Task.Task): class generate_bin(Task.Task):
color='CYAN' color='CYAN'
run_str="${OBJCOPY} -O binary ${SRC} ${TGT}" # run_str="${OBJCOPY} -O binary ${SRC} ${TGT}"
always_run = True always_run = True
EXTF_MEMORY_START = 0x90000000
EXTF_MEMORY_END = 0x90FFFFFF
INTF_MEMORY_START = 0x08000000
INTF_MEMORY_END = 0x08FFFFFF
def keyword(self): def keyword(self):
return "Generating" return "Generating"
def run(self):
if self.env.HAS_EXTERNAL_FLASH_SECTIONS:
ret = self.split_sections()
if (ret < 0):
return ret
return ret
else:
cmd = "{} -O binary {} {}".format(self.env.get_flat('OBJCOPY'), self.inputs[0], self.outputs[0])
self.exec_command(cmd)
'''list sections and split into two binaries based on section's location in internal, external or in ram'''
def split_sections(self):
# get a list of sections
cmd = "{} -A -x {}".format(self.env.get_flat('SIZE'), self.inputs[0])
out = self.generator.bld.cmd_and_log(cmd, quiet=Context.BOTH)
extf_sections = []
intf_sections = []
is_text_in_extf = False
found_text_section = False
ramsections = []
for line in out.splitlines():
section_line = line.split()
if (len(section_line) < 3):
continue
try:
if int(section_line[2], 0) == 0:
continue
else:
addr = int(section_line[2], 0)
except ValueError:
continue
if (addr >= self.EXTF_MEMORY_START) and (addr <= self.EXTF_MEMORY_END):
extf_sections.append("--only-section=%s" % section_line[0])
if section_line[0] == '.text':
is_text_in_extf = True
found_text_section = True
elif (addr >= self.INTF_MEMORY_START) and (addr <= self.INTF_MEMORY_END):
intf_sections.append("--only-section=%s" % section_line[0])
if section_line[0] == '.text':
is_text_in_extf = False
found_text_section = True
else: # most likely RAM data, we place it in the same bin as text
ramsections.append(section_line[0])
if found_text_section:
for section in ramsections:
if is_text_in_extf:
extf_sections.append("--only-section=%s" % section)
else:
intf_sections.append("--only-section=%s" % section)
else:
Logs.error("Couldn't find .text section")
# create intf binary
if len(intf_sections):
cmd = "{} {} -O binary {} {}".format(self.env.get_flat('OBJCOPY'),
' '.join(intf_sections), self.inputs[0], self.outputs[0])
else:
cmd = "cp /dev/null {}".format(self.outputs[0])
ret = self.exec_command(cmd)
if (ret < 0):
return ret
# create extf binary
cmd = "{} {} -O binary {} {}".format(self.env.get_flat('OBJCOPY'),
' '.join(extf_sections), self.inputs[0], self.outputs[1])
return self.exec_command(cmd)
def __str__(self): def __str__(self):
return self.outputs[0].path_from(self.generator.bld.bldnode) return self.outputs[0].path_from(self.generator.bld.bldnode)
@ -149,17 +219,25 @@ class generate_apj(Task.Task):
return "apj_gen" return "apj_gen"
def run(self): def run(self):
import json, time, base64, zlib import json, time, base64, zlib
img = open(self.inputs[0].abspath(),'rb').read() intf_img = open(self.inputs[0].abspath(),'rb').read()
if self.env.HAS_EXTERNAL_FLASH_SECTIONS:
extf_img = open(self.inputs[1].abspath(),'rb').read()
else:
extf_img = b""
d = { d = {
"board_id": int(self.env.APJ_BOARD_ID), "board_id": int(self.env.APJ_BOARD_ID),
"magic": "APJFWv1", "magic": "APJFWv1",
"description": "Firmware for a %s board" % self.env.APJ_BOARD_TYPE, "description": "Firmware for a %s board" % self.env.APJ_BOARD_TYPE,
"image": base64.b64encode(zlib.compress(img,9)).decode('utf-8'), "image": base64.b64encode(zlib.compress(intf_img,9)).decode('utf-8'),
"extf_image": base64.b64encode(zlib.compress(extf_img,9)).decode('utf-8'),
"summary": self.env.BOARD, "summary": self.env.BOARD,
"version": "0.1", "version": "0.1",
"image_size": len(img), "image_size": len(intf_img),
"extf_image_size": len(extf_img),
"flash_total": int(self.env.FLASH_TOTAL), "flash_total": int(self.env.FLASH_TOTAL),
"flash_free": int(self.env.FLASH_TOTAL) - len(img), "flash_free": int(self.env.FLASH_TOTAL) - len(intf_img),
"extflash_total": int(self.env.EXTERNAL_PROG_FLASH_MB * 1024 * 1024),
"extflash_free": int(self.env.EXTERNAL_PROG_FLASH_MB * 1024 * 1024) - len(extf_img),
"git_identity": self.generator.bld.git_head_hash(short=True), "git_identity": self.generator.bld.git_head_hash(short=True),
"board_revision": 0, "board_revision": 0,
"USBID": self.env.USBID "USBID": self.env.USBID
@ -201,7 +279,11 @@ def chibios_firmware(self):
link_output = self.link_task.outputs[0] link_output = self.link_task.outputs[0]
hex_task = None hex_task = None
bin_target = self.bld.bldnode.find_or_declare('bin/' + link_output.change_ext('.bin').name) if self.bld.env.HAS_EXTERNAL_FLASH_SECTIONS:
bin_target = [self.bld.bldnode.find_or_declare('bin/' + link_output.change_ext('.bin').name),
self.bld.bldnode.find_or_declare('bin/' + link_output.change_ext('_extf.bin').name)]
else:
bin_target = [self.bld.bldnode.find_or_declare('bin/' + link_output.change_ext('.bin').name)]
apj_target = self.bld.bldnode.find_or_declare('bin/' + link_output.change_ext('.apj').name) apj_target = self.bld.bldnode.find_or_declare('bin/' + link_output.change_ext('.apj').name)
generate_bin_task = self.create_task('generate_bin', src=link_output, tgt=bin_target) generate_bin_task = self.create_task('generate_bin', src=link_output, tgt=bin_target)
@ -219,7 +301,7 @@ def chibios_firmware(self):
if self.bld.env.HAVE_INTEL_HEX: if self.bld.env.HAVE_INTEL_HEX:
if os.path.exists(bootloader_bin.abspath()): if os.path.exists(bootloader_bin.abspath()):
hex_target = self.bld.bldnode.find_or_declare('bin/' + link_output.change_ext('.hex').name) hex_target = self.bld.bldnode.find_or_declare('bin/' + link_output.change_ext('.hex').name)
hex_task = self.create_task('build_intel_hex', src=[bin_target, bootloader_bin], tgt=hex_target) hex_task = self.create_task('build_intel_hex', src=[bin_target[0], bootloader_bin], tgt=hex_target)
hex_task.set_run_after(generate_bin_task) hex_task.set_run_after(generate_bin_task)
else: else:
print("Not embedding bootloader; %s does not exist" % bootloader_bin) print("Not embedding bootloader; %s does not exist" % bootloader_bin)