Generate Rust register maps (structs) from SVD files

This project is developed and maintained by the Documentation

svd2rust

Generate Rust register maps (structs) from SVD files

This project is developed and maintained by the Tools team.

Documentation

API

Minimum Supported Rust Version (MSRV)

The generated code is guaranteed to compile on stable Rust 1.40.0 and up.

If you encounter compilation errors on any stable version newer than 1.40.0, please open an issue.

Testing Locally

svd2rust-regress is a helper program for regression testing changes against svd2rust. This tool can be used locally to check modifications of svd2rust locally before submitting a PR.

Check out the svd2rust-regress README for information on how to use this tool.

License

Licensed under either of

  • Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
  • MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Code of Conduct

Contribution to this crate is organized under the terms of the Rust Code of Conduct, the maintainer of this crate, the Tools team, promises to intervene to uphold that code of conduct.

Issues

Collection of the latest Issues

rcls

rcls

2

svd2rust accounts for alignment padding incorrectly.

E.g., in the attached example, struct ALIGNME has 6 bytes of data and 2 bytes of alignment padding, a total of 8 bytes. The following field next32 at offset 8 therefore needs no explicit padding added before it.

But svd2rust has not counted the alignment padding and ends up inserting 2 bytes of incorrect padding. After further alignment, this appears to leave next32 at offset 12 instead of the correct 8.

.svd and part of the output .rs inline below. Github wouldn't let me add them as attachments.....

#[repr(C)]
pub struct RegisterBlock {
    #[doc = "0x00 - u32+u16"]
    pub alignme: ALIGNME,
    _reserved1: [u8; 2usize],
    #[doc = "0x08 - Following 32 bit field"]
    pub next32: crate::Reg<next32::NEXT32_SPEC>,
}
#[repr(C)]
pub struct ALIGNME {
    #[doc = "0x00 - Thirty two and serious"]
    pub reg32: crate::Reg<self::alignme::reg32::REG32_SPEC>,
    #[doc = "0x04 - 16 bit reigster"]
    pub reg16: crate::Reg<self::alignme::reg16::REG16_SPEC>,
}

and the SVD

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator version: 1.6.0.225 -->
<device schemaVersion="1.3" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd">
  <vendor>Testing 123</vendor>
  <vendorID>NotReal</vendorID>
  <name>dummy</name>
  <series>dumb</series>
  <version>1.0</version>
  <description>dummy</description>
  <licenseText>Made up example license.</licenseText>
  <cpu>
    <name>CM4</name>
    <revision>r0p1</revision>
    <endian>little</endian>
    <mpuPresent>true</mpuPresent>
    <fpuPresent>true</fpuPresent>
    <vtorPresent>1</vtorPresent>
    <nvicPrioBits>3</nvicPrioBits>
    <vendorSystickConfig>0</vendorSystickConfig>
  </cpu>
  <addressUnitBits>8</addressUnitBits>
  <width>32</width>
  <resetValue>0x00000000</resetValue>
  <resetMask>0xFFFFFFFF</resetMask>
  <peripherals>
    <peripheral>
      <name>PERI</name>
      <description>A peripheral</description>
      <baseAddress>0x40000000</baseAddress>
      <addressBlock>
        <offset>0</offset>
        <size>4096</size>
        <usage>registers</usage>
      </addressBlock>
      <registers>
        <cluster>
          <name>alignme</name>
          <description>u32+u16</description>
          <addressOffset>0x00000000</addressOffset>
          <register>
            <name>REG32</name>
            <description>Thirty two and serious</description>
            <addressOffset>0x0</addressOffset>
            <size>32</size>
            <access>read-write</access>
            <resetValue>0x0</resetValue>
            <resetMask>0x0</resetMask>
            <fields>
              <field>
                <name>F32</name>
                <description>A 32 bit field.</description>
                <bitRange>[31:0]</bitRange>
                <access>read-write</access>
              </field>
            </fields>
          </register>
          <register>
            <name>REG16</name>
            <description>16 bit reigster</description>
            <addressOffset>0x4</addressOffset>
            <size>16</size>
            <access>read-write</access>
            <resetValue>0x0</resetValue>
            <resetMask>0x0</resetMask>
            <fields>
              <field>
                <name>F16</name>
                <description>A 16 bit field.  Sweet 16.</description>
                <bitRange>[15:0]</bitRange>
                <access>read-write</access>
              </field>
            </fields>
          </register>
        </cluster>
        <register>
          <name>NEXT32</name>
          <description>Following 32 bit field</description>
          <addressOffset>8</addressOffset>
          <size>32</size>
          <access>read-write</access>
          <resetValue>0</resetValue>
          <resetMask>0</resetMask>
          <fields>
            <field>
              <name>F32</name>
              <description>32 bits again</description>
              <bitRange>[31:0]</bitRange>
              <access>read-write</access>
            </field>
          </fields>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>


hegza

hegza

1

Preconditions:

We have an experimental SVD generator that produces presumably incorrect CMSIS-SVD XML: file.svd.

What I did

Compiled svd2rust from master branch in debug mode, then executed:

RUST_LOG=trace ./svd2rust -i file.svd --log=trace --target=riscv

with all combinations of RUST_LOG & --log for good measure. Additionally, same results reproduce with svd2rust from cargo install svd2rust.

Output

[ERROR svd2rust] expected ,

Expected output

More context. Like, possibly a line number or more debug/trace. Discussion on Rust Embedded at Matrix yields that likely source is svd-parser itself or the error interface to it. Example output:

[TRACE svd2rust] parsing line 56 [ERROR svd2rust] expected ',' on line 56

daym

daym

3

It would be nice to be able to use svd2rust for SVDs that describe indirect accesses via a data port register (for example the infamous pci index and pci data register, MSRs, etc).

I'll try to extend svd2rust to do that, but I wanted to ask first

(1) Whether there will be unforseen hurdles

(2) Whether there is interest in that

For these kind of indirect accesses, svd2rust would not be able to use RegisterBlocks that are represented as real C structs directly accessed via MMIO. Reason is because the indirect access only allows you to read/write one word at a time.

daym

daym

0

