Code Monkey home page Code Monkey logo

svd's Introduction

Rust SVD manipulating libraries

This project is developed and maintained by the Tools team.

It consists of:

  • svd-rs. Basic structures and builders, also (de)serializers under serde feature.
  • svd-parser. Library for parsing SVD XML source in Rust Device structure.
  • svd-encoder. Library for creating SVD XML.

Minimum Supported Rust Version (MSRV)

This crate is guaranteed to compile on stable Rust 1.65.0 and up. It might compile with older versions but that may change in any new patch release.

License

Licensed under either of

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.

svd's People

Contributors

ahixon avatar bors[bot] avatar brainstorm avatar brandonedens avatar burrbull avatar disasm avatar duskmoon314 avatar emilgardis avatar gkelly avatar homunkulus avatar japaric avatar kossnikita avatar leseulartichaut avatar lucab avatar lucasbrendel avatar mabezdev avatar marcoieni avatar nickray avatar nsabovic avatar pftbest avatar rahix avatar ryankurte avatar ryochack avatar simonvandel avatar therealprof avatar tiannian avatar tiwalun avatar victorkoenders avatar wez avatar whitequark avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

svd's Issues

0.15 roadmap

Let's write here ideas for next major release:

  • Update to serde-yaml 0.9 (changes enum format)
  • Improve error system. More checks on different validation levels.
  • Support xml comments (not sure how it should look). #228
  • Value enum Val(u64)/Default

dimIndexType support for [A-Z]-[A-Z] pattern

The CMSIS SVD v1.3.9 specification describes the valid patterns for dimIndexType as "[0-9]+\-[0-9]+|[A-Z]-[A-Z]|[_0-9a-zA-Z]+(,\s*[_0-9a-zA-Z]+)+". When parsing R7FA6M5BH.svd from vendor Renesas found here, svd2rust throws the following error: "invalid digit found in string".

Requesting support for the full dimIndexType specification, thanks!

bitOffset parser in BitRange doesn't handle hex numbers

In parsing a SVD from TI for their ARM-based MSP432 line, I got a panic in svd2rust when it came across bitRange elements with hex-valued offsets and lengths, e.g. "0x3".

According to the SVD schema, these are supposed to be scaledNonNegativeInteger values, and those are supposed to be acceptable as decimal, hex, or binary; they apparently also support a unit suffix. Here's the pattern from the schema: "[+]?(0x|0X|#)?[0-9a-fA-F]+[kmgtKMGT]?"

A quick look through the lib.rs source shows a lot of uses of the core from_str implementation for u32; I haven't checked yet how many of them are meant to be scaledNonNegativeInteger values, but I suspect there are more than the bitRange ones that ought to be switched over to parser::u32.

Proposal: struct instead of enum for arrays

Instead of enum:

pub enum Register {
    /// A single register.
    Single(RegisterInfo),
    /// An array of registers.
    Array(RegisterInfo, DimElement),
}

I propose to use struct:

struct Register {
    info: RegisterInfo,
    dim: Option<DimElement>,
}

where dim: None corresponds to Register::Single.
The main goal is to simplify serialize/deserialize.

cc @Emilgardis @therealprof @adamgreig

`svd-parser` doesn't extract `noNamespaceSchemaLocation` correctly

xmlns is used to define a namespace. Thus xmlns:xs defines a namespace called xs, and xs:noNamespaceSchemaLocation is under namespace xs.

Say we have this line in the SVD file:

<device schemaVersion="1.3" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="https://raw.githubusercontent.com/ARM-software/CMSIS_5/develop/CMSIS/Utilities/CMSIS-SVD.xsd">

We have a namespace xs whose URI is http://www.w3.org/2001/XMLSchema-instance. And noNamespaceSchemaLocation under xs is https://raw.githubusercontent.com/ARM-software/CMSIS_5/develop/CMSIS/Utilities/CMSIS-SVD.xsd.

roxmltree parse the above line to this:

Element {
  tag_name: device,
  attributes: [
    Attribute { name: schemaVersion, value: "1.3" },
    Attribute {
      name: {http://www.w3.org/2001/XMLSchema-instance}noNamespaceSchemaLocation,
      value: "https://raw.githubusercontent.com/ARM-software/CMSIS_5/develop/CMSIS/Utilities/CMSIS-SVD.xsd" }
  ],
  namespaces: [
    Namespace { name: Some("xs"), uri: "http://www.w3.org/2001/XMLSchema-instance" }
  ]
}

In svd-parser, the below code is used to extract these info currently:

if let Some(xmlns_xs) = tree.attribute("xmlns:xs") {
    device = device.xmlns_xs(xmlns_xs.to_string());
}
if let Some(location) = tree.attribute("xs:noNamespaceSchemaLocation") {
    device = device.no_namespace_schema_location(location.to_string());
}

This doesn't extract either xmlns:xs or xs:noNamespaceSchemaLocation.

Thus svd-parse always ignores these attributes.


A possible solution:

  1. extract URI of xs
  2. extract noNamespaceSchemaLocation through tree.attribute(("<uri_of_xs>", "xs:noNamespaceSchemaLocation"))

Notes:

  • If we can assert there is only one namespace with the name xs, then maybe using tree.lookup_namespace_uri(Some("xs")) is ok.

Builder Option arguments

Why the builders have Option in some parameters? For example:

svd/src/svd/peripheral.rs

Lines 100 to 103 in 6d61af9

pub fn version(mut self, value: Option<String>) -> Self {
self.version = value;
self
}

should be:

pub fn version(mut self, value: String) -> Self { 
     self.version = Some(value); 
     self 
 } 

I think that there is no point in calling this function with a None, since it is the default value.

Is Continuous Integration working?

I was looking at #131 and I don't see something that checks if the code is formatted and that tests are working on each commit you do in the PR.

Is travis still working?
We add some issues with it in delta, might be related?
If you want I can add GitHub actions in this project really easily.

deserialize bugs

[ERROR svd2rust] Error parsing SVD YAML file
    
    Caused by:
        peripherals[0]: invalid type: string "bitOffset", expected a borrowed string at line 19 column 9

`displayName`

stm32 SVD's have this tag, but it is absent in CMSIS specification

SVD for s32k344 leads to uncompilable output due to many duplicated methods

Hi!

I'm new to embedded rust, and I probably just don't understand the cli options to svd2rust and how to get working output.

An example from the SVD I'm using that leads to many duplicated functions:

<field>
<name>RR_INITMOD</name>
<description>Initialization Delay Modulus</description>
<bitOffset>16</bitOffset>
<bitWidth>6</bitWidth>
<access>read-write</access>
<enumeratedValues>
  <enumeratedValue>
    <name>MOD_63</name>
    <description>63 cycles (same as 111111b)</description>
    <value>0</value>
  </enumeratedValue>
  <enumeratedValue>
    <name>MOD_1_63</name>
    <description>1 to 63 cycles</description>
    <value>0x1</value>
  </enumeratedValue>
  <enumeratedValue>
    <name>MOD_1_63</name>
    <description>1 to 63 cycles</description>
    <value>0x2</value>
  </enumeratedValue>
  <enumeratedValue>
    <name>MOD_1_63</name>
    <description>1 to 63 cycles</description>
    <value>0x3</value>
  </enumeratedValue>
  <enumeratedValue>
    <name>MOD_1_63</name>
    <description>1 to 63 cycles</description>
    <value>0x4</value>
  </enumeratedValue>
  <enumeratedValue>
    <name>MOD_1_63</name>
    <description>1 to 63 cycles</description>
    <value>0x5</value>
  </enumeratedValue>
  <enumeratedValue>
    <name>MOD_1_63</name>
    <description>1 to 63 cycles</description>
    <value>0x6</value>
  </enumeratedValue>
  <enumeratedValue>
    <name>MOD_1_63</name>
    <description>1 to 63 cycles</description>
    <value>0x7</value>
  </enumeratedValue>
  <enumeratedValue>
    <name>MOD_1_63</name>
    <description>1 to 63 cycles</description>
    <value>0x8</value>
  </enumeratedValue>
  <enumeratedValue>
    <name>MOD_1_63</name>
    <description>1 to 63 cycles</description>
    <value>0x9</value>
  </enumeratedValue>
</enumeratedValues>

Leads to code like:

#[doc = "Initialization Delay Modulus\n\nValue on reset: 0"]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum RrInitmod {
    #[doc = "0: 63 cycles (same as 111111b)"]
    Mod63 = 0,
    #[doc = "1: 1 to 63 cycles"]
    Mod1_63 = 1,
    #[doc = "2: 1 to 63 cycles"]
    Mod1_63 = 2,
    #[doc = "3: 1 to 63 cycles"]
    Mod1_63 = 3,
    #[doc = "4: 1 to 63 cycles"]
    Mod1_63 = 4,
    #[doc = "5: 1 to 63 cycles"]
    Mod1_63 = 5,
    #[doc = "6: 1 to 63 cycles"]
    Mod1_63 = 6,
    #[doc = "7: 1 to 63 cycles"]
    Mod1_63 = 7,
    #[doc = "8: 1 to 63 cycles"]
    Mod1_63 = 8,
    #[doc = "9: 1 to 63 cycles"]
    Mod1_63 = 9,
}

