Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

svd2rust support for autogenerating ARM device drivers/memory maps #10

Closed
cwoodall opened this issue Oct 3, 2016 · 19 comments
Closed

Comments

@cwoodall
Copy link

cwoodall commented Oct 3, 2016

Rust should support the ability to autogenerate device drivers/memory maps from SVD files similar to the ARM CMSIS support or the AdaCore support for for Ada provided by svd2ada.

I know that @japaric started working on this in the japaric/svd repository, but I think in the long run this would go a long way to improving Rusts ability to compete in the ecosystem. The team at AdaCore has been doing some great work building out Ada support for embedded systems, while their model is a little more centralized than the more modular nature of the rust community, it would be interesting to be able to match their capabilities one day.

@posborne
Copy link
Member

posborne commented Oct 4, 2016

👍 I'm the maintainer of https://github.com/posborne/cmsis-svd which currently has a bunch of SVD files from various vendors and a reference SVD parser in python. Generating definitions for Rust would not necessarily require the parser to be in Rust, but I am not opposed to it by any means.

This is something we have explored some on Zinc: hackndev/zinc#327

@japaric
Copy link
Member

japaric commented Oct 4, 2016

@posborne Thanks for cmsis-svd! I'm using the "bunch of SVD files" in my svd parser as a test suite.

@cwoodall I haven't look at svd2ada yet but I expect they generate an API that does a bunch of validation at compile time thanks to its integer ranges and what not (I'm not really familiar with Ada).

I have a hacky, unpublished svd -> Rust generator where I'm using my svd parser plus the awesome aster to generate Rust structs. It's not fully automatic and doesn't generate a compile-time unbreakable API but it does get the part of read/write access right (I think) and generates nice documentation about the register fields. I'll post a link to the stuff it outputs later today.

One important thing to consider when writing svd2rust is that there are SVD files of different qualities out there. For example, the STM32 ones that I've seen don't make use of EnumeratedValues at all so you have idea whether a 2-bit register field accepts all the 4 possible values or just 3 of them nor you know what the value 0b00 does because there's no documentation about it in the SVD. The svd2rust will have to handle this and either generate the lowest common denominator API for all the SVD files you feed to it or be smart and generate a better API if the SVD file provides more information like EnumeratedValues.

@jdub
Copy link

jdub commented Oct 4, 2016

Out of interest, how does SVD compare/contrast to DeviceTree?

@cwoodall
Copy link
Author

cwoodall commented Oct 4, 2016

For reference device tree and svd. I haven't compared them yet, but both seemed like good resources.

@posborne
Copy link
Member

posborne commented Oct 4, 2016

SVD is a more pure description of a particular processor whereas Device Tree typically contains more configuration that is specific to a given design. I would never create an SVD to describe my board (using a particular SoC) but this is exactly what I do frequently for board bringup with embedded Linux on various SoCs.

@japaric
Copy link
Member

japaric commented Oct 5, 2016

I'll post a link to the stuff it outputs later today.

This is what I'm automatically generating: docs and code. Pretty simple but enough for my current needs. Ah, and this is the source SVD.

@jdub
Copy link

jdub commented Oct 5, 2016

@posborne Thanks!

@brandonedens
Copy link

Hi folks. I built a SVD to Rust source code generator as CLI or Rust macro. Its called svd-mmap and is available at:
https://github.com/brandonedens/svd-mmap
The resulting output is very similar to what Zinc ioreg generates and its using the quasi and aster crates which hopefully protects it some from upstream changes.

It needs a little more work; a README and possible alternative backend to Zinc's VolatileCell that I've locally modified to work xargo built cores. I'll also post some of my example usage of the software in short order.

@japaric
Copy link
Member

japaric commented Oct 8, 2016

Awesome, @brandonedens!

