🌐
Reddit
reddit.com › r/rust › bare metal blink on raspberry 4 with rust 2021
r/rust on Reddit: Bare metal blink on Raspberry 4 with Rust 2021
July 27, 2023 - I saw you were using the soft-float target, does the pi 4 not have a hardware floating point unit or was that just to make things easier? ... Yes! The arm core used by Rasp has a FPU. Honestly, I just copied from rust-raspberrypi-OS-tutorials
🌐
Reddit
reddit.com › r/raspberry_pi › help with qemu simulated raspberry, and bare metal rust
r/raspberry_pi on Reddit: Help with QEMU simulated raspberry, and bare metal Rust
April 9, 2024 -

Hello there,

I've started my journey on bare metal Rust written on a Respberry (simulated with QEMU for now, I'm using the raspberry pi 2B model), and i'm still trying to make a "Hello world" program to run.

So far, I have written rust code that activates the mini UART, activates the GPIO 14/15 accordingly, and fills the send buffer of the mini UART. The main code looks like this :

let mut selector = GPFSEL1::read();
    selector &= !(7<<12);                   // clean gpio14
    selector |= 2<<12;                      // set alt5 for gpio14
    selector &= !(7<<15);                   // clean gpio15
    selector |= 2<<15;                      // set alt5 for gpio 15
    GPFSEL1::write(selector);
    
    GPPUD::write(0);
    delay(150);
    GPPUDCLK0::write((1<<14)|(1<<15));
    delay(150);
    GPPUDCLK0::write(0);
    
    AUX_ENABLES::write(1);                   // Enable mini uart (this also enables access to its registers)
    AUX_MU_CNTL_REG::write(0);               // Disable auto flow control and disable receiver and transmitter (for now)
    AUX_MU_IER_REG::write(0);                // Disable receive and transmit interrupts
    AUX_MU_LCR_REG::write(3);                // Enable 8 bit mode
    AUX_MU_MCR_REG::write(0);                // Set RTS line to be always high
    AUX_MU_BAUD_REG::write(270);             // Set baud rate to 115200
    AUX_MU_CNTL_REG::write(3);               // Finally, enable transmitter and receiver
    
    loop {
        AUX_MU_IO_REG::write('c' as u32);
        // print("Hello, World !")
    }

I've made a linker file, and explored the assembly, my code properly starts ar 0x8000:

target/armv7a-none-eabi/debug/harmony:     file format elf32-littlearm


Disassembly of section .text:

00008000 <_start>:
    8000:       e24dd010        sub     sp, sp, #16
    8004:       eb000061        bl      8190 <_ZN717Register$LT$_$GT$4read17ha9d176502c8214e9E>
    8008:       e58d000c        str     r0, [sp, #12]
    800c:       e59d000c        ldr     r0, [sp, #12]
    8010:       e3c00a07        bic     r0, r0, #28672  @ 0x7000
    8014:       e58d000c        str     r0, [sp, #12]
    8018:       e59d000c        ldr     r0, [sp, #12]
    801c:       e3800a02        orr     r0, r0, #8192   @ 0x2000
....

I then copy my elf file into a flat binary. Now, I'm running a simulated raspberry on QEMU, using the following command: qemu-system-arm -M raspi2b -kernel target/binary/my_custom_kernel.img -nographic

unfortunately, nothing happens. I've tried connecting to the QEMU process with the -s option on QEMU, and with gdb and the target remote localhost:1234 command, but then the stack pointer is shown to be at 0x0000, and when I try to see the registers they do not match the register names of the BCM2837-ARM. This makes me wondering if I'm using the QEMU+GDB thinhy properly.

I've been using this datasheet, following partly this tutorial.

Now, I'm out running out of ideas on what could go wrong, and I'm asking for help here. I have no clue where to look next !

If you guys need any more details, please ask !

Thanks in advance

🌐
Medium
medium.com › @thiagopnts › raspberry-pi-bare-metal-programming-with-rust-a6f145e84024
Raspberry Pi Bare Metal Programming with Rust | by Thiago | Medium
August 21, 2016 - With our `kernel.img` built, we just need to copy it to our Raspberry SD together with the other boot files (`start.elf` and `bootcode.bin`), stick our micro SD back into the Raspberry PI and turn it on to see our tiny kernel running and the LED blinking! There is a lot of other cool stuff we can do, like using the system timer on chip to implement our `sleep` function or create some abstractions of top of the GPIO addresses to encapsulate all the `unsafe` calls in a more elegant API. But I think for now this is a good way to get started with bare metal programming with Rust.
🌐
Raspberry Pi Forums
forums.raspberrypi.com › board index › programming › other programming languages
Baremetal + Rust - choosing the correct AArch64 build target - Raspberry Pi Forums
Looks to me that if you take the bare metal Rust you will have a lot of work to do to get it running on the Pi. Presumably there is no run time support, no drivers for any peripheral hardware etc, etc, You would effectively have to write a mini OS for yourself to get it running.
🌐
Reddit
reddit.com › r/raspberry_pi › raspberry pi 2 bare metal with rust, system timer not working
r/raspberry_pi on Reddit: Raspberry Pi 2 Bare Metal with Rust, System Timer not working
June 28, 2016 -

Hi there,

I've been doing some embedded Raspberry Pi stuff with Rust and I'm having some trouble getting the system timer on the RPi2 to work. Here is my kernel:

#![feature(lang_items, start, asm)]
#![no_std]

const GPIO_SET: u32 = 0x3F200020; //location of gpio set register
const GPIO_CLR: u32 = 0x3F20002C; //location of gpio clear register
const GPIO47: u32 = 0x8000; //location of gpio47, which is bit 16 in either register

const SYS_TIMER: u32 = 0x4000001c; //location of sys timer afaik

fn gpio_set(port: u32, enabled: bool) {
    let fun = match enabled {
            true => GPIO_SET as *mut u32, //fun = pointer to GPIO set or GPIO clear
            false => GPIO_CLR as *mut u32,
    };
    unsafe {
        *fun = port; //1 is written to bit 16 of either set or clear register.
    }
}

fn get_time() -> u32 {
    let pointer = SYS_TIMER as *mut u32;
    unsafe { *pointer } //dereference pointer to 
}

#[start]
fn main(argc: isize, argv: *const *const u8) -> isize {
    let mut old = get_time();

    loop {
        if get_time() - old > 1000000 {
            gpio_set(GPIO47, true); // This loop here should blink the light every second using the systimer
            old = get_time();
        };
    };

}

//lang features, need to be implemented or compiler shits itself.
#[lang = "eh_personality"]
extern fn eh_personality() {}

#[lang = "panic_fmt"]
extern fn panic_fmt() {}

This code does not make the led light up at all. I've based my kernel off of this bare metal Rust tutorial. After I completed that tutorial I've been trying to port Step 03 of the Valvers C tutorial to Rust, but it doesn't seem to be working. Any suggestions?

🌐
OSDev Wiki
wiki.osdev.org › Raspberry_Pi_Bare_Bones_Rust
Raspberry Pi Bare Bones Rust - OSDev Wiki
This is it! You've built Rust code for bare metal arm that will run on the Raspberry Pi!
🌐
Raspberry Pi Forums
forums.raspberrypi.com › board index › projects › other projects
Trouble running baremetal Rust kernel on Raspberry Pi Zero W! - Raspberry Pi Forums
Tue Nov 08, 2022 7:57 pm thats an aarch64 binary, but the pi-zero is armv6 only rustc doesn't support any targets for armv6, actually, so I'm currently following https://wiki.osdev.org/Raspberry_Pi_Bare_Bones_Rust, maybe it'll work...
Find elsewhere
🌐
GitHub
github.com › rsta2 › circle › issues › 127
Creating a list of Circle based bare metal projects for the Raspberry Pi · Issue #127 · rsta2/circle
August 4, 2020 - Rust: https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials, https://github.com/RusPiRo/ruspiro-kernel · I once have created a link list to other pages on the web with lists like this one. Just dropping them here for the moment: https://www.raspberrypi.org/forums/viewtopic.php?f=72&t=72260#p653097 · https://www.reddit.com/r/EmuDev/comments/7ys6w1/bare_metal_raspberry_pi_programming_resources_and/
Author   hpingel
🌐
Rust Programming Language
users.rust-lang.org › t › can-i-compile-rust-bare-metal-for-a-raspberrypi-4b › 125960
Can I compile rust bare metal for a RaspberryPi 4b? - The Rust Programming Language Forum
February 21, 2025 - Hello, I am as you can see an absolute newcomer to Rust and did not find any helpful information on whether I can compile Rust code bare metal for a RaspberryPi 4b. I want to do this because I want to build an operatin…
🌐
Reddit
reddit.com › r/rust › any clever ideas to make debugging bare metal code simpler?
r/rust on Reddit: Any clever ideas to make debugging bare metal code simpler?
December 28, 2022 -

I'm building a bare metal project for the Raspberry Pi 4 which is like a small kernel, game engine, and game together in a single raw binary. The idea is to go through a similar experience of what DOS game developers went through long ago by developing everything from scratch, entertain myself since I'm totally blind on disability benefits, and gain experience in embedded Rust along the way. After implementing the kernel part with drivers and an executor to take advantage of cooperative multitasking with the async / await coroutines supported by Rust, I have now built a software 3D rasterizer which is grinding to a halt after just a couple of frames. My belief is that deadlocks are to blame for the problem, but unfortunately since this is a bare metal project and qemu does not support emulating the Raspberry Pi 4, I'm kinda stuck debugging on actual hardware with messages sent over a serial cable. My locks are capable of catching some deadlocks, particularly those caused by locking twice in the same core, but this is not the only possible kind of deadlock.

My problem is that I cannot find an easy way to change my spin-lock to print the file and line where it was called, which would allow me to easily check where it got locked and not unlocked. I did build a backtrace function that displays the return addresses of all the functions in the call stack all the way back to the function called by the boot code, but matching its output to the contents of the raw binary is quite cumbersome since I have to link the final binary as an ELF instead of a raw binary, and then manually objcopy that to the final raw binary since Cargo's build scripts aren't powerful enough, and to make things worse there is no binutils targeting AArch64 on MacPorts, so I've been doing the objcopy step from a Docker container. If I was coding in C the solution would be easy: I'd just make a macro to replace all lock and unlock calls and send the file and line from the caller over the serial cable, but unfortunately since Rust macros require an extra bang, and since to my knowledge it is not possible to create a macro that simulates an associated function, this would never be a viable solution in Rust.

Has anyone here faced a similar problem with embedded Rust? And if so, how did you address it? I'm posting my backtrace function, its generated output, and my custom target file below just in case someone has suggestions for changes that could be made to improve the situation.

The backtrace function:

/// Sends the return addresses of all the function calls from this function all the way to the start function through the UART.
fn backtrace() {
    let mut uart = UART.lock();
    let mut fp: usize;
    let mut lr: usize;
    unsafe {asm!("mov {fp}, fp", "mov {lr}, lr", fp = out (reg) fp, lr = out (reg) lr, options (nomem, nostack, preserves_flags))};
    let mut frame = 0usize;
    writeln!(uart, "Backtrace:").unwrap();
    while fp != 0x0 {
        writeln!(uart, "#{frame}: 0x{lr:X}").unwrap();
        unsafe {asm!("ldp {fp}, {lr}, [{fp}]", fp = inout (reg) fp, lr = out (reg) lr, options (preserves_flags))};
        frame += 1;
    }
}

Example of the serial output that I get in a session with a forced panic to display the backtrace (core #3 was already sailing on weeds at this point since it didn't catch the software generated interrupt that was supposed to halt it on a panic):

Booted core #0
Booted core #1
Booted core #2
Tick in!
Booted core #3
Starting tasks...
Frame #0
Frame #1
Tasks finished!
Core #0 panicked at src/gfx/mod.rs:201: Test!
Backtrace:
#0: 0x854EC
#1: 0x85450
#2: 0x8FB08
#3: 0x8973C
#4: 0x880D0
#5: 0x872A8
#6: 0x84D84
Halted core #0
Halted core #2
Halted core #1

My custom target file:

{
  "cpu": "cortex-a72",
  "arch": "aarch64",
  "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
  "disable-redzone": true,
  "features": "+strict-align",
  "is-builtin": false,
  "linker": "rust-lld",
  "linker-flavor": "ld.lld",
  "pre-link-args": {
    "ld.lld": ["-Tlink.ld", "-nostdlib", "--oformat=binary"]
  },
  "llvm-target": "aarch64-unknown-none",
  "max-atomic-width": 128,
  "panic-strategy": "abort",
  "relocation-model": "static",
  "target-pointer-width": "64",
  "frame-pointer": "always"
}
🌐
Hacker News
news.ycombinator.com › item
Raspberry Pi Bare Metal Programming with Rust | Hacker News
January 19, 2016 - Yes, and that is unsafe. Rust makes you put that in an unsafe block, to encourage you to build safe interfaces. This is a good thing · The alternative to name mangling is not having a module system, with all the fun name conflict issues that come with it. Rust made the right decision here
🌐
Hacker News
news.ycombinator.com › item
Bare Metal Programming on Raspberry Pi 3 | Hacker News
October 2, 2020 - What does he mean by this? Rust has no-std mode, you can run it on an ARM M0 if you so desire · That said, nobody is obligated to use Rust. He should write his tutorial in whatever he wants. This isn't an actual blocker, though
🌐
GitHub
github.com › wizofe › rust-raspi3-tutorial
GitHub - wizofe/rust-raspi3-tutorial: Bare metal Raspberry Pi 3 tutorials in Rust
Hi all. This repository aims to provide easy reference code for programming bare metal on the Raspberry Pi 3 in the Rust systems programming language.
Author   wizofe
🌐
Fponzi
blog.fponzi.me › 2023-08-13-bare-metal-space-invaders.html
Bare Metal Space Invaders
August 13, 2023 - Bare metal programming is programming on hardware without an Operating System. In this post, I will share some of the learning I gained after programming a Space Invaders-like game in Rust.