Years ago, I measured peripheral access crate (PAC) build times for i.MX RT MCUs. The three PACs have different structure, depending on the code generation tool. There’s

  1. the svd2rust PAC, recommended by the Rust embedded working group.
  2. the chiptool PAC, preferred by embassy.
  3. the register access layer (RAL) design, first pioneered by stm32ral and later adopted by imxrt-ral.

Back then, imxrt-ral built the fastest on my laptop, the laptop I still use today. It was worth it for me to maintain raltool, a chiptool fork to generate imxrt-ral. But now that years have passed and the Rust compiler has improved, is that still true? I’d like to know if I should maintain a unique PAC and supporting code generation tools.

As I write this, the imxrt-ral PAC still builds faster than chiptool and svd2rust PACs. However, there are likely chiptool transformations that could improve on chiptool-generated PACs. Let’s look at the new build times for different MCU and PAC designs.

Want to reproduce these measurements? Here is the repository. Share your benchmarks by email, and I’ll include them below.

Caveat

I’m the imxrt-ral maintainer, and I prefer what I know and use. Nevertheless, I try to maintain a fair benchmark. Let me know if I could improve these benchmarks by emailing me. I left some considerations in the Future Work section, at the end of this post.

Approach

All three code generation tools injest SVD files, or files that describe the MCU’s peripherals and registers. The imxrt-ral project patches these SVDs to correct defects and consolidate contents. This benchmark feeds the same patched SVDs into each code generation tool.

Later in the code generation pipeline, raltool applies transformations to the patched SVD contents. Since raltool is forked of chiptool, we can apply equivalent transformations when using chiptool to generate a PAC.

All times represent how long it took cargo build --release to complete after all dependencies were downloaded from the network. Note that the build time includes the time to build any PAC dependencies.

Results

svd2rust did not generate (DNG) PACs for certain chips. I think there’s something about these SVDs that this tool can’t handle.

Some larger PACs did not compile (DNC). My guess is that my virtual machines run out of memory or compute time. I haven’t looked into this.

Daily laptop

Most of my imxrt-rs development happened on this computer. It’s served me well over the past 5 years, but I’m due for an upgrade.

Chip / Codegen svd2rust chiptool raltool
imxrt1011 22.02s 21.02s 3.20s
imxrt1062 51.60s 48.18s 5.37s
imxrt1176_cm7 DNG 2m 05s 11.18s
imxrt1189_cm33 DNG 9m 30s 35.17s
  • Rust version 1.88.0.
  • MacBook Pro, 16-inch, 2019.
    • 2.3 GHz 8-Core Intel i9.
    • 16 GB 2667MHz DDR4 RAM.

VPS

A smaller VPS that I use for public infrastructure.

Chip / Codegen svd2rust chiptool raltool
imxrt1011 17.81s 18.16s 2.16s
imxrt1062 41.82s 38.00s 3.81s
imxrt1176_cm7 DNG 1m 37s 7.63s
imxrt1189_cm33 DNG DNC 22.43s
  • Rust version 1.88.0.
  • Hetzner CCX13.
    • 2 dedicated vCPUs of an AMD EPYC Milan, approx 2 GHz each.
    • 8 GB RAM.

What about a real chiptool PAC?

We have an example. Kiteshield AB maintains a chiptool-generated PAC specifically for the 118x MCUs. How does it compare to the imxrt-ral build for the same MCU?

git clone https://gitlab.com/kiteshield-ab/imxrt118x-pac
cargo build --release --manifest-path imxrt118x-pac/Cargo.toml --target=thumbv8m.main-none-eabihf
  • Daily laptop: 38.01s (35.17s using raltool).
  • VPS: 29.30s (22.43s using raltool).

It’s a drastic improvement over the 9m 30s chiptool build time I’m seeing! These times are closer to the imxrt-ral build times. The PAC includes transforms which aren’t used in imxrt-ral. If those improve this PAC’s build time, I’m curious if they’ll improve imxrt-ral build times, too.

Why focus on build times?

As I write this, crates.io reports 10000 imxrt-ral downloads over the last 90 days. I expect each download becomes at least one clean-build of the package.

Those PAC build times add up! If something equivalent to my VPS built a 1062 PAC 10000 times, that’s

  • around 10 hours building imxrt-ral code.
  • over 100 hours building chiptool or svd2rust code.

I’m lucky that I can afford periodic computer upgrades and decent CI infrastructure. However, I won’t assume that my users are so lucky.

But it’s not type safe!

That’s right. imrt-ral users risk reading the contents of a status register, then incorrectly writing those contents to a control register. From my understanding, the strong types emitted by chiptool and svd2rust prevent that problem. On the other hand, imxrt-ral uses primitive types, like a u32, for status and control registers.

I’m typically writing my own driver wrappers around imxrt-ral. I do need to be careful when writing those drivers. But after that, I’m OK.

Future work

Most SVD patches are corrections or improvements that all code generation tools can use. However, there may be some that optimize for RAL code generation. A fairer benchmark would remove those patches when generating PACs with chiptool or svd2rust.

The same applies to the chiptool / raltool transformations. A raltool transform might hurt the code that chiptool has to generate. These should be removed, selecting those that benefit both PACs.

Until I can see improvements in other PAC build times, I’ll continue maintaining and improving the RAL design. Next up: removing MMIO references in the generated RAL code. I’d also like to rebase my raltool patches onto a newer version of chiptool so we can better share transforms.