Cubieboard-启动指南-全-

Cubieboard 启动指南(全)

原文:annas-archive.org/md5/227bc9af4eee0d7b6445fbda6fe7a262

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

近年来,ARM 芯片已经变得流行并广泛应用,从手机和平板电脑市场到节能的服务器农场。这些芯片与其强大特性结合的低成本,使其成为爱好者和发烧友的理想选择。除了提供大量的连接功能外,这些芯片已经被多个厂商用于他们的开发板。Cubieboard 是一种集成网络功能和各种输入输出端口的开发板,适用于多种用途,如媒体中心、机器人项目、智能家居、Web 服务器和家庭安防系统等。Cubieboard 是一种微控制器,提供了类似桌面计算机的扩展能力,但没有笨重和噪音。

低成本、高可扩展性、性能强劲,且拥有广泛多样的用途和应用,Cubieboard 将彻底改变我们对计算和编程的思考方式。凭借其强大的特性和多功能性,你可以创造许多有趣的东西。没有固定的方式来开发复杂的项目;然而,本书将为你提供 Cubieboard 在多个领域的基础知识,帮助你深入研究。

本书内容

第一章,选择合适的开发板,首先概述了各种开发板,并比较了几款流行的开发板,帮助你选择一款符合需求的开发板。你还将了解一些附加硬件和外设,帮助你理解项目所需的设备。

第二章,硬件入门,帮助你在尝试使用之前进行初始设置。在拆开 Cubieboard 后,你将学习如何将串口连接到开发板,并继续启动预装的软件。

第三章,安装操作系统,解释了将操作系统安装到 microSD 卡并安装完整功能的图形桌面环境的过程。它还指出了操作系统镜像与干净安装之间的区别,接着介绍了安装 Fedora 以及将操作系统镜像写入 microSD 卡的过程。

第四章,手动安装替代操作系统,帮助你了解如何在替代介质(SATA SSD)上安装自定义操作系统,并使用命令行使目标介质可引导。

第五章,设置家庭服务器,解释了如何高效地使用 Cubieboard 作为家庭服务器,并设置在家庭环境中使用的不同服务。你可以学习设置 Web 服务器、文件服务器、种子服务器的过程,并最终通过设置个人云进行总结。

第六章,更新引导加载程序和内核,帮助你理解各种引导加载程序和内核类型之间的区别,同时帮助你获取并安装新的引导加载程序或内核到 SD 卡中,作为启动设备。内核通常会更新为包含安全修复或对新硬件支持的版本,因此在处理许多 ARM 板时,了解这些内容是必须的,例如 Cubieboard。

第七章,使用 BSP 编译引导加载程序和内核,讲解了板级支持包(BSP),帮助你在需要对引导加载程序和内核的源代码进行修改时,从源代码编译引导加载程序和内核。你将学习如何结合 Git 使用 BSP,并创建易于使用的设备特定硬件包。

第八章,闪烁的灯光与感知世界,从解释基本的电子概念开始,接着讲解如何切换 GPIO 引脚并使 LED 灯闪烁,从而鼓励你在进入 Cubieboard 的无限可能世界时尝试新事物。

附录 A,获取帮助和查找其他有用的在线资源,让你了解可用的在线资源,得益于活跃的社区,并且如何获取这些资源以及如何从社区获得帮助。

附录 B,基本 Linux 命令备忘单,是各种 Linux 命令的集合,在使用 Cubieboard 时它们是你工作的重要组成部分,帮助你掌握这项技术。

附录 C,FEX 配置文件,帮助你理解 FEX 文件,它们在配置驱动程序时至关重要。

附录 D,排除常见问题,是一本小指南,当你遇到错误和障碍时(例如启动失败、稳定性问题和执行命令时的错误)会非常有用。

本书所需内容

本书中涵盖的几乎所有内容都可以在开发板上完成。要与开发板进行通信,需要一台工作正常的 PC,并且需要一个可以连接 USB 到串行 3.3 伏特 UART 适配器的 USB 接口。根据所使用的操作系统,需要一个终端仿真器,例如 PuTTY。本书中使用的源代码可以通过两种方式进行编译:一种是在开发板上本地编译,另一种是通过所谓的交叉编译器在常规 PC 上编译。如果使用常规 PC,则需要 Linux,但可以通过虚拟机运行。本书仅使用了免费且开源的软件编写。

本书适用人群

本书面向所有希望开始使用 Allwinner A10、A13 或 A20 ARM 硬件的人群。这可以是从在家做有趣项目的爱好者和开发者,到对 ARM 或 Linux 知识了解较少、但希望开发新 ARM 基础产品的专业人士。本书不要求您具备 Linux 知识,但如果您有 Linux 知识,将会使事情变得容易得多。虽然 Android 是许多开发板上预装的常见操作系统,但本书并不涉及 Android 或 Android 应用程序。

约定

在本书中,您将看到多种文本样式,用于区分不同类型的信息。以下是一些样式的示例,并解释它们的含义。

文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟网址、用户输入和 Twitter 账号如下所示:“可以随时使用l命令查看可用的类型。”

任何命令行输入或输出都按如下方式书写:

packt@PacktPublishing:~$ tar xJvf u-boot-sunxi-cubieboard.tar.xz
u-boot-sunxi-cubieboard-20140307T104232-b5bd4c9/
u-boot-sunxi-cubieboard-20140307T104232-b5bd4c9/u-boot-sunxi-with-spl.bin
u-boot-sunxi-cubieboard-20140307T104232-b5bd4c9/u-boot.bin
u-boot-sunxi-cubieboard-20140307T104232-b5bd4c9/sunxi-spl.bin

新术语重要单词用粗体显示。您在屏幕上看到的词语,例如在菜单或对话框中,像这样出现在文本中:“确保检查串口。”

注意事项

警告或重要注意事项会以框框的形式出现,如下所示。

提示

提示和技巧像这样出现。

读者反馈

我们始终欢迎读者的反馈。让我们知道您对本书的看法——您喜欢什么,或者可能不喜欢什么。读者反馈对我们开发能让您真正受益的书籍非常重要。

要向我们发送一般反馈,只需发送电子邮件至 <feedback@packtpub.com>,并在邮件主题中提到书名。

如果您在某个领域有专业知识,并且有兴趣写作或为书籍做贡献,请查看我们在www.packtpub.com/authors上的作者指南。

客户支持

现在,您已经成为一本 Packt 图书的自豪拥有者,我们为您提供了一些帮助,帮助您从购买中获得最大收益。

下载示例代码

您可以从您的账户中下载所有已购买的 Packt Publishing 图书的示例代码文件,网址是 www.packtpub.com。如果您在其他地方购买了本书,您可以访问 www.packtpub.com/support 并注册,以便直接通过电子邮件接收文件。

下载本书的彩色图片

我们还为您提供了一个包含本书中使用的截图/图表的彩色图片的 PDF 文件。彩色图片将帮助您更好地理解输出结果的变化。您可以从以下链接下载该文件:www.packtpub.com/sites/default/files/downloads/1572OS_ColoredImages.pdf

勘误

尽管我们已经尽力确保内容的准确性,但错误仍然会发生。如果您在我们的一本书中发现错误——可能是文本或代码错误——我们将非常感激您向我们报告。这样,您可以帮助其他读者避免困扰,并帮助我们改进后续版本。如果您发现任何勘误,请通过访问 www.packtpub.com/submit-errata,选择您的书籍,点击 Errata Submission Form 链接,并输入勘误详情。一旦您的勘误被验证,您的提交将被接受,勘误将上传至我们的网站,或添加到该书标题下的任何现有勘误列表中。任何现有的勘误都可以通过选择您的书籍从 www.packtpub.com/support 查看。

要查看之前提交的勘误,请访问 www.packtpub.com/books/content/support,并在搜索框中输入书名。所需信息将显示在 Errata 部分。

盗版

网络上版权材料的盗版问题是各类媒体中持续存在的问题。在 Packt,我们非常重视保护我们的版权和许可证。如果您在互联网上发现我们作品的任何非法复制,无论形式如何,请立即提供其位置或网站名称,以便我们采取补救措施。

如果您发现任何涉嫌盗版的资料,请通过 <copyright@packtpub.com> 联系我们,并附上相关链接。

我们感谢您帮助保护我们的作者,以及我们为您提供有价值内容的能力。

问题

如果您在本书的任何方面遇到问题,请通过 <questions@packtpub.com> 与我们联系,我们将尽力解决。

第一章. 选择合适的开发板

又到了每年这个时候,几天的空闲时间让你迫不及待地想玩一玩大家都在谈论的新 ARM 开发板。然而,市面上有很多开发板可供选择。在众多选择中,应该选择哪款板子呢?选择开始工作的开发板可能会在后续产生很大影响,因此本章提供了各种开发板的介绍,并指出它们之间的主要区别。虽然本书的重点确实是 Cubietech 的 Cubieboard 系列,但为了有可能选择第二块开发板,仍然建议阅读本章。此外,本书同样适用于这里提到的这些开发板。

在本章的第一部分,我们将涵盖以下主题:

  • 为什么会有这么多开发板可供选择?

  • 各种开发板概览

  • 突出介绍最受欢迎的开发板

  • 需要额外硬件的建议

穿越可用的芯片和开发板的丛林

在进行 ARM 开发时,有许多芯片和更多的开发板可以选择。本章还简要介绍了各种芯片,并进行了比较。

芯片概览

在过去的几年里,基于 ARM 的系统级芯片SoC)变得极为流行。与传统的基于 x86 的英特尔或 AMD CPU 相比,它们更加节能,同时性能也足够满足需求。它们还集成了许多外设,如图形处理单元GPU)、视频加速器VPU)、音频控制器、各种存储控制器以及各种总线(如 I2C 和 SPI)等。这大大减少了开发板所需的组件数量。随着所需组件的减少,带来了一些显而易见的优势,例如降低成本,从而使得开发板的设计变得更加简单。因此,许多拥有电子工程师的公司能够以低廉的成本设计和生产这些开发板。

那么,有这么多开发板,是否意味着有许多 SoC 呢?实际上确实有不少,但为了简洁,以下只列出了最受欢迎的几款:

  • 全志的 A 系列

  • 博通的 BCM 系列

  • 飞思卡尔的 i.MX 系列

  • 联发科的 MT 系列

  • 瑞芯微的 RK 系列

  • 三星的 Exynos 系列

  • NVIDIA 的 Tegra 系列

  • 德州仪器的 AM 系列和 OMAP 系列

  • 高通的 APQ 系列和 MSM 系列

尽管许多潜在的芯片都很有趣,但 Allwinner 的 A 系列 SoC 将是本书的重点。由于它们价格低廉且供应充足,许多公司围绕这些芯片设计开发板,并以低价销售。此外,A 系列目前是最友好的开源芯片系列。它有一个完全开源的引导加载程序,几乎所有硬件都可以通过开源驱动程序支持。在 A 系列芯片中,有一些选择。以下是最常见且最有趣的设备列表:

  • A10:这是 A 系列的第一款芯片,也是支持最好的芯片,因为它已经存在很长时间。它能够通过 I2C、SPI、MMC、NAND、数字和模拟视频输出、模拟音频输出、SPDIF、I2S、以太网 MAC、USB、SATA 和 HDMI 与外界进行通信。最初,这款芯片面向所有设备,如手机、平板电脑、机顶盒和迷你 PC 棒。其 GPU 采用 MALI-400。

  • A10S:这款芯片继承了 A10,主要面向 PC 棒市场,并省略了若干部分,例如 SATA 和模拟视频输入/输出,并且没有 LCD 接口。省略这些部分是为了降低芯片成本,使其在廉价电视棒中具有吸引力。

  • A13:这款芯片大致与 A10S 同时推出,主要用于平板电脑。它没有 SATA、以太网 MAC,也没有 HDMI,从而进一步降低了芯片的成本。

  • A20:这款芯片在其他芯片之后很久才推出,并且与 A10 具有引脚兼容性,旨在替代 A10。正如名字所示,A20 是 A10 的双核版本。ARM 核心略有不同,A10 采用的是 Cortex-A7,而以前使用的是 Cortex-A8。

  • A23:这款芯片是在 A31 和 A31S 之后推出的,设计上与 A31 相似。它采用双核 Cortex-A7 设计,旨在替代 A13。它主要用于平板电脑。

  • A31:这款芯片具有四个 Cortex-A7 核心,通常具有 A10 所具备的所有连接功能。然而,由于它采用 PowerVR GPU,至今没有得到社区支持,因此在社区中不太受欢迎。此外,目前没有常见的开发板可用。

  • A31S:这款芯片在 A31 之后稍微推出,解决了一些 A31 存在的问题。目前没有常见的开发板可用。

选择合适的开发板

Allwinner 的 A 系列 SoC 由于价格便宜而被许多公司应用于产品中,例如平板电脑、机顶盒,最终还用于开发板。在开发板可用之前,人们主要在平板电脑和机顶盒上进行开发。最常见和流行的开发板来自 Cubietech 和 Olimex,部分原因是这两家公司向社区开发者免费提供开发板。

Olimex

Olimex 发布了大量不同的开发板和外设。许多开发板是开源硬件,提供了原理图和布局文件,而且 Olimex 对开源非常友好。你可以在下图中看到 Olimex 开发板:

Olimex

Olimex 提供了 A10-OLinuXino-LIME,这是一款基于 A10 的微型开发板,主要以与著名的 Raspberry Pi 在价格上竞争为目标。由于其体积较小,它使用了较少标准的 1.27 毫米间距引脚,但几乎所有的引脚都暴露出来供使用。

你可以在下图中看到 A10-OLinuXino-LIME 开发板:

Olimex

Olimex OLinuXino 系列开发板有 A10、A13 和 A20 三种版本,并且配备了更为标准的 2.54 毫米间距引脚,这些引脚兼容旧版 IDE 和串口连接器。Olimex 还提供了多种传感器、显示器和其他外设,这些外设也与这些引脚兼容。

Olimex 最近宣布将发布一个 模块化系统SoM)。它的概念与稍后提到的 Itead 开发板相同。

Cubietech

Cubietech 由前 Allwinner 员工创办,是首批使用 Allwinner SoC 的开发板之一。虽然它不是开源硬件,但提供了原理图供下载。Cubietech 发布了三款开发板:Cubieboard1、Cubieboard2 和 Cubieboard3,也被称为 Cubietruck。与这些板的接口可能会比较棘手,因为它们使用 2 毫米间距的引脚,这些引脚在欧洲或美国可能比较难找。你可以在下图中看到 Cubietech 开发板:

Cubietech

Cubieboard1 和 Cubieboard2 使用相同的开发板,唯一的区别是 Cubieboard2 使用了 A20,而不是 A10。这些开发板仅暴露了部分引脚。你可以在下图中看到 Cubietruck 开发板:

Cubietech

Cubietruck 与前几款板有所不同,它是一款设计良好的 A20 开发板。它具备了前几款开发板的所有功能,并且增加了千兆以太网、VGA、蓝牙、Wi-Fi 和光学音频输出。尽管如此,它的成本也相对较高,因为它为了保持较小的尺寸,减少了引脚数量。与 Raspberry Pi 或 LIME 相比,它几乎是其两倍大小。

Lemaker

Lemaker 在发布其 Banana Pi 开发板时做出了一个聪明的设计选择。它是一块基于 Allwinner A20 的开发板,但使用与 Raspberry Pi 相同的板尺寸和连接器布局,因此得名 Banana Pi。由于这一点,许多 Raspberry Pi 的外壳都可以适配 Banana Pi,甚至一些扩展板也能使用。然而,在软件上,它有很大的不同,不能使用 Raspberry Pi 的镜像文件。但它具有复合视频输出、立体声音频输出、HDMI 输出、千兆以太网、两个 USB 端口、一个 USB OtG 端口、CSI 输出和 LVDS 输出,并且还有一些引脚可供使用。它还提供了 LiPo 电池连接器、SATA 连接器和两个按钮,但这些可能在很多标准外壳上无法访问。请看以下图片,了解 Banana Pi 的顶视图:

Lemaker

Itead 和 Olimex

Itead 和 Olimex 都提供了有趣的开发板,值得单独提及。Iteaduino Plus 和 Olimex A20-SoM 是非常有趣的概念;它们是计算模块,这是一块包含 SoC、内存和闪存的板,这些模块可以插入,并配有独立的主板。它们都提供非常完整的开源硬件主板,但任何人都可以设计自己的主板,并购买计算模块。你可以看到以下 Itead 提供的开发板:

Itead 和 Olimex

请参考 Olimex 提供的以下板:

Itead 和 Olimex

额外的硬件

虽然开发板是一个关键组成部分,但还有一些其他必需的配件。例如,电源并不总是提供的,而且有一些考虑因素。此外,初步通信和调试还需要额外的硬件。

串行接口与开发板连接

对于像这样的无头系统,事情并不总是能顺利进行。有时,需要在更低层次上进行调试。对于这些开发板,情况也正是如此。当发生错误且没有输出时,可能出了什么问题呢?因此,避免花费数小时的反复试验是可能的;许多类型的硬件上都有老式而可靠的串口。对于 Allwinner 的 SoC,它们的串口实现有两种方式。

通用异步接收器/传输器

在本书中讨论的所有开发板上,都有专门的引脚可以连接到芯片的串口。如果用于连接开发板的 PC 有串口,要小心连接方式。尽管它们使用相同的协议,但它们的工作电压不同,因此至少需要一个电平转换器。如今大多数 PC 已经没有串口了,需要依赖 USB 转 通用异步接收器/传输器 (UART) 适配器。在购买 USB 到 UART 适配器时,重要的是选择 3.3V TTL 适配器。Cubieboard 通常会配备 USB 到 UART 适配器,如下图所示:

通用异步接收器/传输器

microSD 适配器

有时,UART 端口可能无法使用,像大多数平板电脑一样。在这种情况下,通过 microSD 卡槽提供第二个 UART 接口。需要特定的适配器来连接之前提到的 UART 接口。在下面的图片中,可以看到一个 microSD 到 UART 适配器(该特定版本还能够访问 JTAG 引脚):

microSD 适配器

microSD 卡

通常,microSD 卡是这些开发板的启动介质。它可以被视为类似于 PC 上的可启动 CD 或 USB 驱动器。当创建 microSD 卡作为启动介质时,建议使用 Class 10 或更快的 microSD 卡。

电源

信不信由你,大多数开发板实际上是不包含电源的,这通常是由于以下原因:

  • 没有电源的开发板无需通过 FCC 认证。

  • 进口电源可能需要特定的本地认证,甚至可能被禁止。

  • 它可能引发开发者不清楚需要为某个国家提供哪种电源的问题。

  • 这样可以降低成本,因为不附带电源就减少了成本。

大多数开发板的输入电压为 5 伏,但它们至少应提供 700 毫安的电流,当不使用大功耗设备(如硬盘或液晶显示器)时。如果连接了额外的外设,这一要求也会增加。一个适当的 5 伏、2 安的电源就足以在满载情况下为开发板供电,且连接了液晶显示器时也能正常工作。根据硬盘的电力需求,甚至这类电源也应能顺利工作。如果不确定,请始终检查电力消耗或电源稳定性,以排除其造成异常问题的可能性。市场上便宜的电源通常会被过度标定,因此它们可能无法提供所需的电流,进而导致系统不稳定。

总结

在完成本章内容后,你应该对现有的、流行的开发板有所了解,并能判断哪一款可能适合你。最后需要指出的是,有时额外的硬件是必须的,或者至少对于使用这些开发板非常有帮助。

下一章将介绍如何使用新购买的硬件,并解释如何与其进行交互。如果所选的开发板预装了软件,也会涉及到启动过程。

第二章:硬件入门

当你开始使用一款新设备时,可能会有一些问题浮现在脑海中。如何判断它是否正常工作?如何从设备获取输出或向设备输入,比如从显示器获取视频或从键盘输入按键?这些可能是当开发板首次拆开或启动时最基本的问题。

本章将涵盖以下内容:

  • 将串口连接到开发板

  • 启动预装的软件

连接串口

串口可能看起来像是过时的设备,但实际上在某些设备上仍然非常常见。其主要原因之一是它非常简单且可靠。它在硬件和软件实现上都很简单,正因为简单,它通常非常可靠,几乎总是能够正常工作——这也是它自六十年代起一直被应用于设备的原因。然而,串口连接速度较慢,但对于基于文本的输入输出,它完全足够。然而,为什么一开始会想要使用串口呢?正如墨菲定律所证明的那样,事情往往会出错,而对于这些开发板来说,串口往往是唯一能够提供输出的接口。

连接串口或 UART 到设备有两种方式,要么使用 USB 转 UART 适配器,要么使用真实的串口并加装电平转换器以将电压转换为合适的电压。