#[doc = "Field `RR_INITMOD` writer - Initialization Delay Modulus"]
pub type RrInitmodW<'a, REG> = crate::FieldWriter<'a, REG, 6, RrInitmod>;
impl<'a, REG> RrInitmodW<'a, REG>
where
    REG: crate::Writable + crate::RegisterSpec,
    REG::Ux: From<u8>,
{
    #[doc = "63 cycles (same as 111111b)"]
    #[inline(always)]
    pub fn mod_63(self) -> &'a mut crate::W<REG> {
        self.variant(RrInitmod::Mod63)
    }
    #[doc = "1 to 63 cycles"]
    #[inline(always)]
    pub fn mod_1_63(self) -> &'a mut crate::W<REG> {
        self.variant(RrInitmod::Mod1_63)
    }
    #[doc = "1 to 63 cycles"]
    #[inline(always)]
    pub fn mod_1_63(self) -> &'a mut crate::W<REG> {
        self.variant(RrInitmod::Mod1_63)
    }
    #[doc = "1 to 63 cycles"]
    #[inline(always)]
    pub fn mod_1_63(self) -> &'a mut crate::W<REG> {
        self.variant(RrInitmod::Mod1_63)
    }
    #[doc = "1 to 63 cycles"]
    #[inline(always)]
    pub fn mod_1_63(self) -> &'a mut crate::W<REG> {
        self.variant(RrInitmod::Mod1_63)
    }
    #[doc = "1 to 63 cycles"]
    #[inline(always)]
    pub fn mod_1_63(self) -> &'a mut crate::W<REG> {
        self.variant(RrInitmod::Mod1_63)
    }
    #[doc = "1 to 63 cycles"]
    #[inline(always)]
    pub fn mod_1_63(self) -> &'a mut crate::W<REG> {
        self.variant(RrInitmod::Mod1_63)
    }
    #[doc = "1 to 63 cycles"]
    #[inline(always)]
    pub fn mod_1_63(self) -> &'a mut crate::W<REG> {
        self.variant(RrInitmod::Mod1_63)
    }
    #[doc = "1 to 63 cycles"]
    #[inline(always)]
    pub fn mod_1_63(self) -> &'a mut crate::W<REG> {
        self.variant(RrInitmod::Mod1_63)
    }
    #[doc = "1 to 63 cycles"]
    #[inline(always)]
    pub fn mod_1_63(self) -> &'a mut crate::W<REG> {
        self.variant(RrInitmod::Mod1_63)
    }
}

