MMIO Registers - CMSIS-SVD & Template Based Code Generation
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:
- Read in the SVD from the file
args.svd
.parser = SVDParser.for_xml_file(args.svd) svd_dict = parser.get_device().to_dict()
- Tell Jinja about the templates in the directory
args.templates
.loader = jinja2.loaders.FileSystemLoader(args.templates)
- Use the template
args.device
to process the SVD and write toout_path
.
tmpl = device_env.get_template(args.device)
with open(out_path, "w") as fout:
fout.write(tmpl.render(device=svd_dict))
- 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>
- The example output is here.
Subscribe via RSS