由于大多数个人电脑实际上没有串口,本章将仅讨论 USB 转串口的方式。第一步是将 USB 转 UART 适配器连接到你的 Cubieboard,这本身可能就是一个挑战,因为有些 USB 转 UART 适配器只有三根线,而有些则有四根甚至更多。此外,电缆的颜色可能因产品不同而有所不同。最后,还有 3.3 伏或 5 伏的适配器。请查看电缆的用户手册,了解每根线的颜色对应的信号以及电压是否为 3.3 伏。例如,Cubieboard 随附的 USB 转串口适配器遵循以下规则:

  • 黑色是 GND 或接地,连接到 GND 引脚

  • 绿色是 TX 或发送端,连接到开发板上的 RX 或接收端引脚

  • 白色是 RX 或接收端,连接到开发板上的 TX 或发送端引脚

  • 红色是 VCC 或电源,永远不应连接,否则设备可能会损坏

请参考下面的图像查看各种连接方式:

连接串口

Cubieboard1 上的 UART 连接

连接好 UART 端后,另一端可以直接插入 USB 端口。根据使用的操作系统,可能需要安装驱动程序;此外,还需要一个程序来连接此串口,这样就创建了一个所谓的串口终端。PuTTY 就是这样一个程序,并且它可以在大多数操作系统上使用。Windows 平台上的下载地址为www.chiark.greenend.org.uk/~sgtatham/putty/download.html

其他操作系统可能通过内置的软件商店提供该软件,并可以通过此方式安装。其他可用的软件类型,如 GNU Screen 或 minicom,也能同样有效地用于查看串口控制台。

要使串口通信正常工作,需要一些参数;需要 115,200 位每秒的波特率。此外,可能需要八个数据位、无校验位和一个停止位(通常简称为 8n1),但在前面提到的 PuTTY 或默认的 screen 中,可能可以省略。对于 screen,可以使用screen /dev/ttyUSB0 115200命令行,假设/dev/ttyUSB0是正在使用的串口。

提示

查找正确的设备名称或编号可能会有些棘手;这不仅因操作系统不同而有所不同,而且获取正确的编号也可能很复杂。例如,在 Linux 和 OSX 下,插入 USB 转换器后使用dmesg或在/dev/ttyUSB上使用自动完成功能可能会有所帮助。在 Windows 上,可以使用设备管理器。

对于 PuTTY,以下截图展示了所需的设置,假设COM5是串口。确保选中串口

连接串口

如果串口连接已正确建立,给 Cubieboard 供电后,串口控制台应该会显示文本。以下截图展示了此文本的示例。在此,通常安装在 microSD 卡上的引导加载程序被显示。首先加载的是 SPL,它探测内存并打印当前的 CPU 配置,接下来是 U-Boot,它打印当前的配置。请查看以下截图:

连接串口

上面的截图仅是示例。这会根据所使用的引导加载程序、启动介质和板子而有所不同。它仅展示了首次启动时可能看到的内容。

启动预安装的软件

当 Cubieboard 首次开机时,会发生一些事情。首先,SoC 会检查各种设备,看是否能从中启动。如果可用,板载的 NAND 闪存很可能已由制造商预先编程。使用任何预安装的系统启动 Cubieboard 都有其意义。它允许你检查 Cubieboard 是否正常运行。

如果 Cubieboard 没有预安装操作系统或 NAND 闪存,可以使用专门准备的 microSD 卡。由于 microSD 卡实际上是 SoC 尝试启动的第一个设备,因此它应该能产生类似的结果。拥有这样一张卡片是非常有用的。接下来的章节将向你展示如何准备这样的 SD 卡。预安装的操作系统很可能需要连接显示器、键盘和鼠标以便与之交互。虽然大多数版本预安装了 Android 操作系统,但也有一些情况下安装的是命令行版本的 Linux。使用预安装的 Android 操作系统,可以轻松测试各种组件。使用以下清单测试最明显的项目:

  • 显示器是否正常工作?

  • 鼠标是否正常工作?

  • 键盘是否正常工作?

  • 网络连接是否正常工作?

  • 音频播放是否正常?

  • MMC 卡是否正常工作?

在测试显示器是否正常工作时,图像可能已配置为与其他外设一起使用,而不是预期的那些。例如,可能预期连接 HDMI 显示器,而实际上连接的是 VGA 显示器。音频也是如此,可能被路由到 HDMI,而实际上通过音频插孔连接的是普通耳机。

对上述清单进行检查在命令行安装下更具挑战性,但并非完全不可能。显示器和键盘的测试相对容易。甚至网络功能也应该能被检测到。具备一些基础 Linux 知识后,前面提到的所有组件都能轻松测试。

提示

为了让网络几乎自动配置,建议在网络上设置一个 DHCP 服务器。大多数调制解调器/路由器或无线接入点默认提供此功能。

总结

学会如何连接和使用串口后,你现在应该能够观看 Cubieboard 启动并使用预安装的软件检查系统是否正常运行。

在下一章中,你将最终开始进行一些实际的工作,也就是,你将设置一个完整的桌面系统。

第三章:安装操作系统

拥有一个 Cubieboard 只有在你能够实际使用并最终开发和/或玩弄它时才有意义。预装的操作系统可能足够,也可能不够。通常,这些设备上预装的是 Android,因为所使用的 SoC 通常出现在 Android 设备中,且制造商大多或仅支持它。虽然 BSD 或 Minix 也是由不同开发者开发的操作系统,但本书将仅限于 Linux 作为操作系统。本章的前几节将为教育目的深入探讨相关概念。

本章将涵盖以下主题:

  • 找出 SoC 芯片决定从哪个地方启动

  • 操作系统镜像与干净安装的区别

  • 下载并安装 Fedora

  • 从 SD 卡启动新安装的操作系统

  • 使用 Fedora 并连接有线网络的基本概念

  • 通过软件包管理器维护 Fedora

启动 Cubieboard

尽管看起来系统只是简单地启动了,但实际情况远不止如此。Allwinner 系列的 SoC 有一个叫做Boot Read Only MemoryBROM)的东西。BROM 实际上是一个嵌入到芯片中的小程序,它总是首先执行。这个程序包含了一些驱动程序,用于支持最小集的硬件,以确保其小巧简洁。

首先,BROM 会尝试在第一个 SD 卡中查找有效的引导加载程序,这个 SD 卡也叫做 MMC 插槽。如果那里没有找到有效的引导加载程序,就会检查 NAND 是否有有效的引导加载程序。同样,如果那里也没有找到,就会检查第二个 MMC 插槽。如果那里也没有找到,则会探测第一个 SPI 总线是否有 SPI 内存闪存芯片,并检查是否有有效的引导加载程序。最后,如果前面的所有方法都失败了,就会进入 FEL 模式。FEL 模式是一种恢复模式,可以通过 USB 连接上传一段代码并执行它。这对于在启动失败且第一个 MMC 插槽无法启动时恢复板子非常有用。FEL 模式不需要手动启动。有人可能会疑惑为什么要探测两个 MMC 插槽。有时,制造商会在设计中集成一个嵌入式 MMC 芯片,或者 eMMC,它与 SD 或 MMC 卡不同,外观看起来像常规芯片,类似于 NAND 闪存芯片,但行为和外观像 MMC 卡。通过探测两个 MMC 插槽,可以使板子使用 eMMC 芯片,同时仍然有第一个 MMC 插槽可供像启动恢复这样的用例使用。Cubietruck 有多种这些存储选项的组合。

操作系统镜像安装背景

许多网站和论坛在讨论嵌入式设备的安装时会提到固件或 ROM。这一切听起来一开始非常神秘,但事实远非如此。ROM 不过是一个完整的磁盘映像,而这个映像可以写入存储设备,板子可以从中启动。ROM这个名称来源于数据曾经存储在 ROM 芯片中的事实。许多为 Allwinner 开发板提供的操作系统镜像都针对非常特定的开发板量身定制。这并不令人惊讶,因为所使用的芯片可能在多个开发板中是相同的,但某些附加外设可能完全不同;例如,一个开发板可能使用不同的内存芯片。另一个开发板可能没有板载闪存,完全依赖于第二个 MMC 槽来存储操作系统。几乎不可能有一个单一的磁盘镜像能够适用于所有这些不同硬件组合,因此干净的安装看起来是一个相当合理的方式。虽然一些发行版正在慢慢开始支持基于 ARM 的系统,但要有一个通用的安装程序能够安装到任何基于 ARM 的开发板上,仍然并不容易。为了连接这些世界,少数 linux-sunxi 社区成员和 Red Hat 员工开发了一种混合安装方案,Fedora 的这个版本可以下载、配置,最后在安装程序中启动。

获取和准备 Fedora

Fedora 已经为 A10、A10S、A13 和 A20 系列的 SoC 发布了多个版本。由于本书重点介绍的是最新版本,Fedora 20-r1,因此推荐使用最新版本。另外,如果失败了,可以将 Fedora 20-r1 写入 SD 卡,这张卡可以作为恢复启动盘。此项工作的第一步是下载该磁盘镜像。大约需要 2 GB 的空闲磁盘空间。

本章的 Fedora 可以从 Packt Publishing 网站的本书支持页面中的帮助与支持部分下载。

接下来的几个步骤假设你有一台 Linux 电脑。如果没有的话,也可以使用 Cubieboard 上预装的操作系统;虽然稍微复杂一点,但应该完全可以实现。如果预装的操作系统是 Android,则需要一个可能未安装的终端应用程序。需要注意的是,在 Mac OSX 上,设备路径名会有所不同。最后,也可以使用虚拟机,但对虚拟机的详细说明超出了本书的范围。

提示

Mac OSX 使用的设备节点与 Linux 类似,但略有不同。例如,插入的 USB 闪存驱动器的第二个分区在 Linux 中通常会显示为/dev/sdb2,而在 OSX 中则会显示为/dev/disk2s2

将操作系统镜像写入 SD 卡

首先,镜像需要写入一个至少 4 GiB 大小的 microSD 卡。

注意

接下来的几个步骤将删除 SD 卡上的所有内容。

microSD 卡应连接到 PC。如果没有读卡器,可以使用 USB 转 microSD 读卡器。xzcat 命令用于将下载的 xz-compressed 压缩包解压到 SD 卡上。

在以下示例中,假设 microSD 卡已插入 USB 卡读卡器,并已分配设备节点 /dev/sdd。设备节点的确定需要由读者自行判断,但可以通过 dmesg 或其中一个已安装的图形磁盘工具来获得答案。以下是一个示例输出,显示 SD 卡在设备节点 /dev/sdd 上找到:

usb 2-5: new high-speed USB device number 14 using ehci-pci
usb 2-5: New USB device found, idVendor=14cd, idProduct=8123
usb 2-5: New USB device strings: Mfr=1, Product=3, SerialNumber=2
usb 2-5: Product: USB 2.0  SD MMC READER
usb 2-5: Manufacturer: SDMMC MA8123
usb 2-5: SerialNumber: 312811122181
usb-storage 2-5:1.0: USB Mass Storage device detected
scsi14 : usb-storage 2-5:1.0
scsi 14:0:0:0: Direct-Access     USB 2.0  SD MMC Reader         PQ: 0 ANSI: 0 CCS
sd 14:0:0:0: [sdd] 248320 512-byte logical blocks: (127 MB/121 MiB)
sd 14:0:0:0: [sdd] Write Protect is off
sd 14:0:0:0: [sdd] Mode Sense: 03 00 00 00
sd 14:0:0:0: [sdd] No Caching mode page found
sd 14:0:0:0: [sdd] Assuming drive cache: write through
sd 14:0:0:0: [sdd] No Caching mode page found
sd 14:0:0:0: [sdd] Assuming drive cache: write through
 sdd: sdd1
sd 14:0:0:0: [sdd] No Caching mode page found
sd 14:0:0:0: [sdd] Assuming drive cache: write through
sd 14:0:0:0: [sdd] Attached SCSI removable disk

该命令可能需要 root 权限;为此,请在 dmesg 前加上 sudo。此处使用的文件名应与下载的文件匹配。成功完成后,将强制执行 sync 命令进行缓存刷新。刷新缓存很重要,这样我们才能确保所有数据都已实际写入 SD 卡,而不会停留在缓存中。这个过程可能会花费相当长的时间——通常需要 10 分钟。以下命令是一个示例,演示如何将镜像写入 SD 卡并刷新缓存:

root@packt:~# xzcat Fedora-Xfce-armhfp-20-a10-1-sda.img.xz > /dev/sdd && sync

在 Linux、OSX、BSD、Solaris 以及许多现代 POSIX 系统上,应该能够编写操作系统镜像。在 Windows 上,则需要稍加注意。可以使用如 7-Zip 之类的程序来解压镜像,使用像 WinDD 这样的镜像写入工具来代替。

完成后,拔出 USB 设备并重新插入,以强制重新读取 SD 卡的分区表。在大多数情况下,打开文件管理器将显示 SD 卡上新创建的分区,一个名为 u-boot,另一个名为 rootfs

编写引导加载程序

引导加载程序是非常特定于设备的,甚至在同一板卡的生产批次之间也可能有所不同。这是因为内存初始化由引导加载程序执行,因此可能有所不同。为此,除了多个引导加载程序和多个内核外,设置脚本会预安装在不同代 SoC 的系统上。此脚本需要从 microSD 卡上的 u-boot 分区执行。如果当前操作系统自动挂载分区,可以使用 mount 命令来查找挂载点,如下所示:

[root@packt:~]# mount
/dev/sdd1 on /media/u-boot type ext2 (rw,errors=remount-ro)

在前面的示例中,microSD 卡挂载在 /media/u-boot,设置脚本应从那里运行。此路径应根据需要进行调整。以下是一个示例,显示可用板卡的示例输出。引导加载程序正在使用 Cubietruck 安装。可能需要在命令前加上 bash,以强制 bash 执行脚本。

[root@packt:~]# bash /media/u-boot/select-board.sh

如果没有可用的 Linux 系统,设置脚本应能够在原生 Android 环境中运行。但是,这需要 ADB 或终端应用程序的支持。

这将提供一个受支持板卡的列表。找到正在使用的确切板卡,并使用所选板卡作为参数再次运行命令。注意,只会显示一个小范围的选项,如下图所示:

写入引导加载程序

设置好板卡后,卸载 microSD 卡并进行同步,以确保所有数据已正确写入。让我们看一下以下命令:

[root@packt:~]# umount /dev/sdd1 && eject /dev/sdd1 && sync

根据运行此脚本的环境,可以启动图形版本;然而,思路是相同的:选择正确的板卡,脚本会将镜像写入正确的位置。

完成操作系统安装

连接显示器、USB 键盘和 USB 鼠标,并将 microSD 卡插入 Cubieboard。每个板卡在第一次启动时都有默认的输出配置。对于许多无头板卡,这将是 HDMI 端口。对于带有 LCD 屏幕的平板或系统,这将是 LCD 屏幕。虽然并非严格要求,但连接 UART,如前一章所述,可能会有帮助,以防出现问题,如下图所示:

完成操作系统安装

施加电源将启动设备,经过几分钟以及几次有意的重启来调整 SD 卡上的分区大小后,Fedora 安装程序应该会弹出。如果显示器没有输出,参见附录 D, 排除常见问题。此外,参见以下截图查看 Fedora 的第一个图形化安装界面:

完成操作系统安装

如果连接了鼠标,或者至少连接了键盘,可以设置系统的各种参数。验证时区是否正确,并为 root 用户设置密码。此外,应为常规使用创建一个新用户,如下图所示:

完成操作系统安装

在创建用户并完成安装及短暂重启后,应该会出现登录屏幕,允许新创建的用户登录。现在可以登录到桌面,如下图所示:

完成操作系统安装

将要遇到的桌面环境称为Xfce4,其中字母仅具有历史意义,数字表示版本号。版本 4 自 2003 年以来一直在积极开发。Xfce4 是一个非常轻量级的桌面环境,并且是 Fedora 在 ARM 架构上的默认桌面环境,以便在系统资源有限的情况下保持较轻的负担。Xfce4 可能会向新用户询问几个关于桌面外观的问题,但默认设置通常能够正常工作,并且在本示例中也使用了这些设置。可以随意探索这个新的桌面,启动一些应用程序,或者只是浏览互联网。请参见以下截图查看默认桌面:

完成操作系统安装

安装更新的预防措施

虽然现在有一个完全可用的桌面环境,但其中一个非常常见的任务是保持操作系统的最新和安全。Fedora 配备了 Yum 命令行工具的图形化前端,称为Yum Extender。然而,在使用它之前,需要发出一个警告。此时,Fedora 和所有其他发行版一样,并不正式支持 Allwinner 系列的 SoC。这在更新操作系统时有一个主要的缺点。更新工具,无论是 Yum 还是 Yum Extender,都将尝试更新内核和引导加载器配置。

在编写本书时,Fedora 20-r1 版本将尝试更新内核和引导加载器配置,导致设备无法启动。然而,通过将 SD 卡插入一个正常工作的系统并像以前一样运行select-device.sh脚本,这个问题可以很容易地解决。为了防止这种损坏,编辑/etc/yum.conf位置的文件,并向该文件添加以下行,强制 Yum 忽略任何内核更新:

exclude kernel*

应该在 Fedora 的任何新版本中添加内核排除,因为它可能不适用于后续版本。

提示

由于内核和引导加载器存在于各自的分区中,因此未挂载u-boot分区可以避免需要更新引导加载器和内核。在下一章中,读者将能够轻松编辑其fstab文件。

维护操作系统并安装更新

如前所述,可以方便地通过图形用户界面使用 Yum Extender 来更新系统或安装新软件包。Yum Extender 可以在应用程序菜单管理标签下找到,如下图所示:

维护操作系统并安装更新

由于 Yum Extender 是一个管理员应用程序,因此当前用户需要授权其使用。假设这一点,用户将获得管理员权限。系统的第一个用户将拥有这些权限。请参见以下截图查看Yum Extender

维护操作系统并安装更新

点击全选按钮,然后点击应用将开始安装所有新的系统更新。根据 SD 卡的速度等级,这个过程可能需要很长时间。在为本章准备插图时,我使用的是一个 8GB 4 类 SD 卡,整个过程花费了 5 分钟少于 6 小时。因此,建议使用至少 10 类或更高级别的 SD 卡。虽然 4 类卡比较慢,但在使用操作系统时仍然是可以用的。

提示

比如,你可以考虑在周五晚上更新 SD 卡,因为这个过程可能会占用整个周末时间而不会打扰到任何人。

如果在更新过程中出现如下截图所示的警告,接受它是安全的。这是一个导入缺失 GPG 密钥的通知。在这种情况下,它已经得到了 Fedora 项目的批准,正如可以从所用电子邮件地址看到的那样。这个消息可能会在更新过程的前 10 分钟左右出现。

维护操作系统和安装更新

向操作系统添加更多软件

由于 Linux 发行版中的软件包管理器已经存在多年,安装额外的软件变得非常容易。Yum Extender 不仅可以用于更新操作系统,还可以向系统中添加新软件,正如下图所示,这里演示了安装 Firefox。你也可以选择使用命令行版本的 yum。

向操作系统添加更多软件

总结

完成本章内容后,你应该能够顺利创建一个全新的基于 Xfce4 的 Fedora 操作系统 SD 卡。此外,保持系统更新和添加新软件也不会有问题。这一切要归功于 Fedora 的混合磁盘映像!

下一章将更深入地手动安装操作系统,并重点介绍基于命令行的界面,因为它通常用于服务器设置、嵌入式系统等。整个安装过程将从零开始进行,以学习如何创建定制化的系统。

第四章:手动安装备用操作系统

将一个完整的桌面操作系统OS)通过镜像安装到 SD 卡上是非常有用的,但很快就会遇到限制。如果需要将操作系统安装到 SSD 上怎么办?或者,如果希望有一个非常精简的安装用于作为服务器使用呢?显然,对于这个需求不需要重型 GUI 界面吧?所有这些问题将在本章中讨论。

本章将涵盖以下主题:

  • 分区和格式化目标介质

  • 创建 rootfs

  • 允许目标介质启动

  • 更新操作系统

  • 安装额外软件

本章的前提条件

在本章中,Debian(甚至 Ubuntu)将安装到一个备用安装介质上。将使用 SATA SSD,但只要有足够的电力来为驱动器提供电源,也可以使用普通的 SATA 硬盘;在这种情况下,至少需要一个 2 安培的电源适配器。或者,也可以使用第二个 microSD 卡,通过 microSD 到 USB 适配器来连接。

然而,当安装到 SATA 驱动器时,Cubieboard 仍然需要 SD 卡来启动,因为 SoC 不能直接从 SATA 驱动器启动。从技术上讲,板载 NAND 闪存或板载 SPI 闪存也可以用于此,但支持 SPI 闪存的 Cubieboard 很难找到,而且使用 NAND 需要一个非常旧的 u-boot,它缺少很多新特性。在本章中,之前章节创建的 microSD 卡将重新使用,并完成所有这些任务。

提示

USB 闪存驱动器理论上可以使用,但在撰写本书时,USB 引导代码尚未进入 u-boot。目前,USB 闪存驱动器只能在引导一个带有 USB 支持的内核后使用,该内核已从 NAND 或 SD 卡加载。

准备目标介质

若要将 Debian 安装到 SATA 驱动器,目标驱动器需要一些准备工作。需要对其进行分区和格式化。

