waf: automatically build intel hex fw when possible

this combines the bootloader and application code into a single binary
This commit is contained in:
Andrew Tridgell 2018-06-23 14:53:20 +10:00
parent e868a4fe8b
commit 338ff6ae64
5 changed files with 196 additions and 13 deletions

View File

@ -82,10 +82,18 @@ class set_default_parameters(Task.Task):
defaults.save()
class generate_fw(Task.Task):
class generate_bin(Task.Task):
color='CYAN'
run_str="${OBJCOPY} -O binary ${SRC} ${SRC}.bin && \
python '${UPLOAD_TOOLS}/px_mkfw.py' --image '${SRC}.bin' --prototype '${BUILDROOT}/apj.prototype' > '${TGT}'"
run_str="${OBJCOPY} -O binary ${SRC} ${TGT}"
always_run = True
def keyword(self):
return "Generating"
def __str__(self):
return self.outputs[0].path_from(self.generator.bld.bldnode)
class generate_apj(Task.Task):
color='CYAN'
run_str="python '${UPLOAD_TOOLS}/px_mkfw.py' --image '${SRC}' --prototype '${BUILDROOT}/apj.prototype' > '${TGT}'"
always_run = True
def keyword(self):
return "Generating"
@ -102,34 +110,53 @@ class build_abin(Task.Task):
def __str__(self):
return self.outputs[0].path_from(self.generator.bld.bldnode)
class build_intel_hex(Task.Task):
'''build an intel hex file for upload with DFU'''
color='CYAN'
run_str='${TOOLS_SCRIPTS}/make_intel_hex.sh ${SRC} ${FLASH_RESERVE_START_KB} ${TGT}'
always_run = True
def keyword(self):
return "Generating"
def __str__(self):
return self.outputs[0].path_from(self.generator.bld.bldnode)
@feature('ch_ap_program')
@after_method('process_source')
def chibios_firmware(self):
self.link_task.always_run = True
link_output = self.link_task.outputs[0]
self.objcopy_target = self.bld.bldnode.find_or_declare('bin/' + link_output.change_ext('.apj').name)
generate_fw_task = self.create_task('generate_fw',
src=link_output,
tgt=self.objcopy_target)
generate_fw_task.set_run_after(self.link_task)
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)
generate_bin_task = self.create_task('generate_bin', src=link_output, tgt=bin_target)
generate_bin_task.set_run_after(self.link_task)
generate_apj_task = self.create_task('generate_apj', src=bin_target, tgt=apj_target)
generate_apj_task.set_run_after(generate_bin_task)
if self.env.BUILD_ABIN:
abin_target = self.bld.bldnode.find_or_declare('bin/' + link_output.change_ext('.abin').name)
abin_task = self.create_task('build_abin', src=link_output, tgt=abin_target)
abin_task.set_run_after(generate_fw_task)
abin_task.set_run_after(generate_apj_task)
bootloader_bin = self.bld.srcnode.make_node("Tools/bootloaders/%s_bl.bin" % self.env.BOARD)
if os.path.exists(bootloader_bin.abspath()):
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.set_run_after(generate_apj_task)
if self.env.DEFAULT_PARAMETERS:
default_params_task = self.create_task('set_default_parameters',
src=link_output)
default_params_task.set_run_after(self.link_task)
generate_fw_task.set_run_after(default_params_task)
generate_apj_task.set_run_after(default_params_task)
if self.bld.options.upload:
_upload_task = self.create_task('upload_fw',
src=self.objcopy_target)
_upload_task.set_run_after(generate_fw_task)
_upload_task.set_run_after(generate_apj_task)
def setup_can_build(cfg):
'''enable CAN build. By doing this here we can auto-enable CAN in

125
Tools/scripts/bin2hex.py Executable file
View File

@ -0,0 +1,125 @@
#!/usr/bin/python
# Copyright (c) 2008,2010,2011,2012,2013 Alexander Belchenko
# All rights reserved.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain
# the above copyright notice, this list of conditions
# and the following disclaimer.
# * Redistributions in binary form must reproduce
# the above copyright notice, this list of conditions
# and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the author nor the names
# of its contributors may be used to endorse
# or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''Intel HEX file format bin2hex convertor utility.'''
VERSION = '1.5'
if __name__ == '__main__':
import getopt
import os
import sys
from intelhex import bin2hex
usage = '''Bin2Hex convertor utility.
Usage:
python bin2hex.py [options] INFILE [OUTFILE]
Arguments:
INFILE name of bin file for processing.
Use '-' for reading from stdin.
OUTFILE name of output file. If omitted then output
will be writing to stdout.
Options:
-h, --help this help message.
-v, --version version info.
--offset=N offset for loading bin file (default: 0).
'''
offset = 0
try:
opts, args = getopt.getopt(sys.argv[1:], "hv",
["help", "version", "offset="])
for o, a in opts:
if o in ("-h", "--help"):
print(usage)
sys.exit(0)
elif o in ("-v", "--version"):
print(VERSION)
sys.exit(0)
elif o in ("--offset"):
base = 10
if a[:2].lower() == '0x':
base = 16
try:
offset = int(a, base)
except:
raise getopt.GetoptError('Bad offset value')
if not args:
raise getopt.GetoptError('Input file is not specified')
if len(args) > 2:
raise getopt.GetoptError('Too many arguments')
except getopt.GetoptError, msg:
txt = 'ERROR: '+str(msg) # that's required to get not-so-dumb result from 2to3 tool
print(txt)
print(usage)
sys.exit(2)
def force_stream_binary(stream):
"""Force binary mode for stream on Windows."""
if os.name == 'nt':
f_fileno = getattr(stream, 'fileno', None)
if f_fileno:
fileno = f_fileno()
if fileno >= 0:
import msvcrt
msvcrt.setmode(fileno, os.O_BINARY)
fin = args[0]
if fin == '-':
# read from stdin
fin = sys.stdin
force_stream_binary(fin)
elif not os.path.isfile(fin):
txt = "ERROR: File not found: %s" % fin # that's required to get not-so-dumb result from 2to3 tool
print(txt)
sys.exit(1)
if len(args) == 2:
fout = args[1]
else:
# write to stdout
fout = sys.stdout
force_stream_binary(fout)
sys.exit(bin2hex(fin, fout, offset))

