Jak uruchomić program C bez systemu operacyjnego na Raspberry Pi?

Chciałbym poeksperymentować używając Raspberry Pi dla różnych aplikacji wbudowanych niskiego poziomu. Jedynym problemem jest to, że w przeciwieństwie do dostępnych płyt mikrokontrolerów AVR i PIC, Raspberry Pi zazwyczaj uruchamia system operacyjny (jak Raspbian), który rozkłada czas procesora we wszystkich uruchomionych programach i sprawia, że jest niepraktyczny dla niektórych aplikacji czasu rzeczywistego.

Ostatnio dowiedziałem się, że zakładając, że masz zainstalowany bootloader taki jak GRUB, uruchamiający program C na x86 (w postaci kernel) zajmuje bardzo mało rzeczywistej konfiguracji, wystarczy program do składania, aby wywołać główną funkcję i rzeczywisty kod C.

Czy istnieje sposób, aby to osiągnąć z Raspberry Pi? To byłby świetny sposób, aby dowiedzieć się o niskopoziomowym programowaniu ARM, A ma już kilka skomplikowanych urządzeń peryferyjnych do bałaganu (USB, Ethernet itp.)

5 answers

Podczas gdy bare metal jest możliwy na Pi, unikałbym tego, ponieważ Linux staje się tak lekki i obsługuje całą masę rzeczy dla Ciebie.

Oto tutorial, który pomoże Ci zacząć, jeśli chcesz nadal uczyć się nagich metalowych rzeczy: http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/

Mając to wszystko powiedziane, po prostu załadowałbym Twoje ulubione DISTRO Linux embedded (RT patched może być preferowany w oparciu o twoje wymagania) i nazwał go dobrze.

 13
Author: It'sPete,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-24 03:00:36

Właściwie Raspberry Pi jest jednym z łatwiejszych ramion do programowania bare metal (bez systemu operacyjnego) mam wiele przykładów na github, aby zacząć

Https://github.com/dwelch67/raspberrypi

Jedną miłą rzeczą w raspberry pi jest to, że nie potrzebuje bootloadera, takiego jak uboot, jest gpu, który faktycznie przynosi układ najpierw, a następnie ładuje jądro (lub aplikację z gołym metalem, cokolwiek) do pamięci ram i gałęzi do niego w taki sam sposób, jak uboot. Kolejną miłą rzeczą jest to, że nie można go cegła jak można z tak wielu innych płyt w tej klasie, jeśli bałagan można wyciągnąć kartę sd, spróbuj ponownie, jeśli się poddać, a następnie umieścić kartę sd z Linuksem na nim z powrotem i uruchomić Linuksa...

 33
Author: old_timer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-14 15:05:16

W pełni zautomatyzowany minimal bare metal Migacz przykład

Testowane na Ubuntu 16.04 host, Raspberry Pi 2.

Dwelch ' S jest najbardziej wszechstronnym przykładem, ale jest to minimalnie łatwy w konfiguracji hello world.

Użycie:

  1. Włóż kartę SD na host

  2. Make the image:

    ./make.sh /dev/mmblck0 p1
    

    Gdzie:

    • /dev/mmblck0 jest urządzeniem karty SD
    • p1 jest pierwszą partycją urządzenia (/dev/mmblck0p1)
  3. Wstaw kartę SD na PI

  4. Wyłączanie i włączanie zasilania

Tutaj wpisz opis obrazka

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.
    The device tree files (dtb / dts), which are provided by hardware vendors,
    tell the Linux kernel about those magic values. */
    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"

QEMU friendly bare metal examples

Problem z Migacz jest to, że trudno obserwować Diody LED w QEMU: https://raspberrypi.stackexchange.com/questions/56373/is-it-possible-to-get-the-state-of-the-leds-and-gpios-in-a-qemu-emulation-like-t

Tutaj opisuję kilka ustawień bare metal QEMU, które mogą być interesujące: jak tworzyć programy bare metal ARM i uruchamiać je na QEMU? zapis do UART jest najprostszym sposobem na uzyskanie wyjścia z QEMU.

Bonus

Oto przykład x86 dla ciekawych: Jak uruchomić program bez systemu operacyjnego?

 11
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-22 06:08:12

Https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ jest świetnym tutorialem, i jak powiedzą, najlepszym szybkim i brudnym sposobem na uruchamianie kodu na bare metal jest przejęcie dystrybucji Linuksa, aby to zrobić, wystarczy skompilować do jądra.img (z odpowiednimi opcjami architektury) i użyć go do zastąpienia istniejącej w dystrybucji Linuksa tylko w tej części samouczka możesz przejść do: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html#pitime

 3
Author: joshbooks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-24 03:17:09

Pi może być nieco nieoptymalne dla tego, co chcesz zrobić, ponieważ konstrukcja SoC jest taka, że procesor ARM jest obywatelem drugiej klasy-co oznacza, że jest kilka obręczy do przeskoczenia, aby uruchomić na nim nagi metalowy program.

Możesz jednak nieco oszukać i użyć U-Boot API , aby dać ci dostęp do niektórych funkcji, które oferuje U-Boot, ale możesz dodawać własne funkcje z boku.

 2
Author: unixsmurf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-24 10:27:00