假设 Cubieboard 已使用之前创建的 Fedora 镜像启动,并且已连接 SATA 硬盘、USB 闪存驱动器或带 USB 适配器的 microSD 卡,现在是时候开始在目标介质上使用fdisk,假设目标介质为/dev/sda。请确保使用正确的设备节点,否则以下操作将销毁介质上的所有内容。

分区设备时,最常用的工具是fdisk。虽然fdisk有一些参数,但以设备节点启动它将使fdisk进入交互模式,在其中可以准备磁盘。使用fdisk需要 root 权限,因此可能需要加上sudo前缀,如下图所示:

准备目标介质

应确保目标介质上没有任何以前的数据,或者至少已经备份,这部分内容将在此不做讨论。按下o键应清除任何先前创建的分区,如下所示:

准备目标介质

分区是非常有用的,它们允许逻辑分隔。分区时有许多原因和选择,在这里,我们只关注以下四个分区:

  • 启动:此分区包含所有相关的启动文件

  • :此分区包含所有相关的系统文件

  • :此分区包含所有用户文件

  • 交换:此分区扩展 RAM 内存

在此示例中,将只创建三个主分区,因为启动分区将位于 SD 卡上。根分区使用 6 GB,交换分区使用 512 MB。剩余空间用于 home 分区。

然而,最终由读者决定什么是对你有用的,因为这可能因人而异。使用 n 命令可以创建新分区。以下截图中,展示了之前解释过的三个分区的创建:

准备目标介质

当未输入最后一个扇区的值时,fdisk 会默认使用可用的最后一个扇区,从而使用剩余的介质空间。

分区不仅需要创建,还需要分类。默认情况下,fdisk 会将所有新创建的分区转化为常规的 Linux 文件系统分区,这对于除了交换分区之外的其他分区来说是没问题的。交换分区需要应用不同的类型。t 命令用于对分区进行分类,这需要知道要使用的具体类型。对于交换分区,其类型为 82。任何时候都可以使用 l 命令来查看可用的类型。以下截图展示了如何将分区 2 转换为交换分区:

准备目标介质

使用 w 命令保存并使用 q 命令退出,新创建的分区表会被写入磁盘,fdisk 随之退出,如下所示:

准备目标介质

格式化新创建的分区

在新创建的分区可用后,它们需要进行格式化。本书中将使用 ext4 作为文件系统。

提示

尽管本书中使用的 3.4.x 内核尚不支持,f2fs 是一个非常有趣的文件系统,因为它针对 SSD、USB 或 microSD 闪存的使用进行了优化。这在未来可能会很有意思。

格式化分区的命令是 mkfs.ext4,其中值得关注的参数是正在格式化的设备节点和可选的 -L,用于给分区命名。

格式化根分区的操作如下:

格式化新创建的分区

格式化交换分区可以通过以下截图中的命令来完成:

格式化新创建的分区

格式化剩余的空间用于用户文件,如下所示:

格式化新创建的分区

为了确保所有数据都写入到适当的位置,分区会按照现有文件系统进行挂载,如下所示:

[root@packt ~]# mount /dev/sda1 /mnt
[root@packt ~]# mkdir /mnt/home
[root@packt ~]# mount /dev/sda3 /mnt/home

创建 Debian 或 Ubuntu 的 rootfs

这里首先要提到的是,Ubuntu 是 Debian 的衍生版。简而言之,它基本上就是 Debian,因此安装时使用哪个发行版并没有太大区别,不论是 Debian 还是 Ubuntu。所以,谈论安装 Ubuntu 或 Debian,其实是在说同一件事。这里使用的安装工具是 debootstrap,它在许多发行版中都可以找到。

安装 debootstrap

Fedora 提供了 debootstrap,并可以通过 Yum 工具安装,如下所示:

安装 debootstrap

运行 debootstrap

安装了 debootstrap 后,差不多可以开始了。首先需要提及一些事情;debootstrap,即 Debian bootstrap,可以用于安装任何架构的 Debian 变种,至少支持 Debian 和 Ubuntu。它确实需要在其参数列表中提供一个镜像。Debian 的镜像列表可以通过 www.debian.org/mirror/list-full 获取,而 Ubuntu 则没有官方的镜像列表。然而,通过在 URL 中使用国家代码可以找到镜像,例如在荷兰,nl.ports.ubuntu.com 就是一个有效的镜像。使用镜像的明显优点是下载会更快。

由于 Allwinner SoC 基于 ARMv7 架构,因此该架构将使用 armhf

suite(套件)取决于需要的版本。对于 Debian,有稳定版、测试版和不稳定版,Wheezy 是稳定版的名称,Jessie 是测试版,而 sid 是不稳定版的名称。需要注意的是,未来 Wheezy 和 Jessie 会更改为新的套件名称,但 sid 永远是未稳定的开发版本。

最后,debootstrap 被加上 PATH 变量前缀,以确保 debootstrap 使用正确的路径。这是因为当前 debootstrap 与新发行版的组合中存在一个 bug。

提示

–foreign 参数可以用来引导任何架构,即使是在 x86 系统上,因为没有代码会被执行。引导过程还需要通过 –second-stage 参数进行一些额外的操作。读者可以在进行跨架构引导时深入了解这方面的内容。

以下命令将使用 ftp.nl.debian.org/debian/ 镜像,将 Debian Wheezy 安装到 /mnt 目录中,适用于 arm-hard-float 架构,如下所示:

运行 debootstrap

由于 debootstrap 是用 Perl 编写的,因此可能系统中尚未安装 Perl。安装 Perl 可能会导致需要下载和安装一长串包。

提示

同样,可以使用 debootstrap –foreign --arch=armhf trusty /mnt http://nl.ports.ubuntu.com 来安装 Ubuntu Trusty Tahr,但请注意,这将仅是基础系统。此外,debootstrap 可能不会带有所有预期的套件。只要 /usr/share/debootstrap/scripts 下存在,所有 Ubuntu 套件都是指向 gutsy 套件的符号链接,链接目标是 ports.ubuntu.com/dists/。例如,在脚本目录中使用 ln -s gutsy utopic 来将 utopic 添加为有效套件。

配置基础系统

Linux 中所谓的 fstab 文件负责将分区挂载到指定的位置。使用任何编辑器,以下更改需要添加到 fstab 文件中。虽然可以使用基于 UUID 的挂载点,但这里只使用标准条目。不过,你可以使用基于 UUID 的挂载点,并且我们鼓励你这么做。一个相对易用的常见编辑器是 nano。修改完文件后,按 Ctrl 键和 x 键退出 nano,并回答问题以通过 y 键保存修改过的缓冲区。文件名应保持不变,因此按 Enter 键确认。编辑器中的 fstab 文件如下所示:

配置基础系统

/boot 挂载为只读模式,可以确保不仅没有意外的写入发生,而且也没有故意的写入操作。此外,正如本章前面提到的,上一章创建的 microSD 卡的启动分区在这里被重复使用。

配置网络

Debian 和 Ubuntu 使用 /etc/network/interfaces 文件来配置网络。请注意,这是在不使用图形工具(如网络管理器)时所用的更持久的配置。如果该配置的最终目标是图形桌面,跳过配置 interfaces 文件可能是明智的选择。

提示

使用网络接口 eth0 作为 dhclient 的参数应能建立有效的网络连接,如以下命令所示。但请注意,这一配置在重启后会丢失。

dhclient eth0

使用 nano 打开 /mnt/etc/network/interfaces 文件,并在文件底部添加以下内容:

auto eth0
iface eth0 inet dhcp

通常,类似的部分也存在于回环设备中。

如果需要静态 IP 配置,可以参考以下示例(请用目标网络的所有数字替换相应的值)。

auto eth0
iface eth0 inet static
 address 192.168.0.10
 network 192.168.0.0
 netmask 255.255.255.0
 broadcast 192.168.0.255
 gateway 192.168.0.1

使用静态 IP 地址时,系统还需要告诉它如何解析内容;/etc/resolv.conf 中的 resolv.conf 文件负责此操作。请注意,如果网络通过 dhcp 或网络管理器进行配置,文件将被覆盖。以 nano 为例,打开 /mnt/etc/resolv.conf 文件,并在其中添加以下行:

search homedomain.local
nameserver 192.168.0.1

同样,在这里,我们需要根据所使用的网络正确地替换值。记得使用Ctrl + x保存文件。

如果本地网络上有多个名称服务器,则应为每个额外的名称服务器使用一行,以“nameserver”开头。

提示

如果本地网络上没有可用的名称服务器,可以使用 Google 或 OpenDNS 的名称服务器。对于 Google,它们是8.8.8.88.8.4.4,而对于 OpenDNS,它们是208.67.222.222208.67.220.220

最后,系统需要在网络上命名——即所谓的hostname。只需在/mnt/etc/hostname中的hostname文件里写下一个在网络上唯一的名称,如下所示:

[root@packt ~]# echo "PacktPublishing" > /mnt/etc/hostname

另一个需要设置的文件是所谓的 hosts 文件。它是查找主机名的最基本方式,例如,当没有 DNS 服务器可用时。主机名需要出现在这里,此外还需要列出任何其他必须能够从网络中访问的主机名;例如,网络中有一个时间服务器,所有计算机从中获取当前时间。每个系统通过time.example.com查询此服务器。即使没有互联网连接和没有 DNS 服务,为了确保时间服务器始终能够被查找,可以在 hosts 文件中添加一个条目。假设192.168.0.15是本地时间服务器,可以使用以下命令作为主机名的示例,并作为添加其他主机的指南。请注意,通常情况下,很少需要添加其他主机,因为 DNS 几乎总是用于此目的。记得使用Ctrl + x保存文件。

[root@packt ~]# nano /mnt/etc/hosts
127.0.0.1       localhost
127.0.0.1       PacktPublishing
192.168.0.15    time.example.com
::1             localhost ip6-localhost ip6-loopback
fe00::0         ip6-localnet
ff00::0         ip6-mcastprefix
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters

使目标介质可引导

不幸的是,正如之前提到的,SoC 无法从 SATA 驱动器或 USB 闪存驱动器引导,它需要一个辅助组件。在本书中,使用了一张小的 microSD 卡来实现这个目的。因此,它将容纳引导加载程序、内核和一些配置,将所有内容粘合在一起。在上一章中,用于 Fedora 安装的安装脚本是自动完成的。将安装到 microSD 卡上的内核默认情况下将继续从 microSD 卡加载 rootfs。显然,需要调整它,以便 microSD 卡能引导新创建的介质。为此,需要首先挂载引导分区,如下所示的命令所示:

[root@packt ~]# mount /dev/mmcblk0p1 /mnt/boot

使用 nano 编辑uEnv.txt文件,修改以 root /dev/sda1开头的行,如下所示的屏幕截图所示。记得使用Ctrl + x保存文件。

使目标介质可引导

当 microSD 卡设置为从新创建的介质引导时,可以安全地使用以下命令再次卸载它:

[root@packt ~]# umount /mnt/foo

如果出现问题并且 Cubieboard 无法启动,可以将 microSD 卡插入 microSD 转 USB 适配器,并使用本地安装的文本编辑器打开 uEnv.txt 文件。然而,用于进行此修改的操作系统需要能够读取和写入 ext4 或至少 ext2 文件系统。

root 用户

尽管任何默认的 Debian 或 Ubuntu 安装都会存在 root 用户,但问题是如何作为 root 用户登录。以下是两种选择:

  • 预先创建一个具有管理权限的常规用户,通过 sudo 使用,并且不允许 root 用户登录

  • 或者使用更简单的方法,为 root 用户设置一个 root 密码并使用它

从安全角度看,第一个选项更安全。这里将简要介绍这两种方法。选择哪种方式更适合以及安全性的重要性由读者自行决定。本书并不是关于如何正确地保护系统的内容。这部分留给读者作为练习,远超出本书的范围。

准备 chroot 命令

要设置 root 密码,需要执行一些步骤,因为这必须在系统内部完成。chroot 命令使得能够像系统已启动一样进入该系统。但这有一个前提条件,那就是必须填充某些动态目录,即 /dev/proc,如下所示:

[root@packt ~]# mount --rbind /dev /mnt/dev
[root@packt ~]# mount none -t proc /mnt/proc

在这里,现有的 /dev 挂载被重用,而 proc 文件系统则正常挂载。现在,可以像这样使用 chroot 进入文件系统:

[root@packt ~]# PATH=/bin:/sbin:/usr/bin:/usr/sbin chroot /mnt /bin/bash
root@packt:/#

更改 root 密码

passwd 命令将用于启动 root 用户的密码更改,在此过程中需要输入新密码两次。系统不会将任何信息回显给用户,如下所示:

root@packt:/# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
root@packt:/#

创建一个新的超级用户

要创建一个新用户,可以使用 useradd 命令。该命令有许多选项,读者可以熟悉它们。然而,本例中使用的选项是最常见的。除了新用户外,还将自动创建一个与用户用户名匹配的新组;-U 标志用于此功能。此外,-s 标志用于提供替代的登录 shell。这是完全可选的,但推荐使用,因为 Debian 默认使用的是默认的 sh shell,功能相对有限。-m 标志用于为用户创建目录并复制一些基本文件。在下面的示例中,使用的用户名将是 packt

root@packt:/# useradd -m -G sudo -s /bin/bash -U packt
root@packt:/#

为了赋予新用户管理员权限,需要为其提供 sudo 命令的使用权。用户已通过 -G 参数成为 sudo 用户组的一部分。但该命令需要实际上可用才能使用。虽然本章后面会讨论如何使用 apt,可以使用以下命令来安装 sudo

root@packt:/# apt-get install sudo

最后,用户还需要一个密码才能实际登录。可以使用以下 passwd 命令来设置密码:

root@packt:/# passwd packt
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
root@packt:/#

退出 chroot

现在可以使用exit命令退出chroot环境,如下所示:

root@packt:/# exit
exit
[root@packt ~]#

添加串行控制台

如果此时系统重启,登录控制台将显示在tty0上,这是当连接显示器和键盘时的正常控制台。然而,可能会出现某些情况下,连接的显示器不立即兼容,或者由于某种原因,USB 键盘或显示器无法使用。直到现在,串行控制台对我们非常有用,因此,强烈建议在此情况下启用串行控制台,并推荐使用 Debian 或 Ubuntu 安装。在这里,Debian 和 Ubuntu 之间的第一个区别变得明显。Debian 仍然使用较旧的sysvinit,而 Ubuntu 仍然使用upstart,虽然两者都在逐步迁移到systemd,但此时这一点不适用。具有讽刺意味的是,在使用systemd时,或者至少在安装并当前运行的systemd版本下,Fedora 镜像默认设置了串行控制台。

将串行控制台添加到 Debian

负责生成各种init服务的文件是位于/etc/inittabinittab,可以使用 nano 进行编辑以添加串行控制台。找到以下部分,取消注释以#T0开头的行,并删除井号。还需要注意的是,默认的波特率为9600,而我们的整个设置假定波特率为115200,因此请确保已进行此更改,如以下示例所示。记得使用Ctrl + x保存文件。

[root@packt ~]# nano /mnt/etc/inittab
# Example how to put a getty on a serial line (for a terminal)
#
T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100

将串行控制台添加到 Ubuntu

对于upstart,情况完全不同。/etc/init/目录中的文件由upstart解析。首先,将文件tty1.conf复制到ttyS0.conf,这样可以更方便地进行编辑;毕竟文件相似,如下所示:

[root@packt ~]# cd /mnt/etc/init/
[root@packt init]# cp tty1.conf ttyS0.conf

但是,需要对这个文件进行一些更改。首先,将所有出现的tty1替换为ttyS0。接着,除了2345外,还要在运行级别中添加1。此外,删除and (…)部分。最后,getty行需要调整为监听串行端口,波特率为115200 bps。以下命令展示了文件最终应有的样子。或者,可以创建一个新的文件,内容如下。记得使用Ctrl + x保存文件。

# ttyS0 - getty
#
# This service maintains a getty on ttyS0 from the point the system 
# is started until it is shut down again.

start on stopped rc RUNLEVEL=[12345]
stop on runlevel [!12345]

respawn
exec /sbin/getty -L 115200 ttyS0 vt102

重启新操作系统

在所有必要的更改完成后,应该是时候重启进入新操作系统了。首先,卸载所有已挂载的分区。确保没有挂载的目录正在使用中。可以使用umount -l命令,其中-l参数表示懒惰卸载,这意味着umount会首先尝试卸载所有子目录,最后卸载请求的目录。如果遇到错误,可能需要手动卸载。然后,使用reboot命令重新启动系统,如下所示:

[root@packt etc]# cd
[root@packt ~]# umount -l /mnt
[root@packt ~]# reboot

重启后,你将看到一个登录提示,如下图所示。显然,这在 Debian 和 Ubuntu 之间有所不同。使用创建的用户或 root 登录后,本章的安装部分完成,恭喜你!

重启新操作系统

通过命令行操作新操作系统

如果你是 GNU/Linux 新手,使用附录 B 中展示的备忘单,基本 Linux 命令备忘单,将会很有帮助,因为可以探索一些常见的 Linux 命令,并且它可以作为 GNU/Linux 新手的指南。本节将更多地关注一些常见任务,比如保持 Debian 或 Ubuntu 最新以及安装新软件。

介绍 apt

Debian 和 Ubuntu 都在软件需求方面严重依赖 apt。Apt 是一组命令,用于安装新的软件包或保持现有软件包的最新。Apt 与 dpkg 紧密配合,尽管普通用户可能永远不会直接调用 dpkg。Apt 负责下载所请求的软件,检查其依赖关系,并告诉 dpkg 安装它们。它是 Debian 和 Ubuntu 下的瑞士军刀,是在 AppStore 存在之前的命令行应用商店。

配置 apt

Apt 并不需要很多配置。apt 需要的是一个可以检查和下载软件的地方列表。Debian 和 Ubuntu 的默认设置可能无法提供所有感兴趣的内容。负责 apt 配置的文件是 /etc/apt/sources.list 中的 sources.list,如果你以普通用户身份登录,则需要 sudo 提供额外权限来编辑该文件。在下面的示例中,将非自由组件和安全库添加到主组件中。请注意,sources.list 文件中的各种源会因不同的套件或衍生版(如 Ubuntu)而有所不同。

packt@PacktPublishing:/etc/apt$ sudo nano sources.list
[sudo] password for packt:
deb http://ftp.nl.debian.org/debian wheezy main non-free

deb http://security.debian.org/ wheezy/updates main non-free
deb-src http://security.debian.org/ wheezy/updates main non-free

完成这些更改后,apt 需要更新,但这将在下一小节中处理。

Debian 提供了一个很好的教程,供深入阅读,网址是 wiki.debian.org/SourcesList,附加的组件和库可以在 wiki.debian.org/UnofficialRepositories 上找到。对于 Ubuntu,可以在 help.ubuntu.com/community/SourcesList 查找源列表,附加的库则在 help.ubuntu.com/community/Repositories/Ubuntu 上列出。除了本小节所列的配置外,其他配置留给读者自己完成。请注意,虽然理论上 Ubuntu 和 Debian 的仓库可以混用,但不推荐这样做,这可能会导致问题。

保持操作系统最新

定期检查和安装更新对于安全性至关重要。 此外,通过这种方式还可以获得现有软件包的新版本,这可能带来新功能或修复错误。 对于 Ubuntu 和 Debian,步骤是相同的。

要使用新的软件列表下载并更新 apt,首先引入了第一个 apt 命令apt-get。 然而,没有参数的apt-get命令将不会做更多事情,只会打印一个帮助屏幕。 由于预期的操作是更新应用程序列表,所以将传递update参数。 再次强调,如果以普通用户身份运行,则应以sudo为前缀。 此外,如果尚未配置网络并且打算让图形用户界面配置网络,则请记住运行dhclient eth0以获取临时网络配置。 屏幕截图中的以下命令运行了 apt 的更新:

保持操作系统更新

如果在前一小节中未添加部分和组件,则列表显然会更短。 此时,apt 已经有了可用软件的最新列表。 要升级所有已安装的软件包,尤其是因安全更新而需执行apt-getupgrade参数,如下面的屏幕截图所示:

保持操作系统更新

在前面的示例中,只有一个可用的更新,即对libgnutls的更新。 这个列表可能会因更新数量的不同而有所变化。

提示

位于/etc/cron.daily/aptapt文件负责每天更新 apt 并安装安全关键软件包,因此不总是需要运行apt-get update。

安装额外的软件

任何操作系统最令人兴奋的可能是软件。 然而,默认创建的 Debian 或 Ubuntu 安装缺乏大多数软件。 毕竟,这只是最基本的。

查找软件包

在安装软件包时,当名称粗略记住但不完全记得时可能会出现问题。 在这种情况下,有一个名为apt-cache的合适工具。 使用search参数,可以搜索内部缓存的 apt 数据库以查找可用的软件包。 特别是与grep命令结合使用时,这两个命令可以帮助找到所需的内容,如下面的屏幕截图所示。 grep –命令在《附录 B》Basic Linux Commands Cheatsheet中有解释。

查找软件包

