36

I'm interested in using the Raspberry Pi as a pure embedded CPU unit, for the development of embedded applications. Since the Raspberry Pi has a powerful CPU with quite a bit of memory, it makes an excellent embedded board.

Is it possible to use the Raspberry Pi without a Linux OS? How can I do this?

iconoclast
  • 105
  • 3
FarhadA
  • 1,847
  • 2
  • 16
  • 20

4 Answers4

24

I've looked into bare metal programming on the Raspberry Pi and it sounds like what you want to do. There are several good forum topics about bare metal programming with some people who have put in a lot of effort to get their code to work. Check these out for getting started:

Guide to Beginning Bare Metal on Raspi

Programming the RPi on the bare metal

Programming in Basic on Bare Metal Tutorial 1

or in general you can go to Raspberry Pi's Bare Metal Forum and just browse around.

My understanding is that you will have to boot from the SD card due to the boot sequence built into the Broadcom chip. I'm trying to find the link for the boot sequence but my google fu isn't working, I'll edit later if I find it.

Dan B
  • 2,907
  • 2
  • 21
  • 20
6

the only way it will boot is from a fat32 formatted sdcard, goes from poweron to gpu firmware loading that executes any arm binary file named kernel.img so if you want to make a custom kernel that does whatever it is you are looking to do its at this point

joe
  • 69
  • 1
4

I have created an IBM S/390 emulator in C# that theoretically will run under Mono/Linux as it compiles to CIL code and doesn't use any non-supported .NET resources. This will allow embedded solutions using platform independent control tables with a custom finite state machine interpreter. It would still have essential Linux O/S in the background though.

3

Fully automated minimal bare metal blinker example

Tested on Ubuntu 16.04 host, Raspberry Pi 2. Usage:

  1. Insert SD card on host

  2. Make the image:

    ./make.sh /dev/mmblck0 p1
    

    Where:

    • /dev/mmblck0 is the device of the SD card
    • p1 is the first partition of the device (/dev/mmblck0p1)
  3. Inset SD card on PI

  4. Turn power off and on

enter image description here

GitHub upstream: https://github.com/cirosantilli/raspberry-pi-bare-metal-blinker/tree/d20f0337189641824b3ad5e4a688aa91e13fd764

start.S

.global _start
_start:
    mov sp, #0x8000
    bl main
hang:
    b hang

main.c

#include <stdint.h>

/* This is bad. Anything remotely serious should use timers
 * provided by the board. But this makes the code simpler. */
#define BUSY_WAIT __asm__ __volatile__("")
#define BUSY_WAIT_N 0x100000

int main( void ) {
    uint32_t i;
    /* At the low level, everything is done by writing to magic memory addresses. */
    volatile uint32_t * const GPFSEL4 = (uint32_t *)0x3F200010;
    volatile uint32_t * const GPFSEL3 = (uint32_t *)0x3F20000C;
    volatile uint32_t * const GPSET1  = (uint32_t *)0x3F200020;
    volatile uint32_t * const GPCLR1  = (uint32_t *)0x3F20002C;

    *GPFSEL4 = (*GPFSEL4 & ~(7 << 21)) | (1 << 21);
    *GPFSEL3 = (*GPFSEL3 & ~(7 << 15)) | (1 << 15);
    while (1) {
        *GPSET1 = 1 << (47 - 32);
        *GPCLR1 = 1 << (35 - 32);
        for (i = 0; i < BUSY_WAIT_N; ++i) { BUSY_WAIT; }
        *GPCLR1 = 1 << (47 - 32);
        *GPSET1 = 1 << (35 - 32);
        for (i = 0; i < BUSY_WAIT_N; ++i) { BUSY_WAIT; }
    }
}

ldscript

MEMORY
{
    ram : ORIGIN = 0x8000, LENGTH = 0x10000
}

SECTIONS
{
    .text : { *(.text*) } > ram
    .bss : { *(.bss*) } > ram
}

make.sh

#!/usr/bin/env bash

set -e

dev="${1:-/dev/mmcblk0}"
part="${2:-p1}"
part_dev="${dev}${part}"
mnt='/mnt/rpi'

sudo apt-get install binutils-arm-none-eabi gcc-arm-none-eabi

# Generate kernel7.img
arm-none-eabi-as start.S -o start.o
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -c main.c -o main.o
arm-none-eabi-ld start.o main.o -T ldscript -o main.elf
# Get the raw assembly out of the generated elf file.
arm-none-eabi-objcopy main.elf -O binary kernel7.img

# Get the firmware. Those are just magic blobs, likely compiled
# from some Broadcom proprietary C code which we cannot access.
wget -O bootcode.bin https://github.com/raspberrypi/firmware/blob/597c662a613df1144a6bc43e5f4505d83bd748ca/boot/bootcode.bin?raw=true
wget -O start.elf https://github.com/raspberrypi/firmware/blob/597c662a613df1144a6bc43e5f4505d83bd748ca/boot/start.elf?raw=true

# Prepare the filesystem.
sudo umount "$part_dev"
echo 'start=2048, type=c' | sudo sfdisk "$dev"
sudo mkfs.vfat "$part_dev"
sudo mkdir -p "$mnt"
sudo mount "${part_dev}" "$mnt"
sudo cp kernel7.img bootcode.bin start.elf "$mnt"

# Cleanup.
sync
sudo umount "$mnt"