Skip to content
Snippets Groups Projects
firmwareprep.py 3.78 KiB
Newer Older
  • Learn to ignore specific revisions
  • #!/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")