-
Notifications
You must be signed in to change notification settings - Fork 158
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] user defined memory layout #402
Comments
I like the idea but if we're going to introduce such major breakage I would propose that we collect additional breaking changes (e.g. from the wishlist) and do it in one big swoop. E.g. I'd like to pitch my idea of splitting the If there's interest in this I'd be happy to put it into an RFC. |
Overall I like this idea as it gives a sane interface to memory layout. What I am worried about though is that this might not be transparent for people using it and being a bit too much "magic". If this starts going forward I can help test is as well. |
Sounds good! This seems a lot friendlier than requiring users put additional custom Does this make it harder to use a custom linker script entirely? At the moment you can just copy I wonder if we can combine the proposed new reset handling with the worries in rust-embedded/bare-metal#15 and @therealprof's suggestion of a separate optional |
While we're talking about higher level customizability I'd love the ability to make the reset handler naked and manually set up the stack inside it, since in my context it's being called by a bootloader. |
As for suggestions on how to make this less complicated - obviously you can't be reductive with a cargo feature, but who says it's got to still all be the same crate? Why not split up the frameworkiness of this crate with the 'default profile' that loads memory.x, pick one to keep in this crate, put the other in a new one, and set the framework as a dependency from the profile? Depending on how it's implemented, it might not even warrant a minor release bump. Would this work? |
224: Allow general exception / interrupt discovery in cortex-m-rt-macros r=korken89 a=mciantyre We propose changes to the `cortex-m-rt-macros` crate that should help us use the macros independent of the `cortex-m-rt` runtime. The changes in this PR should be backwards compatible for all `cortex-m-rt` users, while expanding the utility of the macros beyond the cortex-m-rt repository. In the [Teensy 4 libraries](https://github.com/mciantyre/teensy4-rs) we're developing, we've opted to create our own runtime crate, `teensy4-rt`. We require more support than what's available in `cortex-m-rt` to boot and take advantage of NXP iMXRT106x variants. Specifically, we have a unique start-up process, and a custom memory layout with tightly-couple memory (TCM) regions. As discussed in #164, the `cortex-m-rt` crate does not support custom memory layouts. To address the limitations and provide a faster proof-of-concept, we forked the `cortex-m-rt` crate, focusing on the runtime needs of our specific system. Despite the fork, we strive for compatibility with the `cortex-m-rt` crate. Our eventual goal is to drop the `teensy4-rt` crate, and rely on a future version of the `cortex-m-rt` crate that supports our use-case. Compatibility means supporting the macros; just as the `cortex-m-rt` crate exports the macros, the `teensy4-rt` crate exports the same macros. By requiring that the macros maintain `extern crate cortex_m_rt` declarations, we assume that the `cortex_m_rt` crate is available. However, we don't believe this is a necessary requirement. To take advantage of the `#[interrupt]` and `#[exception]` macros, a set of crates need to export two identifiers: `interrupt`, an enumeration of valid interrupt handlers; and `exception`, an enumeration of exceptions for the Cortex M variant. We have a precedent for this pattern, in that crates generated by `svd2rust` export the enumeration of valid interrupt handlers (provided the correct features are enabled) for discovery by the `#[interrupt]` macros. The PR proposes a similar strategy: export the `Exceptions` enumeration as `exception` (lower case) from the `cortex-m-rt` crate, so that exception variant discovery occurs the same as it does for interrupts. After the rename, and with the removal of `extern crate cortex_m_rt` in the two macros, it doesn't matter where the `exception` or `interrupt` enums are defined. The changes let us define a similar `exception` enumeration in our `teensy4-rt` crate, which may be picked up by the `#[exception]` macro. We've shown this to be a successful strategy in the Teensy 4 Rust libraries, which are based on our fork of the macros crate. We realize that the macros are a feature of the `cortex-m-rt` crate, not a library that others should directly depend on. Ideally, we rally around the `cortex-m-rt` crate, and keep the macros coupled to that implementation. But until we reach that point, having the macros defined without expectations of the `cortex-m-rt` crate lets us bring up new embedded targets faster while maintaining compatibility with the existing ecosystem. Co-authored-by: Ian McIntyre <[email protected]>
I don't think there was a decision on this RFC. |
Adding this to the 1.0 milestone. It would be very unfortunate if we shipped 1.0 without being able to have this sort of fine-grained control over the memory layout. |
I started working on the basics provided in this API as the NXP i.MX RT series has quite a few features that are usable only with varying linker settings. See https://github.com/imxrt-rs/imxrt-rt-gen |
This adds a `cortex-m-rt-patch` directory that contains a tiny crate that re-exports `teensy4-rt` in its entirety under the crate name `cortex-m-rt` to provide a convenient way of patching upstream crates. The hope is to make workarounds for issues like mciantyre#62 a little easier pending solving rust-embedded/cortex-m-rt#164 and the reconciliation of `cortex-m-rt` and `teensy4-rt`.
Summary
Change how the memory layout of
cortex-m-rt
programs is defined. Let the userspecify memory regions and linker sections using a high level API from build
scripts.
Background
Some embedded devices contain more than a single RAM region; these memory
regions usually have different performance characteristics (e.g. Tightly Coupled
Memory (TCM) is faster to access than regular RAM but it may have the downside
that it cannot be accessed by the DMA). In these cases one may want fine grained
control over the location of
static
variables and the (call) stack(s).Other devices may have a mixture of Cortex-M and Cortex-A cores where the M
cores have no Flash and the A cores directly load programs onto the M cores'
RAM. In these cases one would like to skip doing the initialization of .bss and
.data on the M cores as the A cores will take care of that.
None of the above scenarios can be properly handled with the current system.
Design
User API
End users will define the memory layout of their device in a build script. The
code below depicts a build script that defines a complex memory layout that
makes use of two RAM regions. Note that the presented API is not final.
Library changes
The
Reset
handler will be removed from thecortex-m-rt
crate. Instead the#[entry]
attribute will expand into bothReset
andmain
.main
will continue to be the user entry point. The contents of thereset.rs
file will be generated by
LinkerScript::generate
. The code inreset.rs
willcall
pre_init
; initialize.bss
,.data
and other user defined sections;initialize the FPU, if present; and finally call
main
.#[ramfunc]
,#[bss]
,#[data]
,#[uninit]
Attributes to place
static [mut]
variables and functions in custom sectionswill be added to
cortex-m-rt
.#[ramfunc]
can be used to place a function in a RAM region.#[data]
can be used to place astatic [mut]
variable in a user defined.data
section.#[bss]
can be used to place astatic [mut]
variable in a user defined.bss
section. As this section is always zeroed the user must assert this factby wrapping the initial value, which should evaluate to "all zeros", in an
unsafe
block.#[uninit]
can be used to leavestatic [mut]
uninitialized. These variableswill be placed in a
.uninit
section.Drawbacks
This is a breaking change.
It's not possible to retain the existing "just define a
memory.x
file"model with the proposed changes. The reason is that the build script that
describes the memory layout of the target must live in the top crate
(otherwise
reset.rs
can't be located by#[entry]
) and there must only existone of such build scripts in the dependency graph (or you'll end with multiple
link.x
and the linker will pick one randomly). Thus, all end users will haveto deal with build scripts.
We can ease the migration by providing a helper function that replicates today's
behavior but the user will have to modify their projects to include a build
script that looks like this:
Also note that we can't put "user defined memory layout" behind a Cargo feature
because Cargo features must be strictly additive since any dependency is free to
enable them. If this were a feature enabling it would require adding or
modifying the top build script.
Unresolved questions
An API to let users specify linker section offsets (required on NXP devices to
avoid placing .text on top of Flash configuration memory) has yet to be
designed.
Alternatives
We could rename the
#[ramfunc]
to#[text]
and make its argument mandatory.Accordingly, instead of output
[.$REGION].ramfunc
sections we would use.$REGION.text
sections to place functions in RAM.This proposal obsoletes rust-embedded/cortex-m-rt#32, rust-embedded/cortex-m-rt#100 and #398
cc @rust-embedded/cortex-m
The text was updated successfully, but these errors were encountered: