.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很好。
#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
我强烈推荐它。
评论
C被设计为Unix的可移植汇编语言。 Linux是用C编写的,通过查看它是如何完成的,您可以节省大量时间。@ThorbjørnRavnAndersen我想我不应该阅读Linux的源代码。 Linux比我想知道的要复杂得多,因此掩盖了我感兴趣的部分。
嗯,“连接”一些LED。
谢谢,但是我想自己做大多数事情。这是一个学习项目。
我必须承认,我以前从未在任何地方遇到过有关如何编写操作系统的问题。并且有一些有趣的答案。真是疯了...