Add _iter and _len methods to block and fieldset arrays#140
Conversation
diondokter
left a comment
There was a problem hiding this comment.
Implementation looks good
| } | ||
|
|
||
| #doc | ||
| #[inline(always)] |
There was a problem hiding this comment.
Should these be inline always?
Not sure. We could make them #[inline] too which only gives a strong signal to the compiler to inline it, but not force it.
But maybe it should be always inlined...
|
I do agree we need something like this, i've also been annoyed with having to redefine lengths in HALs. The approach of generating The downside is it is a syntax breaking change, but that's perhaps okay? We just made the enum casing breaking change which is much bigger.
btw this is not true. |
|
I am unsure if If we want the concept to apply to register fields as well, we'll probably need a separate type for that. |
Is it reasonable to include index checking for holey/sparse arrays or is that veering too much towards bloat? |
This reverts commit 5d4515b.
|
Using core::ops::Index is not really going to work as that always returns a reference, so we cannot construct say a I'll update this PR with a proposal and then we can discuss further. |
|
Pushed a proposal for how the array for ptrs (registers & blocks) could look like. Still need to consider how this would look for fieldsets. I am not too hot on the FromPtr trait being in the public API. Let me know what you think, |
We could also add that, but perhaps it might be better to add it as a separate PR later. |
This comment was marked as outdated.
This comment was marked as outdated.
|
I played around with arrays for fields and have come to the conclusion that it (currently) is infeasible. My approach basically meant having a
Accessing field that is an array basically requires owning a mutable reference to the underlying fieldset so that the value in the fieldset can be updated. This is problematic as:
Currently I would rather just add |
|
I'm just thinking out loud (so feel free to ignore/dismiss), but am wondering: what (major) benefits does this bring over wrapping array accessors in const blocks in the places where one really cares about it, i.e. let my_reg = const { MY_PERIPHERAL.array(2) };which will fail to build if The main use-case I can think of is that you can have a The current behaviour of panicking at runtime on out-of-bounds accesses isn't really improved by this beyond that the HAL can catch it now, but what will it do with that information beyond also panicking? I'd also be quite interested (because I haven't encountered it) to see what one could use these iterators/lengths for. Any example use cases that you already have in mind? |
Typically you would want to update all registers and fields in one go. For Trustzone for example, large sets of memory regions need to be set to secure (and parts optionally non-secure). Forgetting a single register is a security issue. This PR will make it possible to express the following (which is not const): for rom_mem_rule in ahb_secure_ctrl.rom_mem_rule() {
rom_mem_rule.write(|w| {
for j in 0..w.rule_len() {
w.set_rule(j, Rule::SecurePrivUserAllowed);
}
});
} |
|
The other TZ example that comes to mind are interrupts. The NVIC and ICU expose interrupts as 32-bit registers and it'd be nice to reduce the boilerplate code to a (const?) iterator over each (NVIC,ICU) instead of a mess of cfg directives. |
Arrays in blocks and fieldsets result in accessors being generated with an index argument. This argument is then checked in an assert-block, which is only checked in debug builds typically. The amount of elements though is not emitted as of yet. Hence it requires HAL implementors to define a constant themselves. If for whatever reason the amount of elements changes, the code thus is incorrect.
We could add methods like
_lento denote the number of elements. We could also add_iterto conveniently allow the user to iterate over every element. For fieldsets an iterator is not a straightforward API. I considered adding a callback interface for this, but for now I did not add it.Unsure whether this is actually in line with what we want from chiptool, as we tend to favor 'light and simple' code per my understanding. I am very happy to discuss what is a good API to achieve similar results.