How to specify memory region for multiple devices in memory.x file?


I would like to have memory regions defined for different device in memory.x file which is correctly selected somehow based on "cargo build --features 'device' " during build process.

Is there a way to do it?

something like this:
FLASH : ORIGIN = 0x10000000, LENGTH = 512k
RAM : ORIGIN = 0x20000000, LENGTH = 20K
#elif defined(device_2)
FLASH : ORIGIN = 0x10005000, LENGTH = 256k
RAM : ORIGIN = 0x20000000, LENGTH = 8K
#error "Unsupported device"


What do you mean by that? How is the correct device selected? Is it specified by you before building or is it somehow discovered during the build process?

If you define the devices beforehand as features (which is how I'd interpret your "cargo build --features 'device' " and the preprocessor usage in your snippet), I believe this'd be close to a Rust equivalent of that snippet:

struct MEMORY;

struct Region {
    ORIGIN: usize,
    LENGTH: usize,

impl MEMORY {
    cfg_if::cfg_if! {
        if #[cfg(feature = "device_1")] {
            const FLASH: Region = Region { ORIGIN: 0x10000000, LENGTH: 512_000 };
            const RAM: Region = Region { ORIGIN: 0x20000000, LENGTH: 20_000 };
        } else if #[cfg(feature = "device_2")] {
            const FLASH: Region = Region { ORIGIN: 0x10005000, LENGTH = 256_000 };
            const RAM: Region = Region { ORIGIN: 0x20000000, LENGTH: 8_000 };
        } else {
            // panics at compile time if we haven't specified either feature 
            // `device_1` or `device_2`
            compile_error!("unsupported device");

Note though, if you were to specify both device_1 and device_2 as features (Cargo currently does not have mutually exclusive features), you'd always get just the device_1 values.

1 Like

rust doesn't have a pre-processor, and the cargo feature flags are translated to rustc compiler flags, and the memory.x file is an input script to the linker, it's not processed by the rust compiler in any means.

you can do the "selection" using a build script, and I see several options available here:

a) include one linker script per each device, and based on the cargo feature flags, the build script will copy and rename (or pass correct command line flags to the linker without renaming it to the predefined "memory.x") the desired one.

b) pre-process the file yourself in the build script. it doesn't necessarily use the C pre-processor syntax, you can use whatever templating engine you like, or you can do your custom text process algorithm.

c) put all the configuration logic into the build script, and compose/generate the linker script without the need for a pre-defined template file.