此外,您可能还想搜索应用程序的文件名。 也有一个适用的 apt 工具。 使用search参数的apt-file工具将允许您在软件包内搜索文件。 不幸的是,在撰写本书时,apt-file工具尚未包含在当前稳定版本的 Debian 或 Ubuntu 中,但希望很快会添加。

使用 apt-get 安装软件包

安装软件包的最基本方法也是通过 apt-get,参数当然是 install。Nano 经常被用作示例编辑器。这是因为它非常易于使用,并且通常预安装,因为它体积很小。Vi 是另一个小型编辑器,几乎总是预安装,但使用起来远不如 Nano 简单。Vi 有一个更强大的版本,叫做 Vi 改进版(vim)。让我们通过 apt-get 安装 vim,如下所示:

使用 apt-get 安装软件包

下载并安装了一些软件包后,vim 现在已安装。

使用 tasksel 安装软件包

更常见的是,需要一组软件包才能使系统执行某些功能。tasksel 命令可以用来安装一组执行特定任务的软件包。以提升权限运行 tasksel 将显示菜单,如下图所示。Ubuntu 没有预安装 tasksel,需要通过 apt-get 安装,就像前面安装 vim 的例子一样。

使用 tasksel 安装软件包

安装 Debian 桌面环境任务将安装基于GNOME的图形桌面环境以及一些由 Debian 标记为标准的附加包,如 LibreOffice。

下载和安装过程可能需要一些时间,这取决于目标媒介和网络连接速度。在配备高速互联网连接的 SSD 上安装大约需要三十分钟。

在 Ubuntu 下,tasksel 会略有不同,但这里也有一个 Ubuntu 桌面选项,如下图所示。这将大约需要相同的时间,三十分钟或更长。

使用 tasksel 安装软件包

通过元包安装软件包

通过 tasksel 可用的任务似乎相当有限。相反,使用元包可能更为简便。元包实际上与任务没有太大区别;事实上,它们可能在后台是一样的。元包并不是一个真正安装任何东西的包,而是一个软件包列表或一组通过它安装的软件包。例如,xfce4 是 Debian 的一个元包,它将安装所有 xfce4 桌面环境所需的软件包,并且还会安装包维护者认为对完整桌面环境有用的软件,如文件管理器。

注意

对于 Ubuntu,这个元包被称为 xfce,不过 xubuntu-desktop 元包在这里更为有趣。

另一个与 xfce4 元包相匹配的有趣元包是 xfce4-goodies。实际上,以下命令将展示如何一次安装多个软件包。运行该命令会产生一个庞大的待安装软件包列表,但最终会得到一个可用的 xfce4 桌面,就像从 CD 安装的一样。例如,有人甚至可以争辩说,安装 CD 恰恰能做到这一点,如下所示:

packt@PacktPublishing:~$ sudo apt-get install xfce4 xfce4-goodies

等待大约 30 分钟,xfce4 桌面安装完成后,可以使用 startx 命令启动 xfce4。然而,这时必须使用显示器和键盘。Xfce4 不能通过串口控制台启动或使用。这时的桌面环境几乎可以使用。“几乎”意味着某些权限设置缺失。例如,默认情况下用户无法关闭机器。

有几种方法可以让这些功能正常工作,其中之一是使用登录管理器;然而,xfce4 并没有自带登录管理器,但这没关系。市面上有很多可以选择的登录管理器。GNOME 自带 gdm,但考虑到 Xfce4 是一个轻量级的桌面管理器,选择一个轻量级的登录管理器,比如 LightDM,应该是一个不错的选择。安装 lightdm 包不需要额外的指令。现在重启 Cubieboard 后,您会看到一个活动的登录窗口,登录后,便完成了本章内容。

概述

完成了这一章,虽然这算是一个大章节,但技术上,结果应该和前一章相同;无论是基于 Debian 还是 Ubuntu 的工作桌面环境。通过命令行安装额外的软件现在已经变得非常简单,而且系统的更新也不成问题。

下一章将以此安装为基础,将其转变为一个用于各种任务的服务器,您可以选择保留桌面功能。

第五章:设置家庭服务器

既然你现在已经熟悉了从头创建完整的根文件系统,是时候创建一些稍微复杂一点的东西了。尽管桌面操作系统本身非常有用,但这些 ARM 开发板上的桌面操作系统往往可能有点过慢。然而,这些设备在低功耗家庭服务器中非常有用。

这里使用“家庭服务器”这一术语,因为大多数服务对家庭用户很有用,但例如将 Cubieboard 放在托管中心,作为 Web 服务器和邮件服务器使用,同样也能很好地工作。然而,在这种情况下,安全性是必须考虑的问题。本章并未强烈涉及安全性,因为这是一个需要大量关注和强大安全知识的主题,而这些内容超出了本书的范围。必须指出,这些说明完全不是针对 Cubieboard 的,显然还有许多其他服务可以考虑。

本章将涵盖以下主题:

  • 远程访问 Cubieboard

  • 学习如何启动、停止和重启服务

  • 添加和移除开机启动的服务

  • 在预定时间自动运行任务

  • 设置各种服务(Squid、Apache、Samba、transmission 和 ownCloud)

家庭服务器板的先决条件

本章将在之前的 Debian 或 Ubuntu 安装基础上安装多个软件包。如果此安装因实验而受损,建议重新查看第四章,手动安装替代操作系统

明智的做法是跳过最后一部分,安装图形桌面环境,因为它在本章中没有任何用途。SD 卡上的初始 Fedora 安装也可以重复使用,但你需要自己识别这些发行版之间的差异。

远程访问服务器

大多数时候,如果不是每次,Cubieboard 都是通过串行控制台访问的,或者在连接到显示器时直接通过键盘和鼠标进行操作。这种方式很好,但在完成设置和调试后,可能会希望将其放在另一个房间中,让它独立执行任务。甚至可以想象多个板子一起运行在数据服务器中,例如,在这种情况下,远程访问可能变得至关重要。因此,拥有远程访问功能是非常有用的。

连接到 Debian 或 Ubuntu 机器的最常见和最成熟的方式是通过 ssh 服务器。安装 ssh 服务器很简单,只需使用以下命令:

packt@PacktPublishing:~$ sudo apt-get install openssh-server

就像 UART 访问一样,PuTTY 也可以用于ssh访问。然而,关键在于将连接类型设置为ssh。端口应默认设置为22,并且需要使用正确的 IP 或主机名。请参考以下截图查看示例:

远程访问服务器

如果你正在使用现有的 Linux 命令行,ssh可以很容易地调用,示例如下所示:

远程访问服务器

第一次连接主机时,会显示ssh指纹,然后询问是否确定要连接。在这种情况下,可以安全地接受继续连接的提议。

提示

当通过互联网连接时,建议始终验证密钥。如果有人篡改了服务器或试图进行中间人攻击,密钥将不再匹配,你就会知道出现了问题。

输入密码后,会出现熟悉的packt@PacktPublishing:~$命令提示符。

与服务交互

在服务器上,启动、停止或重启服务是很常见的。这不仅仅是在尝试解决问题时,也有时是为了重新加载配置。例如,某个服务可能只偶尔使用,而不是每次启动时都需要。因此,所谓的启动脚本可供使用。当服务被安装时,通常会在/etc/init.d中放置一个控制其行为的脚本。

提示

对于服务器来说,通常建议通过interfaces文件以静态方式或通过 DHCP 服务器配置网络。这是为了确保网络始终可用,因为图形桌面通常并未安装。

以网络脚本为例,它负责启动网络设备,但仅限于在/etc/networking/interfaces中配置的设备。有关如何正确设置网络配置,请参阅第四章,手动安装替代操作系统;假设eth0已按此方式配置。

注意

停止网络服务将会停用所有网络接口!虽然这不一定是问题,但如果你是远程使用此命令时,请小心。

启动、停止、重启或重新加载服务

要停止网络接口,输入以下命令。如果以 root 身份登录(不推荐这样做),可以省略sudo命令。

packt@PacktPublishing:~$ sudo /etc/init.d/networking stop
Deconfiguring network interfaces...done.

同样,网络接口可以使用start参数重新启动,如下所示:

packt@PacktPublishing:~$ sudo /etc/init.d/networking start
Configuring network interfaces...

使用restartreload参数也可以做到这一点,其中reload会强制服务重新加载其配置。

提示

一些发行版,例如 Ubuntu,可能会使用 upstart 或甚至 SystemD。有时,某些脚本会留在 /etc/init.d 目录中,可以按照前述方式使用,但并非总是如此,因此你可能需要熟悉 SystemD 或 upstart。

添加或移除开机启动的服务

有时,需要始终在启动时启动某个服务。例如,在前一章中,安装了 lightdm 来提供图形登录服务。此服务会自动添加到启动时启动的服务中。若要阻止 lightdm 在启动时再启动,可以使用 update-rc.d 命令。传递可选的 -f 参数强制移除,如下所示:

packt@PacktPublishing:~$ sudo update-rc.d -f lightdm remove
update-rc.d: using dependency based boot sequencing

使用前面的章节停止 lightdm 后,图形登录管理器将不再在重启后启动;此时甚至无需重启。

添加服务的过程非常类似;与要求从启动服务中移除它不同,默认关键字要求在启动时启动该服务,如下所示:

packt@PacktPublishing:~$ sudo update-rc.d lightdm defaults
update-rc.d: using dependency based boot sequencing

默认设置指示所有默认运行级别的服务应启动或停止。Linux 系统有多个运行级别,你可以进一步了解它们。

每次重启后,lightdm 都会启动。前面所述的内容仅适用于 Debian。不过,Ubuntu 也为大多数服务提供了向后兼容的脚本,这些脚本位于 /etc/init.d 目录下,可以按前述方式使用。

注意

正如前一章所提到的,Debian 的 SystemV 和 Ubuntu 的 upstart 最终将被 SystemD 或两者取代。届时,你需要自己了解更多关于 SystemD 的内容。

自动运行计划任务

通常,需要在预定的时间间隔内执行某些任务。比如下载并更新病毒数据库。为此,Linux 系统配备了一个名为 Cron 的程序。Cron 通常在后台运行,检查是否有任务需要在某个时间执行。虽然你应该深入了解 Cron,但在 Debian 上,Cron 默认通过在 /etc 下提供四个目录,cron.hourlycron.dailycron.weeklycron.monthly,使得执行 Cron 作业变得非常简单。从这些目录的名称可以明显看出它们的用途。在这些目录中放置一个可执行文件,使得 Cron 每小时、每天、每周或每月运行该命令。

一个简单的例子是要求 apt-get 每天更新其本地数据库;可以为此目的创建一个简单的脚本。以 root 用户身份使用编辑器,在 /etc/cron.daily/ 目录中创建一个名为 apt-update 的新文件,如下所示:

packt@PacktPublishing:~$ sudo nano /etc/cron.daily/apt-get
#!/bin/sh
apt-get update

第一行很重要,它告诉系统这是一个 shell 脚本,或者更确切地说,需要使用 /bin/sh 来执行文件中的其余命令。Cron 默认以 root 用户身份在 /etc/cron.* 目录下运行所有作业,因此无需在前面加上 sudo

保存文件后,重要的是要赋予它执行权限。默认情况下,它只是一个文本文件。Cron 只会执行具有适当权限的文件。可以通过使用 chmod 命令将这个新创建的脚本标记为可执行文件,下面的命令展示了这一点:

packt@PacktPublishing:~$ sudo chmod u+x /etc/cron.daily/apt-update

需要说明的是,尽管这是一个非常有用的示例,但 Debian 和 Ubuntu 默认每天会更新 apt 仓库。因此,虽然这个示例很好,但建议你在之后清理它,示例如下所示的命令:

packt@PacktPublishing:~$ sudo rm /etc/cron.daily/apt-update

设置代理服务器

当带宽紧张并且需要与家庭成员共享时,若还希望减少广告,可以使用代理服务器来提供解决方案。此外,它允许在不需要复杂防火墙规则的情况下访问互联网;只需要配置浏览器使用代理。接下来的子章节中将解释设置代理服务器的步骤。

安装 Squid

本书使用的代理服务器叫做 Squid,正如你在上一章中了解到的,它可以通过以下命令轻松安装:

packt@PacktPublishing:~$ sudo apt-get install squid

Debian 中的 Squid 配有合理的默认配置文件,位于 /etc/squid/squid.conf。你可以使用 nano 或其他编辑器打开并查看该文件。Squid 配置文件中有大量的注释,它们作为指南或手册使用。

默认情况下,Squid 只会监听它认为来自内部网络的连接流量。以 acl localnet 开头的行后跟内部网络的 IP 范围表示这一点。需要注意的是,您可以添加额外的 localnet 行,但要小心——如果添加了一个非本地的 IP 范围作为内部网络,可能会导致代理服务器被全球访问,因此在进行实验时要小心。不过,这只定义了 localnet,尚未授予访问权限。通过搜索 squid.conf,可以找到一个注释部分,内容如下命令:

#http_access allow localnet

