Created
November 16, 2015 21:07
-
-
Save basilfx/49a467ffeb5e7678d90f to your computer and use it in GitHub Desktop.
Initialize EFM32 targets.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import shutil | |
import glob | |
import sys | |
import os | |
import re | |
# This file contains all templates for files | |
import templates | |
def main(argv): | |
""" | |
Run the converter. Script expects write access and an 'input/' directory | |
containing: | |
- Device/ | |
- emlib/ | |
These folers are installed with Simplicity Studio in the | |
'developer/sdks/efm32' folder. | |
""" | |
# Start by removing the output directory. | |
shutil.rmtree("output/", ignore_errors=True) | |
# Index all CPUs | |
cpus = find_cpus() | |
for cpu in cpus: | |
variants = find_variants(cpu) | |
# Create structure for CPU. | |
create_folder_structure(cpu) | |
# Copy the exm32_x.h files. | |
copy_includes(cpu) | |
# Copy the system_x.h files. | |
copy_system(cpu) | |
# Create cpu_conf.h | |
create_cpu_conf(cpu, variants) | |
once = False | |
for variant in variants: | |
# Has to be done once, but each device has the metadata on the | |
# architecture (lazy over here). | |
if not once: | |
create_makefiles(variant) | |
once = True | |
# Create linker script from template. | |
create_linker_script(variant) | |
# Create structure for common files. | |
create_folder_structure_common(cpu) | |
# Create commong makefiles. | |
create_makefiles_common() | |
# Copy emlib. | |
copy_emlib() | |
def find_cpus(): | |
""" | |
Index all available CPUs. | |
""" | |
folders = glob.glob("input/Device/SiliconLabs/*") | |
cpus = [] | |
for folder in folders: | |
if not os.path.isdir(folder): | |
continue | |
cpus.append({ | |
"id": os.path.basename(folder).lower(), | |
"directory": folder, | |
"name": os.path.basename(folder), | |
"name_upper": os.path.basename(folder).upper() | |
}) | |
return cpus | |
def find_variants(cpu): | |
""" | |
Index all available variants of a cpu. Read configuration settings. | |
""" | |
includes = glob.glob( | |
"input/Device/SiliconLabs/%(id)s/Include/%(id)s*.h" % cpu) | |
variants = [] | |
for include in includes: | |
if not os.path.isfile(include): | |
continue | |
if "_" in os.path.basename(include): | |
continue | |
# Derrive settings from the device header files. | |
hex_re = re.compile(r".*(0x\d+).*") | |
irq_re = re.compile(r"\s*([a-zA-Z_]+)\s* = (\d+).*") | |
flash_size = None | |
ram_size = None | |
architecture = None | |
has_fpu = False | |
max_irq = None | |
max_irq_name = None | |
last_line = None | |
with open(include, "r") as fp: | |
for line in fp: | |
if "#define" in line: | |
if "FLASH_SIZE" in line: | |
flash_size = int(hex_re.match(line).group(1), 16) | |
elif "SRAM_SIZE" in line: | |
ram_size = int(hex_re.match(line).group(1), 16) | |
elif "__FPU_PRESENT": | |
has_fpu = True if "1" in line else False | |
elif "Cortex-M4" in line: | |
architecture = "m4" | |
elif "Cortex-M3" in line: | |
architecture = "m3" | |
elif "Cortex-M0+" in line: | |
architecture = "m0+" | |
elif "IRQn_Type" in line: | |
last_irq = irq_re.match(last_line) | |
if last_irq: | |
max_irq = last_irq.group(2) | |
max_irq_name = last_irq.group(1) | |
last_line = line | |
if not flash_size or not ram_size: | |
raise Exception("Missing flash/ram size in include %s" % include) | |
variants.append({ | |
"id": cpu["id"], | |
"name": cpu["name"], | |
"name_upper": cpu["name"].upper(), | |
"variant": os.path.basename(include).split(".")[0], | |
"variant_upper": os.path.basename(include).split(".")[0].upper(), | |
"flash_size": flash_size, | |
"ram_size": ram_size, | |
"architecture": architecture + ("f" if has_fpu else ""), | |
"max_irq": max_irq, | |
"max_irq_name": max_irq_name | |
}) | |
return variants | |
def copy_includes(cpu): | |
""" | |
Copy all include files. Add 'Extern C' if needed. | |
""" | |
includes = glob.glob("input/Device/SiliconLabs/%s/Include/*.h" % ( | |
cpu["name_upper"])) | |
for include in includes: | |
if not os.path.isfile(include): | |
continue | |
if "_" in os.path.basename(include) and "em_device" not in include: | |
add_extern_c(include, "output/%s/include/%s" % ( | |
cpu["id"], os.path.basename(include))) | |
else: | |
shutil.copy(include, "output/%s/include/%s" % ( | |
cpu["id"], os.path.basename(include))) | |
def copy_system(cpu): | |
""" | |
Copy the system_x.c file. | |
""" | |
shutil.copy( | |
"input/Device/SiliconLabs/%(name_upper)s/Source/system_%(id)s.c" % cpu, | |
"output/%(id)s/system_%(id)s.c" % cpu) | |
def copy_emlib(): | |
""" | |
Copy the contenst of emlib. | |
""" | |
shutil.copytree("input/emlib", "output/efm32_common/emlib") | |
def create_folder_structure(cpu): | |
""" | |
Create a per-cpu folder layout. | |
""" | |
os.makedirs("output/%(id)s/include" % cpu) | |
os.makedirs("output/%(id)s/ldscripts" % cpu) | |
def create_folder_structure_common(cpu): | |
""" | |
Create the EFM32 common folder. | |
""" | |
os.makedirs("output/efm32_common/periph") | |
def create_linker_script(variant): | |
""" | |
Create a per-variant linker script. | |
""" | |
script = "output/%(id)s/ldscripts/%(variant)s.ld" % variant | |
template = templates.linker_script % variant | |
with open(script, "w") as fp: | |
fp.write(template) | |
def create_makefiles(cpu): | |
""" | |
Create a per-cpu Makefile and Makefile.include. | |
""" | |
script = "output/%(id)s/Makefile" % cpu | |
template = templates.makefile | |
with open(script, "w") as fp: | |
fp.write(template) | |
script = "output/%(id)s/Makefile.include" % cpu | |
template = templates.makefile_include % cpu | |
with open(script, "w") as fp: | |
fp.write(template) | |
def create_makefiles_common(): | |
""" | |
Create the EFM32 common Makefile and Makefile.include. | |
""" | |
script = "output/efm32_common/Makefile" | |
template = templates.common_makefile | |
with open(script, "w") as fp: | |
fp.write(template) | |
script = "output/efm32_common/Makefile.include" | |
template = templates.common_makefile_include | |
with open(script, "w") as fp: | |
fp.write(template) | |
def create_cpu_conf(cpu, variants): | |
""" | |
Create a per-cpu cpu_conf.h file. | |
""" | |
# Generate a long if-elseif-else list of devices supported. | |
devices = None | |
for variant in variants: | |
if not devices: | |
devices = templates.cpu_conf_devices_if % variant | |
else: | |
devices = devices + templates.cpu_conf_devices_elif % variant | |
devices = devices + templates.cpu_conf_devices_else | |
script = "output/%(id)s/include/cpu_conf.h" % cpu | |
variables = {"devices": devices} | |
variables.update(variant) | |
template = templates.cpu_conf % variables | |
with open(script, "w") as fp: | |
fp.write(template) | |
def add_extern_c(source_file, target_file): | |
""" | |
Add 'Extern C' to a given 'source_file'. Write it back to 'target_file'. | |
""" | |
with open(source_file, "r") as fp: | |
source = fp.read() | |
offset = source.index(templates.extern_marker) + \ | |
len(templates.extern_marker) + 1 | |
part_one = source[:offset] | |
part_two = source[offset:] | |
with open(target_file, "w") as fp: | |
fp.write( | |
part_one + templates.extern_start + part_two + | |
templates.extern_end) | |
# E.g. `python convert.py'. | |
if __name__ == "__main__": | |
sys.exit(main(sys.argv)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# cpu/ldscripts/variant.ld | |
linker_script = """/* | |
* Copyright (C) 2015 Freie Universität Berlin | |
* | |
* This file is subject to the terms and conditions of the GNU Lesser | |
* General Public License v2.1. See the file LICENSE in the top level | |
* directory for more details. | |
*/ | |
/** | |
* @addtogroup cpu_%(id)s | |
* @{ | |
* | |
* @file | |
* @brief Memory definitions for the %(name)s CPU | |
* | |
* @} | |
*/ | |
MEMORY | |
{ | |
rom (rx) : ORIGIN = 0x00000000, LENGTH = %(flash_size)d | |
ram (rwx) : ORIGIN = 0x20000000, LENGTH = %(ram_size)d | |
} | |
INCLUDE cortexm_base.ld | |
""" | |
# cpu/Makefile | |
makefile = """# define the module that is build | |
MODULE = cpu | |
# add a list of subdirectories, that should also be build | |
DIRS = periph $(RIOTCPU)/cortexm_common $(RIOTCPU)/efm32_common | |
include $(RIOTBASE)/Makefile.base | |
""" | |
# cpu/Makefile.include | |
makefile_include = """export CPU_ARCH = cortex-%(architecture)s | |
include $(RIOTCPU)/Makefile.include.cortexm_common | |
""" | |
# efm32_common/Makefile | |
common_makefile = """# define the module that is build | |
MODULE = efm32_common | |
# add a list of subdirectories, that should also be build | |
DIRS = periph $(RIOTCPU)/cortexm_common emlib/src | |
include $(RIOTBASE)/Makefile.base | |
""" | |
common_makefile_include = """ | |
""" | |
# cpu/include/cpu_conf.h | |
cpu_conf = """/* | |
* Copyright (C) 2015 Freie Universität Berlin | |
* | |
* This file is subject to the terms and conditions of the GNU Lesser | |
* General Public License v2.1. See the file LICENSE in the top level | |
* directory for more details. | |
*/ | |
/** | |
* @defgroup cpu_%(id)s Silicon Labs %(name_upper)s | |
* @ingroup cpu | |
* @brief Support for the Silicon Labs %(name_upper)s CPU | |
* @{ | |
* | |
* @file | |
* @brief Implementation specific CPU configuration options | |
*/ | |
#ifndef CPU_CONF_H | |
#define CPU_CONF_H | |
%(devices)s | |
#include "em_device.h | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
/** | |
* @brief ARM Cortex-M specific CPU configuration | |
* @{ | |
*/ | |
#define CPU_DEFAULT_IRQ_PRIO (1U) | |
#define CPU_IRQ_NUMOF (%(max_irq_name)s + 1) | |
#define CPU_FLASH_BASE FLASH_BASE | |
/** @} */ | |
/** | |
* @brief CPUID_ID_LEN length of cpuid in bytes | |
*/ | |
#define CPUID_ID_LEN (8U) /* 64-bit unique ID */ | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif /* __CPU_CONF_H */ | |
/** @} */ | |
""" | |
cpu_conf_devices_if = """#if (CPU_MODEL == %(variant)s) | |
#define %(variant_upper)s | |
""" | |
cpu_conf_devices_elif = """#elif (CPU_MODEL == %(variant)s) | |
#define %(variant_upper)s | |
""" | |
cpu_conf_devices_else = """#else | |
#error "No CPU headers for the defined CPU_MODEL found" | |
#endif | |
""" | |
# General | |
extern_start = """#ifdef __cplusplus | |
extern "C" { | |
#endif | |
""" | |
extern_end = """#ifdef __cplusplus | |
} | |
#endif | |
""" | |
extern_marker = " *****************************************************************************/" # noqa |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment