Skip to content
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

[RFC] supporting other architectures #203

Closed
japaric opened this issue Jun 14, 2019 · 10 comments
Closed

[RFC] supporting other architectures #203

japaric opened this issue Jun 14, 2019 · 10 comments
Labels
RFC This issue needs you input! S-accepted This RFC has been accepted but not yet implemented
Milestone

Comments

@japaric
Copy link
Collaborator

japaric commented Jun 14, 2019

Current state

cortex-m-rtfm is the main port of the RTFM framework. There are two outdated
ports of RTFM for MSP430 and RISCV and two experimental Cortex-R and Linux
ports. None of these ports shares code with one another so they have diverged or
stalled since their inception.

The cortex-m-rtfm port is under @japaric's GitHub account and currently has 3
people maintaining it.

Proposal

This RFC proposes refactoring out the RTFM syntax (meta-language) and analysis
pass that currently live in cortex-m-rtfm into a crate that can be used to
easily implement ports for different architectures.

Rationale

We want to make RTFM available on as many architectures as possible with minimal
maintenance effort and with as similar APIs / syntax as possible.

Detailed design

This RFC proposes the following crate hierarchy:

rtfm-core

This crate will only contain the Mutex trait and the Exclusive newtype and
it's meant to be used to implement generic library code.

pub trait Mutex {
    type Data;

    fn lock<T>(&mut self, f: impl FnOnce(&mut Self::Data) -> T) -> T;
}

pub struct Exclusive<T>(pub &'a mut T);

// trivial implementation (no-op)
impl<T> Mutex for Exclusive<T> { .. }

rtfm-syntax

This crate will contain the parser of the #[app] and the analysis pass (e.g.
priority ceiling analysis) of the RTFM specification.

The main function in this crate is the parse function which parse the input of
the #[app] attribute.

use syn::Parse;

use crate::{ast::App, analyze::Analysis};

pub fn parse(
    args: TokenStream,
    input: TokenStream,
    settings: Settings,
) -> parse::Result<(App, Analysis) {
    ..
}

To accommodate the different capabilities of the many RTFM ports this function
takes a Settings struct that indicates which extensions the port implements.

pub struct Settings {
    // multi-core support: `#[app(cores = ..)]`, `#[task(core = ..)]`, etc.
    pub parse_cores: bool,

    // `#[exception]`
    pub parse_exception: bool,

    // `#[interrupt]`
    pub parse_interrupt: bool,

    // `schedule` API
    pub parse_schedule: bool,

    // `extern { fn interrupt(); }`
    pub parse_extern_interrupt: bool,

    // ..
}

$ARCH-rtfm

These are the actual ports. These crates will use the rtfm-syntax crate to
implement the #[app] attribute and they'll re-export the rtfm-core API.

All ports must implement the following API:

  • the lock API
  • runtime initialized (late) resources
  • software #[task]s and spawn API

And they may implement any of these extensions:

  • #[exception] API

  • #[interrupt] API

  • schedule API

  • multi-core support

GitHub org

All these crates will be owned by the rtfm-rs GitHub organization and
maintained by the members of the organization. The idea is to grow the
membership of the organization to include people with expertise on
architectures other than ARM Cortex-M.


I have already done the refactor and have tested the portability of the
rtfm-syntax crate by implementing a Linux port (base features +
schedule + multi-core support) and the single-core and multi-core variants of
cortex-m-rtfm (see PR #205).

cc'ing people that may be interested in other ports:

@Disasm (rust-embedded/riscv)
@cr1901 @pftbest (rust-embedded/msp430)

@japaric japaric added the RFC This issue needs you input! label Jun 14, 2019
@japaric japaric added this to the v0.5.0 milestone Jun 14, 2019
@Disasm
Copy link

Disasm commented Jun 14, 2019

I'm interested in having RTFM for RISC-V, however I need to understand possible RISC-V-related limitations and how to deal with them (if possible).

  • We have "exception", "interrupt" and "IRQ" concepts. IRQs are different and defined on device-level and even may not exists at all.
  • SMP (not AMP) support on some chips.
  • We have priorities only for IRQs. Additionally, platform-dependent PLIC implementation can support an arbitrary (yet fixed) number of priorities.
  • Timers are accessed in a device-dependent way.
  • Some "devices" are FPGA softcores that do not have Privileged Architecture parts at all. No timers, no interrupts (standardized), no ability to check the current core id.

P.S. I'm not quite familiar with RTFM, so I need to study it first in detail.

@cr1901
Copy link

cr1901 commented Jun 14, 2019

I need to view @korken89's presentation on RTFM before I could meaningfully contribute a port, but I am very interested and supportive of this proposal.

This would also be a good opportunity to flesh out what features are feasible to support on archs more constrained than cortex-m (e.g. msp430 has nowhere near the amount of priority levels NVIC does).

@japaric
Copy link
Collaborator Author

japaric commented Jun 16, 2019

@Disasm I have a prototype implementation that targets the HiFive1 board here. The prototype implements the core API plus the schedule and #[interrupt] extensions.

IRQs are different and defined on device-level and even may not exists at all.

Even if you have zero IRQs, you can use the (machine) software (MSI) / timer (MTI) interrupt to implement (software) tasks.

We have priorities only for IRQs

But you can individually mask interrupts (MSIE, MTIE, etc.); it's possible to implement some form of prioritization (and critical sections) using interrupt masking.

SMP (not AMP) support on some chips.

(I have one of those K210 chips; too bad my "development" board has no on-board debugger (and I have no JTAG probe around) so I can't actually do any actual development on it ...)

Timers are accessed in a device-dependent way.

mtime and mtimecmp seem rather standard to me. They may be memory mapped registers and their address may be device-dependent but their binary interface and semantics are well specified. In any case, timers are not necessary to implement the core API.

Some "devices" are FPGA softcores that do not have Privileged Architecture parts at all.

We could state that some privileged parts are required to use RTFM on RISCV. If the softcore has zero support for interrupts / preemption then we can't run RTFM on it.

@Disasm
Copy link

Disasm commented Jun 16, 2019

@japaric Thanks for making the prototype!

too bad my "development" board has no on-board debugger (and I have no JTAG probe around)

I use BusBlaster based on FTDI chip, but I think that any JTAG adapter for FPGA would work.

mtime and mtimecmp seem rather standard to me. They may be memory mapped registers and their address may be device-dependent but their binary interface and semantics are well specified. In any case, timers are not necessary to implement the core API.

They are standard, but due to their device-dependent addressing I have no idea how to pass them to the RTFM implementation. Of cause, we could tie riscv-rtfm to the FE310 chip family, but this solution is far from perfect.

@japaric
Copy link
Collaborator Author

japaric commented Jun 19, 2019

@Disasm

They are standard, but due to their device-dependent addressing I have no idea how to pass them to the RTFM implementation.

As part of the prototype I wrote a riscv crate from scratch (to force me to read the RISC-V spec). That crate contains an API to access the mtime and mtimecmp registers. To get around the device specific address I used symbols. In the riscv crate the address of the mtime register is an external symbol; this symbol must be provided by a device crate (PAC) like the hifive1 crate in that repository.

With this approach any crate can use the mtime register by depending only on riscv and not on any particular device crate. When building an application where the mtime API is used a device crate must appear in the dependency graph or you get a not really helpful error. The symbol, and the device crate, don't need to appear in the dependency graph when building libraries that use the mtime API.

There are other ways to pass device specific information to the RTFM runtime though. The Cortex-M port uses a device argument, which is a path to a module, in its #[app] attribute. This module is expected to contain an enumeration of all interrupts (Interrupt), the number of priority bits (const NVIC_PRIO_BITS: u8), etc. It's also possible for ports to define other custom #[app] arguments. One example is the monotonic argument proposed in RFC #200.

@korken89
Copy link
Collaborator

I think this is a great idea!
The power that SRP gives through this framework should fit a lot more than Cortex-M, and this is indeed a great way to get there.
I also hope that something like this would help with the readability of the code, as this is quite a challenge today.

@japaric
Copy link
Collaborator Author

japaric commented Jun 29, 2019

This proposal has been well received so I'm going to FCP it with disposition to merge it.

We can start right away with the refactor and take our time to roll out the org. (One extra thing I'd like to do is create an rfcs repo and archive all these RFCs as proper markdown files).

@TeXitoi
Copy link
Collaborator

TeXitoi commented Jun 29, 2019

OK for me

@japaric
Copy link
Collaborator Author

japaric commented Jul 8, 2019

🎉 This RFC has been formally approved. The refactor part is in PR #205.

@japaric japaric added S-accepted This RFC has been accepted but not yet implemented and removed disposition-merge labels Jul 8, 2019
bors bot added a commit that referenced this issue Sep 15, 2019
205: rtfm-syntax refactor + heterogeneous multi-core support r=japaric a=japaric

this PR implements RFCs #178, #198, #199, #200, #201, #203 (only the refactor
part), #204, #207, #211 and #212.

most cfail tests have been removed because the test suite of `rtfm-syntax`
already tests what was being tested here. The `rtfm-syntax` crate also has tests
for the analysis pass which we didn't have here -- that test suite contains a
regression test for #183.

the remaining cfail tests have been upgraded into UI test so we can more
thoroughly check / test the error message presented to the end user.

the cpass tests have been converted into plain examples

EDIT: I forgot, there are some examples of the multi-core API for the LPC541xx in [this repository](https://github.com/japaric/lpcxpresso54114)

people that would like to try out this API but have no hardware can try out the
x86_64 [Linux port] which also has multi-core support.

[Linux port]: https://github.com/japaric/linux-rtfm

closes #178 #198 #199 #200 #201 #203 #204 #207 #211 #212 
closes #163 
cc #209 (documents how to deal with errors)

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
bors bot added a commit that referenced this issue Sep 15, 2019
205: rtfm-syntax refactor + heterogeneous multi-core support r=japaric a=japaric

this PR implements RFCs #178, #198, #199, #200, #201, #203 (only the refactor
part), #204, #207, #211 and #212.

most cfail tests have been removed because the test suite of `rtfm-syntax`
already tests what was being tested here. The `rtfm-syntax` crate also has tests
for the analysis pass which we didn't have here -- that test suite contains a
regression test for #183.

the remaining cfail tests have been upgraded into UI test so we can more
thoroughly check / test the error message presented to the end user.

the cpass tests have been converted into plain examples

EDIT: I forgot, there are some examples of the multi-core API for the LPC541xx in [this repository](https://github.com/japaric/lpcxpresso54114)

people that would like to try out this API but have no hardware can try out the
x86_64 [Linux port] which also has multi-core support.

[Linux port]: https://github.com/japaric/linux-rtfm

closes #178 #198 #199 #200 #201 #203 #204 #207 #211 #212 
closes #163 
cc #209 (documents how to deal with errors)

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
@japaric
Copy link
Collaborator Author

japaric commented Sep 15, 2019

Done in PR #205

@japaric japaric closed this as completed Sep 15, 2019
andrewgazelka pushed a commit to andrewgazelka/cortex-m-rtic that referenced this issue Nov 3, 2021
203: Update to Syn 1.0 r=korken89 a=dtolnay

Release notes: https://github.com/dtolnay/syn/releases/tag/1.0.0

Co-authored-by: David Tolnay <dtolnay@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
RFC This issue needs you input! S-accepted This RFC has been accepted but not yet implemented
Projects
None yet
Development

No branches or pull requests

5 participants