#!/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 ########################### # Firmware image to deploy 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() loader.loadhex(HEX_FILE) 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")