Skip to content

Generic PLIC peripheral #125

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

Closed
wants to merge 26 commits into from
Closed

Conversation

romancardenas
Copy link
Contributor

I developed a generic driver for interfacing PLIC peripherals, as mentioned in #124.

References

For developing this peripheral, I got inspired by the following resources:

Particularities

For atomic operations, I use the volatile-register crate (as done in cortex-m).

Unlike the NVIC for Cortex-M microcontrollers, the standard leaves the base address as "implementation-specific". Thus, my implementation uses a const generic to define the base address of the PLIC. In PACs, developers can do something like this:

pub type PLIC = riscv::peripheral::PLIC<BASE_ADDRESS>;

I decided to use associated functions whenever possible, so we don't need to steal/pass the control of the PLIC. However, those functions that are not atomic are defined as methods.

Finally, I followed the safety guidelines of the NVIC implementation, so those associated functions that modify priorities/thresholds are marked as unsafe.

Let me know what you think. If you prefer any other style, I'll happily modify my implementation.

@romancardenas romancardenas requested a review from a team as a code owner February 23, 2023 09:42
@dkhayes117
Copy link
Member

Thank you for the PR. I'll look it over as soon as I can.

@dkhayes117
Copy link
Member

Not all riscv targets will have a PLIC, should this be feature gated?

@dkhayes117
Copy link
Member

Although, having to supply a PLIC base address would kind of act like a feature gate 🤔

@romancardenas
Copy link
Contributor Author

I'm fine with both. I plan to develop other peripherals (e.g., CLIC and (A)CLINT) in the same fashion. From what I read, they all have an implementation-specific base address. Using feature gates to only import the peripherals implemented on each PAC sounds reasonable.

@romancardenas
Copy link
Contributor Author

romancardenas commented Mar 11, 2023

Maybe we need to reconsider the concept of a context for the PLIC peripheral. These are my thoughts:

  • The main purpose of the contexts is to provide a "safe", isolated interface to the interrupts for each HART.
  • Probably, there will be as many contexts as HARTs in the platform.
  • Interrupt priorities are shared among contexts
  • Each context enables/disables the interrupt sources for their context.
  • Each HART attends interrupts via its context.

So I was thinking that the Context trait may be a bit annoying to maintain. Maybe it would be more useful to have one PLIC per context, and the context number could be a const generic too. Something like PLIC<BASE, CTX>. From what I saw, most boards only implement one context. Thus, their crate would have:

pub type PLIC = riscv::peripheral::PLIC<BASE_ADDRESS, 0>;

If the microcontroller has two contexts, then it would look like this:

pub type PLIC0 = riscv::peripheral::PLIC<BASE_ADDRESS, 0>;
pub type PLIC1 = riscv::peripheral::PLIC<BASE_ADDRESS, 1>;

And each HART can own a context. What do you think?

@romancardenas
Copy link
Contributor Author

@dkhayes117 I developed an alternative implementation of the PLIC that stores the context as a const generic.
I personally like this approach more, because otherwise, I think that dealing with the context number would be non-ergonomic in practice.

I also added a feature gate for optionally adding the peripheral. Let me know what you think!

@romancardenas
Copy link
Contributor Author

I added additional methods and generics to the current traits. The reason for that is that I am currently working on a port of RTIC for the E310X microcontrollers. As part of this work, I identified nice-to-have features that will ease the integration of RTIC to any platform with PLIC.

Copy link
Member

@dkhayes117 dkhayes117 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I left one comment about validating that the source priority != 0. @almindor @Disasm, It would be nice to have another pair of eyes on this if possible. Thanks!

dkhayes117
dkhayes117 previously approved these changes Mar 13, 2023
Copy link
Member

@dkhayes117 dkhayes117 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is good to merge, but I'll give it a couple of days to see if the other members have any opinions.

@romancardenas
Copy link
Contributor Author

@dkhayes117 take a look at my latest commit. Basically, I added utility functions to access the MIE and MIP CSRs. I also take advantage of the try_from methods of the traits to avoid returning raw numbers. This is aligned with the PLIC implementation of e310x-hal.

@romancardenas
Copy link
Contributor Author

Sorry for all these changes, but I've been discovering some deficiencies in my proposal.

Unlike the cortex-m crate, we need to provide a new/default constructor for the peripherals, as they are all optional and PACs are responsible for creating them when needed.

I developed an alternative version of the e310x crate that uses this generic implementation and compiles OK. Take a look to see how this peripheral would work.

I think this PR is now good to go (fingers crossed).

@romancardenas
Copy link
Contributor Author

I developed an alternative version of the e310x-hal that uses the generic PLIC peripheral. Later today I'll try a toy example on mi Sparkfun RED-V to confirm and illustrate that it works.

@romancardenas
Copy link
Contributor Author

Yaaay it works :D
I'm having some issues with the RTC and debugging, but the PLIC works as expected.

https://github.com/romancardenas/hifive1/blob/master/examples/interrupt.rs

@romancardenas romancardenas mentioned this pull request Mar 21, 2023
@romancardenas
Copy link
Contributor Author

I opened a new PR with a clean commit history of this very same implementation

bors bot added a commit that referenced this pull request May 12, 2023
129: PLIC peripheral r=romancardenas a=romancardenas

Same as #125 (closing right now) but with a clean commit history. I've been playing around with this implementation and detected nice-to-have features and boring patterns that could be implemented using macros. Pointers to repos that are already working with it:

- [`e310x` PAC](https://github.com/greenlsi/e310x)
- [`e310x-hal` HAL](https://github.com/greenlsi/e310x-hal)
- [`hifive1` BSP](https://github.com/romancardenas/hifive1) with an illustrative [example](https://github.com/romancardenas/hifive1/blob/master/examples/interrupt.rs)

Co-authored-by: Román Cárdenas <[email protected]>
romancardenas pushed a commit that referenced this pull request Nov 17, 2023
Remove label-check from merge_group
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants