我已经找到了Baking Pi教程,但是它们仅使用汇编语言。我遵循了第一课,但是我已经想知道如何使用C了。我的意思是,他们发明高级语言是有原因的。我尝试仅将C代码编译到一个对象(.o)文件,将

.section .init
.globl _start
_start:

bl main

loop$:
b loop$


编译到另一个目标文件并将它们链接在一起,从而获得kernel.img。然后,我用自己的内核替换了已经存在的内核,但是它不执行C代码。我编写的C代码应该只打开OK LED,然后返回(然后出现loop$: b loop$)。但是“ OK” LED随机闪烁几次,然后一直保持熄灭状态。这是我的C代码:

int main(int argc, char ** argv) {
    volatile unsigned *gpioAddr = (volatile unsigned *)0x20200000;
    *(gpioAddr + 4) = 1 << 18;
    *(gpioAddr + 40) = 1 << 16;
    return 0;
}


如何在Raspberry Pi上使用C进行操作系统开发?

我怀疑这是错误的在代码中(尽管我只是一个业余爱好者)。我知道设置C可能很复杂,但我不是第一个这样做的人。 AFAIK,当前所有占主导地位的OS主要都是用C编写的,因此必须有一篇介绍该过程的文章。我也会对步骤列表感到非常满意,因此我可以用谷歌搜索这些步骤,甚至可以问一个不太宽泛的问题。

注意:与上述C代码等效的ARM程序集仅能正常工作精细。它会点亮LED(稍稍闪烁之后)。我认为(希望)表明我的Raspberry Pi很好。

评论

C被设计为Unix的可移植汇编语言。 Linux是用C编写的,通过查看它是如何完成的,您可以节省大量时间。

@ThorbjørnRavnAndersen我想我不应该阅读Linux的源代码。 Linux比我想知道的要复杂得多,因此掩盖了我感兴趣的部分。

嗯,“连接”一些LED。

谢谢,但是我想自己做大多数事情。这是一个学习项目。

我必须承认,我以前从未在任何地方遇到过有关如何编写操作系统的问题。并且有一些有趣的答案。真是疯了...

#1 楼

几年前,我编写了一个非常简单的内核,并在386上运行。多年来,我都没有进行裸机编程,但是从广义上讲,您需要编写一些汇编程序代码,该代码将:


在引导过程中禁用中断
如果Pi具有内存控制器,则需要进行设置
设置计时器刻度
配置中断控制器
设置堆栈以便执行C代码

设置堆栈很容易-找到一些未使用的内存,并将该地址装入曾经用作寄存器的寄存器。

在C代码中,您需要初始化OS数据结构,例如内存池和线程表。您将无法使用C库函数-您需要自己编写这些东西。

如果要编写一个简单的多任务os,则需要编写一些汇编程序来将CPU寄存器保存在堆栈中,并从另一个线程的堆栈中加载一组不同的寄存器值。并且您需要编写一个API来创建不同的线程。

评论


在这个答案和乔治·杜佩隆的答案之间很难选择。我接受了这个,并给了另一个。

– 11684
2013年9月17日下午17:39

#2 楼

我没有深入研究您的代码,但是在我看来,您的方向正确。请确保:


_start符号确实是在编译和链接程序集文件和C文件时使用的符号(而没有使用main())。调用main()时,您需要使用C调用约定:


将调用后指令的地址推入堆栈(返回地址,该地址将由return语句在C)
推送函数的参数。在您的情况下,您可以压入两个32位值(总共8个字节),但是为了简化起见,您也可以删除参数,只是让int main() { ... }

可以在堆栈上为返回值
我不记得应该按什么顺序推送这些东西
要知道C函数的确切期望,请对其进行反汇编(objdump -S main.o),然后看看它如何操纵堆栈。


如果您不遵守调用约定,那么C编译器生成的汇编代码可能会篡改堆栈上的返回地址,并且在您的情况下,您甚至没有推送返回地址,因此返回指令将随机跳转到某个地方,而不是跳转到loop$

OSDev Wiki将是一个非常有用的资源-它主要与x86开发有关,但是大多数信息仍然适用于树莓派pi。

更多raspberry-pi osdev特定资源:


http://elinux.org/RaspberryPi_Osdev

https://github.com/hermanhermitage/videocoreiv有关GPU指令集的信息,该指令集将在您的kernel.img插入之前执行启动序列。

https://github.com / christinaa / rpi-open-firmware此项目旨在替换执行kernel.img之前用于引导pi的专有blob。


评论


在这个答案和史蒂夫的答案之间很难选择。我给了你一个支持,并接受了另一个。我对5名代表的差异感到遗憾。

– 11684
2013年9月17日下午17:39

OSDev Wiki非常好-甚至有一些特定的RasPi内容

– wally
2014年12月30日15:24

#3 楼

您可能遇到的主要问题是C库和序言代码。它是在您自己的代码开始执行并设置堆栈,堆以及执行许多其他有用的操作之前启动的。但是,当您尝试为裸机编程时,您下面没有运行任何操作系统,因此最好避免调用这些函数。为此,您需要修改后的C库版本和/或定义或替换为自己的某些全局符号。这个过程有点涉及,这就是为什么“ Baking Pi”用户选择在他们的教程中使用汇编的原因。

评论


感谢您回答我的问题(并很抱歉这么晚回复)。但是(惊讶!)我买了我的pi只是为了了解这一点,这涉及低级的流程(我宁愿不要在昂贵的台式机上这样做,否则会破坏个人文件/邮件/照片)。您能否添加我如何设置堆栈,或提供说明这一点的文章/教程/一些资源? (还有我可能还需要运行C)。

– 11684
13年8月5日在7:24



#4 楼

改为尝试以下方法:

http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/

同样,x86体验也有所不同。它可能适用于一般的ARM裸机OS编程。但是对于Pi来说,很抱歉,这是gpu首先启动,并且在您的OS(?)代码之前进行了很多设置。

评论


多一点细节会很棒,如果答案中的链接断开,会发生什么?

–达斯·维达♦
16年5月22日在7:34

它仍然存在,但我认为对于那些来这里的人,可以使用Google“阀门裸机”,并更好地尝试OSDEV系列(要在我奋斗的过程中越过交叉开发者,请阅读论坛;我发布了一个您可以尝试使用Google“ OSDEV”论坛六个月跨度”)

–吴丹
16年6月13日在10:15

我知道这是对一个甚至更老的问题的旧答案,但是该页面位于web.archive.org上,以防万一它掉了。

– anonymoose
18年6月12日在20:28



#5 楼

s-matyukevich/raspberry-pi-os

https://github.com/s-matyukevich/raspberry-pi-os

这个很棒的仓库既进行了C引导,也涉及了非常复杂的主题。

此外,它研究了Linux内核的工作方式,并注释了Linux内核代码。

看看第一个简单设置教程:https:// github.com/s-matyukevich/raspberry-pi-os/tree/43f682d406c8fc08736ca3edd08a1c8e477c72b0/src/lesson01/src

我强烈推荐它。