It would be nice if svd2rust also supported peripheral arrays of SVD 1.3.

See https://arm-software.github.io/CMSIS_5/SVD/html/elem_peripherals.html#elem_peripheral .

Starting version 1.3 of the SVD specification, arrays of peripherals can be specified. The single peripheral description gets duplicated automatically into an array. The number of array elements is specified by the <dim> element. To define arrays, the needs the format myPeripheral[%s]. The tag <dimIncrement> specifies the address offset between two peripherals. To create copies of a peripheral using different names, you must use the derivedFrom attribute.

thejpster

thejpster

5

I built a PAC using svd2rust 0.17 and it didn't compile (https://github.com/rp-rs/rp2040-pac).

I had to:

  • Remove a bunch of lints that rustc 1.49 didn't like
  • Replace bare_metal::Nr with cortex_m::interrupt::Nr

I also really struggled with the docs, which in the SVD are full of \n character pairs. It would really help if svd2rust could process out these character pairs and split the docs into multiple lines.

burrbull

burrbull

0

Now if we have 2 or more registers FOO and FOO1, we replace appropriate space in RegisterBlock with empty bytes and create functions foo() and foo1(). I suggest not to do it if all registers except 1 marked with alternateRegister. Just create foo1() in previous example.

This let us add registers alternate to existing without breaking changes. cc @therealprof

couchand

couchand

29

The methods Reg::write, Reg::write_with_zero, and Reg::modify all expect a closure that accepts a mutable reference and then must return the same mutable reference. This would seem to violate the usual API design guidance.

My reading of the code & examples is that the rationale is to make one-liners easy, for instance, the example in the docs on Reg::write https://github.com/rust-embedded/svd2rust/blob/29129c0e4e261bf4c38057f7585e7ddfc05fafd0/src/generate/generic.rs#L95-L99

However, the ramification of this design on real-world code is not as nice. See, for instance, in stm32-rs or avr-hal.

The last statement in each register update must omit the trailing semicolon, making it inconsistent with the rest of the statements in the closure, causing issues with, for instance, refactoring of the method.

If the return value were removed, the real-world examples would see a maintainability improvement, and the example on Reg::write would hardly need to change at all, either:

 periph.reg.write(|w| {
     w.field1().bits(newfield1bits) 
         .field2().set_bit() 
         .field3().variant(VARIANT);
 });

or

 periph.reg.write(|w| {
     w.field1().bits(newfield1bits);
     w.field2().set_bit();
     w.field3().variant(VARIANT);
 });

My preference is for the latter, and as an aside, also dropping the return value of the field modifiers (though since that's simple enough to ignore I'm not as concerned about it).


There's also a significant improvement in terms of the user's mental model (which goes to the more general API design guidelines). As it stands, there's potential for confusion about how exactly these mutators do their job:

  • they take a mutable reference, so you'd think that mutating that is what matters
  • but they require you to return a mutable reference, so is that what matters?

The unfortunately reality is that it's the latter, and the input parameter just happens to be the way you get the relevant struct. This seems quite awkward.

The potential for misuse of the current API is relatively low, since it's not simple to conjure a reference. But that can't be enforced by the compiler in the way that the same API without the return value does let the compiler enforce correct usage. And since the generated code is frequently integrated with hand-written code in a register access crate, pub(crate) is hardly any protection.


The biggest concern that I can see with this proposal is a purely practical one: how would it actually be implemented? It would amount to a big breaking change across all users of this crate. That sounds scary (but not impossible!).

I'm not sure what the policy of this crate is regarding breaking changes in the generated code. Certainly it would need to be approached with care and great tact, and lots of warnings/advice/autoconvert-tooling/something would need to be provided. But the API without the return value seems so much stronger to me that I thought it was at least worth bringing up.


I originally suggested this in a bit of a throwaway comment in #463, but since running into it again with #475/#477, I thought I'd log it as a separate issue so there's at least a place to discuss it.

If breaking changes were on the table, I'd suggest changing the API of Reg::write. Requiring the closure to return the input doesn't seem like the right thing to do. It sows doubt about how exactly the changes propagate, and it makes one-liners slightly shorter at the expense of making multi-line closures an extra line.

coherent-lyn

coherent-lyn

1

RA6M2.zip

I am trying to process the RA6M2.svd file.

This requires changes to the svd-parser that I have already reported and to register.rs file, which I have attached, to filter out enumerated values without a value element.

When I run svd2rust with these modification I get a [ERROR svd2rust] unexpected token

ryan-summers

ryan-summers

2

This issue is being moved after originally posted in https://github.com/rust-embedded/wg/issues/459

Because of the implementation of svd2rust (and some issues with trait implementations in the debug information outlined here), register blocks cannot be printed in a GDB interface. Attempts to do so only result in an output similar to the following:

(gdb) print clocks.rb
$1 = stm32h7x::stm32h743v::RCC {_marker: core::marker::PhantomData<*const ()>}

Similarly, if the register block is correctly type-cast in GDB, the output is equally unhelpful:

(gdb) print *(0x5802_4400 as &stm32h7::stm32h743v::rcc::RegisterBlock)                                                                                                                                     $5 = stm32h7::stm32h743v::rcc::RegisterBlock {cr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_CR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 251687333}}, _marker: core::marker::PhantomData<stm32h7::stm32h743v::rcc::_CR>}, _reserved_1_icscr: [242, 6, 0,                                                                                                           
    64], crrcr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_CRRCR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 272}}, _marker: core::marker::PhantomData<stm3
2h7::stm32h743v::rcc::_CRRCR>}, csicfgr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_CSICFGR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 536871018}}, _marke
r: core::marker::PhantomData<stm32h7::stm32h743v::rcc::_CSICFGR>}, cfgr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_CFGR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32
> {value: 27}}, _marker: core::marker::PhantomData<stm32h7::stm32h743v::rcc::_CFGR>}, _reserved5: [0, 0, 0, 
    0], d1cfgr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_D1CFGR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 72}}, _marker: core::marker::PhantomData<stm3
