<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Raspberry_Pi</id>
	<title>Raspberry Pi - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Raspberry_Pi"/>
	<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Raspberry_Pi&amp;action=history"/>
	<updated>2026-04-07T06:20:17Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>http://wiki.foofun.cn//index.php?title=Raspberry_Pi&amp;diff=1015&amp;oldid=prev</id>
		<title>Zhang3：创建页面，内容为“{{In Progress}} {{FirstPerson}} {{Sole Editor}} 这是关于Raspberry Pi上裸机[OS]开发的教程。 本教程是专门为Raspberry PI Model B Rev2编写的，因为作者没有其他硬件可以测试。 但是到目前为止，从本教程的目的出发，这些型号基本上是相同的 (Rev 1有256MB ram，Model A没有以太网)。  这是作者的第一个ARM系统，我们在写作时学习，没有任何关于ARM的知识。 假定并要求具备Li…”</title>
		<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Raspberry_Pi&amp;diff=1015&amp;oldid=prev"/>
		<updated>2022-03-24T07:58:02Z</updated>

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