This is one example of many in the generated output. Am I holding this wrong? There isn't any output from svd2rust to indicate that I might be doing something wrong.

Here is the command I'm running:
svd2rust -i S32K344_M7.svd -o src --target cortex-m -s --atomics --keep-list

Support `modifiedWriteValues`

This element specifies side effects when writing to the field.

  <!-- modifiedWriteValuesType specifies the pre-defined tokens for the write side effects -->
  <xs:simpleType name="modifiedWriteValuesType">
    <xs:restriction base="xs:token">
      <xs:enumeration value="oneToClear"/>
      <xs:enumeration value="oneToSet"/>
      <xs:enumeration value="oneToToggle"/>
      <xs:enumeration value="zeroToClear"/>
      <xs:enumeration value="zeroToSet"/>
      <xs:enumeration value="zeroToToggle"/>
      <xs:enumeration value="clear"/>
      <xs:enumeration value="set"/>
      <xs:enumeration value="modify"/>
    </xs:restriction>
  </xs:simpleType>

Reset value should not be required

The SVD spec does not require reset values to be present. This happens in real data, e.g. on TM4C series it looks like all writable registers are always initialized to 0.

Here's my workaround:

diff --git a/src/generate.rs b/src/generate.rs
index 06f9d13..0c20bf0 100644
--- a/src/generate.rs
+++ b/src/generate.rs
@@ -494,11 +494,8 @@ pub fn register(
 
         let rv = register.reset_value
             .or(defs.reset_value)
-            .map(|rv| util::unsuffixed(u64(rv)))
-            .ok_or_else(|| {
-                            format!("Register {} has no reset value",
-                                    register.name)
-                        })?;
+            .or(Some(0))
+            .map(|rv| util::unsuffixed(u64(rv)));
 
         w_impl_items.push(
             quote! {

M302: Size of Register must be 8, 16 or 32 Bits

From CMSIS SVDConv docs

Message Number Type Message Text
M302 ERROR Size of Register 'NAME':'NUM' must be 8, 16 or 32 Bits

This limitation is not obvious to me. For example, it is easier to create a 12-bit register for a 12-bit ADC than a 32-bit register with only one field.
svd2rust handles this by creating an unsafe method for working with such registers. But CMSIS prohibits such svd files. Should utilities handle this error?

remove `unproven` flag

Encoding works fine as for me.

I think we should prove it and remove unproven option.

Alternative:
Split this crate on several like svd-base, svd-parser, svd-encoder, svd-utils, tests.

Unknown access variant 'read-write ' found

Unnecessary space in access variant read-write results to error

[2023-08-28T07:35:10Z ERROR svdtools::cli] by svdtools (0.3.0)

    Caused by:
        0: In device `AT32F415xx_v2`
        1: In peripheral `ERTC`
        2: In register `BPR20DT`
        3: Parsing unknown access at 7318:11
        4: unknown access variant 'read-write ' found

Also does it make sense to handle such issue for all tags by default? I have to use patches like this:

SPI1:
    CTRL2:
      _modify:
        "MDIV3EN ":
          name: MDIV3EN

reject duplicate fields

In stm32-rs/stm32-rs#83 (comment) we found that duplicate fields in a register aren't rejected by svd2rust. (There are probably other duplicate conditions that could be caught, such as duplicate register names?)

I'll make the required changes, but I need to know if you want to handle this in svd-parser already, while reading the SVD, or in svd2rust, while generating the output?

Better error handling

See related issue rust-embedded/svd2rust#51
svd-parser uses Option<String> for ElementExt::get_child_text, and an expect is done with the defined try! macro in lib.rs, avoiding any way of knowing what had gone wrong. I propose for svd-parser to use error-chain to fix this problem, but also to use a logging crate to make debugging svd errors easier for the user without having to use utilities like SVDConv.exe to check for errors in the svd file and to see if the error is by missing implementation in svd2rust.

Should Peripheral support array?

Register can take the variant Single(RegisterInfo) or Array(RegisterInfo, RegisterArrayInfo). The svd dim stuff is also valid for a peripheral, shouldn't that mean Peripheral should do the same?

What I suggest is to:

  1. Rename RegisterArrayInfo to DimInfo (or something else that's generic over these types, like ArrayInfo)
  2. Rename Peripheral to PeripheralInfo (to make it analog to RegisterInfo)
  3. Introduce the new enum Peripheral which is analog to enum Register
  4. Add Peripheral::parse analog to how Register::parse works

Breakage

There are 3 crates listed on crates.io as dependent on this crate. Only svd2rust have received updates in 2017.

Right now svd2rust silently generates garbage code when given peripheral arrays. It should be trivial to apply a quick patch which crashes the program when faced peripheral arrays and works as previous when faced single peripherals. This patch is also a prerequisite of supporting peripheral arrays in svd2rust. In other words, the breakage caused by this patch would be trivial to fix and benefit svd2rust greatly both immediately and in the future.

<dim> can have hexadecimal values

Running svd2rust on this svd:

https://raw.githubusercontent.com/particle-iot/nrf5_sdk/master/modules/nrfx/mdk/nrf52840.svd

yields a panic because this code:

impl RegisterClusterArrayInfo {
    fn parse(tree: &Element) -> RegisterClusterArrayInfo {
        RegisterClusterArrayInfo {
            dim: try!(tree.get_child_text("dim").unwrap().parse::<u32>()),

doesn't know how to parse the hexadecimal values in that file.

I know that there's a refactoring happening, so I'll just stick this little diff here that allowed me to get through generating code for this file:

$ git diff
diff --git a/src/lib.rs b/src/lib.rs
index 88dc43e..949d7de 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -391,7 +391,9 @@ impl RegisterInfo {
 impl RegisterClusterArrayInfo {
     fn parse(tree: &Element) -> RegisterClusterArrayInfo {
         RegisterClusterArrayInfo {
-            dim: try!(tree.get_child_text("dim").unwrap().parse::<u32>()),
+            dim: try!(tree.get_child("dim").map(|t| {
+                try!(parse::u32(t))
+            })),
             dim_increment: try!(tree.get_child("dimIncrement").map(|t| {
                 try!(parse::u32(t))
             })),

error parsing an svd file generated by this library

In this test I try to

  1. parse an svd from a file
  2. encode that svd to xml
  3. parse the xml in step 2

Step 3 panics with the error:

thread 'read_and_write' panicked at 'called `Result::unwrap()` on an `Err` value: STM32L4x2 invalid

Caused by:
    invalid digit found in string', tests/svd_parser.rs:17:20
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Since the xml was generated by this library, I think it should be valid.

allow `isDefault` to have optional `value`

In my SVD file an enumerated value of a field is labeled with <isDefault>true</isDefault>, which seems okay as per the spec. When this is parsed I get an error like:

[ERROR svd2rust] Error parsing SVD XML file
    
    Caused by:
        0: In device `PAC52XX`
        1: In peripheral `SYSCLK`
        2: In register `SCCTL`
        3: In field `CLKIN`
        4: Parsing enumeratedValue `ROSC` at 57:17
        5: `EnumeratedValue error: EnumeratedValue must contain one of `value` (passed Some(0)) or `is_default` (passed Some(true)) tags

Changing the value from true to 1 gives the error:

[ERROR svd2rust] Error parsing SVD XML file
    
    Caused by:
        0: In device `PAC52XX`
        1: In peripheral `SYSCLK`
        2: In register `SCCTL`
        3: In field `CLKIN`
        4: Parsing enumeratedValue `ROSC` at 57:17
        5: `EnumeratedValue error: EnumeratedValue must contain one of `value` (passed Some(0)) or `is_default` (passed Some(true)) tags

However, changing the value to 1.0 does work. Seems to be an issue where something expects an integer.

Here is the SVD file in question: pac22140.svd.txt

[svd_parser]: Tags that contain a XML comment are ignored.

svd_parser 0.14.1

If a tag contains a XML comment the tag content is ignored.
see tag licenseText
Below XML has been validated against latest svd.xsd.

How to reproduce:

use svd_parser;


fn main() {

    let xml=r#"<?xml version="1.0" encoding="utf-8"?>
<device schemaVersion="1.1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="svd.xsd">

	<name>ARM_Example</name>
	<series>ARMCM3</series>
	<version>1.2</version>
	<description>SVD Test for Rust PAC generator</description>
	<licenseText><!-- this license text will appear in header file. \n force line breaks --> Test license\n </licenseText>
	<cpu>
		<!-- details about the cpu embedded in the device -->
		<name>CM3</name>
		<revision>r1p0</revision>
		<endian>little</endian>
		<mpuPresent>true</mpuPresent>
		<fpuPresent>false</fpuPresent>
		<nvicPrioBits>3</nvicPrioBits>
		<vendorSystickConfig>false</vendorSystickConfig>
	</cpu>
	<addressUnitBits>8</addressUnitBits>
	<width>32</width>
	<size>32</size>
	<access>read-write</access>
	<resetValue>0x00000000</resetValue>
	<resetMask>0xFFFFFFFF</resetMask>
	<peripherals>
		<peripheral>
			<name>UART</name>
			<baseAddress>0x50000000</baseAddress>
			<registers>
				<register>
					<name>Reg1</name>
					<addressOffset>0x0</addressOffset>
					<resetMask>0xFFFFFFFF</resetMask>
				</register>
			</registers>
		</peripheral>
	</peripherals>
</device>
    "#;
    let device = svd_parser::parse(xml).unwrap();
    println!("{:?}",device.license_text);
    println!("{:?}",device.description);

}

Change xml crate

I am working on this issue and I noticed that this library is really slow if compared to what I built by using quick-xml.

I am assuming that the difference of performances is due to the different xml library used.

If you want to compare the two solutions:

git clone -b riir https://github.com/MarcoIeni/svdtools
cd svdtools

# try version the version with quick-xml 
git checkout be257c679028d10c6d86e0ae9c869a0ee421cb7c
cargo build --release
time ./target/release/svdtools mmap example/stm32l4x2.svd

# try the version that uses svd-parser
git checkout fad7abfd923312ec95f307286a05017be1218217
cargo build --release
time ./target/release/svdtools mmap example/stm32l4x2.svd

These are the results I get on my laptop by running the executable about ten times:

quick-xml version:
minimum: 0.03s user 0.02s system 79% cpu 0.066 total
maximum: 0.08s user 0.01s system 87% cpu 0.100 total

svd-parser version:
minimum: 0.26s user 0.02s system 96% cpu 0.291 total
maximum: 0.30s user 0.02s system 95% cpu 0.332 total

Of course the version I built by using quick-xml is incomplete and doesn't handle errors well (I originally wrote it because I didn't know this crate existed), but I just wanted to tell you that I saw this huge performance difference.

Of course I know that these benchmark are not rigorous, but I think that they are sufficient at least to raise this point to your attention.

Incorrect names in SVDs

Many Fujitsu and Freescale SVDs have incorrect enumerated value names that start with digit like:

                <enumeratedValue>
                  <name>0</name>
                  <description>Configured interrupt is not detected.</description>
                  <value>#0</value>
                </enumeratedValue>

For now svd2rust just adds _ prefix.
But check_name blocks this:

check_name(&self.name, "name")?;

What should we do:

  1. Remove this validation check.
  2. Add _ prefix during parsing.
  3. Ignore incorrect files.
  4. Allow digit on start of name.

cc @therealprof @Emilgardis

Incorrect "out of range" values displayed with <enumeratedValue>

I'm using a project that uses this SVD crate and I found that the error message displayed with an out-of-range value is misleading.

I'm currently using this tool from this repository: https://github.com/bjoernQ/svd2html
I ran this tool against an SVD I'm generating from a bunch of .def files. This tool found some issues with my SVD, but displays a slightly incorrect message:

    3: `EnumeratedValue error: Value 4 out of range 0..4', src/main.rs:39:39

As you can see, "Value 4" is inside "range 0..4", so this shouldn't be an error. The error that should have been printed is "range 0..3".
If you inspect the SVD File around the line it complains about, you will find a "2" which translates to the correct range 0..3.

You can find my SVD at this repository: https://github.com/DualTachyon/rk3588-svd

Please checkout a specific commit that contains the unfixed SVD:

$ git checkout 044f00b1f244fc4502c228e3b29c7bd930e8b0cd

After building the svd2html tool, you can reproduce the issue in the following way:

$ ./target/debug/svd2html --input $(folder_to_my_svd)/rk3588.svd

I don't know rust much, so I was unable to figure out how to fix this myself and send a PR.

Let me know if you need further clarifications.

svd-parser v0.14.3 fails to compile with svd-rs version v0.14.2 and v0.14.3

Hi,

I'm seeing a problem where v0.14.3 of the svd-parser fails to compile:

error[E0425]: cannot find function `expand` in module `cluster`
   --> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/svd-parser-0.14.3/src/expand.rs:322:31
    |
322 |             for c in cluster::expand(&info, &dim) {
    |                               ^^^^^^ not found in `cluster`
    |
help: consider importing this function through its public re-export
    |
3   + use crate::expand;
    |
help: if you import `expand`, refer to it directly
    |
322 -             for c in cluster::expand(&info, &dim) {
322 +             for c in expand(&info, &dim) {
    |

(from probe-rs/probe-rs#1897)

These are the dependencies:

 svd-parser v0.14.3
 585   │ │   ├── anyhow v1.0.75
 586   │ │   ├── roxmltree v0.18.0
 587   │ │   │   └── xmlparser v0.13.5
 588   │ │   ├── svd-rs v0.14.2
 589   │ │   │   ├── once_cell v1.18.0
 590   │ │   │   ├── regex v1.10.1 (*)
 591   │ │   │   └── thiserror v1.0.49 (*)
 592   │ │   └── thiserror v1.0.49 (*)

After updating svd-rs to version v0.14.4 it compiles again.

This seems to indicate that svd-parser needs to explicitly depend on the newer version of svd-rs.

<field> can have more than one <enumeratedValues> children node

For example, see the nrf51.svd

        <register>
          <name>OUTSET</name>
          ...
            <field>
              <name>PIN0</name>
              <description>Pin 0.</description>
              <lsb>0</lsb> <msb>0</msb>
              <enumeratedValues>  <-
                <usage>read</usage>
                <enumeratedValue>
                  <name>Low</name>
                  <description>Pin driver is low.</description>
                  <value>0</value>
                </enumeratedValue>
                <enumeratedValue>
                  <name>High</name>
                  <description>Pin driver is high.</description>
                  <value>1</value>
                </enumeratedValue>
              </enumeratedValues>
              <enumeratedValues>  <-
                <usage>write</usage>
                <enumeratedValue>
                  <name>Set</name>
                  <description>Set pin driver high.</description>
                  <value>1</value>
                </enumeratedValue>
              </enumeratedValues>
            </field>

The Field struct will have to be update to reflect this.

Check writeConstraint range

The range of values for a enumeration is checked against a field size. But there is no such check for a range. It is possible to assign a range that out of bounds field.

The Refactor

We have a few outstanding issues that to move forward with could use a refactor of the existing codebase.

Issues:

Proposal

Things to do and PRs to accept. I'll update this list from any discussion in this issue to reflect our plan and progress.

Project Level

  1. Introduce Error types for svd decoding (@Emilgardis?)
  2. Introduce Encode and Decode traits for svd objects (@ryankurte?)
  3. Refactor all svd objects (anyone and everyone)

Once we've defined Error types and Encode/Decode traits the refactoring part should be reasonably simple, and we can accept a PR for each to avoid nightmare refactoring.

For each SVD object (ie. object implementing an SVD element)

  1. Move from src/lib.rs to srv/svd/object.rs and add pub mod object; to src/svd/mod.rs
  2. Update decode method to match Decode trait (and add error handling)
  3. Create encode method to match Encode trait (svd#37 has many pre-written)
  4. Add tests for encoding and decoding each variant for an object.

I propose that we put a freeze on changes to master while undertaking this and make these changes against a refactor branch until we reach stability again, then merge back to master in what is bound to be a spectacularly breaking change.

Warnings for strict

I'd prefer if this was on runtime and not compiletime. That can be done with either "unstrict" functions, a bool flag to functions or with recoverable errors in Ok path.

My preference is the latter.

Something like this

pub(crate) fn check_name(name: &str, tag: &str) -> Result<Option<E>> {
...
}

Or similar

Originally posted by @Emilgardis in #134 (comment)

do validation when parsing serde yaml/json

I was handcrafting some svd (yaml) and early on ran into a generator issue.

To reproduce run the following in an empty directory:

cargo init simple_bit_field_failure \
&& cd simple_bit_field_failure \
&& cargo add cortex_m vcell \
&& cd src \
&& echo """
name: MyDevice
version: 0
description: My Device
addressUnitBits: 32
width: 32
peripherals:
  - name: MyPeripheral
    baseAddress: 0xb8000300
    registers:
      - register:
          name: MyRegister
          description: My register.
          addressOffset: 0
          size: 1
          fields:
            - name: MyBitField
              description: My bit field.
              bitRange: \"[0:0]\"
""" |  RUST_LOG=debug svd2rust --strict --source_type yaml \
&&cargo fmt -- --config normalize_doc_attributes=true \
&&cargo build

result:

...
error[E0308]: mismatched types
   --> src/lib.rs:779:37
    |
779 |                 MY_BIT_FIELD_R::new(self.bits)
    |                 ------------------- ^^^^^^^^^ expected `bool`, found `u8`
    |                 |
    |                 arguments to this function are incorrect
    |
...

The first doc line reports version:

//!Peripheral access API for MYDEVICE microcontrollers (generated using svd2rust v0.28.0 ( ))

Invalid Enum values are permitted

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>

Handle hex numbers

The nRF9160 SVD file (https://github.com/NordicSemiconductor/nrfx/blob/master/mdk/nrf9160.svd) has lines like:

<dim>0x4</dim>
<dimIncrement>0x4</dimIncrement>

I don't know what these mean semantically, but the SVD XSD says they must be "scaledNonNegativeInteger", which includes 0x and # prefixes (https://github.com/ARM-software/CMSIS/blob/master/CMSIS/Utilities/CMSIS-SVD.xsd#L168).

Currently this crate uses string.parse::<u32>(), which does from_str_radix with a fixed radix of 10 (see https://doc.rust-lang.org/src/core/num/mod.rs.html#4665-4670) . It therefore doesn't parse these hexadecimal numeric values and panics.

$ svd2rust -i nrf9160.svd
thread 'main' panicked at '/home/jpallant/.cargo/registry/src/github.com-1ecc6299db9ec823/svd-parser-0.6.0/src/lib.rs:377 tree.get_child_text("dim").unwrap().parse::<u32>(): ParseIntError { kind: InvalidDigit }', src/libcore/result.rs:999:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

As std can't parse integers based on their prefix (rust-lang/rfcs#1098) I propose we add an integer parse function which handles all the numeric formats specified in the XSD and use that instead of string.parse::<u32>().

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.