2h7::stm32h743v::rcc::_D1CFGR>}, d2cfgr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_D2CFGR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 1088}}, _marker: cor
e::marker::PhantomData<stm32h7::stm32h743v::rcc::_D2CFGR>}, d3cfgr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_D3CFGR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {
value: 64}}, _marker: core::marker::PhantomData<stm32h7::stm32h743v::rcc::_D3CFGR>}, _reserved8: [0, 0, 0, 
    0], pllckselr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_PLLCKSELR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 33686016}}, _marker: core::marker::Phan
tomData<stm32h7::stm32h743v::rcc::_PLLCKSELR>}, pllcfgr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_PLLCFGR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 312
60706}}, _marker: core::marker::PhantomData<stm32h7::stm32h743v::rcc::_PLLCFGR>}, pll1divr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_PLL1DIVR> {register: vcell::VolatileCell<u32> {value: cor
e::cell::UnsafeCell<u32> {value: 16842951}}, _marker: core::marker::PhantomData<stm32h7::stm32h743v::rcc::_PLL1DIVR>}, pll1fracr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_PLL1FRACR> {registe
r: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 0}}, _marker: core::marker::PhantomData<stm32h7::stm32h743v::rcc::_PLL1FRACR>}, pll2divr: stm32h7::generic::Reg<u32, stm32h7::stm32
h743v::rcc::_PLL2DIVR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 16975559}}, _marker: core::marker::PhantomData<stm32h7::stm32h743v::rcc::_PLL2DIVR>}, pll2fracr: stm
32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_PLL2FRACR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 0}}, _marker: core::marker::PhantomData<stm32h7::stm32h743v::
rcc::_PLL2FRACR>}, pll3divr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_PLL3DIVR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 16843392}}, _marker: core::mar
ker::PhantomData<stm32h7::stm32h743v::rcc::_PLL3DIVR>}, pll3fracr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_PLL3FRACR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32>
 {value: 0}}, _marker: core::marker::PhantomData<stm32h7::stm32h743v::rcc::_PLL3FRACR>}, _reserved16: [0, 0, 0, 
    0], d1ccipr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_D1CCIPR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 0}}, _marker: core::marker::PhantomData<stm
32h7::stm32h743v::rcc::_D1CCIPR>}, d2ccip1r: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_D2CCIP1R> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 0}}, _marker: 
core::marker::PhantomData<stm32h7::stm32h743v::rcc::_D2CCIP1R>}, d2ccip2r: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_D2CCIP2R> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCe
ll<u32> {value: 0}}, _marker: core::marker::PhantomData<stm32h7::stm32h743v::rcc::_D2CCIP2R>}, d3ccipr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_D3CCIPR> {register: vcell::VolatileCell<u32> 
{value: core::cell::UnsafeCell<u32> {value: 0}}, _marker: core::marker::PhantomData<stm32h7::stm32h743v::rcc::_D3CCIPR>}, _reserved20: [0, 0, 0, 
    0], cier: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_CIER> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 0}}, _marker: core::marker::PhantomData<stm32h7::
