Newer
Older
#!/usr/bin/env python
#
# Firmware prep utility for Fadecandy production.
#
# This tool bundles a bootloader and firmware image into a source
# file that can be included in the "production" firmware for the testjig.
#
########################### Configuration ###########################
HEX_FILE = "../bin/fc-firmware-v106.hex"
ELF_FILE = "../bin/fc-firmware-v106.elf"
# Which GDB to use for the firmware image
GDB_COMMAND = "arm-none-eabi-gdb"
# Table of expressions to evaluate under GDB, and names to give them
DEFINITIONS = [
('fw_pFlags', '&buffers.flags'),
('fw_pFbPrev', '&buffers.fbPrev'),
('fw_pFbNext', '&buffers.fbNext'),
('fw_pLUT', '&buffers.lutCurrent.entries[0]'),
('fw_usbPacketBufOffset', '&((usb_packet_t*)0)->buf'),
]
# Where to generate output
OUTPUT_FILE = "production/firmware_data.h"
#####################################################################
import intelhex, time, hashlib, struct, subprocess
# Flash memory sector size
SECTOR_SIZE = 1024
output = open(OUTPUT_FILE, 'w')
output.write("""/*
* Firmware data for Fadecandy production.
* AUTOMATICALLY GENERATED by firmwareprep.py
*
* Date: %s
* Firmware: %s
* SHA1: %s
*
* Copyright (c) 2013 Micah Elizabeth Scott
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
""" % (time.asctime(),
HEX_FILE,
hashlib.sha1(open(HEX_FILE, 'rb').read()).hexdigest()))
# Load all .hex files into a flat memory image
loader = intelhex.IntelHex()
image = loader.tobinstr()
# Pad to a sector boundary
numSectors = (len(image) + SECTOR_SIZE - 1) // SECTOR_SIZE
numBytes = numSectors * SECTOR_SIZE
numWords = numBytes / 4
image += chr(loader.padding) * (numBytes - len(image))
# Use a GDB subprocess to evaluate symbols, and write those out to the file
gdbArgs = [GDB_COMMAND, '--batch', ELF_FILE]
for name, expression in DEFINITIONS:
gdbArgs.append('-ex')
gdbArgs.append('p (uint32_t)' + expression)
lines = subprocess.Popen(gdbArgs, stdin=subprocess.PIPE,
stdout=subprocess.PIPE).communicate()[0].split('\n')
for i, (name, expression) in enumerate(DEFINITIONS):
addr = int(lines[i].split('=', 2)[1])
output.write("static const uint32_t %s = 0x%x; // %s\n" % (name, addr, expression))
output.write("\n")
# Write the combined firmware image
output.write("static const unsigned fw_sectorCount = %d;\n" % numSectors)
output.write("static const uint32_t fw_data[%d] = {\n" % numWords)
wordsPerLine = 4
numLines = numWords / wordsPerLine
for line in range(numLines):
addr = line * wordsPerLine * 4
words = [
"0x%08x, " % struct.unpack('<I',
image[addr+4*x:addr+4*(x+1)]
)[0]
for x in range(wordsPerLine)
]
output.write(" %s // 0x%08x\n" % (''.join(words), addr))
output.write("};\n")