Skip to content

Instantly share code, notes, and snippets.

@basilfx
Created November 16, 2015 21:07
Show Gist options
  • Save basilfx/49a467ffeb5e7678d90f to your computer and use it in GitHub Desktop.
Save basilfx/49a467ffeb5e7678d90f to your computer and use it in GitHub Desktop.
Initialize EFM32 targets.
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))
# -*- 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