这行配置允许 HTTP 访问,源地址来自 localnet,我们刚刚了解过,它定义为内部网络范围。你可以通过去掉注释符号(#)来取消注释,或者去掉数字符号;这会授予对所谓的 localnet 行的访问权限,重新启动 Squid 后,代理应该允许来自内部网络的使用。

设置缓存代理

代理服务器可以临时存储经常访问的数据,这样它只需要通过互联网连接下载一次。在某些情况下,这可以大大减少带宽使用;例如,假设一个五台计算机的家庭,所有计算机都需要下载某个更新文件。如果五台计算机都通过代理下载此更新文件,代理只在首次请求文件时下载它。当第二台计算机请求同一个文件时,代理会提供其内部存储的文件,从而使下载更快,不会增加互联网连接的负担。

注意

默认情况下,Squid 仅使用 100 MB 的缓存。可以查看cache_dir参数了解更多信息。

Squid 不需要额外配置即可作为缓存代理工作。安装后,它会自动启动并配置为在重启时启动。要更改这些行为,请参考前面两个小节。

配置浏览器使用代理

这里不会覆盖所有浏览器或操作系统,至少会展示一个示例。在此,我们选择 Mozilla Firefox。要配置浏览器使用代理,请按照以下步骤操作:

  1. 首先,打开首选项选项,具体位置取决于使用的操作系统,可能在编辑下或工具下。

  2. 在首选项界面中,进入高级选项卡,然后再进入网络选项卡。右侧第一个按钮为设置,它包含网络配置,如下图所示:配置浏览器使用代理

  3. 设置对话框中,选择手动代理配置,这将启用编辑框。

  4. 对于HTTP 代理,需要输入主机名或 IP 地址。Squid 的默认端口是3128

  5. 最后,可以安全地启用为所有协议使用此代理服务器选项,因为 Squid 覆盖了所有协议,如下图所示:配置浏览器使用代理

  6. 如果 IP 地址未知,可以使用ifconfig命令在运行 Squid 的 Cubieboard 上获取。在此例中,IP 地址为192.168.0.10,如下图所示:配置浏览器使用代理

并不严格要求使用sudo访问ifconfig信息。大多数情况下,可以通过其完整路径(在此为/sbin/ifconfig)访问,而无需提升权限。此外,ifconfig可能在某些发行版中被ip addr命令替代。

启动网页浏览会通过代理进行。手动配置代理并非严格要求。如这里所示,有使用系统代理设置自动检测此网络的代理设置选项。使用第一个选项时,浏览器将使用操作系统配置的代理作为默认代理。后一个选项用于通过所谓的 WPAD 检测代理设置,关于 WPAD 的更多信息可以参见en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol。然而,这两种选项不在这里详细说明。

设置阻止代理

使用代理的一个优点是某些网站可以很容易地被阻止。假设hotmail.comebay.comlive.com需要被阻止。这些域名列表必须存储在某个地方,例如在/etc/squid目录中的blocked.domains.acl文件中。为了实现这一点,按照以下步骤操作:

  1. 开始编辑文件,并按照如下方式添加这些名称:

    packt@PacktPublishing:~$ sudo nano /etc/squid/blocked.domains.acl
    hotmail.com
    ebay.com
    live.com
    
    
  2. 接下来,进入配置文件中的一个非常具体的部分,因为顺序很重要。找到名为# TAG: acl的部分,并向下滚动,穿过包含acl标签的注释部分。acl localnet定义将会显示,正如之前的安装 Squid部分所示。在下一个部分开始之前,找到# TAG: http_access,并添加以下内容:

    acl blockeddomain dstdomain "/etc/squid/blocked.domains.acl"
    
    

    简而言之,在名为acl的部分下,将会添加一个新项,紧接在http_access部分之前。在这里,Squid 被指示创建一个名为blocked domainacl,并将文件中创建的目标域名标记为阻止的域名。所以现在应该有一个acl列表,其中被阻止的域名项排在最后。

  3. 紧接着acl部分,http_access部分开始。在这里,顺序非常关键。在允许本地主机和localnet的部分上方,需要添加以下命令:

    http_access deny blockeddomain
    
    

    原因是,首先被拒绝的内容(如被阻止的域名),然后本地主机和localnet被允许访问其余内容。最后,其他一切内容都被阻止给那些没有被允许任何访问权限的用户。

  4. 使用本章之前学到的restart命令,Squid 可以重新启动,并且现在将拒绝加载来自提到的这些网站的所有内容。

进一步举这个例子,阻止所有仅提供广告的域名会是一个不错的选择。虽然创建一个文件列出所有这些域名当然是一个有效的解决方案,但列出所有的域名及其变体会非常繁琐。Squid 可以使用正则表达式处理一个列表,这样就变得更简单了。为了做到这一点,请按照以下步骤操作:

  1. 如前所述,创建一个名为squid.adservers的文件,并输入以下正则表达式。如果你不理解其中的含义也没关系;这只是一个示例。

    (^|\.)wikia-ads\.wikia\.com$
    
    
  2. 保存文件后,打开squid.conf,并像之前一样,将以下行添加到适当的部分:

    acl ads dstdom_regex -i "/etc/squid/squid.adservers"
    http_access deny ads
    
    
  3. Squid 被指示创建一个遵循文件的列表,但这次使用正则表达式来表示目标域名列表。Squid 将拒绝对列表中的域名(在本例中是wikia-ads.wikia.com)的所有 HTTP 访问。

手动为每个广告网络添加正则表达式可能会很麻烦,尤其是在尝试维护它们时。幸运的是,一些人维护了一个已知广告服务器的列表,可以无过多工作地使用;该列表可以在 pgl.yoyo.org/adservers/ 找到。有人甚至很贴心地提供了一个脚本,可以用来下载该列表并准备好与 Squid 一起使用。使用 wget 下载以下文件,如下所示:

packt@PacktPublishing:~$ wget http://pgl.yoyo.org/adservers/scripts/squid/update-squid-adservers.txt

在能够使用此脚本之前,需要进行一些小的修改。为此,请按照以下步骤操作:

  1. 打开文件,找到 listurl,并按如下所示替换:

    listurl='http://pgl.yoyo.org/adservers/serverlist.php?hostformat=squid-dstdom-regex&mimetype=plaintext'
    
    
  2. 此外,请再次检查目标文件参数,因为它必须与广告的 acl 规则中定义的内容相匹配,如此处所示:

    targetfile='/etc/squid/squid.adservers'
    
    
  3. 保存文件后,可以以 root 用户身份运行它,它将下载一个最新的广告服务器列表并将其重新加载到 Squid 中。在这里使用 sh,因为 sh 以 root 用户身份运行,并且被告知像运行 Shell 脚本一样执行该脚本:

    packt@PacktPublishing:~$ sudo sh update-squid-adservers.txt
    Reloading Squid configuration files.
    done.
    packt@PacktPublishing:~$
    
    
  4. 为了再次确认一切是否正常工作,可以打开目标文件,通常是默认的 /etc/squid.adservers,除非之前已按建议进行调整。

  5. 最后一步是让此脚本每月更新一次。参考前面关于如何设置 Cron 作业的部分,应该能轻松完成此任务。

    提示

    使用 cp 命令,可以将文件复制到适当的目录。复制时,最好去掉 .txt 扩展名。

设置 Web 服务器

许多参与 Linux 的人都有自己的个人 Web 服务器。然而,正确设置一个 Web 服务器是一个足以写一本书的话题。在本节中,将仅介绍最基本的步骤,以帮助你开始使用。绝不是完整的或安全的设置,因为我们将依赖 Debian 或 Ubuntu 包中自带的默认设置。

有几个知名的 Web 服务器,但无疑,最著名的是以下 Apache Web 服务器:

packt@PacktPublishing:~$ sudo apt-get install apache2

如前所述,Debian 将自动启动 Apache,并且可以立即使用。使用网页浏览器输入 IP 或主机名,例如之前使用的 http://192.168.0.10,在 URL 栏中打开以下窗口:

设置 Web 服务器

正在提供的文件来自 /var/www/index.html。可以随意编辑此文档,甚至完全替换它。

提示

为 Web 开发人员提供对该目录及其文件的访问权限可能会很有用。通常,webroot 目录会与某个组相关联。管理员通常还会为他们可能拥有的多个 Web 根目录创建几个组。为了简单起见,用户和组设置为我们示例中的用户,如下所示:

sudo chown -R packt:packt /var/www

设置文件服务器

在 Cubieboard 上直接编辑文件确实会让人感到有些疲惫。即使使用之前安装的 Xfce 桌面环境,一旦将其放置在远程位置,远程访问文件会变得相当有用。也可能是因为需要将媒体文件共享到整个家庭网络中。

针对这种情况,有两种方法。通过本章之前安装的ssh服务器,任何现代 Linux 桌面环境都可以通过ssh访问文件。虽然这种方法有效,但作为练习,留给读者自行探索。本节将重点介绍如何安装和设置 Samba 作为文件服务器。为此,请按照以下步骤操作:

  1. 通过 Samba 共享的文件可以通过多种操作系统访问,并且可以轻松安装在多种设备上,如下所示:

    packt@PacktPublishing:~$ sudo apt-get install samba
    
    
  2. 安装 Samba 后,创建一个将要共享的目录,使用mkdir命令。它可以命名为mediafiles,并存放在文件系统的根目录中,如下所示:

    packt@PacktPublishing:~$ mkdir /mediafiles
    
    
  3. 使用编辑器打开 Samba 配置文件/etc/samba/smb.conf,如以下命令所示:

    packt@PacktPublishing:~$ sudo nano /etc/samba/smb.conf
    
    
  4. 可能需要更改的一个变量是所谓的工作组,这是 Samba 尝试加入的网络名称:

    # Change this to the workgroup/NT-domain name your Samba server 
    # will part of
     workgroup = PacktNet
    
    
  5. 文件底部还需要添加的另一项内容是共享之前创建的目录,如下所示:

    [mediafiles]
     comment = Shared media files
     read only = no
     path = /mediafiles
     guest ok = yes
    
    

从安全性角度看,这并不是最好的保护措施,因为每个人都可以读取和写入媒体文件,并且无需有效账户就能访问这些文件。然而,仍然有最后一道防线,那就是目录上设置的权限。当用户尝试访问该目录时,Samba 会根据权限进行操作。

由于这个共享是作为访客用户或无用户身份使用的,因此权限会在读取目录中的媒体文件时应用。

  1. 使用chmod命令更改权限,允许每个人读取和写入,这使得所有人都能使用此共享,如以下命令所示:

    packt@PacktPublishing:~$ sudo chmod o+rw /mediafiles/
    
    

    在家庭网络中,这不是一个问题。然而,如何更好地保护设备,是留给读者的一项不错的练习。Samba 是一个功能强大的套件,提供的不仅仅是文件共享。了解更多信息,请访问www.samba.org/

  2. 保存这些更改后,需要重启 Samba 服务。

  3. 在桌面上使用文件浏览器时,应该能看到一个名为 PacktNet 的网络工作组,这就是为工作组定义的名称。在该网络中,除了其他可能的主机外,还应能看到PacktPublishing,这是主机的名称,如下图所示:设置文件服务器

  4. 最后,在PacktPublishing中,刚刚共享的目录mediafiles将变得可见。设置文件服务器

设置种子服务器

种子(Torrents)是一种常见的数据共享方式。许多 Linux 发行版的 ISO 文件通过种子进行共享。拥有一个专用的服务器来处理种子,而不需要开启主 PC,也是非常有用的。不过需要注意的是,这样做需要一定的存储空间来存储种子数据。将所有数据存储在 SD 卡上可能不是明智的选择。请查看以下命令来安装 Transmission 种子服务器:

packt@PacktPublishing:~$ sudo apt-get install transmission-daemon

安装传输后,如果需要远程管理,必须进行配置。默认情况下,远程管理功能只会监听本地主机。使用sudo,应打开配置文件,并需要更改两个项目,rpc-passwordrpc-whitelistrpc-whitelist项目决定哪些主机可以访问服务器,而rpc-password项目决定哪些密码被客户端用于连接服务器,如下所示:

packt@PacktPublishing:~$ sudo nano /var/lib/transmission-daemon/info/settings.json
 "rpc-password": "mysecretpassword",
 "rpc-whitelist": "127.0.0.1,192.168.*.*",

默认设置的密码是加密的哈希值,但在修改时,可以使用常规的明文密码。这看起来像是一个安全问题,确实是,但仅仅是短暂的。传输被告知重新加载其配置文件后,它会读取密码、加密密码并重写配置文件。

需要重新加载传输(Transmission),因为如果重新启动传输,它不会重新读取配置文件,而是在退出时重写配置文件。其余的默认设置应该是满意的,不过明智之举是再次确认rpc-authentication-required已设置为true,并且rpc-enabled也已设置为true。此外,rpc-username变量可以更改为便于记忆的用户名,但请记住在本章其余部分中使用新用户名,如下所示:

packt@PacktPublishing:~$ sudo /etc/init.d/transmission-daemon reload
Reloading bittorrent daemon: transmission-daemon.

一旦 Transmission 重新加载,就可以使用网页浏览器访问9091端口上的 IP 地址或主机名,并可以从那里进一步配置,如下图所示:

设置一个种子服务器

网络界面非常好用,且非常直观,另外也有多个 Transmission 客户端可以远程连接。它们的工作方式就像客户端在本地运行一样,但实际与网络中的 Transmission 守护进程进行通信。一个这样的程序叫做transmission-remote-gtk。例如,针对 Android 系统,有一款叫做Transdroid的应用程序。

设置个人云

云存储是如今一切的归属地。然而,很多人对将所有数据存储在随机服务器上的云存储方式并不满意。幸运的是,有一个叫做 ownCloud 的东西。它是一项 Web 服务,允许你拥有自己的个人云。

本书中,将使用 SQLite 数据库安装 ownCloud。对于非常轻量的单用户工作负载,SQLite 将足够用。

提示

对于更复杂的多用户安装,使用 PostgreSQL 或甚至 MySQL 将大有裨益;然而,这些系统的设置和使用更为复杂。在对 Linux 系统更加熟悉之后,这将是读者一个值得挑战的任务。

ownCloud 建议安装 邮件传输代理 (MTA);但是,安装 MTA 超出了本书的范围。为了绕过任何 MTA 的安装,存在一个名为 lsb-invalid-mta 的虚假软件包,可以按照以下方式安装:

packt@PacktPublishing:~$ sudo apt-get install lsb-invalid-mta

不幸的是,截至本书编写时,ownCloud 软件包尚未在 Debian Wheezy 中提供,但在更高版本中已经可以使用。同时,Ubuntu 也已经在其仓库中提供了很长一段时间。在某些情况下,比如 ownCloud 软件包,它可以通过一个不同的仓库——backports 仓库获得。前一章节已经提到过这个仓库,提到过 apt 仓库的相关信息。添加 backports 仓库可以通过添加以下行来完成。请根据需要使用适当的镜像,在以下示例中,使用了 nl 镜像:

deb http://ftp.nl.debian.org/debian wheezy-backports main

在添加 backports 仓库后,记得更新 apt 数据库。SQLite 变体的 ownCloud 有一些依赖项,这些依赖项被放入了名为 owncloud-sqlite 的元包中,如下所示:

packt@PacktPublishing:~$ sudo apt-get install owncloud-sqlite

安装好 ownCloud 所需的 SQLite 依赖项后,接下来是安装 ownCloud 本身。不幸的是,ownCloud 软件包默认会尝试安装一些建议的数据库软件包。在 Debian Wheezy 中,它总是会尝试安装 MySQL 数据库,尽管使用的是其他数据库。

为了解决这个问题,我们向 apt-get 引入了新的选项 –no-install-suggests–no-install-recommends,顾名思义,这些选项将不会安装任何建议或推荐的软件包。但即便如此,仍无法阻止 MySQL 的完整安装。通过添加 mysql-server-(注意软件包列表末尾的破折号),apt 将不会安装 MySQL 服务器,如下所示:

packt@PacktPublishing:~$ sudo apt-get install –no-install-suggests – no-install-recommends owncloud mysql-server-

在编写本书时,wheezy-backports 仓库中的 ownCloud 软件包已损坏。ownCloud 至少需要一个特定版本的 php-getid3,该版本在标准仓库中不可用,如下所示:

owncloud : Depends: php-getid3 (>= 1.9.5~) but 1.9.3-1+deb7u1 is to be installed

然而,这个软件包也可以在 wheezy-backports 仓库中找到,但 apt 需要特别指示从那里安装它。-t 参数告诉 apt 从特定的仓库安装软件包,如下所示:

root@PacktPublishing:~$ sudo apt-get -t wheezy-backports install php-getid3

可能需要从 backports 仓库安装此软件包或其他软件包作为 ownCloud 的依赖项。使用网页浏览器,导航到服务器的 IP 地址或主机名,ownCloud 设置向导将显示如下截图:

设置个人云

登录首次时,将创建一个管理员账户。初始设置可能需要一些时间,之后 ownCloud 即可使用。

总结

尽管本章没有涉及 Cubieboard 的具体内容,但它确实教授了一些基本的管理任务,并利用这些任务为家庭服务器设置了一些基础但有用的服务。虽然还有许多更有趣的服务可以考虑,例如 DHCP 服务器(ics)、打印服务器(cups)或 DNS 服务器(bind),在此基础上,还可以构建一个设备,并将其与 web 服务器集成,通过网页控制灯开关。

下一章将重点讲解如何升级启动加载程序和内核,这是两个相对简单的任务。

第六章:更新引导加载程序和内核

前几章教你如何入门并充分利用硬件和软件。如前所述,软件包通过新版本自动更新;但是引导加载程序和内核不会自动更新。本章将介绍各种可用的引导加载程序以及不同的内核,并帮助你选择最合适的版本。

本章将涵盖以下主题:

  • 各种引导加载程序和内核之间的区别

  • 获取新的引导加载程序或内核

  • 安装新的引导加载程序或内核

本章的先决条件

在本章中,你将需要前几章中使用的目标存储介质,如 SSD 或硬盘、USB 驱动器和 microSD 卡,用于引导。你还可以选择使用低容量的 microSD 卡代替。我在本书中使用的是一张 128 MB 的 microSD 卡,但即使是容量较小的卡也可以使用。只需要在 microSD 卡中放置引导加载程序、一些配置文件和一个内核,大约需要 4 MB 的空间,但实际上很难找到这样容量的 microSD 卡。

引导加载程序概述

引导加载程序是第一个加载的、实际上可以由用户修改的程序。社区和本书中使用的引导加载程序的名称是u-boot。它有两种不同的版本。首先是lichee变种,但它不再积极开发。之所以仍然存在,是因为它是目前唯一支持启动板载 NAND 闪存的引导加载程序。这个引导加载程序几乎总是预安装的,通常没有理由更换它。更有趣的是sunxi变种的 u-boot,它由社区积极开发,我们将在接下来的部分中详细介绍。

U-boot-sunxi

由于已经有预编译版本的引导加载程序可用,本章内容并不涉及编译引导加载程序。每当对代码库进行新增时,都会编译一个新的引导加载程序。每个 u-boot 二进制文件都是为每块板子独特定制的,所有引导加载程序的完整列表可以在dl.linux-sunxi.org/nightly/u-boot-sunxi/u-boot-sunxi/u-boot-sunxi-latest/找到。每块板子都有多个文件,具体如下:

  • 一个以 .build.txt 结尾的构建日志文件

  • 一个以 .sha1 结尾的生成文件的 sha1 哈希文件

  • 归档文件中的生成文件清单,以 .txt 结尾

  • .tar.xz 结尾的编译二进制文件的存档

一旦手头的开发板正确的二进制文件进入下载阶段,使用 Linux 工具wget就变得非常简单。为了在 Cubieboard 上使用这个文件,可以使用以下命令:

packt@PacktPublishing:~$ wget http://dl.linux-sunxi.org/nightly/u-boot-sunxi/u-boot-sunxi/u-boot-sunxi-latest/u-boot-sunxi-cubieboard.tar.xz

这个文件需要被解压;tar 是一个常用的工具,x 参数表示提取,J 大写参数表示通过 xz 过滤,v 表示让 tar 显示详细信息,f 告诉 tar 下一个参数是文件名。

注意

压缩包中的目录名有一个复杂的结构附加在最后,很可能与本示例中的目录名不完全相同。

让我们更详细地看一下压缩包。首先,在 u-boot 标识符之后是架构名称,sunxi。接着是开发板的名称,在本例中是 Cubieboard。接下来的命令行是二进制文件编译时的时间戳。最后,末尾是特定 Git 提交的哈希值:

packt@PacktPublishing:~$ tar xJvf u-boot-sunxi-cubieboard.tar.xz
u-boot-sunxi-cubieboard-20140307T104232-b5bd4c9/
u-boot-sunxi-cubieboard-20140307T104232-b5bd4c9/u-boot-sunxi-with-spl.bin
u-boot-sunxi-cubieboard-20140307T104232-b5bd4c9/u-boot.bin
u-boot-sunxi-cubieboard-20140307T104232-b5bd4c9/sunxi-spl.bin

需要对这三个文件进行一些解释。当 Allwinner SoC 芯片第一次启动时,它无法访问主系统内存,也就是我们所说的 RAM。SoC 芯片内有一小部分内存,叫做 SRAM。然而,SRAM 太小,无法容纳整个 u-boot,所以 u-boot 被分成了两个部分:次级程序加载器SPL)和实际的 u-boot。SPL 足以初始化内存并将较大的 u-boot 加载到内存中。这些文件都需要写入非常特定的区域,以便 SoC 理解从哪里启动。为了简化一点,提供了一个第三个文件,叫做 u-boot-sunxi-with-spl.bin。这个文件将两个部分结合并具有适当的间距,是目前唯一需要的文件。

安装引导加载程序

引导加载程序只能安装在一个位置,即使 SoC 可以从三个不同的位置启动。SPI-flash 在本书编写时尚不受支持。然而,一些早期实验表明这应该相对容易。虽然 u-boot 可以写入 NAND flash ROM,但社区开发的 u-boot 版本目前无法从 NAND flash 读取或写入。剩下的唯一选项是 microSD 卡,它一直被使用,且将继续被使用。

引导加载程序可以通过以下方式安装:

  • 在 PC 或 Cubieboard 上使用 USB 转 microSD 适配器

  • 使用 SD 卡读卡器在 PC 或开发板上

    注意

    写引导加载程序时要非常小心。一个小小的错误就可能毁掉 SD 卡上的数据。例如,将引导加载程序写入 SD 卡的开始位置会破坏分区表。将引导加载程序写得稍微偏远一些可能会破坏 SD 卡上的文件系统。在这两种情况下,数据都会丢失,因为引导加载程序没有放在正确的位置,因此 SD 卡无法启动。

一个要求是 microSD 卡必须有一个分区表。microSD 卡没有分区表的情况是相当常见的。使用在第三章《安装操作系统》中获得的知识,应该在 microSD 卡上创建至少一个分区,且该分区至少有 4 MB 的空闲空间。该分区必须被格式化为 fatext2ext3ext4

提示

如果没有从 microSD 卡挂载分区,例如启动分区,那么可以安全地移除当前使用的 microSD 卡并插入另一张卡。根据所使用的设备,确保将 sdb 替换为 mmcblk0 或分配给 SD 卡的任何设备节点。与比特无关。然而,复制某些文件可能会更棘手,并且在此期间可能需要将其存储在其他地方。

使用 dd 工具,将新的引导加载程序写入 /dev/sdb。请确保这真的是包含目标 SD 卡的设备节点。使用错误的设备节点可能会破坏重要数据,甚至导致系统无法启动。重要的参数是 blocksizebs)和 seek,其中 blocksize 乘以 seek 表示 microSD 卡上的确切位置——在此情况下,正好是 8 KB。原因很简单;这是 SoC 芯片在 SD 卡上搜索引导加载程序的确切位置,以下命令对此进行了说明:

packt@PacktPublishing:~$ sudo dd if=u-boot-sunxi-a10-olinuxino-lime-20140307T10232-b5bd4c9/u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8

完成引导加载程序

引导加载程序确实需要一些标准的配置文件,例如需要启动的内核。需要考虑的一些问题是传递给内核的参数和要加载到内存中的内核地址。有三个辅助文件可以安全地从以前的启动介质中复制。它们如下:

  • boot.scr:这是一个编译后的命令列表,u-boot 将执行这些命令

  • uEnv.txt:这是一个将传递给内核的变量列表

  • boot.cmd:这是用于生成 boot.scr 的源文件

    提示

    boot.cmd 命令不是必须使用的,它只是一个非常有用的文件。要从 boot.cmd 创建 boot.scr,可以使用以下命令:

    mkimage -C none -A arm -T script -d boot.cmd boot.scr
    
    

复制了这三个文件后,Cubieboard 几乎可以启动,只剩下内核部分。

探索内核

对于基于 x86 的系统,通常只有一个内核;大多数情况下,这是由发行版提供的内核。这个内核通常是基于 www.kernel.org 的内核。这个内核通常被称为主线内核、原生内核或上游内核。对于基于 Allwinner 的 SoC 芯片,自 2012 年的 3.8 版本以来,社区开发的内核对其支持非常有限。也有一些较旧版本的内核,所有特性都是由 Allwinner 自己添加的。虽然这些更改的质量没有达到主线内核的标准,但目前来说,它是唯一的选择。尽管如此,它已接近功能完备,因此通常是迄今为止唯一可用的选择。所有这些不同的内核版本都可以在 Git 仓库中的各个分支上找到。就像 u-boot 一样,也有夜间预编译的镜像,可以在本书中使用。在继续下载这些预编译的归档文件之前,需要先解释一下不同版本的内容。

SoC 的变种

Allwinner SoC 芯片有多个版本,例如 A10 系列。A10 系列在内部被称为 sun4i——sun 系列的第四代。同样,sun5i 是 A10S 和 A13 的内部名称。A31 和 A31S 被称为 sun6i,A20 被称为 sun7i,而新款 A23 被称为 sun8i。这些芯片的综合名称叫做 sunxi。对于几乎所有的内核版本和每种机器类型,都有一个 Git 分支或者一个夜间预编译的二进制版本。

各种内核的概述

对于初学者来说,加入 sunxi 社区后,他们常常对各种内核版本感到困惑,不确定该使用哪个内核。接下来的几个小节将简要介绍可用的不同版本。

内核版本 2.6.36

内核版本 2.6.36 最初被 Allwinner 扣押,因为 Allwinner 拒绝发布 GPL 许可的代码。后来,Allwinner 基于的平板设备制造商解救了这个版本,Allwinner 官方发布了内核的源代码。随后,一个社区开始围绕这个源代码发布形成。这个版本已经过时很久了。

内核版本 3.0 和 3.0 阶段

版本 3.0 是 sunxi 内核的第一个积极开发版本。3.0 内核的基础最初也是由第三方平板制造商释放的。社区从头开始重新启动,并投入了大量工作来释放这个内核。后来,全志(Allwinner)也发布了他们的 3.0 内核,但与社区构建的内核相比已经分化。例如,社区做的一件重要事情是统一各种机器类型。全志打算完全分开发布 sun4i 和 sun5i 内核,而社区将其合并为通用的 sunxi 内核和驱动程序。它从全志提供的内容中看到了许多其他改进,但并非所有补丁和修复都立即放入 3.0 系列中。补丁总是首先放入所谓的 3.0 阶段树中,在几周的测试后,这些补丁被合并回 3.0 树中。3.0 树在技术上也已经过时,但由于仍然被许多平板电脑使用,因此仍然活跃使用。

内核版本 3.3

全志在社区已经开始并将所有内容移植到主流 3.4 内核之后发布了他们内核的新版本。社区从不使用 3.3 内核,因为全志未采用其中的任何错误修复和改进。有时它也被称为荔枝内核。

内核版本 3.4 和 3.4 阶段

当 3.4 内核发布时,它被标记为长期支持LTS)发布,意味着它将在延长的时间内接收支持和安全补丁。sunxi 硬件的驱动程序从 3.0 转移到 3.4,以在一个得到良好支持的内核版本上支持全志硬件。与 3.0 一样,3.4 的阶段变体持有所有新的补丁,并合并到 3.4 中,因为它被认为是稳定的。3.4 系列目前正在积极开发,并推荐日常使用。

内核版本 experimental-3.14

版本 3.14 的高度实验性分支目前不可用。该想法是取 3.14 内核,这是一个 LTS 发布,然后将 3.4 sunxi 驱动程序应用到其中。与 3.4 的主要区别在于,3.14 是内核的一个发布版本,并且对 sunxi SoCs 有一些实际支持。只要这些内核被标记为实验性,除了用于实验外,不应该使用它们。

内核的开发分支

针对主线内核编写的补丁会被发送到各种邮件列表进行审查。devel 分支(代表开发)尝试捕获所有这些正在审查的补丁,并将它们合并到主线跟随树中。换句话说,这个树目前支持大多数硬件,但随着审查过程的进行,它很可能会发生变化。这个内核应该仅在进行驱动开发、审查或想要帮助测试新事物时使用。然而,随着情况逐渐稳定,这个分支将来可能会被移除。

下一分支的内核

与 devel 分支非常相似,它跟踪主线内核并保存已接受的补丁。它可以被视为 devel 内核的稳定变种。这个内核应该仅在需要下一个即将发布的内核版本时使用。

选择内核