stm32h743v::rcc::_CIER>}, cifr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_CIFR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 0}}, _marker: core::marker::Pha
ntomData<stm32h7::stm32h743v::rcc::_CIFR>}, cicr: stm32h7::generic::Reg<u32, stm32h7::stm32h743v::rcc::_CICR> {register: vcell::VolatileCell<u32> {value: core::cell::UnsafeCell<u32> {value: 0}}, _marker:
 core::marker::PhantomData<stm32h7::stm32h743v::rcc::_CICR>}, _reserved23: [0, 0, 0, 

<snipped>

The simplest way to visualize the registers is to just examine the raw memory, which is not a great alternative:

(gdb) x/10wx 0x5802_4400
0x58024400:     0x0f0071a5      0x400006f2      0x00000110      0x2000006a
0x58024410:     0x0000001b      0x00000000      0x00000048      0x00000440
0x58024420:     0x00000040      0x00000000

Is there a way that we can provide an interface co cleanly print out the bits (or just bytes) of the registers along with their names in GDB?

In https://github.com/rust-embedded/wg/issues/459, https://github.com/bnahill/PyCortexMDebug was pointed out as an option, but we would ideally not require an external tool and the chip SVD (which may or may not have bugs that have been patched by the PAC maintainer) to visualize the registers.

cr1901

cr1901

0

The CMSIS SVD Specification allows WriteConstraint fields to be applied to a Register type, and not just its fields:

  <xs:complexType name="registerType">
    <xs:sequence>
...
     <!-- writeConstraint specifies the subset of allowed write values -->
      <xs:element name="writeConstraint" type="writeConstraintType" minOccurs="0"/>
...
    </xs:sequence>
    <xs:attribute name="derivedFrom" type="dimableIdentifierType" use="optional"/>
  </xs:complexType>

Right now, svd2rust has no provisions for providing a safe bits() function which accesses the entire register (and not just a field), because the generics bits() function for writing a register is- correctly marked as unsafe!

To avoid having application writers have to place unsafe code in their application, I propose some standardized function to safely access all the bits of a register, as a unit, when svd2rust can prove that no invalid values can be written into a register.

svd2rust could either prove this info by reading the WriteConstraint field of a Register type, or keeping a running tally of which bits are stated to be valid in children (fieldType) of the fieldsType sequence.

This is useful for RMW GPIO registers (direction, value, etc) and setting timer values for countdown all at once, without having to chain proxies together for each individual bit.

jeandudey

jeandudey

4

Compiling a complete crate generated using svd2rust results in a big compilation time (at least for my machine), mainly because of all the code that needs to be compiled. Adding a feature gate to each peripherals results in better compilation times.

For example one would use a Peripheral Access Crate like this by specifying the features on demand:

[dependencies.mymcu-pac]
version = "0.1"
features = ["uart", "gpio"]

A flag to svd2rust could be added to generate code with features on peripherals like --use-features (bad name, but gets the point) so I doesn't break existing code and is enabled explicitly.

burrbull

burrbull

1

What are you think about integrate form functionality in svd2rust (optional)?

When this option is enabled we can do not merge mod TokenStreams in one (and then split with form) and write them in different files directly. I think this can give us significant speed-up in this case.

@therealprof

xobs

xobs

4

The implementation for interrupts generates a macro interrupt!() that takes the name of an interrupt, a closure, and optionally a struct of locals.

There are a few things that are unclear from the generated documentation:

  1. Does the name of the ISR really matter? This seems like an ARM-ism.
  2. How does this handler actually get called? The riscv-rt core calls a function called trap_handler, which gets set by default to default_trap_handler() which is a no-op. Should the crate generated by svd2rust generate the trap_handler() to call the appropriate ISR, or should the -rt crate do so?
hugwijst

hugwijst

enhancement
10

With the stabilization of Cargo.lock file publishing in rust-lang/cargo#7026, lets restart the discussion from #148 about adding Cargo.lock to the repo.

My two cents: not having Cargo.lock checked in is a huge road block to using svd2rust in production.

Backgroud: we are running svd2rust on every CI build. By not locking svd2rust, there is a chance that the final artifact is not reproducible if a package dependent on by svd2rust fails to adhere to semver. More realistically, such an update breaks the build, which is completely unacceptable.

maximeborges

maximeborges

6

I was wondering if it was possible to make a single crate from multiple SVDs. Basically, merging all the common registers and peripherals, and compiling only what is needed.

After playing a bit with the code and SVDs from Silabs (EFM32), I think it would be quite easy to build a single crate using conditional compilation using cfg features that compile only what is needed.

Since this goal seemed a bit easy, I was thinking why projects like https://github.com/stm32-rs/stm32-rs were making crates with a way more complicated structure (besides fixing errors from the manufacturer, which could also be merged in svd2rust IMO).

Is there any reasons why this wasn't done ? If it seems to be a good idea, I can try to implement that in the next few days.

heshananupama

heshananupama

question
8

When I use the svd2rust version 0.12.1 and build the peripheral access crate for stm32f301 the size of the rlib file is around 35mb. When I use the objdump to disassemble all the rlib file, it shows me all the functions and all the bit sequences in a proper manner.

However when I repeat the same process with version 0.16.1 the rlib file will have around 17mb and when I try to disassemble using objdump it only shows very few functions(less than 1% from the previous). I don't know what is the issue with the new version and hoping to use the older version as it works correctly. However, I would like to know the exact reason behind for this.

I know it can use the library as before as I checked it with an application code. There's no question regarding it. But I am just confused why the rlib are of different sizes and the fact that it has only few functions when disassembled.

xobs

xobs

0

It looks like the documentation instructs users to create something called a "Virtual manifest" by omitting the [package] directive at https://docs.rs/svd2rust/0.16.1/svd2rust/#target--cortex-m-1

[dependencies]
bare-metal = "0.1.0"
msp430 = "0.1.0"
vcell = "0.1.0"

[dependencies.msp430-rt]
optional = true
version = "0.1.0"

[features]
rt = ["msp430-rt"]

However, when using rustc 1.37.0, this Cargo.toml file does not work:

> cargo check
error: failed to parse manifest at `D:\Code\xoulon-mcu\sw\xoulon-hal\Cargo.toml`

Caused by:
  virtual manifests do not specify [dependencies]
>
axos88

axos88

6

The SVD file below generates two definitions of the struct PIO0_. This seems like a tricky edge case where the repetition is 0-3 + 6-32 with the same type, and exceptions for repetitions 4 and 5. The types for 0-3 and 6-32 are the same, so we should be able to reuse that?

Also I'm baffled by the generated code, why the first definition generates an array, and others an entry for each repetition? Specifically why the code generated by the first and fourth register definition differs, since the definition seems to be exactly the same except offsets and repetition numbers.

I think the correct behaviour would be to generate different entries for each element.

    pub pio0__: [PIO0__; 4],   // Generated by the first register definition with repetition
    #[doc = "0x10 - I/O configuration for open-drain pin PIO0_4"]
    pub pio0_4: PIO0_4,    // Generated by the second register definition without repetition
    #[doc = "0x14 - I/O configuration for open-drain pin PIO0_5"]
    pub pio0_5: PIO0_5,    // Generated by the second register definition without repetition
    #[doc = "0x18 - I/O configuration for port PIO0"]
    pub pio0_6: PIO0_, // Generated by the fourth register definition with repetition
    #[doc = "0x1c - I/O configuration for port PIO0"]
    pub pio0_7: PIO0_,  // Generated by the fourth register definition with repetition
    #[doc = "0x20 - I/O configuration for port PIO0"]
    pub pio0_8: PIO0_,  // Generated by the fourth register definition with repetition
    #[doc = "0x24 - I/O configuration for port PIO0"]
    pub pio0_9: PIO0_,  // Generated by the fourth register definition with repetition

<peripheral>
	<name>IOCON</name>
	<description>I/O control (IOCON) </description>
	<groupName>IOCON</groupName>
	<baseAddress>0x40044000</baseAddress>
	<addressBlock>
	<offset>0x0</offset>
	<size>0xFFF</size>
	<usage>registers</usage>
	</addressBlock>
	<registers>
		<register>
			<dim>4</dim>
			<dimIncrement>0x4</dimIncrement>
			<dimIndex>0-3</dimIndex>
			<name>PIO0_%s</name>
			<description>I/O configuration for  port PIO0</description>
			<addressOffset>0x000</addressOffset>
			<access>read-write</access>
			<resetValue>0x00000090</resetValue>
			<resetMask>0xFFFFFFFF</resetMask>
			<fields>
				<field>
					<name>FUNC</name>
					<description>Selects pin function.</description>
					<bitRange>[2:0]</bitRange>

				</field>
				<field>
					<name>MODE</name>
					<description>Selects function mode (on-chip pull-up/pull-down resistor control).</description>
					<bitRange>[4:3]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>INACTIVE_NO_PULL_DO</name>
							<description>Inactive (no pull-down/pull-up resistor enabled).</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>PULL_DOWN_RESISTOR_E</name>
							<description>Pull-down resistor enabled.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>PULL_UP_RESISTOR_ENA</name>
							<description>Pull-up resistor enabled.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>REPEATER_MODE</name>
							<description>Repeater mode.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>HYS</name>
					<description>Hysteresis.</description>
					<bitRange>[5:5]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>DISABLE</name>
							<description>Disable.</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>ENABLE</name>
							<description>Enable.</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>INV</name>
					<description>Invert input</description>
					<bitRange>[6:6]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>INPUT_NOT_INVERTED</name>
							<description>Input not inverted (HIGH on pin reads as 1; LOW on pin reads as 0).</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>INPUT_INVERTED_HIGH</name>
							<description>Input inverted (HIGH on pin reads as 0, LOW on pin reads as 1).</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[9:7]</bitRange>

				</field>
				<field>
					<name>OD</name>
					<description>Open-drain mode.</description>
					<bitRange>[10:10]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>DISABLE</name>
							<description>Disable.</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>ENABLE</name>
							<description>Enable. Open-drain mode enabled.  This is not a true open-drain mode.</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>S_MODE</name>
					<description>Digital filter sample mode.</description>
					<bitRange>[12:11]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>BYPASS_INPUT_FILTER</name>
							<description>Bypass input filter.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>1_CLOCK_CYCLE</name>
							<description>1 clock cycle. Input pulses shorter than one filter clock are rejected.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>2_CLOCK_CYCLES</name>
							<description>2 clock cycles. Input pulses shorter than two filter clocks are rejected.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>3_CLOCK_CYCLES</name>
							<description>3 clock cycles. Input pulses shorter than three filter clocks are rejected.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>CLKDIV</name>
					<description>Select peripheral clock divider for input filter sampling clock IOCONCLKDIV. Value 0x7 is reserved.</description>
					<bitRange>[15:13]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>IOCONCLKDIV0</name>
							<description>IOCONCLKDIV0. Use IOCON clock divider 0.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV1</name>
							<description>IOCONCLKDIV1. Use IOCON clock divider 1.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV2</name>
							<description>IOCONCLKDIV2 Use IOCON clock divider 2.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV3</name>
							<description>IOCONCLKDIV3. Use IOCON clock divider 3.</description>
							<value>0x3</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV4</name>
							<description>IOCONCLKDIV4. Use IOCON clock divider 4.</description>
							<value>0x4</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV5</name>
							<description>IOCONCLKDIV5. Use IOCON clock divider 5.</description>
							<value>0x5</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV6</name>
							<description>IOCONCLKDIV6. Use IOCON clock divider 6.</description>
							<value>0x6</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[31:16]</bitRange>

				</field>
			</fields>
		</register>
		<register>
			<name>PIO0_4</name>
			<description>I/O configuration for open-drain pin PIO0_4</description>
			<addressOffset>0x010</addressOffset>
			<access>read-write</access>
			<resetValue>0x00000080</resetValue>
			<resetMask>0xFFFFFFFF</resetMask>
			<fields>
				<field>
					<name>FUNC</name>
					<description>Selects pin function. </description>
					<bitRange>[2:0]</bitRange>

				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[7:3]</bitRange>

				</field>
				<field>
					<name>I2CMODE</name>
					<description>Selects I2C mode (see  Section 7.3.8).  Select Standard mode (I2CMODE = 00, default) or Standard I/O functionality (I2CMODE = 01) if the pin function is GPIO (FUNC = 000).</description>
					<bitRange>[9:8]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>STANDARD_MODE_FAST</name>
							<description>Standard mode/ Fast-mode I2C.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>STANDARD_IO_FUNCTIO</name>
							<description>Standard I/O functionality</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>FAST_MODE_PLUS_I2C</name>
							<description>Fast-mode Plus I2C</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>RESERVED</name>
							<description>Reserved.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[31:10]</bitRange>

				</field>
			</fields>
		</register>
		<register>
			<name>PIO0_5</name>
			<description>I/O configuration for open-drain pin PIO0_5</description>
			<addressOffset>0x014</addressOffset>
			<access>read-write</access>
			<resetValue>0x00000080</resetValue>
			<resetMask>0xFFFFFFFF</resetMask>
			<fields>
				<field>
					<name>FUNC</name>
					<description>Selects pin function. </description>
					<bitRange>[2:0]</bitRange>

				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[7:3]</bitRange>

				</field>
				<field>
					<name>I2CMODE</name>
					<description>Selects I2C mode (see  Section 7.3.8).  Select Standard mode (I2CMODE = 00, default) or Standard I/O functionality (I2CMODE = 01) if the pin function is GPIO (FUNC = 000).</description>
					<bitRange>[9:8]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>STANDARD_MODE_FAST</name>
							<description>Standard mode/ Fast-mode I2C.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>STANDARD_IO_FUNCTIO</name>
							<description>Standard I/O functionality</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>FAST_MODE_PLUS_I2C</name>
							<description>Fast-mode Plus I2C</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>RESERVED</name>
							<description>Reserved.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[31:10]</bitRange>

				</field>
			</fields>
		</register>
		<register>
			<dim>18</dim>
			<dimIncrement>0x4</dimIncrement>
			<dimIndex>6-23</dimIndex>
			<name>PIO0_%s</name>
			<description>I/O configuration for  port PIO0</description>
			<addressOffset>0x018</addressOffset>
			<access>read-write</access>
			<resetValue>0x00000090</resetValue>
			<resetMask>0xFFFFFFFF</resetMask>
			<fields>
				<field>
					<name>FUNC</name>
					<description>Selects pin function.</description>
					<bitRange>[2:0]</bitRange>

				</field>
				<field>
					<name>MODE</name>
					<description>Selects function mode (on-chip pull-up/pull-down resistor control).</description>
					<bitRange>[4:3]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>INACTIVE_NO_PULL_DO</name>
							<description>Inactive (no pull-down/pull-up resistor enabled).</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>PULL_DOWN_RESISTOR_E</name>
							<description>Pull-down resistor enabled.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>PULL_UP_RESISTOR_ENA</name>
							<description>Pull-up resistor enabled.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>REPEATER_MODE</name>
							<description>Repeater mode.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>HYS</name>
					<description>Hysteresis.</description>
					<bitRange>[5:5]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>DISABLE</name>
							<description>Disable.</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>ENABLE</name>
							<description>Enable.</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>INV</name>
					<description>Invert input</description>
					<bitRange>[6:6]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>INPUT_NOT_INVERTED</name>
							<description>Input not inverted (HIGH on pin reads as 1; LOW on pin reads as 0).</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>INPUT_INVERTED_HIGH</name>
							<description>Input inverted (HIGH on pin reads as 0, LOW on pin reads as 1).</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[9:7]</bitRange>

				</field>
				<field>
					<name>OD</name>
					<description>Open-drain mode.</description>
					<bitRange>[10:10]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>DISABLE</name>
							<description>Disable.</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>ENABLE</name>
							<description>Enable. Open-drain mode enabled.  This is not a true open-drain mode.</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>S_MODE</name>
					<description>Digital filter sample mode.</description>
					<bitRange>[12:11]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>BYPASS_INPUT_FILTER</name>
							<description>Bypass input filter.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>1_CLOCK_CYCLE</name>
							<description>1 clock cycle. Input pulses shorter than one filter clock are rejected.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>2_CLOCK_CYCLES</name>
							<description>2 clock cycles. Input pulses shorter than two filter clocks are rejected.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>3_CLOCK_CYCLES</name>
							<description>3 clock cycles. Input pulses shorter than three filter clocks are rejected.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>CLKDIV</name>
					<description>Select peripheral clock divider for input filter sampling clock IOCONCLKDIV. Value 0x7 is reserved.</description>
					<bitRange>[15:13]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>IOCONCLKDIV0</name>
							<description>IOCONCLKDIV0. Use IOCON clock divider 0.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV1</name>
							<description>IOCONCLKDIV1. Use IOCON clock divider 1.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV2</name>
							<description>IOCONCLKDIV2 Use IOCON clock divider 2.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV3</name>
							<description>IOCONCLKDIV3. Use IOCON clock divider 3.</description>
							<value>0x3</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV4</name>
							<description>IOCONCLKDIV4. Use IOCON clock divider 4.</description>
							<value>0x4</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV5</name>
							<description>IOCONCLKDIV5. Use IOCON clock divider 5.</description>
							<value>0x5</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV6</name>
							<description>IOCONCLKDIV6. Use IOCON clock divider 6.</description>
							<value>0x6</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[31:16]</bitRange>

				</field>
			</fields>
		</register>
		<register>
			<dim>32</dim>
			<dimIncrement>0x4</dimIncrement>
			<dimIndex>0-31</dimIndex>
			<name>PIO1_%s</name>
			<description>I/O configuration for port PIO1</description>
			<addressOffset>0x060</addressOffset>
			<access>read-write</access>
			<resetValue>0x00000090</resetValue>
			<resetMask>0xFFFFFFFF</resetMask>
			<fields>
				<field>
					<name>FUNC</name>
					<description>Selects pin function.</description>
					<bitRange>[2:0]</bitRange>

				</field>
				<field>
					<name>MODE</name>
					<description>Selects function mode (on-chip pull-up/pull-down resistor control).</description>
					<bitRange>[4:3]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>INACTIVE_NO_PULL_DO</name>
							<description>Inactive (no pull-down/pull-up resistor enabled).</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>PULL_DOWN_RESISTOR_E</name>
							<description>Pull-down resistor enabled.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>PULL_UP_RESISTOR_ENA</name>
							<description>Pull-up resistor enabled.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>REPEATER_MODE</name>
							<description>Repeater mode.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>HYS</name>
					<description>Hysteresis.</description>
					<bitRange>[5:5]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>DISABLE</name>
							<description>Disable.</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>ENABLE</name>
							<description>Enable.</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>INV</name>
					<description>Invert input</description>
					<bitRange>[6:6]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>INPUT_NOT_INVERTED</name>
							<description>Input not inverted (HIGH on pin reads as 1; LOW on pin reads as 0).</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>INPUT_INVERTED_HIGH</name>
							<description>Input inverted (HIGH on pin reads as 0, LOW on pin reads as 1).</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[9:7]</bitRange>

				</field>
				<field>
					<name>OD</name>
					<description>Open-drain mode.</description>
					<bitRange>[10:10]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>DISABLE</name>
							<description>Disable.</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>ENABLED</name>
							<description>Enabled. Open-drain mode enabled.  This is not a true open-drain mode.</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>S_MODE</name>
					<description>Digital filter sample mode.</description>
					<bitRange>[12:11]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>BYPASS_INPUT_FILTER</name>
							<description>Bypass input filter.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>1_CLOCK_CYCLE</name>
							<description>1 clock cycle. Input pulses shorter than one filter clock are rejected.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>2_CLOCK_CYCLES</name>
							<description>2 clock cycles. Input pulses shorter than two filter clocks are rejected.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>3_CLOCK_CYCLES</name>
							<description>3 clock cycles. Input pulses shorter than three filter clocks are rejected.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>CLKDIV</name>
					<description>Select peripheral clock divider for input filter sampling clock IOCONCLKDIV. Value 0x7 is reserved.</description>
					<bitRange>[15:13]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>IOCONCLKDIV0</name>
							<description>IOCONCLKDIV0. Use IOCON clock divider 0.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV1</name>
							<description>IOCONCLKDIV1. Use IOCON clock divider 1.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV2</name>
							<description>IOCONCLKDIV2 Use IOCON clock divider 2.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV3</name>
							<description>IOCONCLKDIV3. Use IOCON clock divider 3.</description>
							<value>0x3</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV4</name>
							<description>IOCONCLKDIV4. Use IOCON clock divider 4.</description>
							<value>0x4</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV5</name>
							<description>IOCONCLKDIV5. Use IOCON clock divider 5.</description>
							<value>0x5</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV6</name>
							<description>IOCONCLKDIV6. Use IOCON clock divider 6.</description>
							<value>0x6</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[31:16]</bitRange>

				</field>
			</fields>
		</register>
		<register>
			<dim>2</dim>
			<dimIncrement>0x4</dimIncrement>
			<dimIndex>0-1</dimIndex>
			<name>PIO2_%s</name>
			<description>I/O configuration for port PIO2</description>
			<addressOffset>0x0F0</addressOffset>
			<access>read-write</access>
			<resetValue>0x00000090</resetValue>
			<resetMask>0xFFFFFFFF</resetMask>
			<fields>
				<field>
					<name>FUNC</name>
					<description>Selects pin function.</description>
					<bitRange>[2:0]</bitRange>

				</field>
				<field>
					<name>MODE</name>
					<description>Selects function mode (on-chip pull-up/pull-down resistor control).</description>
					<bitRange>[4:3]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>INACTIVE_NO_PULL_DO</name>
							<description>Inactive (no pull-down/pull-up resistor enabled).</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>PULL_DOWN_RESISTOR_E</name>
							<description>Pull-down resistor enabled.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>PULL_UP_RESISTOR_ENA</name>
							<description>Pull-up resistor enabled.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>REPEATER_MODE</name>
							<description>Repeater mode.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>HYS</name>
					<description>Hysteresis.</description>
					<bitRange>[5:5]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>DISABLE</name>
							<description>Disable.</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>ENABLE</name>
							<description>Enable.</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>INV</name>
					<description>Invert input</description>
					<bitRange>[6:6]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>INPUT_NOT_INVERTED</name>
							<description>Input not inverted (HIGH on pin reads as 1; LOW on pin reads as 0).</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>INPUT_INVERTED_HIGH</name>
							<description>Input inverted (HIGH on pin reads as 0, LOW on pin reads as 1).</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[9:7]</bitRange>

				</field>
				<field>
					<name>OD</name>
					<description>Open-drain mode.</description>
					<bitRange>[10:10]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>DISABLE</name>
							<description>Disable.</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>ENABLED</name>
							<description>Enabled. Open-drain mode enabled.  This is not a true open-drain mode.</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>S_MODE</name>
					<description>Digital filter sample mode.</description>
					<bitRange>[12:11]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>BYPASS_INPUT_FILTER</name>
							<description>Bypass input filter.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>1_CLOCK_CYCLE</name>
							<description>1 clock cycle. Input pulses shorter than one filter clock are rejected.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>2_CLOCK_CYCLES</name>
							<description>2 clock cycles. Input pulses shorter than two filter clocks are rejected.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>3_CLOCK_CYCLES</name>
							<description>3 clock cycles. Input pulses shorter than three filter clocks are rejected.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>CLKDIV</name>
					<description>Select peripheral clock divider for input filter sampling clock IOCONCLKDIV. Value 0x7 is reserved.</description>
					<bitRange>[15:13]</bitRange>
					<enumeratedValues>
					<name>ENUM</name>
						<enumeratedValue>
							<name>IOCONCLKDIV0</name>
							<description>IOCONCLKDIV0. Use IOCON clock divider 0.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV1</name>
							<description>IOCONCLKDIV1. Use IOCON clock divider 1.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV2</name>
							<description>IOCONCLKDIV2 Use IOCON clock divider 2.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV3</name>
							<description>IOCONCLKDIV3. Use IOCON clock divider 3.</description>
							<value>0x3</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV4</name>
							<description>IOCONCLKDIV4. Use IOCON clock divider 4.</description>
							<value>0x4</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV5</name>
							<description>IOCONCLKDIV5. Use IOCON clock divider 5.</description>
							<value>0x5</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV6</name>
							<description>IOCONCLKDIV6. Use IOCON clock divider 6.</description>
							<value>0x6</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[31:16]</bitRange>

				</field>
			</fields>
		</register>
		<register>
			<dim>22</dim>
			<dimIncrement>0x4</dimIncrement>
			<dimIndex>2-23</dimIndex>
			<name>PIO2_%s</name>
			<description>I/O configuration for port PIO2</description>
			<addressOffset>0x0FC</addressOffset>
			<access>read-write</access>
			<resetValue>0x00000090</resetValue>
			<resetMask>0xFFFFFFFF</resetMask>
			<fields>
				<field>
					<name>FUNC</name>
					<description>Selects pin function.</description>
					<bitRange>[2:0]</bitRange>

				</field>
				<field>
					<name>MODE</name>
					<description>Selects function mode (on-chip pull-up/pull-down resistor control).</description>
					<bitRange>[4:3]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>INACTIVE_NO_PULL_DO</name>
							<description>Inactive (no pull-down/pull-up resistor enabled).</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>PULL_DOWN_RESISTOR_E</name>
							<description>Pull-down resistor enabled.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>PULL_UP_RESISTOR_ENA</name>
							<description>Pull-up resistor enabled.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>REPEATER_MODE</name>
							<description>Repeater mode.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>HYS</name>
					<description>Hysteresis.</description>
					<bitRange>[5:5]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>DISABLE</name>
							<description>Disable.</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>ENABLE</name>
							<description>Enable.</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>INV</name>
					<description>Invert input</description>
					<bitRange>[6:6]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>INPUT_NOT_INVERTED</name>
							<description>Input not inverted (HIGH on pin reads as 1; LOW on pin reads as 0).</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>INPUT_INVERTED_HIGH</name>
							<description>Input inverted (HIGH on pin reads as 0, LOW on pin reads as 1).</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[9:7]</bitRange>

				</field>
				<field>
					<name>OD</name>
					<description>Open-drain mode.</description>
					<bitRange>[10:10]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>DISABLE</name>
							<description>Disable.</description>
							<value>0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>ENABLED</name>
							<description>Enabled. Open-drain mode enabled.  This is not a true open-drain mode.</description>
							<value>1</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>S_MODE</name>
					<description>Digital filter sample mode.</description>
					<bitRange>[12:11]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>BYPASS_INPUT_FILTER</name>
							<description>Bypass input filter.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>1_CLOCK_CYCLE</name>
							<description>1 clock cycle. Input pulses shorter than one filter clock are rejected.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>2_CLOCK_CYCLES</name>
							<description>2 clock cycles. Input pulses shorter than two filter clocks are rejected.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>3_CLOCK_CYCLES</name>
							<description>3 clock cycles. Input pulses shorter than three filter clocks are rejected.</description>
							<value>0x3</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>CLKDIV</name>
					<description>Select peripheral clock divider for input filter sampling clock IOCONCLKDIV. Value 0x7 is reserved.</description>
					<bitRange>[15:13]</bitRange>
					<enumeratedValues>
						<name>ENUM</name>
						<enumeratedValue>
							<name>IOCONCLKDIV0</name>
							<description>IOCONCLKDIV0. Use IOCON clock divider 0.</description>
							<value>0x0</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV1</name>
							<description>IOCONCLKDIV1. Use IOCON clock divider 1.</description>
							<value>0x1</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV2</name>
							<description>IOCONCLKDIV2 Use IOCON clock divider 2.</description>
							<value>0x2</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV3</name>
							<description>IOCONCLKDIV3. Use IOCON clock divider 3.</description>
							<value>0x3</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV4</name>
							<description>IOCONCLKDIV4. Use IOCON clock divider 4.</description>
							<value>0x4</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV5</name>
							<description>IOCONCLKDIV5. Use IOCON clock divider 5.</description>
							<value>0x5</value>
						</enumeratedValue>
						<enumeratedValue>
							<name>IOCONCLKDIV6</name>
							<description>IOCONCLKDIV6. Use IOCON clock divider 6.</description>
							<value>0x6</value>
						</enumeratedValue>
					</enumeratedValues>
				</field>
				<field>
					<name>RESERVED</name>
					<description>Reserved.</description>
					<bitRange>[31:16]</bitRange>

				</field>
			</fields>
		</register>
	</registers>

therealprof

therealprof

0

The interface of svd2rust-regress is a bit iffy. On one hand internally every manufacturer and chip name is converted to a "nice" lower-case name with no special characters and this is used everywhere, also for the output of the --list option. On the other hand all options like --manufacturer and --chip expect to receive the unchanged original name.

Also wildcards are not supported which would be really nice to have.

Next problem is that bad tests are only listed or can be executed when the --bad-tests option is supplied however I'd expect to see bad tests in the listing as well (maybe with some additional marker) to know that they exists and also to execute them without having to explicitly specify that it's in the "bad tests" category when I specifically ask for a certain chip.

axos88

axos88

1

The following will generate code, although the value is invalid, since it doesn't fit into the number of bits described:

<field>
	<name>AADEN</name>
	<description>AAD enable.</description>
	<bitRange>[2:2]</bitRange>
	<enumeratedValues>
		<name>ENUM</name>
		<enumeratedValue>
			<name>AUTO_ADDRESS_DETECT_ON</name>
			<description>Auto Address Detect (AAD) is disabled.</description>
			<value>122213</value>
		</enumeratedValue>
		<enumeratedValue>
			<name>AUTO_ADDRESS_DETECT_OFF</name>
			<description>Auto Address Detect (AAD) is enabled.</description>
			<value>49584798</value>
		</enumeratedValue>
	</enumeratedValues>
</field>
Versions

Find the latest versions by id

v0.17.0 - Dec 31, 2019

v0.16.1 - Aug 17, 2019

v0.16.0 - Aug 05, 2019

v0.15.2 - Jul 29, 2019

v0.15.1 - Jul 29, 2019

v0.15.0 - Jul 25, 2019

v0.14.0 - Dec 07, 2018

v0.14.0-alpha.2 - Nov 11, 2018

v0.13.1 - May 16, 2018

v0.13.0 - May 12, 2018

v0.12.1 - May 06, 2018

v0.12.0 - Jan 15, 2018

v0.11.4 - Sep 08, 2017

v0.11.3 - Aug 02, 2017

v0.11.2 - Jul 22, 2017

v0.11.1 - Jul 08, 2017

v0.11.0 - Jul 07, 2017

v0.10.0 - Jun 12, 2017

v0.9.1 - Jun 06, 2017

v0.9.0 - Jun 06, 2017

v0.8.1 - May 30, 2017

v0.8.0 - May 29, 2017

v0.7.2 - May 08, 2017

v0.7.1 - May 07, 2017

v0.7.0 - Apr 25, 2017

v0.6.2 - Apr 23, 2017

v0.6.1 - Apr 15, 2017

v0.6.0 - Apr 12, 2017

v0.5.1 - Apr 01, 2017

v0.5.0 - Mar 28, 2017

Information - Updated Sep 23, 2021

Stars: 401
Forks: 114
Issues: 71

Rust bindings for libinjection

Add libinjection to dependencies of Cargo

Rust bindings for libinjection

Rust bindings for the C++ api of PyTorch

LIghtweight wrapper for pytorch eg libtorch in rust

Rust bindings for the C++ api of PyTorch

Rust leveldb bindings

Almost-complete bindings for leveldb for Rust

Rust leveldb bindings

rust-analyzer is a modular compiler frontend for the Rust language

It also contains some tips &amp; tricks to help you be more productive when using rust-analyzer

rust-analyzer is a modular compiler frontend for the Rust language

Rust-Lightning is a Bitcoin Lightning library written in Rust

lightning, does not handle networking, persistence, or any other I/O

Rust-Lightning is a Bitcoin Lightning library written in Rust

Rust FUSE - Filesystem in Userspace

Rust library crate for easy implementation of Crate documentation

Rust FUSE - Filesystem in Userspace

Rust crate to implement a counterpart to the PBRT book's (3rd edition) C++ code:

Some images of the test scenes are shown below, but you can find more

Rust crate to implement a counterpart to the PBRT book's (3rd edition) C++ code:

Rust Persian Calendar

1** provides functionality for conversion among Persian (Solar Hijri) and Gregorian calendars

Rust Persian Calendar

Rust DjangoHashers

A Rust port of the password primitives used in alternatice implementation: the package library that requires OpenSSL

Rust DjangoHashers

Rust web application

Diesel (ORM) is used to work with the database

Rust web application

cortex-m-systick

This Rust crate initializes the Cortex-M SysTick timer with a specific tick frequency and provides basic functions for time-based calculations

cortex-m-systick

Interfaces, data structures and utilities for dealing with MIDI messages in Rust according to the

If you want to use it in a no_std context, add this instead:

Interfaces, data structures and utilities for dealing with MIDI messages in Rust according to the
Facebook Instagram Twitter GitHub Dribbble
Privacy