本节书摘来自异步社区《树莓派实战秘籍》一书中的第1章,第1.4节,作者: 【美】Ruth Suehle , Tom Callaway 更多章节内容可以访问云栖社区“异步社区”公众号查看。
1.4 技巧04更新固件
你选择的任何Linux发行版都自带了树莓派所需的固件,但它需要经常从上游得到更新,你的项目可能会受益于(或需要)一个更新的版本。
树莓派和你的笔记本电脑有所不同,甚至和许多传统的嵌入式计算机也不相同。树莓派的心脏是Broadcom的BCM2835片上系统,这是一个将CPU、GPU以及内存组合在一起的单个部件。这个细节很重要,因为树莓派实际是从BCM2835的GPU启动的。当你给树莓派上电时,在BCM2835片上系统中的CPU实际上是处于禁用状态!
树莓派的启动过程如下:
1.第一阶段的bootloader:被编程写入BCM2835片上系统硬件的bootloader程序从SD卡上的Linux发行版中挂载FAT32启动分区。请注意,第一阶段的bootloader是在制造阶段被编程写入的,不能被修改或更换。树莓派GPU上的一个小小的、精心设计的RISC核可启动此进程。
2.第二阶段的bootloader:读出SD卡上的boot分区。此固件(bootcode.bin)访问其他GPU固件文件,并把这些固件文件写入树莓派的GPU,然后启动它。
3.GPU固件:此固件(start.elf)允许GPU启动CPU。在附件文件fixup.dat中配置了GPU和CPU之间的SDRAM分区。此时CPU被释放,执行权从GPU转交过来给它。
4.用户代码:CPU可以启动任何支持的二进制文件,但是Linux内核名称是默认的,它假定文件名是kernel.img,不过你可以在config.txt文件中改变这个缺省设置。
在2012年10月19日之前的树莓派固件版本中包含了一个附加的第三阶段bootloader(loader.bin),但它已经不再需要也不再被使用。以前的构建中也有不同版本的GPU固件,必须通过换入换出的方式来使ARM CPU和GPU之间的不同内存划分生效,不过现在GPU和CPU的内存分配在config.txt文件中配置就可以了。
无论树莓派如何启动,你都必须使用一张SD卡作为启动树莓派的设备,因此你将无法从任何其他设备(如网络或USB存储器)单独启动它。不过这也是一件好事,因为你无法覆盖掉第一阶段的bootloader程序,所以它可以防止你将设备弄得无法使用。如果你遇到了损坏的、破损的或者不完整的固件,你大可以简单地换一张干净的SD卡就能重新开始。
树莓派基金会提供了GPU载入的固件程序,该程序可以让树莓派引导一个特殊格式的Linux内核映像文件,所有的Linux发行版映像文件在拷贝此固件之后都可以在树莓派上使用。但这个固件也在不断更新,如果想启用新的功能(或boot新的Linux内核),你会希望你正在运行的是最新版本的固件。
目前还没有这些固件文件的源代码,所以这个资料库只包含了二进制版本。因为树莓派的速度是如此之慢(尤其是在进行Git操作时),我们强烈建议你将这些文件check out到x86的笔记本电脑上。
首先,你需要在Fedora上运行如下命令,以确保你有一个Git客户端:
![446352e2366ea876c48eff5cd1ec7d00263b19a1](https://yqfile.alicdn.com/446352e2366ea876c48eff5cd1ec7d00263b19a1.png?x-oss-process=image/resize,w_1400/format,webp)
或者在Debian/Ubuntu上运行如下命令:
![8b6468cfab3db8b1963030ff14780fba9baab2ac](https://yqfile.alicdn.com/8b6468cfab3db8b1963030ff14780fba9baab2ac.png?x-oss-process=image/resize,w_1400/format,webp)
接下来创建一个树莓派相关文件的工作目录,比如~/raspi:
进入raspi目录:
![1a90548b7f8c97c7782c5d1c5fa2d59cfe71eaaf](https://yqfile.alicdn.com/1a90548b7f8c97c7782c5d1c5fa2d59cfe71eaaf.png?x-oss-process=image/resize,w_1400/format,webp)
使用Git工具获取固件文件的本地副本:
![380c0d47f75008124625dc5b091667104bbd387b](https://yqfile.alicdn.com/380c0d47f75008124625dc5b091667104bbd387b.png?x-oss-process=image/resize,w_1400/format,webp)
这一步会创建一个名为firmware的check out目录。默认情况下,check out的是主分支,当本书撰写之时,同步主分支得到的最新固件版本可以支持当前的树莓派Linux内核(3.2版本)。如果你使用的是3.2内核,那这就是你想要使用的固件。另一个分支(名为next)启用了在Linux 3.6内核中更新的驱动程序,如果你想使用这个分支,进入firemware目录,并输入:
要切换回主分支,输入:
![67a1c9a87ec2b5e0fd43da283f7d4d380053a42b](https://yqfile.alicdn.com/67a1c9a87ec2b5e0fd43da283f7d4d380053a42b.png?x-oss-process=image/resize,w_1400/format,webp)
如果你希望稍后再更新固件,则不需要重新check out整个文件树。只需要简单地回到checkout出的最上层目录(~/raspi/firmware),然后输入:
![1e0e1f05df6f17275282c66fb42d89c370fd3abb](https://yqfile.alicdn.com/1e0e1f05df6f17275282c66fb42d89c370fd3abb.png?x-oss-process=image/resize,w_1400/format,webp)
请记住,这个命令只pull当前分支的变更部分。如果你想pull其他分支的变更部分,你需要用git checkout命令切换到其他分支并同样在该分支处运行git pull命令。
现在你已经从git仓库选好了分支并check out了版本,下一步是将boot固件复制到安装有树莓派Linux发行版映像文件的SD卡上。要完成这一步,你首先要确保SD卡分区已经被正确挂载(在技巧02中有详细介绍)。
在这里,我们将假定你安装有树莓派Linux发行版映像文件的SD卡的boot分区被挂载在/mnt/raspbi-boot目录下,当前版本的Fedora(包括Pidora)将自动将之挂载到/run/media/$USERNAME/boot目录下面,此处的$USERNAME是你的用户名。因此如果你已经将它挂载到其他地方,则应该在下一组指令中替换该挂载点。
要更新引导分区固件,你所要做的就是从firmware/boot目录拷贝正确的文件到挂载的boot分区下(使用root用户)。
你大概不希望从这个目录中复制所有的文件吧。
在firmware/boot目录下的这些关键固件文件如下:
bootcode.bin
fixup.dat
start.elf
我们强烈建议你此时将现有(如果有的话)的工作副本备份一份。你可以首先在挂载的boot分区中重新命名这些文件(以root用户)来完成备份工作:
![4b70b8f977fdb2b091b2eb0e76a697cc3c606bac](https://yqfile.alicdn.com/4b70b8f977fdb2b091b2eb0e76a697cc3c606bac.png?x-oss-process=image/resize,w_1400/format,webp)
将这些固件文件拷贝到挂载boot分区:
su命令和sudo命令
此处拷贝固件文件的命令例子(以及本书中使用的大多数其他命令例子)中使用的是su命令。su命令将提示你输入你的Linux笔记本电脑的root密码,如果你在你的Linux笔记本电脑中已经配置了sudo命令,你可以使用sudo代替su – c命令,那么拷贝固件文件(以root用户)的命令则相应的应该如下所示:
![7261b4976f021142f747a368c0b09461c14439a8](https://yqfile.alicdn.com/7261b4976f021142f747a368c0b09461c14439a8.png?x-oss-process=image/resize,w_1400/format,webp)
无论你喜欢使用哪种方法都挺好,因为它们对于需要以root用户进行的Linux操作来说都是有效的方法。我们之所以在本书中绝大多数例子中对所有的root操作都使用了su – c语法,是因为这个命令在所有情况下都可以工作。而sudo只有在为你的用户配置了该命令的Linux发行版上才生效。如果你遇到了在指令前面加上sudo前缀的情况,这时应该知道,如果你没有配置sudo,那么可以使用su命令来代替它。
当将新的树莓派固件复制进boot分区后,运行sync命令,确保所有的数据都已经拷贝进SD卡:
![0db3f1fa4528bf2137f1d4484d37b8c6cb163fae](https://yqfile.alicdn.com/0db3f1fa4528bf2137f1d4484d37b8c6cb163fae.png?x-oss-process=image/resize,w_1400/format,webp)
接下来应该安全卸载SD卡分区并弹出SD卡。你可以从Linux笔记本的GUI界面中卸载分区,也可以从终端退出当前挂载分区目录并进入其他目录,然后输入命令手动卸载它们:
![0d0d909eb5f6acf4aaf099bae71ca5835e3dab48](https://yqfile.alicdn.com/0d0d909eb5f6acf4aaf099bae71ca5835e3dab48.png?x-oss-process=image/resize,w_1400/format,webp)
此时,SD卡上有了新的固件。如果树莓派照常启动并进入Linux映像文件,这种情况说明更新起作用了。不过最起码固件应该会在配置的输出设备(通常是一个HDMI连接的设备)上画出一个缤纷的“彩虹”盒(参见花絮“关于彩虹……”),因为这是启动过程的第一步(除非你已经在config.txt文件中明确禁止了这个行为)。如果上述情况出现,这说明固件已经被正确安装到SD卡上了。
关于彩虹……
我们希望,如果你的树莓派一切正常的话,你在其启动时看到的“彩虹”屏幕(如图1-3所示)永远都不要超过1秒钟。“彩虹”屏幕由树莓派的固件在初始化BCM2835片上系统的GPU组件时产生。
为了测试该输出工作正常,GPU绘制屏幕上的四个像素,然后扩展这些像素,从而产生彩色的图像。如果树莓派一直都进入不了“彩虹”界面也进入不了接下来的正常的Linux启动,这说明配置的Linux内核映像(默认为kernel.img)无法启动。
![ef833791560fe3219cbc682765436557ec54f991](https://yqfile.alicdn.com/ef833791560fe3219cbc682765436557ec54f991.png?x-oss-process=image/resize,w_1400/format,webp)
有些树莓派固件文件存在着一些可选版本,可以将树莓派配置成分配最小数量的内存(16MB)给GPU。当这样做时,树莓派的第二阶段Bootloader不再查找start.elf和fixup.dat文件,而代之以start_cd.elf和fixup_cd.dat文件。技巧24关于GPU/CPU内存分配中提供了一个更详细的讨论。