Как запустить программу C без ОС на малиновой пи?

Я бы хотел поэкспериментировать с использованием малины Pi для некоторых различных низкоуровневых встроенных приложений. Единственная проблема заключается в том, что, в отличие от доступных микроcontrollerов AVR и PIC, Raspberry Pi обычно запускает ОС (например, Raspbian), который распределяет время процессора во всех запущенных программах и делает его нецелесообразным для некоторых приложений реального времени.

Недавно я узнал, что, предполагая, что у вас установлен загрузчик, такой как GRUB, запуск программы на x86 (в форме ядра) занимает очень мало фактической настройки, просто программа сборки для вызова основной функции и фактического кода C ,

Есть ли способ достичь этого с помощью малины? Это был бы отличный способ узнать о программировании ARM с низким уровнем, и у него уже есть несколько сложных периферийных устройств, с которыми можно объединиться (USB, Ethernet и т. Д.),

Хотя на Pi возможен голый металл, я бы избегал этого, так как Linux становится таким легким и обрабатывает целую кучу вещей для вас.

Вот учебник, который поможет вам начать работу, если вы хотите все еще изучать голые металлические вещи: http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/

Со всем сказанным, я бы просто загрузил ваш любимый встроенный дистрибутив Linux (RT-исправление может быть предпочтительным на основе ваших требований) и называть его хорошим.

На самом деле малина Pi является одним из легких рук для программирования голого металла (без операционной системы). У меня есть много примеров в github, чтобы вы начали

https://github.com/dwelch67/raspberrypi

Одна приятная вещь о малине pi заключается в том, что ей не нужен загрузчик, такой как uboot, есть gpu, который на самом деле приносит чип первым, тогда он загружает kernel ​​(или голеное металлическое приложение, что угодно) в ram и ветки к нему в так же, как и uboot. Еще одна приятная вещь: вы не можете кирпича, как вы можете, с таким количеством других плат в этом classе, если вы испортите вам вытащить SD-карту, попробуйте еще раз, если вы сдаетесь, тогда положите на нее SD-карту с linux и запустить linux …

Полностью автоматизированный пример минимального голого металлического бликера

Протестировано на хосте Ubuntu 16.04, малина Pi 2.

dwelch является наиболее полным примером , но это минимальный простой в настройке привет мир.

Использование:

  1. Вставьте SD-карту на хост

  2. Сделайте изображение:

    ./make.sh /dev/mmblck0 p1 

    Куда:

    • /dev/mmblck0 является устройством SD-карты
    • p1 – это первый раздел устройства ( /dev/mmblck0p1 )
  3. Вставить SD-карту в PI

  4. Выключите и включите питание

введите описание изображения здесь

GitHub вверх по течению: 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  /* 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 дружественные примеры с открытым металлом

Проблема с blinker заключается в том, что в QEMU трудно наблюдать светодиоды: https://raspberrypi.stackexchange.com/questions/56373/is-it-possible-to-get-the-state-of-the-leds- и-GPIOs-в- для QEMU эмуляции, как-т

Здесь я описываю некоторые голые металлические настройки QEMU, которые могут представлять интерес: как сделать голые металлические ARM-программы и запускать их на QEMU? Запись на UART - это самый простой способ получить выход из QEMU.

бонус

Вот пример x86 для любопытных: как запустить программу без операционной системы?

https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ – отличный учебник, и поскольку они расскажут вам, как быстро и грязно использовать код на голом металле, это захватить linux distro, для этого просто скомпилируйте файл kernel.img (с соответствующими параметрами архитектуры) и используйте его для замены существующего в дистрибутиве linux только для этого раздела учебника, на который вы можете перейти: https: // www. cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html#pitime

Pi может быть немного субоптимальным для того, что вы хотите сделать, поскольку дизайн SoC таков, что процессор ARM является гражданином второго сорта – это означает, что есть несколько обручей, чтобы перепрыгнуть, чтобы запустить на нем голую металлическую программу.

Тем не менее, вы можете немного обмануть и использовать U-Boot API, чтобы предоставить вам доступ к некоторым функциям U-Boot, но сможете добавлять свои собственные функции сбоку.