pub struct RuntimeBuilder { /* private fields */ }
Expand description

Builder for the i.MX RT runtime.

RuntimeBuilder let you assign sections to memory regions. It also lets you partition FlexRAM DTCM/ITCM/OCRAM. Call build() to commit the runtime configuration.

§Behaviors

The implementation tries to place the stack in the lowest-possible memory addresses. This means the stack will grow down into reserved memory below DTCM and OCRAM for most chip families. The outlier is the 1170, where the stack will grow into OCRAM backdoor for the CM4 coprocessor. Be careful here…

Similarly, the implementation tries to place the heap in the highest-possible memory addresses. This means the heap will grow up into reserved memory above DTCM and OCRAM for most chip families.

The vector table requires a 1024-byte alignment. The vector table’s placement is prioritized above all other sections, except the stack. If placing the stack and vector table in the same section (which is the default behavior), consider keeping the stack size as a multiple of 1 KiB to minimize internal fragmentation.

§Default values

The example below demonstrates the default RuntimeBuilder memory placements, stack sizes, and heap sizes.

use imxrt_rt::{Family, RuntimeBuilder, Memory};

const FLASH_SIZE: usize = 16 * 1024;
let family = Family::Imxrt1060;

let mut b = RuntimeBuilder::from_flexspi(family, FLASH_SIZE);
// FlexRAM banks represent default fuse values.
b.flexram_banks(family.default_flexram_banks());
b.text(Memory::Itcm);    // Copied from flash.
b.rodata(Memory::Ocram); // Copied from flash.
b.data(Memory::Ocram);   // Copied from flash.
b.vectors(Memory::Dtcm); // Copied from flash.
b.bss(Memory::Ocram);
b.uninit(Memory::Ocram);
b.stack(Memory::Dtcm);
b.stack_size(8 * 1024);  // 8 KiB stack.
b.heap(Memory::Dtcm);    // Heap in DTCM...
b.heap_size(0);          // ...but no space given to the heap.

assert_eq!(b, RuntimeBuilder::from_flexspi(family, FLASH_SIZE));

§Environment overrides

Certain memory regions, like the stack and heap, can be sized using environment variables. As the provider of the runtime, you can use *_env_override methods to select the environment variable(s) that others may use to set the size, in bytes, for these memory regions.

The rest of this section describes how environment variables interact with other methods on this builder. Although the examples use stack size, the concepts apply to all regions that can be sized with environment variables.

RuntimeBuilder::from_flexspi(family, FLASH_SIZE)
    .stack_size_env_override("YOUR_STACK_SIZE")
    // ...

In the above example, if a user set an environment variable YOUR_STACK_SIZE=1024, then the runtime’s stack size is 1024. Otherwise, the stack size is the default stack size.

As a convenience, a user can use a k or K suffix to specify multiples of 1024 bytes. For example, the environment variables YOUR_STACK_SIZE=4k and YOUR_STACK_SIZE=4K are each equivalent to YOUR_STACK_SIZE=4096.

RuntimeBuilder::from_flexspi(family, FLASH_SIZE)
    .stack_size_env_override("YOUR_STACK_SIZE")
    .stack_size(2048)
    // ...

RuntimeBuilder::from_flexspi(family, FLASH_SIZE)
    .stack_size(2048)
    .stack_size_env_override("YOUR_STACK_SIZE")
    // ...

In the above example, the two builders produce the same runtime. The builder selects the stack size from the environment variable, if available. Otherwise, the stack size is 2048 bytes. The call order is irrelevant, since the builder doesn’t consult the environment until you invoke build().

RuntimeBuilder::from_flexspi(family, FLASH_SIZE)
    .stack_size_env_override("INVALIDATED")
    .stack_size_env_override("YOUR_STACK_SIZE")
    // ...

In the above example, YOUR_STACK_SIZE invalidates the call with INVALIDATED. Therefore, YOUR_STACK_SIZE controls the stack size, if set. Otherwise, the stack size is the default stack size.

Implementations§

source§

impl RuntimeBuilder

source

pub fn from_flexspi(family: Family, flash_size: usize) -> Self

Creates a runtime that can execute and load contents from FlexSPI flash.

flash_size is the size of your flash component, in bytes.

source

pub fn flexram_banks(&mut self, flexram_banks: FlexRamBanks) -> &mut Self

Set the FlexRAM bank allocation.

Use this to customize the sizes of DTCM, ITCM, and OCRAM. See the FlexRamBanks documentation for requirements on the bank allocations.

source

pub fn text(&mut self, memory: Memory) -> &mut Self

Set the memory placement for code.

source

pub fn rodata(&mut self, memory: Memory) -> &mut Self

Set the memory placement for read-only data.

source

pub fn data(&mut self, memory: Memory) -> &mut Self

Set the memory placement for mutable data.

source

pub fn vectors(&mut self, memory: Memory) -> &mut Self

Set the memory placement for the vector table.

source

pub fn bss(&mut self, memory: Memory) -> &mut Self

Set the memory placement for zero-initialized data.

source

pub fn uninit(&mut self, memory: Memory) -> &mut Self

Set the memory placement for uninitialized data.

source

pub fn stack(&mut self, memory: Memory) -> &mut Self

Set the memory placement for stack memory.

source

pub fn stack_size(&mut self, bytes: usize) -> &mut Self

Set the size, in bytes, of the stack.

source

pub fn stack_size_env_override(&mut self, key: impl AsRef<str>) -> &mut Self

Let end users override the stack size using an environment variable.

See the environment overrides documentation for more information.

source

pub fn heap(&mut self, memory: Memory) -> &mut Self

Set the memory placement for the heap.

Note that the default heap has no size. Use heap_size to allocate space for a heap.

source

pub fn heap_size(&mut self, bytes: usize) -> &mut Self

Set the size, in bytes, of the heap.

source

pub fn heap_size_env_override(&mut self, key: impl AsRef<str>) -> &mut Self

Let end users override the heap size using an environment variable.

See the environment overrides documentation for more information.

source

pub fn flexspi(&mut self, peripheral: FlexSpi) -> &mut Self

Set the FlexSPI peripheral that interfaces flash.

See the FlexSpi to understand the default values. If this builder is not configuring a flash-loaded runtime, this call is silently ignored.

source

pub fn linker_script_name(&mut self, name: &str) -> &mut Self

Set the name of the linker script file.

You can use this to customize the linker script name for your users. See the crate-level documentation for more information.

source

pub fn build(&self) -> Result<(), Box<dyn Error>>

Commit the runtime configuration.

build() ensures that the generated linker script is available to the linker.

§Errors

The implementation ensures that your chip can support the FlexRAM bank allocation. An invalid allocation is signaled by an error.

Returns an error if any of the following sections are placed in flash:

  • data
  • vectors
  • bss
  • uninit
  • stack
  • heap

The implementation may rely on the linker to signal other errors. For example, suppose a runtime configuration with no ITCM banks. If a section is placed in ITCM, that error could be signaled here, or through the linker. No matter the error path, the implementation ensures that there will be an error.

Trait Implementations§

source§

impl Clone for RuntimeBuilder

source§

fn clone(&self) -> RuntimeBuilder

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for RuntimeBuilder

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for RuntimeBuilder

source§

fn eq(&self, other: &RuntimeBuilder) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Eq for RuntimeBuilder

source§

impl StructuralPartialEq for RuntimeBuilder

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.