由于有这么多可用的内核,目前唯一值得关注的内核是 3.4 内核。虽然当 3.14 内核脱离实验状态并开始替代 3.4 时,这种情况可能会发生变化,但目前它们并不是一个选择。确定了这个选择后,需要根据所使用的 Cubieboard 类型来选择机器类型。前面讨论过的变种部分将解释选择哪个机器类型。

安装内核

使用 wget,一个基于 A20 的内核将被下载并在以下示例中解压:

packt@PacktPublishing:~$ wget http://dl.linux-sunxi.org/nightly/linux-sunxi/linux-sunxi-3.4-sun7i/linux-sunxi-3.4-sun7i-latest.tar.xz
linux-sunxi-3.4-sun7i-20140215T115414-8ea347b/lib/
linux-sunxi-3.4-sun7i-20140215T115414-8ea347b/boot/

在这里,还将创建一个新的目录,该目录包含一个以 datestampedgithash 命名的目录。在这个目录下,将有两个子目录。boot 目录包含实际的内核文件,一个名为 uImage 的文件。该文件将被放置在 microSD 卡的第一个分区上。

安装内核模块

在内核中,驱动程序可以被编译到内核中并始终加载,或者它们可以从内核中分离出来,根据需要加载。这些分离的驱动程序称为模块,在大多数发行版中位于 /lib/modules/。复制这个目录即复制了新内核所需的所有文件。

提示

以下命令假设在 Cubieboard 上本地执行此操作。如果使用其他系统来执行复制,目标路径会有所不同:

packt@PacktPublishing:~$ sudo cp -ar linux-sunxi-3.4-sun7i-20140215T115414-8ea347b/lib /

内核和模块就位后,系统可以安全地重启,使用新内核及其模块。

总结

本章介绍了各种引导加载程序和内核,并简要解释了它们之间的区别。然后展示了如何将预编译的内核安装到 microSD 卡上,并将其用作引导设备。

下一章将讲解如何使用 sunxi-bsp 或 sunxi 板从头开始编译引导加载程序或内核的步骤。

第七章:使用 BSP 编译引导加载程序和内核

有时候,内核中需要某个特别的功能,但该功能并未包含在预编译的二进制文件中,或者可能获得了某个基于 Allwinner 的新硬件,而该硬件还没有在现有的预编译文件列表中得到支持。为了解决这些问题,需要从源代码编译引导加载程序或内核。虽然可以单独下载并编译引导加载程序和内核,但 linux-sunxi 社区开发了一个板支持包BSP),允许你将所有这些组件一起编译。

本章将涉及以下主题:

  • 安装工具链

  • 获取并使用 BSP

  • 编译引导加载程序

  • 编译内核

  • 创建硬件包

前提条件

编译需要一个编译工具链。在这里,有两种选择。要么在 Cubieboard 上直接编译,要么在普通 PC 上进行交叉编译。除 Linux 外,其他系统上使工具链正常工作需要读者自行解决。因此,选择是使用前几章创建的安装环境,直接在 Cubieboard 上编译,或者使用可用的(虚拟)Linux 机器,安装并使用交叉编译器。本章将描述这两种方法。此外,编译设备需要初始的互联网连接,用于获取源代码。

安装工具链

工具链是一组工具,包括一个编译器,必要时用于将源代码编译为二进制文件。从理论上讲,仅编译器就足够了,但通常还需要其他工具来辅助编译。一个常见的例子就是大家熟悉的 make 命令。所有编译所需工具的集合被称为工具链。安装工具链在不同的发行版中有所不同;我们这里只介绍一些例子。

Debian 或 Ubuntu

对于 Debian,工具链被称为 build-essential,当进行交叉编译时,需要在此基础上安装 arm 编译器;这个包名为 gcc-arm-none-eabi。遗憾的是,在编写本书时,gcc-arm-none-eabi 包在 Debian wheezy 中并不存在。wheezy 之后发布的版本是 jessie,其中包含了这个交叉编译器。获取它的一个方法是设置虚拟机并在其中安装 Debian 的测试版。

Fedora

在 Fedora 上,安装过程稍有不同。这里需要使用 groupinstall 变体来安装 Development ToolsDevelopment Libraries 包。为了进行交叉编译,还需要安装 gcc-arm-linux-gnu 包。由于元包中有空格,使用双引号("")是必要的。

其他发行版

Fedora 和 Debian 当然只是潜在数百个发行版中的两个。然而,这两个发行版很好地指示了其他大多数发行版如何处理工具链的安装。这两个重要的发行版安装方式不同。对于 Gentoo 发行版,有一个 crossdev 工具集,它会编译并安装一个交叉编译器工具链。安装 crossdev 后,使用crossdev --target arm-pc-linux-gnueabi来安装 arm 工具链。Arch 发行版在Arch 用户仓库AUR)中提供了gcc-arm-linux-gnueabihf-bin包。

注意

还有一些厂商提供的工具链,例如 Linaro 和 CodeSourcery 提供的工具链。这些工具链需要从厂商网站手动下载。通常,工具链以 tarball 或 ZIP 包的形式提供,并需要手动解压。这些工具链通常在没有本地 arm-toolchain 时使用。Linaro 甚至为 OSX 和 Windows 提供了交叉编译器;然而,这两者需要大量的工作才能开始编译。

其他必需的工具和软件包

获取了完整的工具链后,仍然需要其他一些软件包。Git 是用于源代码管理的工具;该软件包在几乎所有发行版中都被命名为git

此外,还需要u-boot-tools。在某些发行版中,该软件包也被称为u-boot-toolsuboot-mkimage

在一些发行版中,如前所述,在安装工具链时,pkg-config软件包有时没有被安装,需要在缺少该软件包的发行版上手动安装。该软件包几乎总是被称为 pkg-config。为了编译某些工具,libusb头文件是必需的。该软件包的名称在不同的发行版中可能有所不同。在 Fedora 中,它被称为libusb-devel。在 Debian 和 Ubuntu 中,它被称为libusb-1.0-0-dev。请注意,libusb在许多发行版中通常有多个版本。所需版本是1.0,其他版本可能会导致编译失败。

最后,需要ncurses头文件和库;该软件包被称为ncurses-devncurses-devel

获取和维护 BSP

无论 BSP 是进行交叉编译还是本地编译,获取和使用的方式是相同的,因此说明也是通用的。所有代码都存储在 git 服务器上,可以并且应该使用 GitHub 或 Gitorious 作为主要镜像来获取代码。使用 Git,可以从其中一个镜像克隆仓库,如下图所示:

获取和维护 BSP

进入 sunxi-bsp 目录后,将会看到以下文件和目录列表:

获取和维护 BSP

让我们花一点时间快速浏览一下这些文件目录列表,其中有些实际上是独立的 Git 仓库:

  • allwinner-tools:这是一个文件、驱动程序和工具的集合,用于处理全志提供的材料,如 livesuit。它在使用社区工具时并不重要。

  • rootfs:这些是要放入生成的根文件系统中的文件,通常称为rootfs

  • sunxi-boards:这些是社区支持的开发板的 FEX 文件。有关 FEX 的更多信息,请参见附录 C,FEX 配置文件

  • u-boot-sunxi:这是社区开发的引导加载程序。

  • cedarx-libs:这些是全志提供的专有视频处理单元VPU)的库。

  • linux-sunxi:这是社区开发的 Linux 内核。

  • scripts:这些是 BSP 使用的各种脚本。

  • sunxi-tools:这些是与全志硬件一起使用的社区开发工具,包括将 FEX 文件编译成二进制 script.bin 的工具。

  • Makefile:这是一个控制如何编译各种仓库的文件。

  • Configure:这是一个选择和配置整个 BSP 的脚本。

  • README.md:这是一个简单的文本文件,包含一些基本的使用说明。

更新仓库

BSP 中的一些目录尚未填充。BSP 足够智能,能够在需要时自动填充所需的仓库。然而,如果某个仓库需要手动填充或更重要的是更新,可以使用 Git 来进行操作。更新仓库时,第一次使用时需要添加–init参数,具体如下:

packt@PacktPublishing:~/sunxi-bsp$ git submodule update --init sunxi-tools

如果省略最后一个参数,在这种情况下是sunxi-tools,将会更新并填充所有 Git 子仓库。然而,这并不总是会获得仓库的最新版本。BSP 控制每个仓库使用的版本。可以说,它将每个子仓库锁定到某个特定版本。可以通过 Git 更新 BSP,具体如下:

packt@PacktPublishing:~/sunxi-bsp$ git pull
Already up-to-date.

如果 BSP 没有更新或没有包含子仓库的最新更新,可以手动更新子仓库。要更新某个仓库,进入该仓库并使用常规 Git 命令来更新或切换到不同的分支,具体如下:

packt@PacktPublishing:~/sunxi-bsp$ cd sunxi-tools/
packt@PacktPublishing:~/sunxi-bsp/sunxi-tools$ git pull

请注意,这可能会破坏 BSP 本身的版本控制。也就是说,本地的 BSP 将不再与官方 BSP 匹配。为了删除本地子仓库所做的所有更改,并使 BSP 与上游版本同步,可以使用以下命令:

packt@PacktPublishing:~/sunxi-bsp$ git checkout – sunxi-tools

更新和修改 Git 中的子模块是完全安全的,开发者经常进行此操作。刚开始使用时需要小心,尤其是在不熟悉 Git 的情况下。

注意

强烈建议在修改仓库之前,具备一定的版本控制系统,特别是 Git 的经验。如果一切失败,放心,总是可以删除 BSP 并重新开始。

选择内核

如第六章中讨论的,更新引导加载程序和内核,有几个不同的内核可供选择。这些内核是根据 Git 仓库中可用的不同分支构建的。使用git branch命令可以列出这些分支,添加-a参数告诉 Git 显示所有可用的分支。在下面的截图中,讨论过的内核应该是第六章,更新引导加载程序和内核,可以识别出来:

选择内核

这个分离的分支,在本书编写时,正是与 BSP 相关联的内核版本。使用git checkout,可以轻松切换到其他分支,最终切换到一个内核。这可以在下面的截图中看到:

选择内核

为 Cubieboard 编译

在为 Cubieboard 编译之前,必须首先配置 BSP。每当为不同的开发板进行构建时,都必须重新配置 BSP。然而,使用配置脚本,这是一项非常简单的任务。运行没有参数的 configure 会填充sunxi-boards仓库,因为该仓库包含一个受支持的开发板列表,并会打印出可用的板子列表,如以下代码所示。请注意前缀./,它用于配置脚本。为了清晰和方便,这里简化了 configure 的输出:

packt@PacktPublishing:~/sunxi-bsp$ ./configure
Usage: ./configure <board>
supported boards:
 * a10s-olinuxino-m a10s-olinuxino-m-android
 * a10-olinuxino-lime a10-olinuxino-lime-android
 * a13-olinuxino a13-olinuxino-android
 * a13-olinuxinom a13-olinuxinom-android
 * a20-olinuxino_micro a20-olinuxino_micro-android
 * cubieboard cubieboard-android
 * cubieboard2 cubieboard2-android
 * cubietruck cubietruck-android

每块开发板都有两个变体,需要传递给配置脚本;Android 变体专门用于构建 Android 内核。虽然 Android 是 Linux,但仍然有一些小差异需要考虑。在下面的示例中,BSP 被配置为构建 Cubieboard2:

packt@PacktPublishing:~/sunxi-bsp$ ./configure cubieboard2
cubieboard2 configured. Now run `make`

现在,在运行之前,按照 BSP 的建议,还有一件事情需要提到。BSP 希望知道使用什么编译器,它通过CROSS_COMPILE=参数来判断。默认情况下,Makefile 会强制此参数为arm-linux-gnueabihf-,这是已安装的 arm 编译器的前缀。因此,gcc预计会命名为arm-linux-gnueabihf-gcc。当在这些板子上本地编译时,情况变得更加有趣。这是因为理论上,不需要交叉编译器,gcc应该直接称为 gcc。为了解决这个问题,可以传递一个空的CROSS_COMPILE=参数给 make,如下所示:

packt@PacktPublishing:~/sunxi-bsp$ make CROSS_COMPILE=

否则,需要添加已安装的编译器前缀,是的,末尾的破折号是前缀的一部分。如果在 Debian 上进行编译,可以使用以下命令:

packt@PacktPublishing:~/sunxi-bsp$ make CROSS_COMPILE=arm-none-eabi-

每个发行版通常会使用不同的交叉编译器名称,这没有对错之分。使用 arm-并双击 Tab 补全,几乎可以找到所有发行版的前缀。另外,向 Makefile 中添加正确的交叉编译器前缀也非常有帮助。

根据内存大小以及所使用的系统来进行编译,这个过程可能需要从几分钟到一两个小时不等!如果出现奇怪的崩溃或问题,在查看附录 A,获取帮助与其他有用的在线资源,以及如何联系社区寻求支持之前,请确保所选主板得到了充分的支持,并且电源供应充足。通常情况下,超频内存或电力不足会在内核编译的高负荷下表现出来。

虽然能够编译标准内核是件不错的事情,但通常情况下,有人会因为定制需求而编译内核,例如添加或移除某些驱动程序或选项。即使是定制补丁,也需要定制编译内核。通常情况下,menuconfig命令用于内核目录。BSP(板级支持包)也支持此操作,通过将linux-config参数传递给make命令,如下所示:

packt@PacktPublishing:~/sunxi-bsp$ make linux-config CROSS_COMPILE=arm-none-eabi-

跟随这些步骤会进入一个标准的menuconfig会话。

make命令的其他一些参数有 Linux 或 u-boot,它们仅用于编译 Linux 内核或仅编译 u-boot。生成的二进制文件将位于sunxi-bsp/build目录下各自的子目录中。

当编译完成时,所谓的 hwpack 或硬件包将会在sunxi-bsp/output目录中创建。硬件包是一个包含三个子目录的归档文件。第一个子目录叫做bootloader,其中包含u-boot-sunxi-with-spl.bin引导加载程序。

kernel子目录下,特定板子的内核名为uImage,与特定板子的script.bin文件一起存放。

最后的目录是rootfs目录。这个目录包含了所有特定于所选目标板的内容。内容可以并且应该被复制到目标根文件系统中。

在第六章中,已详细描述了安装 hwpack 中的文件,特别是引导加载程序,更新引导加载程序和内核

总结

本章介绍了 BSP 的基础知识。通过结合使用 Git 这个强大的工具来下载和管理各种源代码仓库,你可以编译各种组件,并生成一个易于使用的设备专用硬件包。

下一章将介绍通用输入输出引脚GPIOs)。这对于执行各种任务非常有用,包括让 LED 闪烁!

第八章:闪烁的灯光与感知世界

到目前为止,我们已经涵盖了 Cubieboard 的多个方面,但它们都是与软件相关的内容。与现实世界场景进行交互时,从让发光二极管LED)闪烁到打开灯光,再到驱动电动机,事情变得更加有趣。一旦你将开发板连接到今天各种可用的设备,你可以做的事情就多了起来。一个机器人吸尘器的开发很大程度上是在开发板上开始的,工程师将各种传感器连接起来,使得机器人能够“看到”周围的环境。连接所有这些设备可能会非常复杂,可能不仅仅涉及电子学的基础;因此,本章将专注于电子学的基础知识,帮助你掌握一些基本内容,如连接 LED、使其闪烁,以及连接按钮以响应按压。

在本章中,我们将涵盖以下主题:

  • 一些基础电子学概念的概述

  • 如何切换通用输入/输出GPIO

  • 如何连接按钮并读取其状态

使 LED 发光

今天,想象一个没有 LED 的世界几乎是不可思议的。它们在我们的智能手机上显示信息,作为电视和立体声设备的指示灯已经使用了多年,甚至有些大型屏幕完全由 LED 构成。具有讽刺意味的是,LED 的发明更像是第一代二极管的一个烦人的副作用。最初的设计并不是为了发光,在早期的设备中,二极管甚至被黑漆覆盖以隐藏它们的光芒。LED 这个名字已经如此普及,以至于它们的真正意义几乎可能被遗忘了。

使 LED 发光,然而,这确实需要一些技巧和专业知识,以确保不会把它弄坏。每个 LED 都有一些特性,例如它需要的工作电压以及能够通过它的最大电流。例如,蓝色 LED 需要比红色 LED 更多的电压和电流。因此,了解 LED 的技术细节是非常必要的。

所需的电阻

LED 只是一种特殊形式的二极管。它是电流的单行道,也就是说,电流只能按照预定的方向流动。而且,在连接 LED 时必须小心;如果它连接的方向错误,电流将无法流动,因而不会发光。然而,反过来就更有意思了。

让我们来看看当 LED 以正确方向连接时会发生什么。一旦提供了某个阈值电压,读取正向电压,二极管开始导通,LED 发光。至于流经二极管的电流,情况看起来有些不同。二极管将导通供给它的所有电流。不同类型的二极管在它们所用的电气设计中有不同的用途;在 LED 的情况下,目的通常是发光。这些类型的二极管通常只能通过非常少量的电流,通常在毫安级别。正如其名称所示,电阻限制通过它的电流流动,因此用于电流的调节,如下图所示:

所需电阻

有很多网站可以帮助计算给定电压和电流的正确电阻;其背后的数学并不复杂。欧姆定律是用来计算电阻的常见公式。它表示如下:

所需电阻

和:

所需电阻

要计算电阻,所需电阻,需要除以电流所需电阻。让我们了解如何确定所需的电压。为此,从可用电压中减去二极管的正向电压。这产生了下面这种形式的欧姆定律:

所需电阻

假设我们的电压源是 3.0 伏特,二极管的正向电压是 1.2 伏特。假设本例所需的电流为 30 毫安,那么在欧姆定律中填入这些值可得到以下结果:

从这点小数学中,我们了解到需要 60 欧姆的电阻来使 LED 发光,而不会试图消耗所有可用电流。然而,60 欧姆的电阻可能很难找到,只有两个选择。连接几个电阻以串联方式一个接一个地获得所需值,或找到一个接近值的电阻,比如 68 欧姆。重新排列欧姆定律并填入值可得到 26.5 毫安的电流流过 LED。这通常足以点亮 LED。这个计算可以在下面的公式中看到:

所需电阻

提示

使用电阻限制 LED 流过的电流不是点亮 LED 的最节能方法,但它是非常常见且最简单的方法。理想情况下,推荐使用恒流电源,这样就不再需要电阻。毕竟,LED 所能接受的最大电流本来就是它想要接收的电流。虽然这超出了本书的范围,但学习恒流电源和驱动 LED 是一个很好的练习。

吸收与输出

要将设备连接到 GPIO,理想情况下,GPIO 应该能够提供正确的电压和电流。不幸的是,这种情况很少发生。引脚提供的电压通常是供电电压或 I/O 电压,这两者都是芯片的输入电压。在全志 A 系列芯片的情况下,这将是 3.3 伏。GPIO 能够提供或吸收的电流是有限的。供电电流或输出电流(通常称为 sourcing)可以从 10 毫安到 40 毫安不等。引脚可以提供的电流量在 FEX 文件中配置,详细内容请参见附录 C,FEX 配置文件。输出电流的反义是吸收电流,但在介绍这一点之前,让我们先看看下图,其中一个 LED 直接连接到 GPIO。

吸收与输出

在前面的图示中,很明显 GPIO 引脚提供了电压,电流通过二极管流入地面。GPIO 是电流的“源”。相反的情况也是可能的;GPIO 吸收或导入电流,如下图所示:

吸收与输出

在前面的图示中,二极管由电源提供电压和电流;在电子学中,它通常被称为 VCC。然后,电流像之前一样流经二极管和电阻,最后被 GPIO 吸收。GPIO“吸收”了电流。虽然这种第二种方法和第一种方法一样有效,但有一些需要注意的地方。电源需要提供适当的电压,否则 GPIO 可能会过载,烧坏部件甚至整个芯片。在软件方面,GPIO 引脚将以相反的方式工作;当 GPIO 为高电平时,电压与 VCC 相同,因此没有电流流动。如果引脚设置为低电平,电压就可以流动。

小贴士

一个细心的读者可能会注意到,如果 GPIO 被设置为提供 30 毫安的电流,那么根本不需要电阻。虽然这是不推荐的做法,但它仍然是可能的;然而,在最终设计中绝对不应采用这种方法。

放大电压和电流

所有前述方法仅适用于需要小量电流的情况。那么,当需求较高电流时该怎么办呢?在这种情况下,会使用一个简单的晶体管。晶体管可以被看作是水管上的阀门。通常,阀门是关闭的,不允许水流动。当电流施加到晶体管的基极 B 时,阀门会慢慢打开,从集电极 C 到发射极 E 导通电流。电流的流动与施加到基极的电流成正比,因为晶体管本质上是一个电流放大器。此外,施加到基极的电流也会加到发射极的输出上,如下图所示:

放大电压和电流

通过 VCC 提供的电压由晶体管的规格决定,而不是由 GPIO 决定。假设晶体管允许,24 伏特的电压可以通过晶体管调节,同时通过 GPIO 的 3.3 伏特进行控制。本质上,这是一个电压放大器,晶体管通常用于实现这个效果。

