Example #1
0
def copy_include_dirs(tile):
    """Copy all include directories that this tile defines as products in build/output/include
    """

    if 'products' not in tile.settings:
        return

    incdirs = tile.settings['products'].get('include_directories', [])
    incdirs = map(lambda x: os.path.normpath(utilities.join_path(x)), incdirs)
    incdirs = sorted(incdirs, key=lambda x: len(x))

    seen_dirs = pygtrie.PrefixSet(
        factory=lambda: pygtrie.StringTrie(separator=os.path.sep))

    env = Environment(tools=[])

    # all include directories are relative to the firmware/src directory
    outputbase = os.path.join('build', 'output', 'include')
    inputbase = os.path.join('firmware', 'src')
    for inc in incdirs:
        if inc in seen_dirs:
            continue

        relinput = os.path.join(inputbase, inc)
        finaldir = os.path.join(outputbase, inc)

        for folder, subdirs, filenames in os.walk(relinput):
            relfolder = os.path.relpath(folder, relinput)
            for filename in filenames:
                if filename.endswith(".h"):
                    infile = os.path.join(folder, filename)
                    outfile = os.path.join(finaldir, relfolder, filename)
                    env.Command([outfile], [infile],
                                Copy("$TARGET", "$SOURCE"))

        seen_dirs.add(inc)
Example #2
0
def build_program(tile, elfname, chip, patch=True):
    """
    Build an ARM cortex executable
    """

    dirs = chip.build_dirs()

    output_name = '%s_%s.elf' % (
        elfname,
        chip.arch_name(),
    )
    output_binname = '%s_%s.bin' % (
        elfname,
        chip.arch_name(),
    )
    patched_name = '%s_%s_patched.elf' % (
        elfname,
        chip.arch_name(),
    )
    patchfile_name = '%s_%s_patchcommand.txt' % (
        elfname,
        chip.arch_name(),
    )
    map_name = '%s_%s.map' % (
        elfname,
        chip.arch_name(),
    )

    VariantDir(dirs['build'], os.path.join('firmware', 'src'), duplicate=0)

    prog_env = setup_environment(chip)
    prog_env['OUTPUT'] = output_name
    prog_env['BUILD_DIR'] = dirs['build']
    prog_env['OUTPUT_PATH'] = os.path.join(dirs['build'], output_name)
    prog_env['OUTPUTBIN'] = os.path.join(dirs['build'], output_binname)
    prog_env['PATCHED'] = os.path.join(dirs['build'], patched_name)
    prog_env['PATCH_FILE'] = os.path.join(dirs['build'], patchfile_name)
    prog_env['PATCH_FILENAME'] = patchfile_name
    prog_env['MODULE'] = elfname

    #Setup all of our dependencies and make sure our output depends on them being built
    tilebus_defs = setup_dependencies(tile, prog_env)

    #Setup specific linker flags for building a program
    ##Specify the linker script
    ###We can find a linker script in one of two places, either in a dependency or in an explicit 'linker' property
    ###First check for a linker script in our dependencies
    ldscripts = list(
        itertools.chain(
            *[x.linker_scripts() for x in prog_env['DEPENDENCIES']]))

    # Make sure we don't have multiple linker scripts coming in from dependencies
    if len(ldscripts) > 1:
        raise BuildError(
            "Multiple linker scripts included from dependencies, at most one may be included",
            linker_scripts=ldscripts)

    #Make sure we don't have a linker script from a dependency and explicity specified
    if len(ldscripts) == 1 and chip.property('linker', None) != None:
        raise BuildError(
            "Linker script specified in dependency and explicitly in module_settings",
            explicit_script=chip.property('linker'),
            dependency_script=ldscripts[0])

    if len(ldscripts) == 1:
        ldscript = ldscripts[0]
    else:
        ldscript = utilities.join_path(chip.property('linker'))

    #Find the linker script directory in case it includes other linker scripts in the same directory
    lddir = os.path.abspath(os.path.dirname(ldscript))
    prog_env['LIBPATH'] += [lddir]

    prog_env['LINKFLAGS'].append('-T"%s"' % ldscript)

    ##Specify the output map file
    prog_env['LINKFLAGS'].extend(
        ['-Xlinker',
         '-Map="%s"' % os.path.join(dirs['build'], map_name)])
    Clean(os.path.join(dirs['build'], output_name),
          [os.path.join(dirs['build'], map_name)])

    #Compile the TileBus command and config variable definitions
    #Try to use the modern 'tilebus' directory or the old 'cdb' directory
    tbname = os.path.join('firmware', 'src', 'tilebus',
                          prog_env["MODULE"] + ".bus")
    if not os.path.exists(tbname):
        tbname = os.path.join('firmware', 'src', 'cdb',
                              prog_env["MODULE"] + ".cdb")

    compile_tilebus(tilebus_defs + [tbname], prog_env)

    #Compile an elf for the firmware image
    objs = SConscript(os.path.join(dirs['build'], 'SConscript'),
                      exports='prog_env')
    outfile = prog_env.Program(os.path.join(dirs['build'], prog_env['OUTPUT']),
                               objs)

    if patch:
        #Create a patched ELF including a proper checksum
        ## First create a binary dump of the program flash
        outbin = prog_env.Command(
            prog_env['OUTPUTBIN'],
            os.path.join(dirs['build'], prog_env['OUTPUT']),
            "arm-none-eabi-objcopy -O binary $SOURCES $TARGET")

        ## Now create a command file containing the linker command needed to patch the elf
        outhex = prog_env.Command(prog_env['PATCH_FILE'],
                                  outbin,
                                  action=prog_env.Action(
                                      checksum_creation_action,
                                      "Generating checksum file"))

        ## Next relink a new version of the binary using that patch file to define the image checksum
        patch_env = prog_env.Clone()
        patch_env['LINKFLAGS'].append(
            ['-Xlinker', '@%s' % patch_env['PATCH_FILE']])

        patched_file = patch_env.Program(prog_env['PATCHED'], objs)
        patch_env.Depends(patched_file, [
            os.path.join(dirs['build'], output_name), patch_env['PATCH_FILE']
        ])

        prog_env.Depends(os.path.join(dirs['build'], output_name), [ldscript])

        prog_env.InstallAs(os.path.join(dirs['output'], output_name),
                           os.path.join(dirs['build'], patched_name))
    else:
        prog_env.InstallAs(os.path.join(dirs['output'], output_name), outfile)

    prog_env.InstallAs(os.path.join(dirs['output'], map_name),
                       os.path.join(dirs['build'], map_name))

    return os.path.join(dirs['output'], output_name)