Added toolchain hooks and support for LPC4088_EA binary generation

A new hooks mechanism (hooks.py) allows various targets to customize
part(s) of the build process. This was implemented to allow generation of
custom binary images for the EA LPC4088 target, but it should be generic
enough to allow other such customizations in the future. For now, only the
'binary' step is hooked in toolchains/arm.py.
pull/46/merge
Bogdan Marinescu 2013-08-30 12:19:08 +03:00
parent 2cdd41d9b1
commit e870a90ff2
6 changed files with 148 additions and 3 deletions

View File

@ -0,0 +1,24 @@
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x00000000 0x00080000 { ; load region size_region
ER_IROM1 0x00000000 0x00080000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x100000E8 0x0000FF18 { ; RW data
.ANY (+RW +ZI)
}
RW_IRAM2 0x20000000 0x00008000 {
.ANY (AHBSRAM1)
}
}
LR_IROM2 0x28000000 0x01000000 {
ER_IROM2 0x28000000 0x01000000 { ; load address = execution address
.ANY (+RO)
}
}

77
workspace_tools/hooks.py Normal file
View File

@ -0,0 +1,77 @@
# Configurable hooks in the build system. Can be used by various platforms
# to customize the build process.
################################################################################
# Hooks for the various parts of the build process
# Internal mapping of hooks per tool
_hooks = {}
# Internal mapping of running hooks
_running_hooks = {}
# Available hook types
_hook_types = ["binary"]
# Available hook steps
_hook_steps = ["pre", "replace", "post"]
# Hook the given function. Use this function as a decorator
def hook_tool(function):
tool = function.__name__
tool_flag = "_" + tool + "_done"
def wrapper(t_self, *args, **kwargs):
# if a hook for this tool is already running, it's most likely
# coming from a derived class, so don't hook the super class version
if _running_hooks.get(tool, False):
return function(t_self, *args, **kwargs)
_running_hooks[tool] = True
# If this tool isn't hooked, return original function
if not _hooks.has_key(tool):
res = function(t_self, *args, **kwargs)
_running_hooks[tool] = False
return res
tooldesc = _hooks[tool]
setattr(t_self, tool_flag, False)
# If there is a replace hook, execute the replacement instead
if tooldesc.has_key("replace"):
res = tooldesc["replace"](t_self, *args, **kwargs)
# If the replacement has set the "done" flag, exit now
# Otherwise continue as usual
if getattr(t_self, tool_flag, False):
_running_hooks[tool] = False
return res
# Execute pre-function before main function if specified
if tooldesc.has_key("pre"):
tooldesc["pre"](t_self, *args, **kwargs)
# Execute the main function now
res = function(t_self, *args, **kwargs)
# Execute post-function after main function if specified
if tooldesc.has_key("post"):
post_res = tooldesc["post"](t_self, *args, **kwargs)
_running_hooks[tool] = False
return post_res or res
else:
_running_hooks[tool] = False
return res
return wrapper
class Hook:
def __init__(self, target, toolchain):
_hooks.clear()
self.toolchain = toolchain
target.init_hooks(self, toolchain.__class__.__name__)
def hook_add(self, hook_type, hook_step, function):
if not hook_type in _hook_types or not hook_step in _hook_steps:
return False
if not hook_type in _hooks:
_hooks[hook_type] = {}
_hooks[hook_type][hook_step] = function
return True
def hook_add_binary(self, hook_step, function):
return self.hook_add("binary", hook_step, function)
################################################################################

View File

@ -23,6 +23,8 @@ CORE_LABELS = {
"Cortex-M4" : "M4"
}
import os
import shutil
class Target:
def __init__(self):
@ -46,6 +48,8 @@ class Target:
def get_labels(self):
return [self.name, CORE_LABELS[self.core]] + self.extra_labels
def init_hooks(self, hook, toolchain_name):
pass
class LPC2368(Target):
def __init__(self):
@ -140,6 +144,42 @@ class LPC4088(Target):
self.supported_toolchains = ["ARM", "GCC_CR"]
# Use this target to generate the custom binary image for LPC4088 EA boards
class LPC4088_EA(LPC4088):
def __init__(self):
LPC4088.__init__(self)
def init_hooks(self, hook, toolchain_name):
if toolchain_name in ['ARM_STD', 'ARM_MICRO']:
hook.hook_add_binary("post", self.binary_hook)
@staticmethod
def binary_hook(t_self, elf, binf):
if not os.path.isdir(binf):
# Regular binary file, nothing to do
return
outbin = open(binf + ".temp", "wb")
partf = open(os.path.join(binf, "ER_IROM1"), "rb")
# Pad the fist part (internal flash) with 0xFF to 512k
data = partf.read()
outbin.write(data)
outbin.write('\xFF' * (512*1024 - len(data)))
partf.close()
# Read and append the second part (external flash) in chunks of fixed size
chunksize = 128 * 1024
partf = open(os.path.join(binf, "ER_IROM2"), "rb")
while True:
data = partf.read(chunksize)
outbin.write(data)
if len(data) < chunksize:
break
partf.close()
outbin.close()
# Remove the directory with the binary parts and rename the temporary
# file to 'binf'
shutil.rmtree(binf, True)
os.rename(binf + '.temp', binf)
t_self.debug("Generated custom binary file (internal flash + SPIFI)")
class LPC4330_M4(Target):
def __init__(self):
@ -254,7 +294,8 @@ TARGETS = [
LPC1347(),
LPC1114(),
LPC11C24(),
LPC11U35_401()
LPC11U35_401(),
LPC4088_EA()
]
# Map each target name to its unique instance

View File

@ -25,6 +25,7 @@ from workspace_tools.utils import run_cmd, mkdir, rel_path, ToolException, split
from workspace_tools.patch import patch
from workspace_tools.settings import BUILD_OPTIONS
import workspace_tools.hooks as hooks
def print_notify(event):
# Default command line notification
@ -144,6 +145,7 @@ class mbedToolchain:
def __init__(self, target, options=None, notify=None):
self.target = target
self.name = self.__class__.__name__
self.hook = hooks.Hook(target, self)
self.legacy_ignore_dirs = LEGACY_IGNORE_DIRS - set([target.name, LEGACY_TOOLCHAIN_NAMES[self.name]])

View File

@ -19,7 +19,7 @@ from os.path import join
from workspace_tools.toolchains import mbedToolchain
from workspace_tools.settings import ARM_BIN, ARM_INC, ARM_LIB, MY_ARM_CLIB, ARM_CPPLIB
from workspace_tools.hooks import hook_tool
class ARM(mbedToolchain):
LINKER_EXT = '.sct'
@ -97,12 +97,13 @@ class ARM(mbedToolchain):
self.default_cmd([self.ar, '-r', lib_path] + objects)
def link(self, output, objects, libraries, lib_dirs, mem_map):
args = ["-o", output, "--userlibpath", ",".join(lib_dirs), "--info=totals", "--list=.link_totals.txt"]
args = ["-o", output, "--userlibpath", ",".join(lib_dirs), "--info=totals", "--list=.link_totals.txt", "--any_placement=first_fit"]
if mem_map:
args.extend(["--scatter", mem_map])
self.default_cmd(self.ld + args + objects + libraries + self.sys_libs)
@hook_tool
def binary(self, elf, bin):
self.default_cmd([self.elf2bin, '--bin', '-o', bin, elf])