有两种类型的晶体管:PNP 和 NPN。上一段已经解释了 NPN 晶体管的基本工作原理。PNP 晶体管的工作方式恰好相反,意味着当没有电流通过 GPIO 输入到晶体管基极时,它会默认导通电流。如果电流被施加到晶体管的基极,晶体管将停止导电。

从软件控制引脚

有几种方法可以从 Linux 内部控制 GPIO。可以通过驱动程序从内核内部控制,或者通过许多编程语言之一,例如 C 程序或 Python 脚本。不过,最快最基本的方法是直接从控制台操作。当然,这假设用于控制 GPIO 的驱动程序已经作为模块加载或编译进内核中。请参考第七章,使用 BSP 编译引导加载程序和内核,重新编译内核并添加 GPIO 驱动程序。根据使用的内核版本,它被称为sunxi 平台的 GPIO 支持,并可以在设备驱动程序选项中的GPIO下找到。根据使用的 GPIO,FEX 文件需要修改以配置 GPIO 引脚。要将某个引脚设置为输出 GPIO,可以使用以下代码片段:

[gpio_para]
gpio_used = 1
gpio_num = 1
gpio_pin_1 = port:PB03<1><1><default><default><default>

如果一切都已正确设置,可以通过文件系统切换 GPIO 引脚,例如,写入 1pb03 会使 GPIO 变为高电平,如下所示:

packt@PacktPublishing:~ $ echo 1 > /sys/devices/virtual/misc/sunxi-gpio/pin/pb03

同样,写入 0 会使其再次变为低电平。

注意

不仅在单个引脚的高电流负载下需要晶体管,通常所有 GPIO 总和能提供的最大电流也是有限的。因此,控制事物的最佳方法是始终使用晶体管。

上拉和下拉

配置为输入的 GPIO 仅仅是测量施加到其上的电压。如果电压高于某一阈值,则被认为是高电平或 1。如果电压低于某一阈值,则被认为是 0。以 Allwinner A 系列为例,一般来说,任何大于 2.5 伏的电压都视为高电平,小于 0.8 伏的电压视为 0。介于两者之间的电压则未定义,可能是 01

有了这些知识,使用一个三位开关并将其连接到地面或 3.3 伏电源就变得很容易。以下图示展示了一个直接连接到 GPIO 的开关:

上拉与下拉

需要注意几个事项。存在一个过渡阶段,其中开关从一种状态切换到另一种状态,电压可能介于 3.3 伏和 0 伏之间。此外,一个引脚可以提供的最大电流将流入 GPIO,导致设计效率低下,甚至可能损坏芯片。通过使用电阻将任何状态永久连接到 GPIO,这两个问题都可以得到解决。如果使用电阻将 VCC 永久连接,则称为上拉电阻,因为电阻将电压拉高。如果电阻用于将引脚拉到地面,则称为下拉电阻,因为电阻将电压拉低到地面。以下图示展示了上拉电阻与开关配合使用的情况:

上拉与下拉

在这种情况下,GPIO 会看到高电压,并将其解释为逻辑 1。当按下开关时,电流会偏好沿着电阻最小的路径流动,由于 GPIO 内部自然有一定的电阻,电流最终会流向地面。

如果交换开关和电阻的位置,则会创建一个下拉电路。在这种情况下,GPIO 默认看到低电压,并将其解释为逻辑 0。当开关被按下时,电流将自然流向地面,GPIO 将其解释为逻辑 1

在这两种情况下,电阻值的计算方式与 LED 电阻的计算方式类似。理想情况下,电阻值应该尽可能高,这样只有极少量的电流能流动,从而不浪费电能。然而,选择一个过高的电阻会导致电流过小,GPIO 无法感知电压。

在这两种 Allwinner SoC 的情况中,都可以通过 FEX 文件配置内部的上拉或下拉电阻。此时可以使用以下命令:

[gpio_para]
gpio_used = 1
gpio_num = 1
gpio_pin_1 = port:PB03<1><0><1><default><default>

如需更多详细信息,请参见附录 C,FEX 配置文件。是否使用上拉电阻或下拉电阻的选择取决于项目的需求。一般来说,如果引脚默认需要读取为0,并在按下按钮时更改为1,则使用下拉电阻。然而,实际上,上拉电阻通常更节能,因此更常用。

读取开关状态

读取开关的状态与写入 LED 类似。所有的先决条件都适用。唯一的区别是 GPIO 是通过cat来读取的,而不是通过echo来写入,如下所示:

packt@PacktPublishing:~ $ cat /sys/devices/virtual/misc/sunxi-gpio/pin/pb03
1

利用这些知识,读取按钮可以通过多种编程语言以各种形式实现。

提示

一个不错的练习是编写一个简单的脚本,读取按钮的状态,并使 LED 反映该状态。前面两个示例使用的是相同的 GPIO 引脚,因此如果尚未配置第二个引脚为 GPIO,则需要配置一个新的引脚。

从这里开始,有更多的方式和方法可以进行交互。有模拟-数字转换器ADC)可用于读取模拟电压,串行外设接口SPI)总线和集成电路间总线I2C),也称为双线接口TWI),可以连接大量外设,每种都能创造出精彩的发明。由于这是一本入门书籍,深入细节将需要更多的篇幅来解释各种技术。但希望它能激发你进一步寻找资源,继续实验并使用基于 Allwinner 的开发板。

总结

在本章中,我们讲解了一些基本的电子学知识,教读者如何连接 LED 和开关。我们还讨论了与 LED 开关接口时最常见的陷阱和最佳实践。让 LED 闪烁被视为嵌入式开发的 Hello World。

附录 A. 获取帮助和寻找其他有用的在线资源

在完成本书的内容后,可能会有许多问题仍未解决,或者即使参考了 附录 D,常见问题排查,也很可能会遇到一些无法解决的问题。幸运的是,有很多愿意提供帮助的志愿者。

本附录将涵盖以下主题:

  • 结识各个社区

  • 哪里可以获得帮助

  • 如何提出正确的问题

  • 获取新的基于 Allwinner 的设备支持

结识社区

随着各种项目和产品周围形成了许多在线社区,这并不奇怪。考虑到本书中涉及的所有开发板及其 SoC,尤其如此。每个社区或多或少地专注于某些任务。关于本书,有三个最重要的社区。首先是 Olimex 社区,专注于所有由 Olimex 创建的产品,并提出与 Olimex 开发板和外围设备相关的问题。类似地,还有一个 Cubietech 社区,围绕着 Cubieboards 展开。最后,还有一个在这一圈内非常知名的志愿者团队,那就是 linux-sunxi 社区。该名称如前所述源自 Allwinner SoC 系列,也与他们的主要兴趣相关。linux-sunxi 社区专注于引导加载程序、内核和驱动程序的开发,并在他们的维基上收集了大量关于 Allwinner SoC 的信息。

在处理 Olimex 或 Cubietech 硬件时,向 Olimex 或 Cubietech 社区寻求帮助,或者更好的是向其他用户提供帮助是明智的选择,而 linux-sunxi 社区非常有知识并且通常很乐于助人。

注意

这些社区中的成员都不是由任何公司雇佣的全职员工。他们是志愿者,愿意帮助其他用户,因为他们自己可能也曾得到过他人的帮助。此外,这个社区的成员来自世界各地,所以请确保保持礼貌和友好。

联系 Olimex 社区

Olimex 的主要联系点显然是他们的网站,www.olimex.com。虽然该网站的初始和主要重点是他们的商店,但它也有链接通向他们的论坛、维基,甚至是由用户完成的项目,目的是激励他人。直接的维基网址是 www.olimex.com/wiki,而论坛的直接网址是 www.olimex.com/forum,如果需要,也可以绕过主站访问这些页面。维基账户需要向 Olimex 提出请求,但任何人都可以创建一个免费的论坛账户并在上面获得支持。此外,在 Freenode IRC 网络上有一个 Internet Relay ChatIRC)频道,叫做 #olimex,在那里可以与其他社区成员进行实时聊天。

联系 Cubietech 社区

Cubietech 的官方网站是www.cubieboard.org。该网站主要是一个博客,发布新产品。虽然网站上有多个论坛链接,但这些实际上是指向各种语言的非官方外部论坛。请注意,这既是一个优点,因为用户可以用自己的母语进行交流,也可能是一个缺点,因为资源分散在不同的论坛中。Cubietech 没有官方论坛,而是使用 Google 群组邮件列表,通过 Google 网页界面访问作为论坛。访问其论坛的直接链接是www.cubieboard.org/forum/。此外,还有一个只读的 wiki,名为docs,可以通过docs.cubieboard.org直接访问。此外,Cubietech 在 Freenode 网络上有一个 IRC 聊天室,名为#cubieboard。最后,Cubietech 还有一个网页www.cubieboard.org/support/,在该页面可以了解如何获取支持的信息。

联系 linux-sunxi 社区

linux-sunxi 社区也有一个官方网站,这是一个非常有用的 wiki,地址是linux-sunxi.org。这个 wiki 本身可能让人感到有些难度,但也非常有帮助。这里有许多教程和如何做的部分,涉及各种任务。内容由内核黑客和普通用户不断更新,包括本书的作者。linux-sunxi 的 wiki 可能比本书更为技术性,但它是一个不可忽视的重要资源。此外,还有一个邮件列表,是进行大量交流的地方。关于如何加入或仅浏览邮件列表的说明,可以在 linux-sunxi 社区网站linux-sunxi.org/Mailing_list找到。和 Olimex 及 Cubietech 一样,linux-sunxi 社区也可以在 Freenode IRC 网络上通过频道#linux-sunxi找到,许多用户和开发者在此贡献他们的知识。

通过提问正确的问题来获取帮助

尽管地点已经在前面的章节中介绍过,但如何获取帮助同样,甚至更为重要。社区成员通常是愿意提供帮助的,但像帮帮我,它不工作这样的问题在多个层面上都是错误的;首先,什么不工作?你为解决问题尝试过什么?此外,这种说法听起来很强势,当向志愿者请求帮助时,要求过多通常根本不会有帮助。所以,在通过论坛、邮件列表或 IRC 频道提问时,一定要尽量礼貌且清晰地描述问题的表现。不要让语言成为障碍;许多社区志愿者自己也不是以英语为母语的人,他们理解你可能也不是母语为英语的人,这没关系。如果有疑问或不确定任何地方,维基百科有一篇小条目,介绍了如何在在线社区中行为,特别是网民礼仪和在线礼节部分,相关内容可以在wikipedia.org/wiki/Etiquette_in_technology找到。此外,Eric S. Raymond 还发布了一篇有趣的文章,名为如何聪明地提问,你可以在www.catb.org/~esr/faqs/smart-questions.html阅读。

获取任何新 Allwinner 硬件的支持

Allwinner 的 SoC 广泛应用,虽然有些设备有很好的文档支持,比如 Cubieboard,但也有一些设备可能尚未被支持。无论你是发现了一款新设备,还是基于众多开发板之一开发新设备,这款新设备可能尚未被支持。别担心,因为基于 Allwinner 的设备彼此之间非常相似,通过本书获得的所有知识仍然非常有用。但相关硬件可能尚未得到内核、社区或其他方面的支持。linux-sunxi 社区在他们的 wiki 上开发了一个新设备如何做指南,你可以用它来自己添加支持!凭借本书中学到的知识,并参考网站linux-sunxi.org/New_Device_howto,这应该不是问题。

总结

本附录向你介绍了可以从志愿者那里获得额外帮助的主要社区。下一个附录将概述本书中使用的各种基本 Linux 命令。

附录 B. 基本 Linux 命令备忘单

基于 Linux 的系统包含许多命令。每个已安装的应用程序实际上都是一个命令。本附录将概述理论上在每个基本 Linux 安装中都应提供的最基本的命令。这些命令大多数都会在本书中使用,其中一些被视为最基本的命令。此附录绝非权威参考,但它应该能帮助你顺利开始。

请求手册

Linux 有一个有趣的命令叫做 man。它特别之处在于,如果安装了该命令,它会打开关于任何命令的手册页面。通过请求 man 的手册页面来试试它,示例如下:

packt@PacktPublishing:~$ man man

运行 man 命令并带上 man 参数将打开 man 的手册页面。你可以通过 q 键退出 man,通过箭头键进行导航。h 键会打开一个帮助屏幕,里面解释了更多的按键功能。

如果没有安装 man 或手册页面,可以使用互联网代替。有许多网站提供常见的手册页面。网站 www.die.net 非常流行,可以用来查询各种手册页面。

需要注意的是,手册页面有多个部分,共有九个部分。man 手册页面将简要解释每个部分。第一部分与命令相关,这些页面是默认查询的。

最后,许多命令通常有一个简短的帮助屏幕,可以通过在命令后添加 -h--help 来激活。

列出目录

ls 命令代表列出,是用来列出目录内容的命令。没有参数时,它会列出当前活动目录的内容;如果提供了参数,它将尝试列出指定的文件或目录,示例如下:

packt@PacktPublishing:~$ ls /home/
packt

在目录间切换

要切换到不同的目录,可以使用 cd 命令。没有参数时,cd 会始终切换到当前用户的主目录;否则,使用通过第一个参数提供的目录,示例如下:

packt@PacktPublishing:~$ cd /home
packt@PacktPublishing:/home$

获取当前工作目录

当前活动目录或当前工作目录可以通过 pwd 命令打印出来。当你想知道自己在当前文件系统中的位置时,这个命令非常有用,示例如下:

packt@PacktPublishing:~$ pwd
/home/packt

获取当前用户

查找当前登录的用户可能很有用,尤其是在多个用户之间切换时。whoami 命令会打印当前活动的登录用户,示例如下:

packt@PacktPublishing:~$ whoami
packt

以 root 用户身份运行命令

在系统管理或设置过程中,常常需要以 root 用户身份执行某些命令。当sudo命令正确设置时,可以让某些用户以 root 身份执行特定的命令。whowhat查询通过/etc/sudoers中的sudoers文件进行控制,并应使用visudo命令进行编辑。sudo命令作为前缀添加到需要以 root 身份执行的命令,如下所示:

packt@PacktPublishing:~$ sudo whoami
[sudo] password for packt:
root

需要注意的是,虽然sudo常用于以 root 身份执行命令,它也可以让任何用户以任何身份执行任何命令。

不退出登录的情况下切换当前用户

要真正切换到另一个用户,就像用该用户登录一样,可以使用su命令。通过在su后面加上不同的用户名,可以切换到该用户的身份。与需要当前用户密码的sudo不同,这里需要的是请求访问的用户的密码,以下命令演示了这一点:

packt@PacktPublishing:~$ su root
Password:

要退出一个 shell 或其他用户,使用以下exit命令。该命令不需要任何参数。或者,几乎所有的 shell 都可以使用Ctrl + d来退出。

packt@PacktPublishing:~$ exit

创建文件或更改其日期

要创建一个新的空文件,可以使用touch命令。此外,要修改已存在文件的访问和修改日期,可以将其更改为新的日期和时间,如下所示:

packt@PacktPublishing:~$ touch /tmp/testfile

创建目录

要创建一个新的空目录,可以使用以下mkdir命令:

packt@PacktPublishing:~$ mkdir /tmp/testdir

删除文件

要删除文件,可以使用rm命令。rm命令会删除作为参数传递的文件。默认情况下,rm会拒绝删除目录;它只对文件有效。

经常传递给rm的两个选项是-r-f。首先,关于-f选项需要注意,它表示强制;虽然rm命令应该小心使用,但-f选项更需要谨慎考虑。-f选项会强制删除rm能够删除的任何东西,忽略任何权限设置。

-r选项也需要小心使用,因为它表示递归删除。具有讽刺意味的是,-r选项接受目录作为参数,因此它可以递归删除传入位置下的每个文件和目录。递归删除文件似乎没有什么意义。以下rm命令展示了删除文件的例子:

packt@PacktPublishing:~$ rm /tmp/testfile

删除目录

删除目录通过rmdir命令完成;不过它仅能对空目录进行操作,如以下命令所示:

packt@PacktPublishing:~$ rmdir /tmp/testdir

复制文件和目录

要复制文件,可以使用cp命令。复制文件时,需要按顺序将源文件和目标文件作为参数传递给cp。可以选择使用目录代替文件以复制目录。虽然copy命令有很多选项,手册页详细解释了这些选项,但在处理目录时,-r选项可能很重要,因为它告诉copy递归复制目录及其下的所有内容。以下命令展示了复制命令的使用:

packt@PacktPublishing:~$ cp /tmp/testfile /tmp/testdir/copy_of_testfile

移动文件和目录

要移动文件,可以使用mv命令。按照源文件和目标文件的顺序将它们作为参数传递给mv。可选地,可以为源和目标提供一个目录或仅指定目标。

重命名文件实际上只是将文件从一个名称移动到另一个名称。以下命令用于移动文件:

packt@PacktPublishing:~$ mv /tmp/testfile /tmp/testdir/moved_testfile

更改文件和目录访问权限

要授予或限制对某些文件和目录的访问权限,可以使用chmod命令。此命令代表更改模式,至少需要两个参数:需要应用的模式和需要应用该模式的文件或目录。

管理权限可能会相当复杂,尽管手册确实很有帮助。基础知识如下。在 Linux 下,有三个标准访问级别:用户、组和其他。还有一个第四个虚拟访问级别,涵盖前三个,全部。让我们详细看看每一个:

  • 用户:此访问级别涉及拥有文件或目录的用户;通常指创建文件或目录的用户

  • :此访问级别授予所有该组成员的用户访问此级别的权限

  • 其他人:此访问级别授予其他所有人访问权限

  • 全部:这是第四个虚拟访问级别,涵盖了前面三个级别

这四个访问级别通常用它们的首字母缩写ugoa表示。在访问级别旁边,有访问权限,这里我们将看到三种常见的访问权限。技术上讲,有四个,但稍后再详细介绍!两个主要的访问权限是对文件或目录的读取和写入访问权限,其缩写分别为rw。第三个访问权限是执行权限,其缩写为x,它允许用户、组或其他人在文件上执行。因此,例如,chmod本身需要设置任何人都能够执行该文件的执行权限。第四个访问权限再次是x,但这次是应用于目录。由于目录无法执行,因此此访问权限在这里有着不同的含义,因此有四个访问权限。对于目录,它允许用户、组或其他人实际上进入目录并读取其中的文件列表。

构建模式的方法如下。首先,使用简写字母来指定用户、组或其他用户类型,后面跟上+来授予或撤销权限,紧接着是权限内容。如果多个用户、组或其他指定符号之间用逗号分隔,也可以组合使用。参考以下示例以查看如何构建模式:

packt@PacktPublishing:~$ chmod g+r-w,o+r-w-x /tmp/testfile

很多时候,访问权限是通过其数值而非字母来应用的。这主要源于历史上实际使用模式位的做法。有关数值的详细信息,您可以参考手册页。

更改文件和目录的所有权

要更改文件或目录的所有者,可以使用chown命令,它代表更改所有者。为此,需要两个参数:新所有者和需要更改所有权的文件或目录,如下所示:

packt@PacktPublishing:~$ chown packt /tmp/testdir

要更改文件的组成员资格,可以使用与chown类似的命令chgroup,即更改组(change group),其功能与chown相同。

更改密码

要更改密码,可以使用passwd命令。在没有参数的情况下执行时,当前用户的密码可以通过提供旧密码和新密码来更改。根用户可以通过将目标用户名作为第一个参数传递给passwd来更改任何用户的密码,如下所示:

packt@PacktPublishing:~$ passwd
Changing password for packt.
(current) UNIX password:
Enter new UNIX password:
Retype new UNIX password:

显示文本文件的内容

有许多工具可以输出文件内容;例如lessmorecat。它们的工作方式类似,传递一个文件名作为参数,它们会开始显示文件内容。lessmore都允许在文件中搜索或滚动,lessmore更先进。cat命令,代表连接(concatenate),会直接输出文件中找到的内容,无论是否是文本,如下所示:

packt@PacktPublishing:~$ cat /tmp/testfile

cat的一个常见操作是将文件的输出内容重定向到其他地方,无论是一个新文件,这时其功能类似于复制文件,还是追加到另一个文件。

有一些程序的功能与cat非常相似,但它们操作的是压缩文件,并在运行时进行解压缩。这些命令包括zcat,用于gzip压缩文件,或者xzcat,用于xz压缩文件。其有用之处在于,当重定向输出时,文件可以被解压,且输出可以被写入到其他地方。第三章,安装操作系统,利用这一点,通过将压缩的二进制文件直接重定向到闪存磁盘,如下所示:

packt@PacktPublishing:~$ xzcat /tmp/archive.xz > /dev/sdb

修改磁盘分区

fdisk 命令,代表固定磁盘,是一个可以在硬盘或闪存磁盘上创建和修改分区的命令。它需要提供磁盘设备节点作为参数。虽然它相当依赖菜单驱动,但fdisk有许多命令。最重要的命令简要总结如下:

  • m:此命令显示帮助菜单

  • p:此命令打印当前的分区表

  • o:此命令清除整个分区表并创建一个新的空分区表

  • n:此命令通过回答fdisk提出的一些问题来创建一个新分区

  • d:此命令删除一个分区

  • w:此命令将创建的分区表写入磁盘并退出