View File

@ -393,7 +393,7 @@ is bob we will attempt to checkout bob-AVR'''
"bin",
"".join([binaryname, framesuffix]))
files_to_copy = []
for extension in [".px4", ".apj", ".abin"]:
for extension in [".px4", ".apj", ".abin", ".hex"]:
filepath = "".join([bare_path, extension])
if os.path.exists(filepath):
files_to_copy.append(filepath)

View File

@ -33,5 +33,6 @@ for board in get_board_list():
run_program(["./waf", "configure", "--board", board, "--bootloader"])
run_program(["./waf", "clean"])
run_program(["./waf", "bootloader"])
shutil.copy('build/%s/bootloader/AP_Bootloader.bin' % board, 'Tools/bootloaders/%s_bl.bin' % board)
shutil.copy('build/%s/bin/AP_Bootloader.bin' % board, 'Tools/bootloaders/%s_bl.bin' % board)
run_program(["Tools/scripts/bin2hex.py", "--offset", "0x08000000", 'Tools/bootloaders/%s_bl.bin' % board, 'Tools/bootloaders/%s_bl.hex' % board])
shutil.copy('build/%s/bootloader/AP_Bootloader' % board, 'Tools/bootloaders/%s_bl.elf' % board)

30
Tools/scripts/make_intel_hex.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/sh
# make an intel hex file including bootloader, for loading with DFU
if [ $# -lt 4 ]; then
echo "Usage: make_intel_hex.sh BINFILE BOOTLOADER RESERVE_KB HEXFILEOUT"
exit 1
fi
SCRIPTS=$(dirname $0)
BINFILE="$1"
BOOTLOADERFILE="$2"
RESERVE_KB="$3"
HEXFILE="$4"
[ -f "$BINFILE" ] || {
echo "Can't find bin file $BINFILE"
exit 1
}
[ -f "$BOOTLOADERFILE" ] || {
echo "Can't find bootloader file $BOOTLOADERFILE"
exit 1
}
cat "$BOOTLOADERFILE" > "$HEXFILE".tmp
dd bs=1024 seek=$RESERVE_KB if="$BINFILE" of="$HEXFILE".tmp 2>&1
"$SCRIPTS"/bin2hex.py --offset 0x08000000 "$HEXFILE".tmp "$HEXFILE"
rm -f "$HEXFILE".tmp
echo "Created $HEXFILE"