For those that want to try out svd-mmap as a CLI tool, you'll first have to switch to nightly-2016-09-30 because aster is not compiling with today's (and yesterday's) nightly. Then you'll also have to set LD_LIBRARY_PATH so they binary can find some dynamic libraries:

$ cd svd-mmap
$ rustup override nightly-2016-09-30
$ cargo build
$ LD_LIBRARY_PATH=$(pwd)/target/debug:$(rustc --print sysroot)/lib target/debug/svd-mmap $DEVICE.svd > $DEVICE.rs

@japaric
Copy link
Member

japaric commented Oct 9, 2016

I've published my generator as well: svd2rust! Which I've just started using in f3 (cf. japaric/f3#22). It's main differences with ioregs are:

  • it doesn't update the register on "drop" (which can be "forgotten" (mem::forget)), instead it uses explici, unforgettable closures (in the read-modify-write case).
  • Instead of a single VolatileCell wrapper for volatile load/stores it uses the volatile-register crate which provides three "volatile" wrappers: RO, WO and RW for read-only, write-only and read-write access.
  • svd2rust also doesn't let you modify (write to) read-write registers via a &- pointer like ioregs does because that can lead to data races in multi "threaded" code (interrupts). As data races are unsafe by definition; in svd2rust, those operations have to go through a &mut - pointer which forces you to use static mut for shared state access which is unsafe (as it should be).
  • svd2rust doesn't generate any statics or symbols that can't be opted out. It just generates struct definitions and it's up to the user to decide how to expose "instances" of those.

@brandonedens
Copy link

brandonedens commented Oct 9, 2016

Neat. I'll poke through svd2rust as soon as possible and investigate switching to volatile-register. I'm also going to look at a possible pull request against Zinc to swap out ioreg for SVD generated hardware interface.

A basic README.md is now present in the svd-mmap repo.

I noticed the aster breakage as well. Hopefully aster / quasi fix soon; they tend to be quick (otherwise I'll maybe issue the pull request Monday or so). svd-mmap is set to use aster / quasi version "*" so the fixes should immediately percolate.

I'll also add a .ld emitter as a CLI argument to svd-mmap.

@japaric
Copy link
Member

japaric commented Oct 9, 2016

I'm also going to look at a possible pull request against Zinc to swap out ioreg for SVD generated hardware interface.

Yes, please. I think it's a great idea to breathe some life back into Zinc. If they check in generated register maps instead of re-rebuilding them at build time using ioregs!, then they should have way less breakage.

I noticed the aster breakage as well. Hopefully aster / quasi fix soon

Someone already sent a PR fixing aster but it hasn't been merged yet.


I think it's healthy to have competition / choices in the svd -> rust generator space. It's relatively easy to build one today using svd + quasi & aster so we'll probably see more popping out as some people have different ideas about what the register manipulation API should look like. But I think it's also important to sit down and discuss that register manipulation API at a high level (e.g. what operations are unsafe, how should register maps be exposed to users, etc.). I'll open a thread about that later; first, I need to collect my thoughts on the matter.

@dtolnay
Copy link

dtolnay commented Oct 18, 2016

Aster 0.30.0 is out with a fix for the most recent nightlies. Sorry about the delay - this was the most complicated merge conflict we have had in a long time because there were significant changes to macro expansion in libsyntax.

@japaric
Copy link
Member

japaric commented Oct 18, 2016

@dtolnay no worries! That build error prompted us to look into syn+quote and we have already ported svd2rust to it 😄. BTW, syn and quote are really nice to use, thanks for creating them ❤️.

@jcsoo
Copy link

jcsoo commented Jan 31, 2017

Any thoughts on strategies for generating shared register access layers within a chip family, particularly in a way that can be used as a base for a common HAL? I'm thinking a vendor-specific HAL similar to the libraries that most provide in C as part of their SDKs, not higher-level cross-vendor traits such as Serial I/O.

I've spent a couple of weeks working on SVD tooling (including testing some non-XML representations that may be easier to work with by hand and to extend) but I'm having a tough time picturing a way to do this without either (a) building massive register access modules for each individual device and selecting between them at a high level with #cfg switches, or (b) building a single register access module with massive amounts of #cfg switches down at individual registers. I'm finding that compile time starts becoming an issue when you start doing codegen for all of the peripherals for a device, and I imagine it would become much worse if you have 4-6 different sets in a single crate.

Or are we simply going to have to live with building and maintaining independent crates for each class of device, including startup code, clock management, etc?

@japaric
Copy link
Member

japaric commented May 18, 2017

So svd2rust has been out there for a while and it has more users and developers than just me 😄. Also, @whitequark wrote the dslite2svd tool which you can use to convert TI's version of SVD to standard SVD and then feed to svd2rust.

Can we consider this issue done? Further discussion about the API that svd2rust generates should be discussed on its issue tracker.

@jcsoo SVD files usually describe whole device families (or at least the STM32 ones do). For example, the stm32f30x.svd works for the stm32f300 devices, the stm32f301 devices, etc. Do you mean abstracting over e.g. the stm32f1x and the stm32f2x series? Not all the registers of those devices match so I don't think you can generate a common register level API that works for both series. You could abstract a little higher and hide away the registers but keep the functionality very close to what the registers do.

@whitequark
Copy link

@japaric btw,

Zinc, in the way it is now, is dead, and that's a horse I stopped beating

from https://users.rust-lang.org/t/zinc-mini-post-mortem/7079

@japaric
Copy link
Member

japaric commented May 18, 2017

@whitequark I know. I saw that post back when it was first posted, but there was still some activity in the repo when I made this comment. Today, Zinc has seen no activity for like 5+ months, so I think it's time to let it rest in peace.

@japaric
Copy link
Member

japaric commented May 25, 2017

I'm going to close this since svd2rust already exists. If you would like to raise an issue against that implementation please open a ticker in the issue tracker.

On that note, I would like to request your help to improve svd2rust! I have created a cmsis-svd milestone that tracks progress towards making svd2rust work with all the SVD files in the cmsis-svd database. I think those issues should be prioritized since some people are hitting bugs in svd2rust when using it with files that are not part of the current svd2rust test suite (which is rather small atm).

@japaric japaric closed this as completed May 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants