Why the value of option is_some() is not expected in a bare metal environment

I'm working in the mini2440 bare metal environment.(no_std)
has the following rust code

mod uart;
mod uart_register;

// use self::uart::Uart;
pub use uart::Uart;

static mut PERIPHERALS: Option<Peripherals> = None;

pub struct Peripherals {
    pub uart0: Uart,
}

impl Peripherals {
    #[inline]
    pub fn take() {
        unsafe {
            let mut uart = Uart::from(0x50000000);
            uart.init_polling();

            if PERIPHERALS.is_none() {
                uart.put_u8('s' as u8);
            } else {
                uart.put_u8('d' as u8);
            }
        }
    }
}

and in the main code, I just call the take function

#![no_std]
#![no_main]
mod lang_items;
mod peripherals;
mod console;

use core::arch::global_asm;

use peripherals::{Peripherals, Uart};

#[macro_use]
extern crate bounded_registers;
#[macro_use]
extern crate typenum;

global_asm!(include_str!("entry.asm"));


#[no_mangle]
pub fn rust_main() -> ! {
    Peripherals::take();
    loop {
    }
}

The expected output in serial should be 's', but is 'd'. I didn't set the value of PERIPHERALS anywhere, so the value of PERIPHERALS should always be none.

in std environment, it's ok.

My question is, why is this so, am I writing something wrong or something else? Please help me :sob:

Could there be a UB in the uart code or an error in the asm?

Is the result the same with debug and release build?

You can try moving around the static in the binary by adding #[link_section = ".my_section"] (I dont know if this actually works).

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.