1

I am an embedded C developer that recently started learning Rust. To help learn, I am beginning to develop a fairly large application in Rust for a Nordic nRf52832 MCU. I am using the nrf52832_pac crate for the project.

I was looking for some better direction or a recommended way to set this as a project global variable instead of passing it through each function in the project. It will function by passing the object around but it feels cluttered and sloppy.

My initial thought was to declare the global variable to be of type Option<Peripherals> initialized to None. Doing this will satisfy the compiler until the global variable is attempted to be assigned.

static mut _PERIPHERALS: Option<nrf52832_pac::Peripherals> = None;

pub fn init(){
   unsafe {_PERIPHERALS = Some(nrf52832_pac::Peripherals::take().unwrap()); }
}

pub fn set_pin_state(pin: u8, state: PinState) {
    unsafe {
        let p = _PERIPHERALS.unwrap();

        match state{
            PinState::PinLow => p.P0.outclr.write(|w| w.bits(1 << pin)),
            PinState::PinHigh => p.P0.outset.write(|w| w.bits(1 << pin)),
            _ => ()
        };
    };
}

This gives the following error at _PERIPHERALS.unwrap():

error[E0507]: cannot move out of static item `PERIPHERALS`
  --> src/mcu.rs:80:17
   |
80 |         let p = PERIPHERALS.unwrap();
   |                 ^^^^^^^^^^^ move occurs because `PERIPHERALS` has type `core::option::Option<nrf52832_pac::Peripherals>`, which does not implement the `Copy` trait

I have begun to derive the Copy trait but I don't feel like this is the right path. There must be a better way for a global peripherals object that I am not familiar with using.

  • 1
    Welcome to Stack Overflow! It looks like your question might be answered by the answers of [How do I create a global, mutable singleton?](https://stackoverflow.com/q/27791532/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Feb 19 '20 at 20:42
  • 1
    By the way, idiomatic Rust uses `snake_case` for variables, methods, macros, fields and modules; `UpperCamelCase` for types and enum variants; and `SCREAMING_SNAKE_CASE` for statics and constants. Do not prefix variables that you use with an underscore. – Shepmaster Feb 19 '20 at 20:43
  • 3
    *instead of passing it through each function* — I think this is actually often the **better** choice. – Shepmaster Feb 19 '20 at 20:45
  • 1
    Have you read the code of any of the myriad of embedded Rust libraries that solve the same problems you are attempting? – Shepmaster Feb 19 '20 at 20:45
  • @Shepmaster thanks for all the info so quickly. I had not found your other answer on global mutable singletons. I had been reading through the [Embedded Rust Book](https://rust-embedded.github.io/book/peripherals/singletons.html) but am having problems unwrapping the nrf52832_pac peripheral. – Taylor Spencer Feb 20 '20 at 05:14
  • As for your other comment on the exact error. I have edited the original post to show the complete error – Taylor Spencer Feb 20 '20 at 05:21

0 Answers0