Skip to content

add code generation support of peripheral arrays #592

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

Merged
merged 4 commits into from
Apr 26, 2022

Conversation

duskmoon314
Copy link
Contributor

@duskmoon314 duskmoon314 commented Apr 22, 2022

Brief Intro

  • generate ArrayProxy of peripherals when const_generic is true
  • generate separate struct of peripherals when const_generic is false

close issue: #492

Design

Notice: This is my first try of implement this feature. Please provide suggestions for this PR to better implement this feature.

This PR aims to achieve what issue #492 is asking for. This PR implements a basic try of generating codes depending on the const_generic flag.

Let's say we have an svd file with descriptions of peripherals like this:

<peripheral>
    <dim>2</dim>
    <dimIncrement>0x100</dimIncrement>
    <name>PTEST[%s]</name>
    <groupName>PGroup</groupName>
    <baseAddress>0x20000000</baseAddress>
    <addressBlock>
        <offset>0</offset>
        <size>0x100</size>
        <usage>registers</usage>
    </addressBlock>
    <registers>
        ...
    </registers>
</peripheral>

If the const_generic is false, there is no ArrayProxy. So I generate separate structs and only one mod:

pub struct PTEST0 {
    _marker: PhantomData<*const ()>,
}
...
impl PTEST0 {
    #[doc = r"Pointer to the register block"]
    pub const PTR: *const ptest::RegisterBlock = 0x2000_0000 as *const _;
    ...
}
impl Deref for PTEST0 {
    type Target = ptest::RegisterBlock;
    #[inline(always)]
    fn deref(&self) -> &Self::Target {
        unsafe { &*Self::PTR }
    }
}

pub struct PTEST1 {
    _marker: PhantomData<*const ()>,
}
...
impl PTEST1 {
    #[doc = r"Pointer to the register block"]
    pub const PTR: *const ptest::RegisterBlock = 0x2000_0100 as *const _;
    ...
}
impl Deref for PTEST1 {
    type Target = ptest::RegisterBlock;
    #[inline(always)]
    fn deref(&self) -> &Self::Target {
        unsafe { &*Self::PTR }
    }
}
#[doc = "PTEST"]
pub mod ptest;

NOTICE: The following design is actually incorrect and has been removed. See the following comment.

If the `const_generic` is `true`, we can use `ArrayProxy`. So I generate code like this:
pub struct PTEST {
    _marker: PhantomData<*const ()>,
}
...

pub struct Peripherals {
    #[doc = "PTEST"]
    pub PTEST: crate::ArrayProxy<PTEST, 2usize, 0x0100>,
...
impl Peripherals {
...
    pub unsafe fn steal() -> Self {
        DEVICE_PERIPHERALS = true;
        Peripherals {
            PTEST: crate::ArrayProxy::new(),

Since _array is a private field of ArrayProxy, I add a new method to implement the steal method of Peripherals.

I also add the support of using `name_of` on `MaybeArray` to achieve this implementation.

Well, I haven't fully tested this implementation yet. So there may be problems that need to be solved.

- generate ArrayProxy of peripherals when const_generic is true
- generate separate struct of peripherals when const_generic is false

close issue: rust-embedded#492
@duskmoon314 duskmoon314 requested a review from a team as a code owner April 22, 2022 13:24
@rust-highfive
Copy link

r? @reitermarkus

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-tools labels Apr 22, 2022
@burrbull
Copy link
Member

Looks good for me in general.
Need advanced test in CI with SVD containing peripheral array. (possibly already present, need to check)

@therealprof any comments?

Co-authored-by: Zgarbul Andrey <zgarbul.andrey@gmail.com>
@duskmoon314
Copy link
Contributor Author

duskmoon314 commented Apr 22, 2022

Need advanced test in CI with SVD containing peripheral array. (possibly already present, need to check)

It seems that CI use SVD in posborne/cmsis-svd to test. I try searching dim in this repo and cannot find a showcase of a peripheral array. May need to find a real example or build up one for testing.

ci failed: pattern bindings after an @ are unstable

I use p @ Peripheral::Array(_, dim) to extract dim_element and keep the p: MaybeArray<PeripheralInfo> at the same time. It is stable after 1.56. I will try to find out an alternative.

My mistake. I don't need to bind it. 🤣

@Emilgardis
Copy link
Member

for future reference. If you need to break msrv, do it ;)

@duskmoon314
Copy link
Contributor Author

I think I have misunderstood how ArrayProxy works. The current design cannot use ArrayProxy to calculate the address since ArrayProxy uses these lines:

let base = self as *const Self as usize;
let address = base + S * index;
&*(address as *const T)

But the generated code when const_generic is false seems to work fine. And the usage in this way is the same as describing peripherals separately in the svd file. (I rearrange the svd file that I am maintaining locally and test a simple case.)

For now, I think maybe there is no need to provide something like ArrayProxy for peripheral arrays. Any suggestions?

@burrbull
Copy link
Member

For now, I think maybe there is no need to provide something like ArrayProxy for peripheral arrays. Any suggestions?

Instead of ArrayProxy you could just create independent instances like if they are just derivedFrom first one.

@duskmoon314
Copy link
Contributor Author

Instead of ArrayProxy you could just create independent instances like if they are just derivedFrom the first one.

Yes. For now, the generated code is only organized in this way.

Though I think there is no problem, I still want to ask if there are any suggestions.

@burrbull
Copy link
Member

I don't have suggestions now.
Except missing CI test.

@burrbull
Copy link
Member

bors r+

@bors
Copy link
Contributor

bors bot commented Apr 26, 2022

Build succeeded:

@bors bors bot merged commit 040f9d4 into rust-embedded:master Apr 26, 2022
@duskmoon314 duskmoon314 deleted the peripheral_array branch April 26, 2022 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-tools
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants