This post is about a common requirement in low level programming - accessing hardware devices via MMIO registers.

CMSIS-SVD is an XML file format used by the Keil IDE and MCU on Eclipse to define a hardware device to the debugger.

The XML file defines the registers, interrupts and CPU cores for many Cortex-M devices. It’s also been used by SiFive for their RISC-V devices. It’s used by debuggers to display register and interrupt information in a device independent way.

However, it’s also useful as database of device info that can be transformed into headers and even model definitions.

There’s a handy python library cmsis-svd that parses SVD. I’ve used that directly to generate code, but embedding code as strings inside of other programming languages is tedious and error prone IMO.

Using a template engine is much easier. It looks like Jinja is a good one for Python, it resembles Ruby on Rails erb and Jekyll’s liquid that I’m already familiar with.

Combining the two is really easy. The script is here , but the core parts are here:

  1. Read in the SVD from the file args.svd.
    parser = SVDParser.for_xml_file(args.svd)
    svd_dict = parser.get_device().to_dict()
    
  2. Tell Jinja about the templates in the directory args.templates.
    loader = jinja2.loaders.FileSystemLoader(args.templates)
    
  3. Use the template args.device to process the SVD and write to out_path.
tmpl = device_env.get_template(args.device)
with open(out_path, "w") as fout:
    fout.write(tmpl.render(device=svd_dict))
  1. The template will set a variable device in the template’s top scope. In this case I’m generating a simple table to list the devices. The template engine makes dictionary members
<h1> Address map for </h1>
<table border=1>
{%- for p in device.peripherals  %}
<tr>
<td>{{p.name }}</td><td>{{'0x%08x'|format(p.base_address)  }}</td><td>{{ p.description }}</td></tr>
</tr>
{%- endfor  %}
</table>
  1. The example output is here.