用C为Raspberry Pi编写操作系统


19

我已经找到了Baking Pi教程,但是它们仅使用汇编语言。我遵循了第一课,但是我已经想知道如何使用C了。我的意思是,他们发明高级语言是有原因的。我尝试将C代码编译为一个object(.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编写的,因此必须有一篇文章解释该过程。我也会对步骤列表感到非常满意,因此我可以在Google上搜索这些步骤,甚至可以问一个不太广泛的问题。

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


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

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

1
嗯,“连接”一些LED。
2013年

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

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

Answers:


14

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

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

设置堆栈很容易-找到一些未使用的内存,然后将该地址加载到曾经用作堆栈指针的寄存器中。

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

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


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

13

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

  • _start符号确实是在编译和链接程序集文件和C文件时使用的符号(而main()没有使用)
  • 调用时main(),您需要使用C调用约定:
    • 在调用之后将指令的地址压入堆栈(返回地址,这将由returnC中的语句使用)
    • 推送函数的参数。在您的情况下,您可以推送两个32位值(总共8个字节),但是为了简化起见,您也可以删除参数,而只需int main() { ... }
    • 也许在堆栈上为返回值保留一些空间
    • 我不记得这些东西应该按什么顺序推
    • 要了解C函数的确切期望,请对其进行反汇编(objdump -S main.o),并查看其如何操作堆栈。
  • 如果您不遵守调用约定,那么C编译器生成的汇编代码可能会篡改堆栈上的返回地址,并且在您的情况下,您甚至没有推送返回地址,因此返回指令将跳转到某个地方随机,而不是去loop$

OSDev维基将是一个非常有用的ressource -它主要关注的x86开发,但大部分信息仍然适用于树莓派。

更多有关raspberry-pi osdev的资源:


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

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

2

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


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

2

尝试以下方法:

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

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


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

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

我知道这是对一个甚至更老的问题的旧答案,但是如果它掉了,页面在web.archive.org上。
anonymoose

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.