programing

라즈베리 파이에서 운영체제 없이 C 프로그램을 실행하는 방법은 무엇입니까?

muds 2023. 7. 15. 10:38
반응형

라즈베리 파이에서 운영체제 없이 C 프로그램을 실행하는 방법은 무엇입니까?

저는 다른 로우 레벨 임베디드 애플리케이션을 위해 라즈베리 파이를 사용하는 실험을 하고 싶습니다.유일한 문제는 사용 가능한 AVR 및 PIC 마이크로컨트롤러 보드와 달리 라즈베리 파이는 일반적으로 실행 중인 모든 프로그램에 CPU 시간을 분산시키는 OS(Raspbian과 같은)를 실행하고 특정 실시간 애플리케이션에 대해 비실용적이라는 것입니다.

최근에 GRUB와 같은 부트로더가 설치되어 있다고 가정할 때 x86에서 C 프로그램을 실행하는 것은 (커널 형태로) 주 기능과 실제 C 코드를 호출하는 어셈블리 프로그램에 불과하여 실제 설정이 거의 필요하지 않다는 것을 알게 되었습니다.

라즈베리 파이로 이것을 달성할 수 있는 방법이 있습니까?이것은 낮은 수준의 ARM 프로그래밍에 대해 배울 수 있는 좋은 방법이 될 것이며, 이미 몇 가지 복잡한 주변 장치(USB, 이더넷 등)를 가지고 있습니다.

완전 자동화된 최소 베어 메탈 블링커의 예

Ubuntu 16.04 호스트, Raspberry Pi 2에서 테스트되었습니다.

https://github.com/dwelch67/raspberrypi 지금까지 본 것 중 가장 포괄적인 예제 집합이지만(이전에 현재 삭제된 답변에서 언급한 바 있음), 이는 신속하게 시작할 수 있는 최소한의 쉬운 hello world입니다.

용도:

  1. 호스트에 SD 카드 삽입

  2. 이미지 만들기:

    ./make.sh /dev/mmblck0 p1
    

    위치:

    • /dev/mmblck0SD 카드의 장치입니다.
    • p1장치의 첫 번째 파티션입니다(/dev/mmblck0p1)
  3. SD 카드를 PI에 삽입합니다.

  4. 전원 끄기 및 켜기

enter image description here

GitHub 업스트림: https://github.com/cirosantilli/raspberry-pi-bare-metal-blinker/tree/d20f0337189641824b3ad5e4a688aa91e13fd764

시작.S.

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

주.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; }
    }
}

원고

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 친화적인 베어 메탈 예제

깜박임의 문제는 QEMU에서 LED를 관찰하기 어렵다는 것입니다. https://raspberrypi.stackexchange.com/questions/56373/is-it-possible-to-get-the-state-of-the-leds-and-gpios-in-a-qemu-emulation-like-t

여기에서는 관심을 가질 수 있는 몇 가지 베어 메탈 QEMU 설정에 대해 설명합니다.베어 메탈 ARM 프로그램을 만들고 QEMU에서 실행하는 방법은 무엇입니까?UART에 쓰는 것이 QEMU에서 출력물을 꺼내는 가장 쉬운 방법입니다.

QEMU가 라즈베리 파이를 얼마나 잘 시뮬레이션하는지는 다음을 통해 부분적으로 추론할 수 있습니다.QEMU로 라즈베리 파이 라스비안을 모방하는 방법은 무엇입니까?리눅스 단말기까지 등장하기 때문에 당신의 베어메탈 제품도 작동할 가능성이 높습니다.

보너스

다음은 호기심 많은 사용자를 위한 x86 예입니다.운영 체제 없이 프로그램을 실행하는 방법은 무엇입니까?

베어메탈은 파이에서 가능하지만 리눅스가 너무 가벼워지고 당신을 위해 많은 것을 처리하기 때문에 피하고 싶습니다.

http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/ 에서 베어메탈을 계속 배우고 싶다면 시작할 수 있는 튜토리얼을 소개합니다.

이 모든 것과 함께, 저는 당신이 가장 좋아하는 임베디드 리눅스 디스트리뷰터(요구 사항에 따라 RT 패치가 더 선호될 수 있음)를 로드하고 좋다고 말할 것입니다.

https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ 은 훌륭한 튜토리얼이며, 베어메탈에서 코드를 실행하는 가장 빠르고 더러운 방법은 리눅스 디스트리뷰터를 하이잭하는 것입니다. 그러기 위해서는 커널로 컴파일만 하면 됩니다.(적절한 아키텍처 옵션을 사용하여) img하고 이를 사용하여 이 튜토리얼 섹션에서만 Linux 디스트리뷰터의 기존 아키텍처 옵션을 교체할 수 있습니다. https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html#pitime

Pi는 ARM CPU가 2등 시민인 SoC 설계이기 때문에 당신이 하고 싶은 일에 다소 최적이 아닐 수 있습니다. 즉, 베어 메탈 프로그램을 실행하기 위해 통과해야 할 몇 가지 후프가 있다는 것을 의미합니다.

그러나 U-Boot API를 사용하여 U-Boot가 제공하는 일부 기능에 액세스할 수 있지만 사용자 자신의 기능을 추가할 수 있습니다.

언급URL : https://stackoverflow.com/questions/29837892/how-to-run-a-c-program-with-no-os-on-the-raspberry-pi

반응형