在操作分区时,请始终小心谨慎。

注意

fdisk命令不会实际将更改写入磁盘,除非明确要求。如果出现错误,可以使用Ctrl + c键退出fdisk而不将更改写入磁盘。

格式化分区

要格式化一个分区,可以使用各种mkfs命令。这取决于是否安装了支持的工具。当创建一个ext4分区时,使用mkfs.ext4。同样,要创建fatvfat分区时,使用mkfs.vfat。每种文件系统分区工具有不同的选项和参数,因此应查看这些命令的手册页以获取详细信息。一般来说,使用默认设置时,传递设备特定的分区节点,如第二硬盘或闪存磁盘上的第一个分区/dev/sdb1,作为参数传递给mkfs命令。创建文件系统是一个破坏性的操作,请小心使用!

在下面的示例中,ext4文件系统被创建在一个之前已经分区的 USB 闪存盘上。注意,这里使用了sudo来获得直接写入闪存驱动器的权限。

packt@PacktPublishing:~$ sudo mkfs.ext4 /dev/sdb1

mkfs的一个特殊变种是mkswap,它创建一个专门用于交换空间的文件系统。

挂载分区

将存储设备连接到系统的过程称为挂载。虽然许多图形桌面环境似乎自动工作,但在后台,它们仍然会挂载和卸载磁盘与分区。执行这项操作的mount命令需要两个参数:设备节点和挂载位置。

如果两个参数中的任何一个已经在fstab文件(位于/etc/fstab)中定义,则可以省略其中一个参数。fstab文件由mount解析,以查看需要挂载的内容、挂载位置以及挂载方式。mount命令的使用方法如下:

packt@PacktPublishing:~$ mount /dev/sdb1 /tmp/testdir

卸载分区

要从正在运行的系统中删除一个分区,可以使用umount命令,它代表卸载n字母似乎被认为是多余的,因此该术语已经缩写为umount。非常重要的一点是,umount在卸载分区时,不要求任何文件或目录被访问或使用。可以使用设备节点或挂载点来卸载分区,如下所示:

packt@PacktPublishing:~$ umount /dev/sdb1

写入数据

本节中描述的程序使用了一个稍微不寻常的名称——dd。目前尚不清楚dd代表什么,但它的功能是复制数据。dd有许多可能的参数,但本书中使用的最重要的参数将在这里介绍。if参数指定输入文件,从中读取数据。of参数是输出文件参数,数据将写入该文件。通过这两个参数,已经可以从源文件复制数据到目标文件。使得dd如此多功能的是其众多其他参数。seek参数允许你更改开始写入的位置。skip参数允许你更改读取数据的起始位置。bs参数,代表块大小(block-size),决定了事务中数据块的大小,并与count参数结合使用,确定要复制的数据量。由于dd允许你非常精确地控制复制操作,它常被用于写入完整镜像、在特定位置写入引导程序等等,如下所示的命令。有关更多信息,请参阅手册页面。

packt@PacktPublishing:~$ dd if=inputfile of=outputfile seek=8 bs=1024

切换到一个特殊的根目录

通常,根目录是主要的系统目录,一切都从这里分支出来。有时,我们希望限制对系统的某些部分的访问,或者临时将某个目录视为根目录。chroot命令,表示更改根目录,确保所提供的目录被视为新的根目录,直到退出为止。作为第二个参数,可以告诉chroot从这个受限根目录中运行什么命令。在以下示例中,根目录被更改为/tmp/testdir,并且要执行的命令bash将位于/tmp/testdir/bin/bash,如下所示:

packt@PacktPublishing:~$ chroot /tmp/testdir /bin/bash

强制系统将所有内容写入磁盘

现代系统将所有内容缓存在内存中,并偶尔将这些内容写入磁盘。这样做的明显原因是磁盘很慢,而内存速度较快。这确实有一个不好的副作用,就是有时我们期望写入磁盘的数据实际上并未写入。sync命令将把所有尚未写入磁盘的数据同步到磁盘,如下所示:

packt@PacktPublishing:~$ sync

添加新用户

要将新用户添加到系统中,可以使用useradd命令。尽管可以提供许多选项和参数,如在第四章《手动安装替代操作系统》中所见,手册页面很好地解释了所有选项。然而,仅仅应用一个新的用户名就足以创建一个基本用户,如下所示的命令所示。请注意,新用户还没有密码,需要通过前面提到的passwd命令创建一个密码。

packt@PacktPublishing:~$ useradd superpackt

其他命令

本章包含了一份最基本命令的简短列表。互联网上有很多其他命令和更多的指南,详细讲解了许多命令。网站www.reallylinux.com/有一个名为Essential Commands(基本命令)的栏目,简要介绍了这些命令及更多内容,但任何涵盖基本 Linux 命令的网站都可以用来深入了解命令。

总结

本附录介绍了最基础的 Linux 命令,以及本书中使用的命令。下一个附录将概述 FEX 配置文件。

附录 C. FEX 配置文件

许多系统都有自我配置的方法,无论是软件还是硬件。在这一点上,以 Allwinner 为基础的硬件也不例外;一些组件确实需要配置,例如 GPIO 引脚。芯片无法自我配置;也就是说,它不能解析配置文件并进行自我配置。芯片的实际配置是由各种驱动程序完成的。此过程在接下来的章节中进行说明。

初始启动

芯片以硬件方式启动,某些组件预先编程以在特定引脚上激活。由于这一点,芯片可以从各种启动介质启动,如第三章中所述,安装操作系统,并加载引导加载程序。引导加载程序也预配置为特定的硬件设置。因此,如前所述,每个板子都有自己的引导加载程序。

除了启动某些组件外,引导加载程序还有以下两个重要任务:

  • 将内核加载到内存并随后执行

  • 将配置文件加载到内存中,以供内核使用

然而,引导加载程序本身并不解析配置文件。

提示

需要提到的是,当使用主线内核时,原理是相同的:引导加载程序仍然加载一个名为设备树二进制的配置文件,内核使用该文件进行配置。

FEX 配置概念本身很有趣,其中一个文件的更改配置了整个设备。如前所述,FEX 文件由引导加载程序加载到内存中,并且引导加载程序仅检查一个特定位置。虽然 u-boot 更灵活,可以配置为允许从任何位置或任何文件名读取配置文件,但预编程在板载 NAND 闪存中的引导加载程序只会检查设备上的第一个分区,而且该分区必须是 FAT 格式。因此,这是一种常见约定,我们将在本章剩余部分遵循此约定。此外,该文件必须使用特定名称script.bin,并且其备份文件为script0.bin。当启动支持板载nand闪存的内核时,该文件将存储在设备节点/dev/nanda中。否则,将使用常规设备节点,最常见的是 SD 卡,存储在/dev/mmcblk0p1

编译和反编译 FEX 文件

script.bin文件顾名思义是一个二进制文件。然而,不能直接修改该文件。linux-sunxi 社区创建了一组工具,可以将该二进制文件转换为文本文件,反之亦然。它们可以在其 GitHub 仓库中找到:github.com/linux-sunxi/sunxi-tools

克隆此仓库后,运行 make fex2bin 命令来构建 fexc,即 fex 反编译工具。最好在具有舒适文本编辑器的系统上编译并运行此工具。

运行 fexc 来反编译二进制文件,命令如下:

[packt@packt:~]$ fexc -I bin -O fex script.bin script.fex

有两个符号链接作为 fexc 的简写,即 fex2binbin2fex。使用这些链接可以省去 -I-O 参数。

理解 FEX 文件格式

使用任何文本编辑器打开,FEX 文件会显示为分为多个部分,每个部分前面都有一个用方括号 [] 括起来的头部。在以下示例中,UART 0 组件的解释如下:

[uart_para0]
uart_used = 1
uart_port = 0
uart_tx = port:PB22<2><1><default><default>
uart_rx = port:PB23<2><1><default><default>

在这里,名为 uart_para0 的组件是第一个串口或 UART,包含四个字段,串口驱动程序将读取这些字段。每个字段以键值对的形式设置,键在等号左侧,值在等号右侧。在此例中,uart_used 键的值设置为数字 1,表示该定义应被解析并激活。

接下来是 uart_port 键,其值设为数字 0,表示该配置与 UART 0(第一个 UART 端口)相关。某些设置非常简单,采用键值对的形式,即左侧为键,右侧为字符串或数字。然而,有一对键值需要特别注意,那就是引脚配置,其中值为端口定义。每个组件可能需要特定的引脚才能正常工作。

一个基本的 UART 需要两个引脚:一个发送引脚和一个接收引脚。SoC(系统级芯片)可以提供多个 UART 和多个引脚。在上述示例中,定义了两个引脚,发送引脚 uart_tx 和接收引脚 uart_rx。SoC 上的引脚通常是分组的,通常是按相关功能来分组的。

对于 A10 来说,它有九个组,称为端口。每个端口可以包含不同数量的引脚。例如,B 端口有 24 个引脚。该组的最后两个引脚分别是 UART 发送引脚和 UART 接收引脚。引脚的编号从 0 开始,因此不难理解,在之前的示例中,PB22PB23 分别是 B 端口的第 22 引脚和第 23 引脚。

如前所述,每个引脚有多个功能,或者可以说,许多功能被复用到一个引脚上。这些复用(mux)被枚举,其中 MUX 0 总是将引脚配置为 GPIO 输入,MUX 1 总是将引脚配置为 GPIO 输出。根据端口和引脚的不同,MUX 2 及以上可能有不同的含义——在 PB22PB23 的例子中,MUX 2 是 UART 引脚。因此,第一个被尖括号 <> 括起来的参数被定义为 MUX 2。

引脚配置

第八章,闪烁的灯光与感知世界,讨论了上拉电阻和下拉电阻的作用。基于 Allwinner 的 SoC 实际上在引脚上内部附加了上拉或下拉电阻。在这种情况下,第二个角括号包围的参数<1>启用内部上拉,<0>禁用上拉/下拉功能,<2>启用下拉功能。然而,下拉功能仅在端口配置为输入时有效;SoC 不支持输出端口的下拉功能。另一个有效选项是使用<default>关键字,告诉驱动程序使用安全的默认值。

第三个角括号包围的参数定义了引脚应该输出的电流强度。有效值有四个:0123,其中0对应 10 毫安,1对应 20 毫安,2对应 30 毫安,3对应 40 毫安。可以使用默认值让驱动程序选择一个安全的默认值。

第四个位置定义了引脚的初始输出电平,可以是低电平<0>或高电平<1>。自然,这仅在将引脚配置为输出时有效。此处的默认值意味着驱动程序使用一个安全的默认值。

提示

虽然在这里讨论和解释了端口 B:引脚 22 和 23,但其余的引脚及其多路复用设置可以在 linux-sunxi 社区的 wiki 上找到,linux-sunxi.org/PIO

深入阅读

FEX 文件包含许多其他可以设置的组件,从配置使用哪些引脚来连接 SD 卡读卡器,到为 LCD 使用哪种颜色格式。所有已发现的选项也已在 linux-sunxi wiki 页面上进行了文档化,linux-sunxi.org/Fex_Guide。然而,由于每个驱动程序都是为读取键值对而编写的,因此根据驱动程序和内核整体的进展,事情很容易并且经常发生变化。如有疑问,始终可以检查内核源代码。

安装配置好的 FEX 文件

将 FEX 文件重新编译成 bin 文件几乎是一样的。

[packt@packt:~]$ fexc -I fex -O bin script.fex script.bin

根据所使用的启动介质,script.bin必须被复制回去,以便设备能够使用这些新更改的值。这可以是板载 NAND 闪存上的/dev/nanda分区,或者是 microSD 卡上第一个 FAT 格式化的分区。

在将script.bin放置到正确位置后,需要重启系统以使其读取这些更改。

总结

本附录简要介绍了 FEX 文件并展示了如何修改它。下一个附录将尝试覆盖最基本的故障排除内容,解决最常见的陷阱。

附录 D. 解决常见问题

在进行新尝试时,很多事情可能会出错。本附录简要涵盖了其中一些常见的陷阱。尽管预见所有可能出错的情况几乎不可能,但本附录的目的是提供最常见问题的概览。

一些常见的问题,往往比人们想象的更容易发生,比如输入命令时的阅读和输入。打字错误很容易发生,或者有些东西被忽视并读错。这些情况是不可避免的,都是在处理令人兴奋和新奇的事物时的一部分。所以,第一个建议是始终检查你的输入。尽管本书中所有页面都经过多人的审阅,但仍然有可能出现错误,如果即使完全按照书中的步骤操作,问题依然存在,可以查阅勘误表。

稳定性问题

很多时候,用户会在这些设备的众多社区中抱怨遇到奇怪的崩溃、系统不稳定或随机重启的情况。虽然设备本身确实有可能出现损坏,但往往是电源不稳定或者功率不足导致的。

测试电源的强度或稳定性没有额外设备是非常困难的。如果电源无法提供足够的电流,通常会导致电压下降。这个可以用标准万用表来测量。

如果电压低于 4.8 伏特,可能会出问题。一个非常嘈杂的电源更难以测试,通常需要示波器。最好是选择一个知名且优质的电源。例如,手机充电器有不同的功率。有些便宜的手机电源最大输出电流只有 500 毫安,而当设备处于高负载状态时,这个电流是不足够的。显然,配备高端智能手机的充电器能提供高达 2000 毫安的电流,但即便如此,与硬盘或固态硬盘一起使用时,电力需求仍可能过高。因此,建议尽可能断开其他设备。不要连接 USB 设备和 SATA 存储,因为它们的电源来自主板。不要连接可能直接从主板获得电力的其他组件。理想情况下,应该只连接电源和串口,并使用万用表或其他电源测量设备,检查电压是否不会降得过低。

如果在进行以上检查后,电路板仍然不稳定,而其他使用相同电路板、相同引导加载程序,并且理想情况下使用相同根文件系统的用户没有问题,那么电路板可能是有缺陷的。最好还是联系购买商请求更换。但请务必先确认其他所有问题,因为更换电路板对所有相关方来说都不是什么愉快的事情。

从 SD 卡启动时的启动失败

没有什么比花费数小时编译和准备 SD 卡以启动板子,但最终却无法启动更令人沮丧了。在此阶段,拥有串行控制台以查看调试输出至关重要,但有时由于 SD 卡或二进制文件错误,根本不会生成任何输出。进行引导加载程序实验时,最重要的一点是始终备有一个已知的工作副本。这是为了确保对 u-boot 的修改不是问题的根源。

来自 linux-sunxi 的 nightlies 是一个替代方案,因为这些应该始终能够工作。查看dl.linux-sunxi.org/nightly/u-boot-sunxi/u-boot-sunxi/u-boot-sunxi-latest/以获取可用引导加载程序的列表。

有时,microSD 卡可能根本不兼容,甚至可能损坏。应该使用不同的 microSD 卡来确保问题不在卡本身上。如果卡上的前几个字节损坏到无法修复的程度并不罕见。对于简单的存储介质使用来说,这通常不是问题。但由于引导加载程序是从 SD 卡的开始处进行写入和读取的,因此这可能导致系统无法启动。

现在,使用 nightlies 或自编译的引导加载程序时,用户往往容易选择错误的文件。对此不大惊讶,因为互联网上有许多文件和各种指南,有时它们会过时并不再准确。一个常见的例子是,许多较旧的指南建议使用各种seek偏移量写入u-boot.binsunxi-spl.bin。使用正确的文件和参数时,这仍然有效,而使用错误的参数或设置则会导致失败。推荐的方式,如第四章《手动安装替代操作系统》中所述,是使用u-boot-sunxi-with-spl.bin,使用blocksize (bs)1024seek8。例如,将此应用于sdb时,应使用以下命令:

packt@packt:~# dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8

这是因为前面提到的文件都被合并成一个大文件,因此出错的机会较少。最后,在写入引导加载程序之后,目的是格式化第一个分区以存储内核。分区号被省略,格式化的不是/dev/sdb1,而是/dev/sdb。这样做是完全合法的;在存储介质上有分区是可选的,尽管通常是有用的。然而,格式化整个磁盘,而不是仅格式化分区,会导致一个副作用,即先前写入的引导加载程序被覆盖并丢失。当板子启动时,引导加载程序已不存在,因此不会生成任何输出。

无法通过连接的显示器输出显示

很多时候,当通过 HDMI 或 VGA 连接显示器时,没有显示输出。可以理解,这非常令人沮丧。更糟的是,可能在预装的 Android 系统下工作正常,但现在从 SD 卡启动 Linux 时,什么都没有发生。导致显示器没有图像的原因当然有很多,比如电缆可能没有正确连接,显示器可能设置为错误的输入等。尽管这些问题看起来非常明显且常见,但它们确实会发生,而且有一些情况并不容易检查。

Allwinner 的 SoC 在显示输出方面实际上并不智能。它需要被告知连接了什么设备,以及使用什么作为输出。为此,显示器和电视(实际上只是一些高级显示器)在电缆中有一个称为显示数据通道DDC)的通信通道。DDC 的目的是让显示器告诉任何询问者它的功能和分辨率。而这就是问题所在。

对于 VGA,曾经有一个共识,插头有两种颜色:如果端口不关心 DDC 并忽略它,则为黑色;如果端口读取 DDC 信息并能够作出相应响应,则为蓝色。不幸的是,许多开发板的创作者只是使用蓝色连接器,认为那就是标准的 VGA 连接器,但却没有实现 DDC。没有 DDC,板子根本不知道连接了什么设备,也不知道如何向其发送信号。而且,由于对蓝色和黑色 VGA 插头的误用,现在已经没有简单的规则可以遵循,比如说如果你的连接器是黑色的,你必须手动设置 VGA 端口。

对于 HDMI,问题非常相似。Allwinner 的 HDMI 显示控制器在大多数情况下是为电视而设计的。因此,在连接 HDMI 显示器或使用 DVI 到 HDMI 适配器时,会有一些小问题。例如,Android 在连接到 DVI 显示器时,图像可能会呈现紫色,这个问题是由驱动程序与显示控制器的设计结合引起的;通常运行 linux-sunxi 内核可以解决这个问题。

第一个可以检查和更改的文件是uEnv.txt,它位于引导加载器分区中,可能是在使用 USB 适配器时的/dev/sdb1。在这里,应该有一个类似于disp.screen0_output_mode=EDID:1280x720p60这样的设置,用于底部的extraargs参数。

这意味着,对于输出,首先尝试通过 EDID 探测显示器,EDID 是 DDC 的扩展形式,如果失败,则回退到以 60Hz 刷新率运行的 1280×720 逐行扫描分辨率。一些显示器可能无法正确宣布其 EDID 信息,因此首先要尝试的是从output_mode中移除 EDID 位,从而强制输出为1280x720p60。此外,可能在 EDID 失败后,提供的固定分辨率是显示器无法接受的。有关有效分辨率和设置,请检查下一个章节中表格的第二列。需要注意的是,当我们使用 VGA 显示器时,必须移除 EDID,因为在这种情况下,驱动程序将忽略整个output_mode。此外,需要将期望的视频输出类型附加到extraargs中,VGA 为disp.screen0_output_type=4,HDMI 为disp.screen0_output_type=3

通过uEnv.txt文件覆盖内核参数可能不足以使系统正常工作,可能会导致某些功能无法运行。相同的设置也应该通过 FEX 文件提供。理论上,驱动程序应该检查内核命令行和 FEX 文件,但一个可能会覆盖另一个,因此,在遇到问题时,应考虑这两种可能性。

要强制设置视频输出模式,需要修改 FEX 文件。控制显示控制器的部分在 FEX 文件中是[disp_init]部分。有关 linux-sunxi wiki 上的所有显示控制器参数,linux-sunxi.org/Fex_Guide,需要查看一些内容。首次设置时,disp_mode最好设置为0,表示screen0上的一个帧缓冲区。根据显示器的连接方式,screen0_output_type应设置为3(HDMI 显示)或4(VGA 显示)。最好通过将screen1_output_type设置为0来禁用screen1_output_type对象。对于screen0_output_mode,应使用下表,任何应用于screen1_output_mode的设置将被忽略:

output_mode 用于电视/HDMI 输出 用于 VGA 输出
0 480i 1680 * 1050
1 576i 1440 * 900
2 480p 1360 * 768
3 576p 1280 * 1024
4 720p50 1024 * 768
5 720p60 800 * 600
6 1080i50 640 * 480
7 1080i60
8 1080p24
9 1080p50
10 1080p60 1920 * 1080
11 pal 1280 * 720
14 ntsc

其他设置对于显示输出应该没有太大影响。现在,显示器应该能够在启动时输出数据,例如 Fedora 安装镜像,这在第三章中有使用,安装操作系统

概述

本附录介绍了三种最常见的问题,这些问题通常出现在开始使用各种开发板时。本附录所涵盖的内容并不包括所有可能的情况,但应该能为你提供一种解决这些早期问题的有效策略。

posted @ 2025-07-05 19:49  绝不原创的飞龙  阅读(4)  评论(0)    收藏  举报