Home

Awesome

msp430_svd

DSLite to SVD converter for MSP430

DSLite is a Texas Instruments-internal file format for describing their microcontroller address layout and peripherals. For the purposes of using svd2rust with TI devices, msp430_svd can generate System View Description files instead. SVD may be an ARM format, but the format is nominally CPU-neutral; TI even previously used SVD for some of their microcontrollers.

This repository supplies a copy of TI's C headers and DSLite files for the msp430 family. All commands are run from the root directory of this repository.

To generate Peripheral Access Crates (PACs) for SVD files from msp430_svd, you will need at a minimum svd2rust version v0.22.1. However, svd2rust commit b3457d7 or later is preferred in order to take advantage of the new critical_section crate. If using commit b3457d7 or later, you will also need msp430 and msp430-rt v0.4.0 or later.

How To Generate An SVD File (Quick Start)

For now, all commands must be run via cargo run; running as an installed binary is unsupported.

This command will create two SVD files (msp430g2553.svd and msp430g2553.svd.patched) for the MSP430G2553 MCU:

$ cargo run -- msp430g2553

If you are interested in just getting started quickly, you can stop here, and use the msp430g2553.svd to generate a PAC using svd2rust:

$ svd2rust -g -i msp430g2553.svd --target msp430

However, you will probably want to patch your shiny new SVD file later; this is what the msp430g2553.svd.patched file and overrides directory are for.

Patching

Although the msp430g2553.svd output from msp430_svd in the first step is usable as-is, it is likely some register fields in the TI-provided DSLite files will be wrong or missing. To fix these registers, we can leverage the work of the stm32-rs team to patch output SVDs using svdtools.

Patches for svdtools are kept under overrides/devices. There is one patch file per device, named after the device (e.g. msp430g2211.yaml). The overrides/peripherals directory is meant to facilitate code reuse. If a file of the name overrides/devices/${MCU}.yaml exists when msp430_svd runs, msp430_svd will invoke svdtools to patch the ${MCU}.svd file based on the YAML file. The results of ${MCU}.svd patching are saved in ${MCU}.svd.patched; msp430_svd will always generate a ${MCU}.svd file.

If a patch file for your MCU doesn't exist under overrides/devices, see the next section for a quick start on finding missing register fields and creating your own patch. The msp430g2553 device is an example with a relatively complete patch. You may wish to compare the unpatched and patched output to double-check the results:

$ cargo run -- msp430g2553
$ diff -u msp430g2553.svd msp430g2553.svd.patched

Contributing Patches

svdtools patch files are written in a YAML format described here. Look at the overrides/devices directory for existing examples on how to write patches, along with the linked documentation.

msp430_svd uses svdtools version 0.3.6 (or a later commit) to generate patches.

Naming Convention

When possible, I use the MSP430x{1,2,3,4,5,6}xx Family User Guide name for missing fields and enums in registers. My theory is that TI deliberately omits the DSLite-equivalent of SVD fields when the entire register contains a single field. In the User Guide, these missing fields tend to be named after the register itself.

The toolchain files (msp430-gcc-support-files/include) seem to omit the field names as redundant. As of this writing (4-23-2020), removing the redundancy is not possible to do safely via svd2rust- the bits() method is always unsafe.

Sometimes, the enum or register name to choose isn't obvious from the User Guide. In that case, I do a grep of device-specific toolchain files- located under msp430-gcc-support-files/include- for hints. Using TAIV for msp430g2211 as an example:

$ grep TAIV msp430-gcc-support-files/include/{msp430g2211.h,msp430g2211.ld,msp430g2221_symbols.ld}
msp430-gcc-support-files/include/msp430g2211.h:sfr_w(TAIV);                                  /* Timer A Interrupt Vector Word */
msp430-gcc-support-files/include/msp430g2211.h:#define TA0IV                  TAIV           /* Timer A Interrupt Vector Word */
msp430-gcc-support-files/include/msp430g2211.h:#define TA0IV_                 TAIV_          /* Timer A Interrupt Vector Word */
msp430-gcc-support-files/include/msp430g2211.h:#define TAIV_NONE              (0x0000)       /* No Interrupt pending */
msp430-gcc-support-files/include/msp430g2211.h:#define TAIV_TACCR1            (0x0002)       /* TACCR1_CCIFG */
msp430-gcc-support-files/include/msp430g2211.h:#define TAIV_2                 (0x0004)       /* Reserved */
msp430-gcc-support-files/include/msp430g2211.h:#define TAIV_6                 (0x0006)       /* Reserved */
msp430-gcc-support-files/include/msp430g2211.h:#define TAIV_8                 (0x0008)       /* Reserved */
msp430-gcc-support-files/include/msp430g2211.h:#define TAIV_TAIFG             (0x000A)       /* TAIFG */
msp430-gcc-support-files/include/msp430g2221_symbols.ld:PROVIDE(TAIV               = 0x012E);

Finding Missing/Wrong Registers

As of this writing (4-23-2020), I'm not sure of a good way to detect missing or downright incorrect registers before a PAC from svd2rust is generated. Missing registers will of course become apparent when you try to access a register on a peripheral you know exists, but the compiler errors unable to find said register name.

It is also possible for registers to be shared between multiple peripherals, such as certain interrupt enable bits. This is okay as long as the DSLite file specifies the registers as belonging to at least one (and ideally one) of the peripherals.

Generating docs via rustdoc for your PAC and using the search facility is an easy way to distinguishing missing registers from registers shared by multiple peripherals. I'm not sure of an obvious way to detect an incorrectly-specified register short of reading all DSLite files and comparing them to the User Guides (impractical!), or checking the documentation of your generated PAC for registers that look wrong.

Registers Missing Some Fields

The same problem as above applies to registers which contain some fields but not all. I'm aware that msp430 DSLite files completely omit the following fields:

Registers Without Fields

The DSLite files from TI sometimes completely omit fields for a register. msp430_svd will print out registers with completely missing register fields and enums while generating an SVD file (msp430g2211 in this example):

skipping aliased vector TIMER0_A1_VECTOR
skipping aliased vector TIMER0_A0_VECTOR
warning: no fields in register CALDCO_1MHZ
warning: no fields in register CALBC1_1MHZ
warning: no fields in register TAIV
warning: no fields in register TAR
warning: no fields in register TACCR0
warning: no fields in register TACCR1

To fix these registers, read the Family User's Guide for your specific MCU to find the missing fields and enums- see Naming Convention section for details.

Note

Currently reset values for all registers are set to 0, because I don't have a good way to get them yet. See https://github.com/pftbest/msp430/issues/4