查看“Raspberry Pi”的源代码
←
Raspberry Pi
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
{{In Progress}} {{FirstPerson}} {{Sole Editor}} 这是关于Raspberry Pi上裸机[OS]开发的教程。 本教程是专门为Raspberry PI Model B Rev2编写的,因为作者没有其他硬件可以测试。 但是到目前为止,从本教程的目的出发,这些型号基本上是相同的 (Rev 1有256MB ram,Model A没有以太网)。 这是作者的第一个ARM系统,我们在写作时学习,没有任何关于ARM的知识。 假定并要求具备Linux/Unix('''非常'''重要)和C/C++语言('''非常非常'''重要,包括如何使用内联汇编器)的经验。 这不是关于如何构建内核的教程,而是关于如何开始使用RPi的简单介绍。 ==准备工作== ===材料=== 你将需要: * '''Raspberry Pi''',简称RPI。 * 用以引导的Sd卡。 * 一个SD卡读卡器,这样你就可以从开发系统中写入SD卡了。 * RPi的串行适配器。 * 来自外部电源,USB或串行适配器的电源。 === 串行适配器 === RPI有2个串口([[UART|UARTS]])。 本教程仅涉及UART0,简称UART或串口。 UART1从此被忽略。 基本UART板载使用3.3V TTL,并连接到板上标有 “P1” 的一些GPIO引脚。 x86个人电脑和Mac电脑实际使用5V的TTL,所以需要一些适配器来转换TTL。 我建议使用 '''USB到TTL串行电缆-用于Raspberry Pi的调试/控制台电缆''',每条引线都有单独的连接器,例如 [http://www.adafruit.com/products/954 商用RPi串行适配器]。 然后连接到RPi[[Media:ARM_RaspberryPi_serial.jpg|像这样]]。 稍微便宜一点的[http://www.ebay.com/itm/USB-To-RS232-TTL-PL2303HX-Auto-Converter-Module-Converter-Adapter-5V-3-3V-Output-/350568364250 USBPL2303HX适配器]被发现也可以使用,但如果用延长电缆连接到端口似乎不可靠(USB2.0集线器可能会解决这个问题)。 注意: 我使用的串行适配器同时提供0v和5v引线 (黑色和红色),为RPi提供电源。 除此之外,不需要额外的电源。 === 测试硬件/串口 === 首先,你要确保所有硬件都能正常工作。 将串行适配器连接到RPi并启动正式的Raspian映像。 引导过程将输出到串口和HDMI,并在串口上启动getty。 设置你的串口,无论你的端口如何工作,并打开minicom。 确保流量控制已关闭。 确保你可以以115200波特率、8N1的速度运行,这是RPi所使用的。 如果你得到提示 “权限被拒绝(Permission Denied)” '''不需要Root!''' 这是不必要的。 相反,你应该: <source lang="bash"> sudo adduser <user> dialout </source> 这将使您的用户无需root即可使用串行端口。 或者执行ls -l /dev/ttyS*以查找拥有该设备的组,然后将你添加到/etc/group下的组中(通常该组为uucp) 如果仅在RPi启动后才启动minicom,则只需在minicom中按 '''return''',这样getty将输出新的登录提示。 否则,等待启动消息出现。 如果你没有得到任何输出,则将RPi连接到显示器以检查它是否真的启动,检查你的连接和Minicom设置。 === 构建交叉编译器 === 像我一样,你可能正在使用一台x86 PC作为主机,并希望在其上编辑和编译源代码,而RPi是一个ARM CPU,所以你绝对需要一个交叉编译器。 但是,即使你在ARM系统上进行开发,构建交叉编译器仍然是一个好主意,以避免意外地将你的开发系统中的东西与你自己的内核混为一谈。 按照 [[GCC Cross-Compiler]] 中的步骤构建自己的交叉编译器,但使用: <source lang="bash"> export TARGET=arm-none-eabi </source> 现在你可以开始了。 ==教程和示例== # [http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ 汇编教程(剑桥大学)] # [[Raspberry Pi Bare Bones|C教程]] #[[Raspberry Pi Bare Bones Rust|Rust教程]] # [https://github.com/dwelch67/raspberrypi dwelch67收集示例和引导程序] # [https://github.com/bztsrc/raspi3-tutorial bzt提供的C语言AArch64教程] # [https://github.com/s-matyukevich/raspberry-pi-os s-matyukevich所著的Raspberry Pi操作系统教程] # [[Detecting Raspberry Pi Board|检测Raspberry Pi板]] == 启动内核 == 当你测试上面的硬件时,SD卡上还有原始的Raspian映像吗? 太棒了。 所以你已经有一个带有引导分区和所需文件的sd卡。 如果没有,则下载一个原始的Raspberry引导映像,并将其复制到SD卡。 现在从SD卡挂载第一个分区并查看它: <source lang="text"> bootcode.bin fixup.dat kernel.img start.elf cmdline.txt fixup_cd.dat kernel_cutdown.img start_cd.elf config.txt issue.txt kernel_emergency.img </source> 当RPi通电时,ARM CPU停止,GPU运行。 GPU从rom加载引导加载程序并执行它。 然后找到SD卡并加载bootcode.bin。 bootcode处理config.txt和cmdline.txt (或者start.elf读那个?),然后运行start.elf。 开始elf加载kernel.img设置为0x00008000,将一些操作码设置为0x00000000,ATAG设置为0x0000100,最后ARM CPU启动。 CPU在0x00000000开始执行,它将初始化R0、R1和R2,并跳转到内核映像启动的0x00008000。 因此,要启动你自己的内核,只需用替换我们自己的kernel.img,umount,sync,将sd卡插入RPi并打开电源即可。 注意:GPU还初始化了视频输出,从监视器(如果是hdmi)或config.txt中检测到正确的分辨率并创建一个2x2像素的帧缓冲区(红色、黄色、蓝色和青色像素),硬件通过颜色插值缩放到全屏。 所以你会得到颜色褪色效果不错的矩形。 == 从串口启动 == RPi直接从SD卡引导内核,并且只能从SD卡引导内核。 没有其他选择。 在开发过程中,由于必须不断地将sd卡从RPi交换到sd卡读卡器,然后再返回,因此变得令人厌烦。 将内核反复写入SD卡也会使SD卡磨损。 另外,SD卡插槽有些易碎;有几个人报告说他们不小心把它弄坏了。 总的来说不是一个理想的解决方案。 那么我们能做些什么呢? 我已经根据上面的C教程编写了一个名为[https://github.com/mrvn/raspbootin Raspboot]的小型引导加载程序,它从串口加载真正的内核。 Raspbootin由作为引导服务器和终端程序的Raspbootcom ([https://github.com/mrvn/raspbootin 相同的存储库]) 提供。 使用这两个,我只需要重新启动我的RPi就可以让它启动最新的内核。 这使得硬件的测试更快、更安全。 Raspbootin对于你的内核是完全透明的。 它为自制内核保留了r0、r1和r2寄存器和GPU放入内存的ATAG。 因此,无论你是直接从SD卡引导内核,还是通过串口使用Raspboot引导内核,都不会对你的代码造成影响。 === Raspbootin串行协议 === 除非你想编写自己的启动服务器,否则你不必关心这个问题。 Raspboot的引导协议相当简单。 Raspboot首先通过串行线发送3个中断(<code>\x03</code>),表示它已经准备好接收内核。 然后,它期望内核的大小为 <code>uint32_t</code>,以小字节序( little endian)排列。 如果尺寸可接受,则在尺寸后回复“<code>OK</code>”;如果尺寸太大,则回复“<code>SE</code>”。 在“<code>OK</code>”之后,它需要<code>大小</code>很多字节来表示内核。 就这样。 ==解析ATAGs== 一个很好的ATAGs文档可以在 [http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html#appendix_tag_reference 这里]找到。 [http://web.archive.org/web/20120605001004/http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html 来自Wayback机器的缓存版本] 请注意,以后Raspberry Pi将在R2中向你传递设备树BLOB。 如果禁用设备树 (在这种情况下r2包含0x0),则仍然可以在0x100处找到ATAGs - 可以通过ATAG_CORE (0x54410001) 开头来识别。 相比之下,设备树可能更有用,但更复杂。 设备树以uint32_t 0xd00dfeed'''(大端字序)'''。请注意big-endian-这适用于所有值。 ARM默认为小端(little endian),所以您可能想要早点编写一些端序例程(endian routines)! [https://www.devicetree.org/ Device Tree Specification] == 帧缓冲区支持 == 在引导时,RPi将显示器配置为2x2像素的虚拟分辨率,缩放为全屏。 每个像素都有不同的颜色,并且硬件缩放会对颜色进行插值以显示出不错的颜色褪色。 所以,在你做任何事情之前,首先连接一个监视器,确保你得到一些输出。 对于帧缓冲区,你需要了解如何[https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes access mailboxes]。 然后,你必须向GPU发送一些 [https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface mail]。 或者,你可以在[http://elinux.org/RPi_Framebuffer 这里]阅读有关帧缓冲区的内容, 首先从一个简单的查询开始,然后构建更复杂的mails。 如果你可以正常工作,那么我建议你仅更改虚拟大小和颜色深度,并保持物理分辨率不变。 RPi似乎可以很好地检测监视器,用户还可以在SD卡上的引导配置文件中配置分辨率。 最好尊重它的意愿。 == 中断和异常 == 默认情况下,ARM上的异常向量表从0x0开始。 你可以这样用,但还有更好的方法。 你可以设置一个标志以在0xffff0000处使用高向量,或者设置异常向量基址寄存器以指向你自己喜欢的任何位置 (32字节对齐) 的表。 注: 中断是电平触发的,因此你必须在从中断返回之前清除中断源或屏蔽它。 RPi中的ARM CPU还支持一些额外的指令,用于将寄存器存储在不同模式,切换模式和从中断返回的堆栈上。 这些扩展在ARM上有很好的描述。 注: 中断期间LR中的返回地址将是0-8字节,这取决于异常的类型,偏移到它应该是什么,并且需要在返回之前进行调整。 再次查看适用于哪个异常的偏移量。 首先实现和测试软件中断是一个好主意,因为你可以以受控的方式触发它。 当配置一些外设发送中断时,在CPSR中禁用中断是一件有用的事情,在3个中断启用寄存器中启用你感兴趣的中断 (或全部),然后在紧密循环中轮询3个挂起的寄存器并输出更改。 这允许你查看外设是否引发中断,以及(如果怀疑)是哪一个。 之后,可以配置和测试实际的中断处理程序。 给你一个很好的中途点来测试你到目前为止的情况。 ==浮点运算支持== 为了能够使用任何浮点操作,例如存储或加载浮点数,你需要在使用FPU之前启用它。 要做到这一点,为了无论谁应该能够使用它,你必须启用对协处理器的访问,你必须启用FPU本身。 <source lang="asm"> # 在协处理器启用寄存器(coprocessor enable register)中启用FPU - 这使每个人都可以访问协处理器的两个位置。 ldr r0, =(0xF << 20) mcr p15, 0, r0, c1, c0, 2 </source> 然后启用FPU本身: <source lang="asm"> # 在FP异常寄存器(FP exception register)中启用FPU MOV r3, #0x40000000 # VMSR FPEXC, r3 # 汇编程序错误 .long 0xeee83a10 </source> 第三行是你想要使用的实际指令,但是由于Binutils 2.23中的一个错误,它不能汇编。 它下面的行是它应该汇编到的,并替换了操作码(opcode)。 完成这两项之后,就可以使用FPU了。 == USB == 一个独立的支持键盘和鼠标的bsd许可的usb驱动程序可以在这里获得:https://github.com/Chadderz121/csud。 这个驱动程序可以保持独立,通过编辑 <code>/source/platform.c</code> 文件来将驱动程序与你的实现 <code>malloc()</code> 和类似的功能接口,或者,你可以将驱动程序与操作系统更紧密地集成在一起。 ==外部参考== # [https://www.scss.tcd.ie/~waldroj/3d1/arm_arm.pdf arm_arm.pdf] - 通用ARM架构参考手册v6 # [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf DDI0301H_arm1176jzfs_r0p7_trm.pdf] - 针对RPi的更具体的ARM # [https://github.com/dwelch67/raspberrypi dwelch67 examples] - 基本工具链 + UART工具 # [http://elinux.org/RPi_Hardware RPi_Hardware] - datasheet表 (以及关于Broadcom芯片上外围设备的一份手册) # [https://github.com/raspberrypi/firmware/wiki GitHub Raspberry Pi firmware wiki] - 邮箱和视频资料 # [http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf BCM2835-ARM-Peripherals.pdf] - RPI外围设备的Datasheet # [http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html Booting ARM Linux] - 描述了RPi引导加载程序模拟的Linux的ARM端口的通用引导加载程序接口 # [http://sourceforge.net/projects/rpiqemuwindows/ RPi Emulator] - 预配置的Windows QEMU RPI仿真环境。 [[Category:ARM]] [[Category:ARM RaspberryPi]]
本页使用的模板:
模板:EditThis
(
查看源代码
)
模板:FirstPerson
(
查看源代码
)
模板:In Progress
(
查看源代码
)
模板:NoteBox
(
查看源代码
)
模板:Sole Editor
(
查看源代码
)
返回至“
Raspberry Pi
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
变体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息