-
Notifications
You must be signed in to change notification settings - Fork 156
Add initial Cluster support #182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok(quote! { | ||
/// Register block | ||
#[repr(C)] | ||
pub struct RegisterBlock { | ||
pub struct #name { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this compatible with frameworks like RTFM?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least in my testing with nrf52, this did not cause any problems with rtfm. This is an artifact of #149, and I admit I do not fully understand it. I can try testing without this change if you would like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'm thinking of the older RTFM where (I think) RegisterBlock was directly used. Now we just deref "into" it so this shouldn't change anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Emilgardis I actually just went and figured out what this does. It controls the name of structs that are clusters, such as https://gist.github.com/jamesmunns/03fd0d7d3595cd0816dbfa8daca0a553#file-ficr-diff-L56. Without this, the other structs inside of this scope would all have the name RegisterBlock
, which would be a problem.
At this point, it is implicit in the code that name
is always Some(...)
in a cluster, and None
when not in a cluster. I will add comments that improve that (now that I understand this 😄)
let name_to_ty = |name: &String, ns: Option<&str>| -> syn::Ty { | ||
let ident = if let Some(ns) = ns { | ||
Cow::Owned( | ||
String::from("self::") + &ns.to_sanitized_snake_case() + "::" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why this change is needed, care to explain?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change allows for generation of names types like this: https://gist.github.com/jamesmunns/03fd0d7d3595cd0816dbfa8daca0a553#file-ficr-diff-L58
Since clusters are nested namespaces, it is necessary for the outer (cluster) structures to refer to types inside of the nested namespaces.
I have also now tested this against Another problem is that the ATSAMD svd has clusters with repeating names. This is currently not handled by my changes. See this snippet: <cluster>
<name>USART</name>
<description>USART Mode</description>
<alternateCluster>I2CM</alternateCluster>
<headerStructName>SercomUsart</headerStructName>
<addressOffset>0x0</addressOffset>
<register>
<name>BAUD</name>
<description>USART Baud Rate</description>
<alternateGroup>DEFAULT_MODE</alternateGroup>
<addressOffset>0x0C</addressOffset>
<size>16</size>
<fields>
<field>
<name>BAUD</name>
<description>Baud Rate Value</description>
<bitOffset>0</bitOffset>
<bitWidth>16</bitWidth>
</field>
</fields>
</register>
<register>
<name>BAUD</name>
<description>USART Baud Rate</description>
<alternateGroup>FRAC_MODE</alternateGroup>
<addressOffset>0x0C</addressOffset>
<size>16</size>
<fields>
<field>
<name>BAUD</name>
<description>Baud Rate Value</description>
<bitOffset>0</bitOffset>
<bitWidth>13</bitWidth>
</field>
<field>
<name>FP</name>
<description>Fractional Part</description>
<bitOffset>13</bitOffset>
<bitWidth>3</bitWidth>
</field>
</fields>
</register>
<register> |
@Emilgardis - apologies for basing this on my "refactoring" branch. It took me a while to understand what components had to do with which parts of the generation process, and the refactoring branch was me organizing things based on my learning while trying to tackle the cluster feature. As previously mentioned, I would be happy to rebase this on top of master (but I am hoping the other PR is merged). Additionally I agree that I need to improve the situation with comments. I will plan to add those in the near future. |
I think #182 (comment) is not technically a blocker to merging this, though clusters that contain multiple registers at the same offset (like Devices (like the nrf52) that do not have |
Don't worry about the FUBAR ATSAMD too much, that'll only make your life miserable but doesn't bring any benefit to the cause. The chat I had with a Microchip guy yesterday at the Embedded World was very revealing, too. |
✌️ Emilgardis can now approve this pull request |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM. I agree with @Emilgardis that some comments would be useful.
Another problem is that the ATSAMD svd has clusters with repeating names.
Is this even allowed by the SVD spec? I doesn't seem to say anything about this. It says:
"String to identify the register. Register names are required to be unique within the scope of a peripheral."
(emphasis mine)
It says something similar about cluster names within a peripheral but it doesn't say anything about register names within a cluster namespace ...
I'd be fine with postponing supporting this odd use case and landing what this PR implements. (We would need to support unions in svd2rust in any case.)
@Emilgardis could you take the review from here? I'll probably be rather busy over the next few days.
bors delegate=Emilgardis
@jamesmunns if Emilgardis is also busy feel free to r+-ing this yourself after adding more comments -- you have bors / reviewers rights.
src/generate/peripheral.rs
Outdated
size: register_size, | ||
}), | ||
Register::Array(ref info, ref array_info) => { | ||
let sequential_addresses = register_size == array_info.dim_increment * BITS_PER_BYTE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole array_convertible
logic repeats in expand_cluster
and here. Could it be refactor into a function that takes array_info
as argument?
@@ -238,3 +239,25 @@ impl U32Ext for u32 { | |||
}) | |||
} | |||
} | |||
|
|||
/// Return only the clusters from the slice of either register or clusters. | |||
pub fn only_clusters(ercs: &[Either<Register, Cluster>]) -> Vec<&Cluster> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
off-topic: this looks like something that could be provided by the either crate. It looks a bit like Iterator::partition
but that method returns two Vec
s of the same type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opened an issue in rayon-rs/either#20 regarding this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least right now, I won't be implementing this, because I can't figure out how to get itertools to figure out the vec of refs. Open to PRs in the future :)
Hey, quick status update on this:
I just wanted to follow up in case anyone other than me was trying to use this branch :). If you want to try out my ugly fixes, I can push those to another branch on my fork, just @ me. |
@jamesmunns I just tried a few SVD and it seems to work great. No regressions with simple ones and nrf51 gets a few more components by using this. Few nits:
|
@therealprof Be careful with the current branch. In the generated output, the Regarding formatting, yeah, its pretty rough. I wonder what we are doing that makes cargo fmt upset. Probably worth an improvement issue. Regarding VolatileCell, I can probably take that out of the generated code, and we can just |
@jamesmunns I've just done some basic regression testing and worked for my curiosity (since you mentioned you require that for the nrf52 I was curious to see whether the nrf51 also has some additional hidden components -- yes it does!). No concrete use case at the moment. |
@therealprof I don't expect this to break anything that already worked before, but the "new stuff" (e.g. the peripherals/registers that were cluster based) I would expect not to work in some cases. Were you testing the new peripherals? Or your existing nrf51-hal code? |
No, just checking that a swapped out version would compile. I haven't even noticed that (albeit very few) peripherals were missing so obviously I didn't those so far. |
d275d6f
to
ef2d9c2
Compare
Fixed size rendering (as far as I can tell). bors r+ |
182: Add initial Cluster support r=jamesmunns a=jamesmunns Add cluster support to svd2rust. I am calling it initial, because I have only tested it against the `nRF52` [svd file](https://github.com/jamesmunns/nrf52/blob/master/nrf52.svd). Note, this is based on #180, so I would prefer that PR be merged first. If that PR is rejected, I can instead rebase these changes on `japaric/master` (just let me know). Edit: All changes relevant to clusters are squashed into the last commit of this PR, so if you want to see the relevant changes, check out 6de6de7. This is based on the work of @brandonedens earlier #149, and I believe would close #107 and related issues. CC @japaric @Emilgardis @therealprof Edit 2: Here are some handy references: * [SVD snippet with clusters](https://gist.github.com/jamesmunns/c4e53fe5bd74dca81fdbff6bb1798ddd) * [code generated before](https://gist.github.com/jamesmunns/d854a6c2665cca59edb88143d82a19c6) * [code generated after](https://gist.github.com/jamesmunns/7558667e34c33124c60b3aaaf679a196) * [diff of code generated](https://gist.github.com/jamesmunns/03fd0d7d3595cd0816dbfa8daca0a553)
Build failed |
Looks like this failed due to the excess "VolatileCell" mentioned above: https://travis-ci.org/japaric/svd2rust/jobs/349051903 - I'll try and find a clever fix, otherwise I'll hit it with an |
bors r+ |
182: Add initial Cluster support r=jamesmunns a=jamesmunns Add cluster support to svd2rust. I am calling it initial, because I have only tested it against the `nRF52` [svd file](https://github.com/jamesmunns/nrf52/blob/master/nrf52.svd). Note, this is based on #180, so I would prefer that PR be merged first. If that PR is rejected, I can instead rebase these changes on `japaric/master` (just let me know). Edit: All changes relevant to clusters are squashed into the last commit of this PR, so if you want to see the relevant changes, check out 6de6de7. This is based on the work of @brandonedens earlier #149, and I believe would close #107 and related issues. CC @japaric @Emilgardis @therealprof Edit 2: Here are some handy references: * [SVD snippet with clusters](https://gist.github.com/jamesmunns/c4e53fe5bd74dca81fdbff6bb1798ddd) * [code generated before](https://gist.github.com/jamesmunns/d854a6c2665cca59edb88143d82a19c6) * [code generated after](https://gist.github.com/jamesmunns/7558667e34c33124c60b3aaaf679a196) * [diff of code generated](https://gist.github.com/jamesmunns/03fd0d7d3595cd0816dbfa8daca0a553)
Timed out |
@japaric I'm a little confused - CI passed but Bors timed out? Is this okay to merge? |
Merging as tests have passed. |
@jamesmunns I increased the timeout to 2 hours the other day. If it still takes longer than that to run the tests feel free to increase it. |
Care to share the details? Also, I'd be curious to know whether you consider previously-Atmel chips FUBAR or just the SVDs. Thing is, I have an ATSAMD21 board that I'd like to bring up and play with the peripherals and the register cluster issue has been blocking, as far as I understand. |
@istankovic For whatever reason the engineers at (formerly) Atmel decided that it would be a great idea to have lots of totally asynchronously running clocks driving the individual peripherals. While (in theory) this yields a ton of freedom tweaking all the clocks to run at just the perfect speed for the job, it actually means that you can never be sure that data arrives at the right place at the right time due to clock drift so whenever you have peripherals working in lockstep (as one pretty much always does) you have to sprinkle costly busy wait loops all over the map in your peripheral access code. Not to mention that getting the clocks set up in the first place is a major PITA and can easily drive one mad because the chips will simply lock up somewhere in the initialisation code and you've no idea why... That combined with the fact that the documentation is in large portions conflicting, incorrect or even absent and Atmel seems to consider examples to be for wussies only is a bit of a buzzkill. I was asking the Microchip guy at the Embedded World for new advancements in the BLE/802.15.4 area to which he frankly replied that they somewhat underestimated the demand for that so they're still playing catchup in their design teams. And when I nudged him a bit about my experience with the ATSAM chips and the crazy clocks he just nodded and said that this probably wasn't the brightest hour of the engineering team. The SVDs are just another sad part of the story... Wez Furlong is working on ATSAMD21 support and if you want to look at something "working" (although definitely not pretty) you might want to have a look at my https://github.com/therealprof/atsamd20e15a which implements something "shiny" for the lowlier but otherwise mostly compatible brother. |
@therealprof thanks for the elaboration. Yes, regarding the Atmel parts, clock configuration can sometimes really be painful and I spent many hours debugging non-functioning peripherals. However, I'd say that once one gets used to it, it isn't such a big deal and it has its advantages (lower power, speed optimization etc.) Regarding the documentation, I'm not sure about the current state, but back when I was actively working with Atmel parts, AVRs upto Cortex-Ms, I considered Atmel docs to be one of the better in the industry, honestly. One could actually build a system solely by following a datasheet and perhaps consulting a few app notes, without needing to spend a great deal of time searching the net for answers/advice. Maybe that changed. Thanks for the pointer, I'll check out your repo. |
That's what they claim, I haven't seen that in real life though.
The AVR documentation is indeed really good; I've worked a lot with ATTiny, ATMega and AT90 in the past and those are well documented in stark contrast to the ATSAMD parts; haven't bothered checking other ATSAM parts though. |
Add cluster support to svd2rust. I am calling it initial, because I have only tested it against the
nRF52
svd file.Note, this is based on #180, so I would prefer that PR be merged first. If that PR is rejected, I can instead rebase these changes on
japaric/master
(just let me know).Edit: All changes relevant to clusters are squashed into the last commit of this PR, so if you want to see the relevant changes, check out 6de6de7.
This is based on the work of @brandonedens earlier #149, and I believe would close #107 and related issues.
CC @japaric @Emilgardis @therealprof
Edit 2: Here are some handy references: