class ELFGenerator: BUILD_FOLDER = '__build/' C_SOURCE_FILE = BUILD_FOLDER + 'main.c' LD_SCRIPT_FILE = BUILD_FOLDER + 'tmp.ld' INITIAL_C_CODE = ''' typedef unsigned char u8_t; typedef unsigned short u16_t; typedef unsigned int u32_t; typedef void (*handler_void_void_t)(void); ''' TYPE_TO_BYTE_SIZE = { 'u8_t': 1, 'u16_t': 2, 'u32_t': 4, 'handler_void_void_t': 4, # TODO: handle 64-bit arch } PREFIX = 'arm-none-eabi-' GCC = PREFIX + 'gcc' OBJCOPY = PREFIX + 'objcopy' def __init__(self, fw_path, target_name=None, map_address=None, irq_no=None): try: makedirs(ELFGenerator.BUILD_FOLDER) except FileExistsError: pass # TODO: figure out target from target name parameter self.target_name = target_name self.target = CortexM(7, map_address, irq_no) self.fw_path = fw_path map_address, stack_pointer, entry_point, irq_no = self.target.determine_information( self.fw_path) self.entry_point = entry_point def generate(self, elf_path): ld = LinkerScript() ld.set_entry_point('reset', self.entry_point) mmap = self.target.get_memory_map() syms = self.target.get_registers() for m in mmap: ld.add_memory(*m) for s in syms: ld.add_symbol(s[0], s[1]) c_code = self._generate_c_file(syms) ld_script = str(ld) open(ELFGenerator.C_SOURCE_FILE, 'w').write(c_code) open(ELFGenerator.LD_SCRIPT_FILE, 'w').write(ld_script) self._compile_file(ELFGenerator.C_SOURCE_FILE, ELFGenerator.LD_SCRIPT_FILE, elf_path) self._update_section('.vt', self.fw_path, elf_path) def _generate_c_file(self, structures): c = ELFGenerator.INITIAL_C_CODE for s_name, s_address, s_members in structures: c += 'struct _%s {\n' % s_name current_address = s_address for m_name, m_type, m_address, m_description in sorted( s_members, key=lambda s: s[2]): # Handle padding here if current_address != m_address: c += ' /* 0x%08x */ u8_t __padding__0x%08x_0x%08x[0x%08x];\n' % ( current_address, current_address, m_address, m_address - current_address) current_address = m_address c += ' /* 0x%08x */ %s %s; // %s\n' % (m_address, m_type, m_name, m_description) if not m_type in ELFGenerator.TYPE_TO_BYTE_SIZE: raise Exception('Unknown type used: %s' % m_type) current_address += ELFGenerator.TYPE_TO_BYTE_SIZE[m_type] c += '} %s __attribute__((section(".%s")));\n' % (s_name.upper(), s_name) return c def _compile_file(self, source_file, link_script, elf_file): compiler = [ELFGenerator.GCC] cflags = [ '-ggdb3', '-nostdlib', '-nostartfiles', '-mcpu=%s' % self.target_name, '-mthumb' ] linker_script = [link_script] source_file = [source_file] output = ['-o', elf_file] call(compiler + cflags + linker_script + source_file + linker_script + output) def _update_section(self, section_name, raw_file, elf_file): objcopy = [ELFGenerator.OBJCOPY] objflags = [ '--update-section', '%s=%s' % (section_name, raw_file), elf_file ] call(objcopy + objflags)