树莓派高级教程(四)
协议:CC BY-NC-SA 4.0
十六、SPI 总线
串行外设接口总线,被亲切地称为 spy ,是由摩托罗拉命名的同步串行接口。18SPI 协议以全双工模式工作,允许它同时发送和接收数据。一般来说,SPI 比 I 2 C 协议有速度优势,但是需要更多的连接。
SPI 基础知识
SPI 总线上的器件以主机/从机方式通信。多个从机共存于一条给定的 SPI 总线上,每个从机由一个从机选择信号(也称为片选)选择通信。图 16-1 显示 Raspberry Pi 作为主机与一个从机通信。除了将使用不同的从机选择信号之外,将如图所示连接额外的从机。
图 16-1
SPI 接口
数据通过 MOSI 线从主机传输到从机(主机输出,从机输入)。当主机发送每个位时,从机同时在 MISO 线上发送数据(主机输入,从机输出)。位从主机移入从机,位从从机移入主机。两次传输都在系统时钟的节拍下进行(CLK)。
许多 SPI 器件仅支持 8 位传输,而其他器件则更加灵活。SPI 总线是事实上的标准,这意味着数据传输宽度和 SPI 模式没有标准。18SPI 控制器也可以配置为首先传输最高有效位或最低有效位。所有这些灵活性都会导致混乱。
SPI 模式
SPI 以四种可能的时钟信号模式之一工作,基于两个参数:
|参数
|
描述
| | --- | --- | | 断续器 | 时钟极性 | | CPHA | 时钟相位 |
每个参数有两种可能性,因此 SPI 有四种可能的工作模式。表 16-1 列出了所有四种可用模式。注意,给定的模式通常用一对数字来表示,如 1,0 或简单地称为模式 2 (对于同一模式,如表中所示)。两种引用类型都显示在模式列中。
表 16-1
SPI 模式
|断续器
|
CPHA
|
方式
|
描述
| | --- | --- | --- | --- | | Zero | Zero | 0,0 | Zero | 同相时钟,在上升沿采样 | | Zero | one | 0,1 | one | 同相时钟,在下降沿采样 | | one | Zero | 1,0 | Two | 反相时钟,在上升沿采样 | | one | one | 1,1 | three | 反相时钟,在下降沿采样 | | | 时钟感应 | 描述 | | 非反转 | 信号为空闲低电平,有效高电平 | | 反向的 | 信号为高电平空闲,低电平有效 |
外围设备制造商在开始时没有定义标准的信号惯例。因此,SPI 控制器通常允许配置四种模式中的任何一种,而其余的只允许两种模式。然而,一旦选择了一种模式,同一总线上的所有从机都必须同意。
发信号
时钟极性决定空闲时钟电平,而相位决定数据线是在时钟信号上升还是下降时进行采样。图 16-2 显示了模式 0,0,这可能是 SPI 信号的首选形式。在图 16-2 中,通过激活(从机选择)首先选择从机。一次只能选择一个从机,因为必须有一个从机驱动 MISO 线。选择从机后不久,主机驱动 MOSI 线,从机用第一个数据位同时驱动 MISO 线。这可能是最高位,也可能是最低位,具体取决于控制器的配置。该图首先显示最低有效位。
图 16-2
SPI 信号,模式 0 和 2
在模式 0,0 下,当时钟线从高电平变为低电平时,第一位被读入主机和从机。该时钟跳变位于数据位单元的中间。随着时钟从高电平变为低电平,其余位依次同时输入主机和从机。当主机停用从机选择线时,传输结束。当时钟极性反转时(CPOL = 1,CPHA = 0),图 16-2 所示的时钟信号简单反转。数据在数据单元中同时计时,但在时钟的上升沿计时。
图 16-3 显示了相位设置为 1 (CPHA = 1)的时钟信号。当时钟不反转时(CPOL = 0),数据在上升沿输入。时钟必须比相位为 0 (CPHA = 0)时提前半个时钟周期转换到非理想状态。当 SPI 模式为 1,1 时,数据在时钟的下降沿读入。
图 16-3
SPI 信号模式 1 和 3
虽然这四种不同的模式可能会造成混淆,但必须认识到,数据是在数据位单元内同时采样的。数据位总是在数据单元的中点进行采样。当时钟相位为 0 (CPHA = 0)时,根据 CPOL,数据在时钟的下降沿或上升沿进行采样。当时钟相位为 1 (CPHA = 1)时,根据 CPOL,数据在时钟的上升沿或下降沿进行采样。
从属选择
与 I 2 C 不同,在 I2C 中,从机通过发送地址寻址,SPI 总线为每个从机使用一条专用选择线。Raspberry Pi 将表 16-2 中列出的 GPIO 引脚用作从机选择线(也称为芯片使能线)。
表 16-2
Raspberry Pi 内置芯片使能引脚
|通用输入输出接口
|
芯片使能
|
第一亲代
|
| --- | --- | --- |
| eight | | P1-24 |
| seven |
| P1-26 |
Raspbian Linux 内核驱动程序只支持使用这两条芯片使能线。但是,驱动程序的设计使得您不必使用它们,或者只使用这些。例如,在用户软件控制下,可以使用不同的 GPIO 引脚作为选择。应用只负责在数据 I/O 之前激活从机选择 GPIO 线,并在之后将其停用。当驱动器控制从属选择时,这是自动完成的。
驱动程序支持
要启用 SPI 驱动程序,请编辑/boot/config.txt文件,取消对该行的注释,如下所示:
dtparam=spi=on
然后重新启动:
# sync
# /sbin/shutdown -r now
重新启动后,使用lsmod命令,您应该看到驱动程序spi_bcm2835列在其他驱动程序中。
$ lsmod
Module Size Used by
fuse 106496 3
rfcomm 49152 6
...
spi_bcm2835 16384 0
...
一旦出现内核模块支持,设备驱动程序节点应该会出现:
$ ls /dev/spi*
/dev/spidev0.0 /dev/spidev0.1
$
这两个设备节点是根据应该激活哪个从机选择来命名的,如表 16-3 所示。
表 16-3
SPI 器件节点
|路径名
|
公共汽车
|
设备
|
通用输入输出接口
|
|
| --- | --- | --- | --- | --- |
| /dev/spidev0.0 | Zero | Zero | eight | |
| /dev/spidev0.1 | Zero | one | seven |
|
如果您用 C 宏SPI_NO_CS打开这些设备节点中的任何一个,所选择的节点没有任何区别。宏SPI_NO_CS指示从机选择将由应用而不是驱动程序执行,如果使用任何选择的话。当只连接一个从设备时,是否可以使用永久硬连线选择。
SPI API
像 Linux 下的 I 2 C 一样,SPI 的裸机 API 包括对ioctl(2)的调用,以配置接口和同步读/写。通常的read(2)和write(2)系统调用可以用于单向传输。
头文件
SPI 编程所需的头文件如下:
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
spidev.h include文件定义了几个宏和struct spi_ioc_transfer。表 16-4 列出了声明的主要宏。宏SPI_CPOL和SPI_CPHA用于值SPI_MODE_x的定义。如果您愿意,可以使用SPI_CPOL和SPI_CPHA来代替模式宏。
表 16-4
SPI 宏定义
|巨
|
支持
|
描述
| | --- | --- | --- | | SPI_CPOL | 是 | 时钟极性反转(CPOL = 1) | | SPI_CPHA | 是 | 时钟相位为 1 (CPHA = 1) | | SPI_MODE_0 | 是 | SPI 模式 0.0(cpol = 0,CPHA = 0) | | SPI_MODE_1 | 是 | SPI 模式 0.1(cpol = 0,CPHA = 1) | | SPI_MODE_2 | 是 | SPI 模式 1.0(cpol = 1,CPHA = 0) | | SPI_MODE_3 | 是 | SPI 模式 1.1(cpol = 1,CPHA = 1) | | SPI _ CS _ 高电平 | 是 | 片选高电平有效 | | SPI_LSB_FIRST | 不 | LSB 首先传输 | | SPI _ 线 | 不 | 使用 3 线数据 I/O 模式 | | SPI_LOOP | 不 | MOSI/MISO 数据线环路 | | SPI_NO_CS | 是 | 不应用芯片选择 | | SPI _ 就绪 | 不 | 启用额外就绪信号 |
与 SPI 器件通信包括以下系统调用:
-
open(2):打开 SPI 设备驱动节点 -
read(2):读取但无传输 -
write(2):写入数据,同时丢弃接收的数据 -
ioctl(2):用于配置和双向输入输出 -
close(2):关闭 SPI 设备驱动节点
在 SPI 通信中,read(2)和write(2)的使用一般不常见。通常,ioctl(2)用于促进同步读/写传输。
开放式设备
为了通过内核驱动程序执行 SPI 通信,您需要使用open(2)打开其中一个设备节点。设备路径名的一般格式是
/dev/spidev<bus>.<device>
以下是打开总线 0、设备 0 的代码片段。
int fd;
fd = open("/dev/spidev0.0",O_RDWR);
if ( fd < 0 ) {
perror("Unable to open SPI driver");
exit(1);
}
因为 SPI 通常涉及读写,所以驱动器通常为读写(O_RDWR)打开。
SPI 宏模式
在执行 SPI 通信之前,需要选择通信模式。表 16-5 列出了可用于配置 SPI 模式的 C 语言宏。
表 16-5
SPI 宏模式
|巨
|
影响
|
评论
| | --- | --- | --- | | SPI_CPOL | CPOL = 1 | 或者使用 SPI_MODE_x | | SPI_CPHA | CPHA = 1 | 或者使用 SPI_MODE_x | | SPI _ CS _ 高电平 | SS 高电平有效 | 与众不同的 | | SPI_NO_CS | 不要断言选择 | 未使用/应用控制 |
这些位值简单地进行“或”运算,以指定所需的选项。使用SPI_CPOL意味着 CPOL = 1。它的不存在意味着 CPOL = 0。类似地,使用SPI_CPHA意味着 CPHA = 1,否则 CPHA = 0。宏SPI_MODE_x使用SPI_CPOL和SPI_CPHA来定义它们,所以不要在你的代码中同时使用它们。模式定义如下所示:
#define SPI_MODE_0 (0|0)
#define SPI_MODE_1 (0|SPI_CPHA)
#define SPI_MODE_2 (SPI_CPOL|0)
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
不支持的选项不会显示,尽管将来可能会支持其中的一个或多个选项。
下面是一个定义SPI_MODE_0的例子:
uint8_t mode = SPI_MODE_0;
int rc;
rc = ioctl(fd,SPI_IOC_WR_MODE,&mode);
if ( rc < 0 ) {
perror("Can't set SPI write mode.");
如果您想了解 SPI 驱动器当前的配置,您可以使用ioctl(2)读取 SPI 模式,如下所示:
uint8_t mode;
int rc;
rc = ioctl(fd,SPI_IOC_RD_MODE,&mode);
if ( rc < 0 ) {
perror("Can't get SPI read mode.");
每字位数
SPI 驱动器需要知道每个 I/O 字要传输多少位。虽然驱动程序可能会默认为 8 位,但最好不要依赖它。请注意,在 LoSSI 模式(低速串行接口)下,Pi 仅支持 8 位或 9 位。这通过以下ioctl(2)调用进行配置:
uint8_t bits = 8;
int rc;
rc = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD,&bits);
if ( rc < 0 ) {
perror ("Can't set bits per SPI word.");
可以用ioctl(2)获取当前配置的值,如下所示:
uint8_t bits;
int rc;
rc = ioctl(fd,SPI_IOC_RD_BITS_PER_WORD,&bits);
if ( rc == −1 ) {
perror("Can't get bits per SPI word.");
当位数不是 8 的偶数倍时,假设这些位是右对齐的。例如,如果字长设置为 4 位,则传输最低有效的 4 位。高阶位被忽略。
同样,当接收数据时,最低有效位包含数据。然而,所有这些在 Pi 上都是理论上的,因为驱动程序只支持字节范围的传输。
时钟频率
要配置数据传输速率,您可以使用ioctl(2)设置时钟速率,如下所示:
uint32_t speed = 500000; /* Hz */
int rc;
rc = ioctl(fd,SPI_IOC_WR_MAX_SPEED_HZ,&speed);
if ( rc < 0 ) {
perror("Can't configure SPI clock rate.");
speed 中提供的时钟速率应该是 2 的倍数(它会自动向下舍入)。可以使用下面的ioctl(2)调用获取当前配置的时钟速率:
uint32_t speed; /* Hz */
int rc;
rc = ioctl(fd,SPI_IOC_RD_MAX_SPEED_HZ,&speed);
if ( rc < 0 ) {
perror("Can't get SPI clock rate.");
数据输入输出
SPI 通信通常会在发送数据的同时接收数据。因此,不能使用read(2)和write(2)系统调用。然而,ioctl(2)调用将同时执行读和写。
ioctl(2)调用的SPI_IOC_MESSAGE(n)形式使用以下结构作为其参数:
struct spi_ioc_transfer {
__u64 tx_buf; /* Ptr to tx buffer */
__u64 rx_buf; /* Ptr to rx buffer */
__u32 len; /* # of bytes */
__u32 speed_hz; /* Clock rate in Hz */
__u16 delay_usecs; /* Delay in microseconds */
__u8 bits_per_word; /* Bits per "word" */
__u8 cs_change; /* Apply chip select */
__u32 pad; /* Reserved */
};
tx_buf和rx_buf结构成员被定义为 64 位无符号整数(__u64)。因此,在对缓冲区指针进行赋值时,必须对其进行强制转换:
uint8_t tx[32], rx[32];
struct spi_ioc_transfer tr;
tr.tx_buf = (unsigned long) tx;
tr.rx_buf = (unsigned long ) rx;
在 Raspberry Pi 上,您将看到简单地将指针指向unsigned long的示例代码。编译器会自动将这些 32 位值提升为 64 位值。这在 Pi 上是安全的,因为指针值的大小是 32 位。
如果您不想接收数据(可能因为它是“无关紧要”的数据),您可以将接收缓冲区清空:
uint8_t tx[32];
struct spi_ioc_transfer tr;
tr.tx_buf = (unsigned long) tx;
tr.rx_buf = 0; /* ignore received data */
请注意,要接收数据,主机必须始终发送数据,以便将数据移出从机外设。如果发送任何字节都可以,可以省略发送缓冲器。然后,驱动器将自动发送零字节,以将从机数据移出。
也允许从您正在接收的缓冲区传输到:
uint8_t io[32];
struct spi_ioc_transfer tr;
tr.tx_buf = (unsigned long) io; /* Transmit buffer */
tr.rx_buf = (unsigned long) io; /* is also recv buffer */
len结构成员表示 I/O 传输的字节数。接收和发送缓冲区(当两者都使用时)应该传输相同数量的字节。
成员speed_hz定义了您希望用于该 I/O 的时钟频率,单位为 Hz。在 I/O 期间,这将覆盖模式设置中配置的任何值。必要时,该值将自动向下舍入到支持的时钟速率。
当值speed_hz为 0 时,使用之前配置的时钟速率(SPI_IOC_WR_MAX_SPEED_HZ)。
当delay_usecs成员不为零时,它指定传输之间延迟的微秒数。它在传输结束时应用,而不是在传输开始时应用。当单个ioctl(2)请求中有多个 I/O 传输时,这允许中间有时间,以便外设可以处理数据。
bits_per_word成员定义了一个“字”单元中有多少位。通常单位是 1 字节(8 位),但也不需要(但注意 Raspbian Linux 驱动程序在 LoSSI 模式下只支持 8 位或 9 位)。
当bits_per_word值为 0 时,使用之前从SPI_IOC_WR_BITS_PER_WORD配置的值。
cs_change成员被视为布尔值。为 0 时,驱动器不执行片选。应用需要通知外设它被选中(通常 GPIO 引脚被拉低)。I/O 完成后,应用必须取消选择从外设。
当cs_change成员为true(非零)时,选择的从机将依赖于打开的设备路径名。总线和从机地址嵌入在设备名称中:
/dev/spidev<bus>.<device>
当cs_change为true时,驱动器在 I/O 之前断言spidev0.0的,断言
spidev0.1的,并在完成后将其去激活。当然,使用这两个节点需要两个不同的
open(2)调用。
SPI_IOC_MESSAGE(n)宏在ioctl(2)调用中用于执行一个或多个 SPI I/O 操作。这个宏不同寻常,因为它需要一个参数 n 。(这与 I2C 的方法有很大不同。)这指定了您想要执行的 I/O 传输次数。为每个所需的传输声明并配置一个spi_ioc_transfer结构数组,如下例所示:
struct spi_ioc_transfer io[3]; /* Define 3 transfers */
int rc;
io[0].tx_buf = ...; /* Configure I/O */
...
io[2].bits_per_word = 8;
rc = ioctl(fd,SPI_IOC_MESSAGE(3),& io[0]);
前面的示例将执行三次 I/O 传输。由于应用从未在这些 I/o 之间执行任何 GPIO 操作,这适用于与一个特定的从设备通信。
以下示例代码将所有概念结合在一起,以演示一个 I/o。spi_ioc_transfer结构被初始化,以便发送 32 个字节,同时接收 32 个字节。
uint8_t tx[32], rx[32];
struct spi_ioc_transfer tr;
int rc;
tr.tx_buf = (unsigned long) tx;
tr.rx_buf = (unsigned long) rx;
tr.len = 32;
tr.delay_usecs = delay;
tr.speed_hz = speed;
tr.bits_per_word = bits;
rc = ioctl(fd,SPI_IOC_MESSAGE(1),&tr);
if ( rc < 1 ) {
perror("Can't send spi message");
这里发生单个 I/O 传输,数据从阵列tx发送,并被阵列rx接收。ioctl(2)调用的返回值返回传输的字节数(本例中为 32)。否则,返回-1以指示发生了错误。
关闭
像所有 Unix I/O 操作一样,当不再需要打开的文件描述符时,设备必须关闭(否则将在进程终止时关闭):
close(fd);
写
如果接收的数据不重要,可以使用write(2)系统调用。但是,请注意,这个调用不可能有延迟。
阅读
read(2)系统调用实际上不适合 SPI,因为主机必须在 MOSI 上传输数据,以便从机在 MISO 线路上发回位。然而,当使用read(2)时,驱动器将自动发送必要的零位以完成读取。(请注意,您的外设将接受零字节,而不会产生意外后果。)就像write(2)呼叫一样,没有延迟是可能的。
SPI 测试
开发 SPI 通信软件时,您可以执行简单的环回测试来测试您的框架。一旦框架通过检查,您就可以将注意力转移到与实际设备的通信上。
虽然 Pi 硬件不支持SPI_LOOP模式位,但您仍然可以通过从 MOSI 输出连接回 MISO 输入引脚的导线(连接 GPIO 10 至 GPIO 9)来实现 SPI 总线的物理环路。
接下来显示的一个简单程序演示了这种类型的环回测试。它会将 4 个字节(0x12、0x23、0x45 和 0x67)写入 SPI 驱动器。因为您已经将 MOSI 引脚连接到 MISO 输入端,所以任何发送的信号都会被接收到。
当程序执行时,它将报告收到的字节数和四个十六进制值:
$ sudo ./spiloop
rc=4 12 23 45 67
$
如果移除 MOSI 与 MISO 之间的导线,并将 MISO 连接到高电平(+3.3 V),则应该能够读取所有接收字节的 0xFF。如果随后将 MISO 接地,则每个字节将接收 0x00。确保使用正确的销以避免损坏(清单 16-1 )。
/********************************************
* spiloop.c − Example loop test
* Connect MOSI (GPIO 10) to MISO (GPIO 9)
********************************************/
0005: #include <stdio.h>
0006: #include <errno.h>
0007: #include <stdlib.h>
0008: #include <stdint.h>
0009: #include <fcntl.h>
0010: #include <unistd.h>
0011: #include <sys/ioctl.h>
0012: #include <linux/types.h>
0013: #include <linux/spi/spidev.h>
0014:
0015: static void
0016: errxit(const char *msg) {
0017: perror(msg);
0018: exit(1);
0019: }
0020:
0021: int
0022: main(int argc, char ** argv) {
0023: static uint8_t tx[] = {0x12, 0x23, 0x45, 0x67};
0024: static uint8_t rx[] = {0xFF, 0xFF, 0xFF, 0xFF};
0025: struct spi_ioc_transfer ioc = {
0026: .tx_buf = (unsigned long) tx,
0027: .rx_buf = (unsigned long) rx,
0028: .len = 4,
0029: .speed_hz = 100000,
0030: .delay_usecs = 10,
0031: .bits_per_word = 8,
0032: .cs_change = 1
0033: };
0034: uint8_t mode = SPI_MODE_0;
0035: int rc, fd=-1;
0036:
0037: fd = open("/dev/spidev0.0",O_RDWR);
0038: if ( fd < 0 )
0039: errxit("Opening SPI device.");
0040:
0041: rc = ioctl(fd,SPI_IOC_WR_MODE,&mode);
0042: if ( rc < 0 )
0043: errxit("ioctl (2) setting SPI mode.");
0044:
0045: rc = ioctl(fd,SPI_IOC_WR_BITS_PER_WORD,&ioc.bits_per_word);
0046: if ( rc < 0 )
0047: errxit("ioctl (2) setting SPI bits perword.");
0048:
0049: rc = ioctl(fd,SPI_IOC_MESSAGE(1),&ioc);
0050: if ( rc < 0 )
0051: errxit("ioctl (2) for SPI I/O");
0052: close(fd);
0053:
0054: printf("rc=%d %02X %02X %02X %02X\n",
0055: rc, rx[0], rx[1], rx[2], rx[3]);
0056: return 0;
0057: }
Listing 16-1The spiloop.c SPI loopback program
摘要
本文介绍了 SPI 总线及其操作,以及 C 编程 API。本章以一个简单的 SPI 环路测试程序结束。运行这个不需要额外的硬件。
该循环测试很好地覆盖了所应用的 API。读取器可以更进一步,通过 SPI 总线访问实际的从机。最后一步是将从机选择添加到整体画面中,以及设备所需的任何命令/响应处理。您现在是 SPI 大师了!
十七、启动
当 Raspberry Pi 第一次通电时,或者已经复位时,启动引导序列。其实是 Pi 的 GPU 造就了 ARM 的 CPU。最初,树莓派的设计方式是,它必须从 SD 卡上的固件启动。GPU 的 RISC 代码由 Raspberry Pi 基金会在文件bootcode.bin中提供。在执行第二阶段引导加载程序之后,可以加载其他操作系统或引导加载程序,比如 U-Boot。
由于公众的兴趣,在这个过程中已经引入了一些变化,允许从 USB 直接引导。本章涵盖了各种配置下的引导过程。
引导 ARM Linux
现代引导过程由以下事件序列组成:
-
通电(或复位)时,ARM CPU 离线,但 GPU 通电。
-
GPU 中的一个小 RISC 内核开始执行 OTP(一次性可编程)ROM 代码(第一阶段引导加载程序)。
-
默认情况下,它从以下优先级列表中确定引导:
-
SD 卡启动
-
USB 设备引导
-
GPIO 引导模式
-
GPIO 引导模式描述如下:
www . raspberrypi . org/documentation/hardware/raspberrypi/boot modes/boot flow . MD
这里描述了几个警告,包括:
-
OTP 设置无法撤消。
-
除非您的固件日期为 2017 年 10 月 20 日或更晚,否则不要尝试使用
program_gpio_bootmode。
与常规 Pi 相比,program_gpio_bootmode可能更适用于计算模块。
根据介质类型(SD 卡、USB 或 GPIO),引导过程继续进行:
-
GPU 初始化 SD 卡/USB/GPIO 硬件。
-
GPU 查看 SD 卡或 USB 介质中的 FAT(文件分配表)分区。搜索继续 FAT 分区,直到找到文件
bootcode.bin。如果修改了 OTP 设置,序列也会改变。通常情况下:-
首先检查 SD 卡,最多需要 5 秒钟才会失败(如果不存在)。
-
然后,当由 OTP 启用时,将尝试 USB 模式引导(这至少需要 3 秒钟来允许驱动器启动和枚举)。
-
-
名为
bootcode.bin的第二阶段引导加载程序固件被加载到本地 128k 缓存中。 -
GPU 控制传递给加载的
bootcode.bin固件,并启用 SDRAM。 -
文件
start.elf由 GPU 从同一个分区加载到 RAM 中,GPU 给予它控制权。 -
检查文件
config.txt中需要处理的配置参数。 -
在
cmdline.txt中找到的信息也由start.elf处理。 -
GPU 允许 ARM CPU 执行程序
start.elf。 -
内核镜像由运行 start.elf 的 GPU 加载到 RAM 中。
-
最后,GPU 启动在 ARM CPU 上执行的内核。
引导文件
当 Raspbian Linux 启动时,包含引导文件的 FAT 分区通常挂载为/boot。表 17-1 列出了适用于引导过程的文件。可以编辑文本文件以影响新的配置。二进制文件也可以被相同的新版本替换。
表 17-1
/引导文件
|文件名
|
目的
|
格式
|
| --- | --- | --- |
| 启动代码,bin | 第二阶段引导加载程序 | 二进制的 |
| 配置文件 | 配置参数 | 文本 |
| 厘米线.txt | 内核的命令行参数 | 文本 |
| 修复它*。 | 在 ARM CPU 和 GPU 之间划分 SDRAM | 二进制的 |
| start .精灵 | ARM CPU 代码即将推出 | 二进制的 |
| 内核. img | 要加载的内核 | 二进制的 |
| | 名称可以用 config.txt 中的kernel=参数覆盖 | |
配置文件
与许多包含 BIOS 系统的 PC 不同,Raspberry Pi 使用的是config.txt文件。该文件是可选的,因此当它丢失时,将应用默认值。当 Raspbian Linux 启动时,这个文件位于/boot/config.txt 中。
该文件中vcgencmd支持的内容可以显示为:
# vcgencmd get_config int
aphy_params_current=819
arm_freq=1400
audio_pwm_mode=514
config_hdmi_boost=5
core_freq=250
desired_osc_freq=0x33e140
desired_osc_freq_boost=0x3c45b0
disable_commandline_tags=2
disable_l2cache=1
display_hdmi_rotate=-1
display_lcd_rotate=-1
dphy_params_current=547
enable_uart=1
force_eeprom_read=1
force_pwm_open=1
framebuffer_ignore_alpha=1
framebuffer_swap=1
gpu_freq=300
hdmi_force_cec_address=65535
init_uart_clock=0x2dc6c00
lcd_framerate=60
over_voltage_avs=31250
over_voltage_avs_boost=0x200b2
pause_burst_frames=1
program_serial_random=1
sdram_freq=450
对于字符串选项,使用:
# vcgencmd get_config str
device_tree=-
此外,还有其他选项,包括设备树设置:
dtparam=spi=on
和
dtoverlay=mcp23017,gpiopin=4,addr=0x20
因为对原有和新选项的支持不断变化,所以随着每个新型号的发布,您可以查看以下资源:
复合长宽比
sdtv_aspect参数配置复合视频宽高比。
sdtv_aspect
|
描述
| | --- | --- | | one | 4:3(默认) | | Two | 14:9 | | three | 16:9 |
彩色脉冲
默认情况下,启用颜色突发。这允许从复合视频插孔中产生颜色。在某些情况下,为了获得更清晰的显示,可能需要将视频设置为单色。
|sdtv_disable_colourburst
|
描述
| | --- | --- | | Zero | 颜色突发使能(默认) | | one | 彩色突发禁用(单色) |
高清视频
本节介绍影响 HDMI 操作的config.txt设置。
HDMI 安全模式
hdmi_safe参数支持自动 HDMI 配置,以实现最佳兼容性。
hdmi _ 安全
|
描述
| | --- | --- | | Zero | 禁用(默认) | | one | 使能够 |
当hdmi_safe=1(启用)时,隐含以下设置:
-
hdmi_force_hotplug=1 -
config_hdmi_boost=4 -
hdmi_group=1 -
hdmi_mode=1 -
disable_overscan=0
HDMI 强制热插拔
此配置设置允许您强制 HDMI 显示器的热插拔信号,无论显示器是否连接。默认情况下,NOOBS 发行版启用此设置。
|hdmi_force_hotplug
|
描述
| | --- | --- | | Zero | 禁用(非 NOOBS 默认) | | one | 即使没有检测到 HDMI 显示器,也使用 HDMI 模式(NOOBS 默认) |
HDMI 忽略热插拔
启用hdmi_ignore_hotplug设置会使系统看起来没有连接 HDMI 显示器,即使有。这有助于在插入 HDMI 显示器时强制合成视频输出。
hdmi_ignore_hotplug
|
描述
| | --- | --- | | Zero | 禁用(默认) | | one | 即使检测到 HDMI 显示器,也使用复合视频 |
HDMI 驱动器
此模式允许您在 DVI(无声音)和 HDMI 模式(有声音,如果支持)之间进行选择。
|hdmi_drive
|
描述
| | --- | --- | | one | 正常 DVI 模式(无声音) | | Two | 正常 HDMI 模式(如果支持并启用,将发送声音) |
HDMI 忽略 EDID
启用此选项会导致来自显示屏的 EDID 信息被忽略。通常,这些信息是有用的,并且被使用。
|HDMI _ ignore _edid(HDMI _ 忽略 _ edid)
|
描述
| | --- | --- | | 未指明的 | 阅读 EDID 信息 | | 0xa5000080 | 忽略 EDID 信息 |
HDMI EDID 文件
当hdmi_edid_file被启用时,EDID 信息从名为edid.txt的文件中获取。否则,当可用时,从显示器中取出。
hdmi _ edid _ 档案
|
描述
| | --- | --- | | Zero | 从设备读取 EDID 数据(默认) | | one | 从 edid.txt 文件中读取 EDID 数据 |
HDMI Force EDID 音讯
启用此选项会强制支持所有音频格式,即使显示器不支持它们。当报告为不受支持时,这允许 DTS/AC3 通过。
|hdmi _ force _ edid _ 音讯
|
描述
| | --- | --- | | Zero | 使用 EDID 提供的值(默认) | | one | 假设支持所有音频格式 |
避免 EDID 模糊匹配
避免 EDID 中描述的模式的模糊匹配。
|避免 _ edid _ 模糊 _ 匹配
|
描述
| | --- | --- | | Zero | 使用模糊匹配(默认) | | one | 避免模糊匹配 |
HDMI 组
hdmi_group选项定义了 HDMI 类型。
hdmi_group
|
描述
| | --- | --- | | Zero | 使用 EDID 报告的首选组(默认) | | one | 成本效益分析(Cost Effectiveness Analysis) | | Two | 深水活动目标(Deep Mobile Target) |
HDMI 模式
该选项定义了 CEA 或 DMT 格式中使用的屏幕分辨率(参见前面“HDMI 组”小节中的参数hdmi_group)。在表 17-2 中,所示的修饰语具有以下含义:
表 17-2
HDMI 模式设置
|组
|
成本效益分析(Cost Effectiveness Analysis)
|
深水活动目标(Deep Mobile Target)
| | --- | --- | --- | |
方式
|
解决
|
恢复精神
|
修饰语
|
解决
|
恢复精神
|
笔记
| | --- | --- | --- | --- | --- | --- | --- | | one | 视频图形阵列 | | | 640×350 | 85 赫兹 | | | Two | 480 便士 | 60 赫兹 | | 640×400 | 85 赫兹 | | | three | 480 便士 | 60 赫兹 | H | 720×400 | 85 赫兹 | | | four | 720 便士 | 60 赫兹 | | 640×480 | 60 赫兹 | | | five | 1080 i | 60 赫兹 | | 640×480 | 72 赫兹 | | | six | 480 i | 60 赫兹 | | 640×480 | 75 赫兹 | | | seven | 480 i | 60 赫兹 | H | 640×480 | 85 赫兹 | | | eight | 240 便士 | 60 赫兹 | | 800×600 | 56 赫兹 | | | nine | 240 便士 | 60 赫兹 | H | 800×600 | 60 赫兹 | | | Ten | 480 i | 60 赫兹 | 4x | 800×600 | 72 赫兹 | | | Eleven | 480 i | 60 赫兹 | 4x H | 800×600 | 75 赫兹 | | | Twelve | 240 便士 | 60 赫兹 | 4x | 800×600 | 85 赫兹 | | | Thirteen | 240 便士 | 60 赫兹 | 4x H | 800×600 | 120 赫兹 | | | Fourteen | 480 便士 | 60 赫兹 | 2x | 848×480 | 60 赫兹 | | | Fifteen | 480 便士 | 60 赫兹 | 2x 高 | 1024×768 | 43 赫兹 | 不要使用 | | Sixteen | 1080 便士 | 60 赫兹 | | 1024×768 | 60 赫兹 | | | Seventeen | 576 便士 | 50 赫兹 | | 1024×768 | 70 赫兹 | | | Eighteen | 576 便士 | 50 赫兹 | H | 1024×768 | 75 赫兹 | | | Nineteen | 720 便士 | 50 赫兹 | | 1024×768 | 85 赫兹 | | | Twenty | 1080 i | 50 赫兹 | | 1024×768 | 120 赫兹 | | | Twenty-one | 576 i | 50 赫兹 | | 1152×864 | 75 赫兹 | | | Twenty-two | 576 i | 50 赫兹 | H | 1280×768 | | 稀有 | | Twenty-three | 288 便士 | 50 赫兹 | | 1280×768 | 60 赫兹 | | | Twenty-four | 288 便士 | 50 赫兹 | H | 1280×768 | 75 赫兹 | | | Twenty-five | 576 i | 50 赫兹 | 4x | 1280×768 | 85 赫兹 | | | Twenty-six | 576 i | 50 赫兹 | 4x H | 1280×768 | 120 赫兹 | 稀有 | | Twenty-seven | 288 便士 | 50 赫兹 | 4x | 1280×800 | | 稀有 | | Twenty-eight | 288 便士 | 50 赫兹 | 4x H | 1280×800 | 60 赫兹 | | | Twenty-nine | 576 便士 | 50 赫兹 | 2x | 1280×800 | 75 赫兹 | | | Thirty | 576 便士 | 50 赫兹 | 2x 高 | 1280×800 | 85 赫兹 | | | Thirty-one | 1080 便士 | 50 赫兹 | | 1280×800 | 120 赫兹 | 稀有 | | Thirty-two | 1080 便士 | 24 赫兹 | | 1280×960 | 60 赫兹 | | | Thirty-three | 1080 便士 | 25 赫兹 | | 1280×960 | 85 赫兹 | | | Thirty-four | 1080 便士 | 30 赫兹 | | 1280×960 | 120 赫兹 | 稀有 | | Thirty-five | 480 便士 | 60 赫兹 | 4x | 1280×1024 | 60 赫兹 | | | Thirty-six | 480 便士 | 60 赫兹 | 4x H | 1280×1024 | 75 赫兹 | | | Thirty-seven | 576 便士 | 50 赫兹 | 4x | 1280×1024 | 85 赫兹 | | | Thirty-eight | 576 便士 | 50 赫兹 | 4x H | 1280×1024 | 120 赫兹 | 稀有 | | Thirty-nine | 1080 i | 50 赫兹 | 稀有 | 1360×768 | 60 赫兹 | | | Forty | 1080 i | 100 赫兹 | | 1360×768 | 120 赫兹 | 稀有 | | Forty-one | 720 便士 | 100 赫兹 | | 1400×1050 | | 稀有 | | forty-two | 576 便士 | 100 赫兹 | | 1400×1050 | 60 赫兹 | | | Forty-three | 576 便士 | 100 赫兹 | H | 1400×1050 | 75 赫兹 | | | forty-four | 576 i | 100 赫兹 | | 1400×1050 | 85 赫兹 | | | Forty-five | 576 i | 100 赫兹 | H | 1400×1050 | 120 赫兹 | 稀有 | | Forty-six | 1080 i | 120 赫兹 | | 1440×900 | | 稀有 | | Forty-seven | 720 便士 | 120 赫兹 | | 1440×900 | 60 赫兹 | | | Forty-eight | 480 便士 | 120 赫兹 | | 1440×900 | 75 赫兹 | | | forty-nine | 480 便士 | 120 赫兹 | H | 1440×900 | 85 赫兹 | | | Fifty | 480 i | 120 赫兹 | | 1440×900 | 120 赫兹 | 稀有 | | Fifty-one | 480 i | 120 赫兹 | H | 1600×1200 | 60 赫兹 | | | fifty-two | 576 便士 | 200 赫兹 | | 1600×1200 | 65 赫兹 | | | Fifty-three | 576 便士 | 200 赫兹 | H | 1600×1200 | 70 赫兹 | | | Fifty-four | 576 i | 200 赫兹 | | 1600×1200 | 75 赫兹 | | | Fifty-five | 576 i | 200 赫兹 | H | 1600×1200 | 85 赫兹 | | | fifty-six | 480 便士 | 240 赫兹 | | 1600×1200 | 120 赫兹 | 稀有 | | Fifty-seven | 480 便士 | 240 赫兹 | H | 1680×1050 | | 稀有 | | Fifty-eight | 480 i | 240 赫兹 | | 1680×1050 | 60 赫兹 | | | Fifty-nine | 480 i | 240 赫兹 | H | 1680×1050 | 75 赫兹 | | | Sixty | | | | 1680×1050 | 85 赫兹 | | | Sixty-one | | | | 1680×1050 | 120 赫兹 | 稀有 | | Sixty-two | | | | 1792×1344 | 60 赫兹 | | | Sixty-three | | | | 1792×1344 | 75 赫兹 | | | Sixty-four | | | | 1792×1344 | 120 赫兹 | 稀有 | | Sixty-five | | | | 1856×1392 | 60 赫兹 | | | Sixty-six | | | | 1856×1392 | 75 赫兹 | | | Sixty-seven | | | | 1856×1392 | 120 赫兹 | 稀有 | | sixty-eight | | | | 1920×1200 | | 稀有 | | sixty-nine | | | | 1920×1200 | 60 赫兹 | | | Seventy | | | | 1920×1200 | 75 赫兹 | | | Seventy-one | | | | 1920×1200 | 85 赫兹 | | | seventy-two | | | | 1920×1200 | 120 赫兹 | 稀有 | | Seventy-three | | | | 1920×1440 | 60 赫兹 | | | Seventy-four | | | | 1920×1440 | 75 赫兹 | | | Seventy-five | | | | 1920×1440 | 120 赫兹 | 稀有 | | Seventy-six | | | | 2560×1600 | | 稀有 | | Seventy-seven | | | | 2560×1600 | 60 赫兹 | | | seventy-eight | | | | 2560×1600 | 75 赫兹 | | | Seventy-nine | | | | 2560×1600 | 85 赫兹 | | | Eighty | | | | 2560×1600 | 120 赫兹 | 稀有 | | Eighty-one | | | | 1366×768 | 60 赫兹 | | | Eighty-two | 1080 便士 | 60 赫兹 | | | | | | Eighty-three | | | | 1600×900 | | 稀有 | | Eighty-four | | | | 2048×1152 | | 稀有 | | eighty-five | 720 便士 | 60 赫兹 | | | | | | Eighty-six | | | | 1366×768 | | 稀有 |
-
H表示正常 4:3 模式的 16:9 变体。 -
2x表示像素加倍(时钟频率更高)。 -
4x表示像素翻两番(时钟速率更高)。 -
R表示减少消隐(数据流中用于消隐的字节减少,从而降低时钟速率)。
HDMI 升压
config_hdmi_boost参数允许您调整 HDMI 信号强度。
配置 _hdmi_boost
|
描述
| | --- | --- | | Zero | 非 non 预设 | | one | | | Two | | | three | | | four | 如果有干扰问题,请使用(NOOBS 默认设置) | | five | | | six | | | seven | 最大强度 |
HDMI 忽略 CEC 初始化
启用此选项时,CEC 初始化不会发送到设备。这可以避免重启时电视脱离待机状态和频道切换。
|hdmi_ignore_cec_init
|
描述
| | --- | --- | | Zero | 正常(默认) | | one | 不发送初始活动源消息 |
HDMI 忽略此选项
使能此选项时,假设 HDMI 设备根本不支持 CEC,即使该设备支持 CEC。因此,不支持任何 CEC 功能。
|hdmi_ignore_cec
|
描述
| | --- | --- | | Zero | 正常(默认) | | one | 禁用 CEC 支持 |
过扫描视频
一些选项控制复合视频输出的过扫描支持。当启用过扫描时,会根据配置跳过屏幕两侧的一定数量的像素。
禁用过扫描
disable_overscan选项可以禁用过扫描功能。默认情况下,它处于启用状态:
禁用 _ 过扫描
|
描述
| | --- | --- | | Zero | 过扫描使能(默认) | | one | 禁用过扫描 |
左、右、上、下过扫描
这些参数控制在屏幕左侧、右侧、顶部和底部跳过的像素数。
|参数
|
要跳过的像素
| | --- | --- | | 过扫描 _ 左=0 | 在左边 | | 过扫描 _ 右=0 | 在右边 | | overscan_top=0 | 在顶端 | | overscan_bottom=0 | 实际上 |
帧缓冲设置
Linux 帧缓冲支持由本节中描述的几个配置选项来配置。
帧缓冲宽度
默认情况下,将帧缓冲器的宽度定义为显示器的宽度减去过扫描像素。
|帧缓冲区 _ 宽度
|
描述
| | --- | --- | | 系统默认值 | 显示宽度过扫描 | | 帧缓冲区宽度=n | 将宽度设置为 n 像素 |
帧缓冲高度
默认情况下,将帧缓冲区的高度定义为显示器的高度减去过扫描像素。
|帧缓冲区 _ 高度
|
描述
| | --- | --- | | 系统默认值 | 显示高度过扫描 | | 帧缓冲区高度=n | 将高度设置为 n 像素 |
帧缓冲深度
该参数定义了每个像素的位数。
|帧缓冲区 _ 深度
|
描述
| | --- | --- | | eight | 有效,但默认的 RGB 调色板使屏幕不可读 | | Sixteen | 默认 | | Twenty-four | 截至 2012 年 6 月 15 日,外观有所改善,但存在腐败问题 | | Thirty-two | 无损坏,但要求 framebuffer_ignore_alpha=1,并且自 2012 年 6 月 15 日起显示错误的颜色 |
帧缓冲区忽略 Alpha
使用此选项可以禁用 alpha 通道。截至本文撰写之时,当使用 32 位帧缓冲深度时,必须使用此选项。
|帧缓冲区 _ 忽略 _ 阿尔法
|
描述
| | --- | --- | | Zero | Alpha 通道使能(默认) | | one | 阿尔法通道禁用 |
常规视频选项
根据display_rotate选项,显示屏可以不同方式翻转或旋转。通过将翻转值与旋转值相加,您应该能够进行翻转和旋转。
90°和 270°旋转需要 GPU 上的额外内存,因此这些选项不适用于 16 MB GPU 分割。
|显示 _ 旋转
|
描述
| | --- | --- | | Zero | 0(默认) | | one | 90° | | Two | 180° | | three | 270° | | 0x1000 | 水平翻转 | | 0x2000 | 垂直翻转 |
虽然记录了翻转选项,但我无法让它们工作。然而,轮换被证实是可行的。
许可的编解码器
以下选项允许您为受影响的编解码器配置购买的许可证密钥代码。
|[计]选项
|
笔记
| | --- | --- | | decode_MPG2=0x12345678 | 硬件 MPEG-2 解码的许可证密钥 | | decode_WVC1=0x12345678 | 硬件 VC-1 解码的许可证密钥 |
测试
以下测试选项在启动期间启用图像/声音测试。这是用于制造商测试的。
|测试模式
|
描述
| | --- | --- | | Zero | 禁用测试模式(默认) | | one | 启用测试模式 |
记忆
本节总结了与内存相关的配置设置。
禁用 GPU L2 缓存
disable_l2cache选项允许禁用 ARM CPU 对 GPU L2 缓存的访问。这需要在内核中禁用相应的 L2。
禁用 _ 缓存
|
描述
| | --- | --- | | Zero | 启用 GPU L2 缓存访问 | | one | 禁用 GPU L2 缓存访问 |
引导选项
本节中的几个选项会影响引导过程。许多选项与正在启动的内核有关,而其他选项则影响文件系统和设备。
命令行
cmdline选项允许您在config.txt文件中配置内核命令行参数,而不是在cmdline.txt文件中。
厘米线
|
描述
|
| --- | --- |
| 未指明的 | 命令行取自cmdline.txt |
| cmdline="command " | 命令行取自参数 |
核心
默认情况下,start.elf 根据 Raspberry Pi 模型从名为kernel.img或kernel7.img的文件中加载内核。这可以被覆盖以指定特定的图像。
内核地址
这个参数决定了内核映像加载到的内存地址。
|内核地址
|
描述
| | --- | --- | | 0x00000000 | 默认 |
RAM 文件系统文件
ramfsfile参数为 RAM FS 文件命名文件,用于内核。
ramfsfile
|
描述
| | --- | --- | | 未指明的 | 没有使用 RAM FS 文件 | | ramfsfile="ramfs.file " | 使用文件 ramfs.file |
RAM 文件系统地址
ramfsaddr参数指定 RAM 文件系统映像加载到内存的位置。
拉姆夫萨德
|
描述
| | --- | --- | | 0x00000000 | 默认地址 |
初始化 RAM 文件系统
该选项是一个方便的选项,它结合了选项ramfsfile和ramfsaddr。
林特克
|
参数 1
|
参数 2
|
描述
| | --- | --- | --- | --- | | 林特克 | initram.gz 文件 | 0x00800000 | 例子 |
设备树地址
device_tree_address选项定义了设备树地址的加载位置。
设备树地址
|
描述
| | --- | --- | | 0x00000000 | 默认 |
初始化 UART 波特率
init_uart_baud选项允许用户重新配置串行控制台,使用不同于默认的波特率。
初始化 uart 波特
|
描述
| | --- | --- | | One hundred and fifteen thousand two hundred | 默认波特率 |
初始化 UART 时钟
init_uart_clock参数允许用户重新配置 UART 以使用不同的时钟速率。
初始化 uart 时钟
|
描述
| | --- | --- | | Three million | 默认 |
初始化 EMMC 时钟
init_emmc_clock参数允许用户调整 EMMC 时钟,这可以提高 SD 卡的性能。
初始化 _ emmc _ 时钟
|
描述
| | --- | --- | | One hundred million | 默认 |
启动延迟
boot_delay和boot_delay_ms选项允许用户在加载内核之前重新配置start.elf使用的延迟。所用的实际延迟时间由下式计算得出:
在哪里
|boot_delay (b)
|
描述
| | --- | --- | | one | 默认 |
-
D 是以毫秒为单位计算的延迟。
-
b 是
boot_delay值。 -
m 为
boot_delay_ms值。
boot_delay_ms增加了boot_delay参数。
启动延迟毫秒(毫秒)
|
描述
| | --- | --- | | Zero | 默认 |
避免安全模式
可以在管脚 P1-05 (GPIO 1)和 P1-06(地)之间放置一个跳线或开关,使start.elf启动安全模式引导。如果 GPIO 1 正用于其他 I/O 功能,则应禁用安全模式检查。
避免 _ 安全 _ 模式
|
描述
| | --- | --- | | Zero | 默认(检查 P1-05 的安全模式) | | one | 禁用安全模式检查 |
厘米线.txt
cmdline.txt文件用于向内核提供命令行参数。标准图像中提供的 Raspbian 值在这里被分成多行,以便于阅读(这个示例是针对 Raspberry Pi 3 B+):
# cat cmdline.txt
dwc_otg.lpm_enable=0 \
console=tty1 \
console=serial0,115200 \
root=PARTUUID=2383b4bd-02 \
rootfstype=ext4 \
elevator=deadline \
fsck.repair=yes \
rootwait \
quiet \
splash \
plymouth.ignore-serial-consoles
提供该文件是为了方便起见,因为可以使用cmdline="text"选项在config.txt文件中配置参数。当提供了config.txt选项时,它会取代cmdline.txt文件。
一旦 Raspbian Linux 内核启动,您可以查看如下所用的命令行选项(这是同一个 Raspberry Pi 3 B+):
$ cat /proc/cmdline
8250.nr_uarts=1 \
bcm2708_fb.fbwidth=1680 \
bcm2708_fb.fbheight=1050 \
bcm2708_fb.fbswap=1 \
vc_mem.mem_base=0x3ec00000 \
vc_mem.mem_size=0x40000000 \
dwc_otg.lpm_enable=0 \
console=tty1 \
console=ttyS0,115200 \
root=PARTUUID=2383b4bd-02 \
rootfstype=ext4 \
elevator=deadline \
fsck.repair=yes \
rootwait \
quiet \
splash \
plymouth.ignore-serial-consoles
这个输出很有趣,因为它显示了cmdline.txt文件中没有的细节。格式name.option=values的选项是特定于内核可加载模块的。
串行控制台=
Linux console 参数指定 Linux 使用什么设备作为控制台。在本例中,它是:
console=ttyS0,115200
这指的是启动后作为/dev/ttyS0可用的串行设备。设备名称后面的参数是波特率。
串行控制台选项的一般形式如下:
console=ttyDevice,bbbbpnf
第二个参数是选项字段:
|地区
|
描述
|
价值
|
拉斯比安笔记
| | --- | --- | --- | --- | | 双侧束支传导阻滞 | 波特率 | One hundred and fifteen thousand two hundred | 可以超过四位数 | | p | 平价 | n | 无奇偶校验 | | | | o | 奇宇称 | | | | e | 偶数奇偶性 | | n | 位数 | seven | 7 个数据位 | | | | eight | 8 个数据位 | | f | 流控制 | r | 即时战略游戏 | | | | 省略 | RTS 时 |
虚拟控制台=
Linux 支持虚拟控制台,也可以通过console=参数进行配置。Raspbian Linux 指定了以下内容:
console=tty1
内核启动后,该设备从/dev/tty1开始可用。可列出用于该虚拟控制台的tty参数(为便于阅读,在此编辑):
$ sudo −i
# stty −a </dev/tty1
speed 38400 baud ; rows 26; columns 82; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; \
eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^Q; stop = ^S ; susp = ^Z; rprnt = ^R; werase = ^W; \
lnext = ^V; flush = ^O; min = 1; time = 0;
−parenb −parodd cs8 hupcl −cstopb cread −clocal −crtscts
−ignbrk brkint −ignpar −parmrk −inpck −istrip −inlcr \
−igncr icrnl ixon −ixoff −iuclc −ixany imaxbel iutf8
opost −o lcuc −ocrnl onlcr −onocr −onlret −ofill −ofdel \
nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok −echonl −noflsh \
−xcase −tostop −echoprt −echoctl echoke
#
根=
Linux 内核需要知道哪个设备持有根文件系统。标准 Raspbian 图像提供以下内容:
root=PARTUUID=2383b4bd-02
该信息可以通过blkid命令获得:
# blkid
/dev/mmcblk0p1: LABEL="boot" UUID="A75B-DC79" TYPE="vfat" PARTUUID="2383b4bd-01"
/dev/mmcblk0p2: LABEL="rootfs" UUID="485ec5bf-9c78-45a6-9314-32be1d0dea38" \
TYPE="ext4" PARTUUID="2383b4bd-02"
/dev/mmcblk0: PTUUID="2383b4bd" PTTYPE="dos"
查看该输出可以确认名为“rootfs”的分区正被用作根文件系统。本例中的分区由分区 UUID(UUID 的缩写,是一个通用的唯一标识符)指定。
root=参数的一般形式支持以下形式:
-
root=MMmm:从主要设备MM,次要设备mm(十六进制)引导。 -
root=/dev/nfs:引导一个由nfsroot指定的 NFS 磁盘(参见nfs-root=和ip=)。 -
root=/dev/name:从名为/dev/name的设备启动。 -
root=PARTUUID=:从由标识为缩短 UUID 的本地唯一分区引导。
rootfstype=
除了指定保存根文件系统的设备之外,Linux 内核有时需要知道文件系统的类型。这是通过rootfstype参数配置的。标准 Raspbian 图像提供以下内容:
rootfstype=ext4
这个例子表明根文件系统是ext4类型。
Linux 内核可以检查 root 参数中给定的设备,以确定文件系统类型。但是也有内核无法解析类型或者混淆的情况。否则,您可能需要强制某种文件系统类型。
电梯=
该选项选择要在内核中使用的 I/O 调度程序方案。标准 Raspbian 图像指定了以下内容:
elevator=deadline
要找出正在使用的 I/O 调度程序选项和其他可用选项(在您的内核中),我们可以参考/sys伪文件系统:
$ cat /sys/block/mmcblk0/queue/scheduler
noop [deadline] cfq
$
名称mmcblk0是根文件系统所在设备的名称(查看前面的示例blkid输出)。方括号中的输出显示正在使用deadline I/O 调度程序。其他的选择是noop和cfq。这些 I/O 调度程序如下:
名字
|
描述
|
笔记
| | --- | --- | --- | | 无操作 | 没有特殊的请求顺序 | | | 完全公平队列 | 完全公平调度程序 | 年长的 | | 最后期限 | 循环调度程序,但请求有截止日期 | 最新的 |
I/O 调度程序是最新的实现,旨在提高效率和公平性。deadline调度器使用循环电梯,除了它额外记录请求的截止日期。循环电梯是根据扇区号和磁头移动(向前和向后)对请求进行排序的电梯。deadline调度器将使用循环电梯行为,但是如果请求看起来即将过期,它将被给予立即的优先权。
rootwait=
当用于根文件系统的设备是与其他内核引导功能异步启动的设备时,使用此选项。这通常是 USB 和 MMC 设备所需要的,这可能需要额外的时间来初始化。rootwait选项强制内核等待,直到根设备准备就绪。
假设根文件系统在 SD 卡(一个 MMC 设备)上,Raspbian 映像使用以下内容:
rootwait
nfsroot=
nfsroot选项允许您定义一个从 NFS 挂载启动的内核(假设内核中编译了 NFS 支持)。方括号显示可选值的位置:
田
|
描述
| | --- | --- | | 服务器 ip | NFS 服务器 IP 号(默认使用 ip=) | | 根目录 | NFS 服务器上的根目录。如果存在%s,IP 地址将被插入其中。 | | nfs 选项 | NFS 选项像 ro 一样,用逗号分隔 |
nfsroot=[server−ip:]root−dir[,nfs−options]
未指定时,将使用默认值/tftpboot/client_ip_address。这需要指定root=/dev/nfs,并且可以选择添加ip=。
为了测试您的内核是否支持 NFS,您可以在系统启动时查询/proc文件系统:
# cat /proc/filesystems
nodev sysfs
nodev rootfs
nodev ramfs
nodev bdev
nodev proc
nodev cpuset
nodev cgroup
nodev cgroup2
nodev tmpfs
nodev devtmpfs
nodev configfs
nodev debugfs
nodev tracefs
nodev sockfs
nodev pipefs
nodev rpc_pipefs
nodev devpts
ext3
ext2
ext4
vfat
msdos
nodev nfs
nodev nfs4
nodev autofs
f2fs
nodev mqueue
fuseblk
nodev fuse
nodev fusectl
从这个例子中,我们看到旧的 NFS ( nfs)和新的 NFS4 文件系统都受支持。
ip=
此选项允许用户配置网络设备的 IP 地址,或者指定如何分配 IP 号码。参见root=和nfsroot=选项。
ip=client−ip:server−ip:gw−ip:netmask:hostname:device:autoconf
表 17-3 描述了该选项中的字段。如果需要,autoconf 值可以单独出现,中间没有冒号。当给出ip=o ff 或ip=none时,不进行自动配置。自动配置协议在表 17-4 中列出。
表 17-4
自动配置协议
|草案
|
描述
| | --- | --- | | 关闭或无 | 不要自动配置 | | on 或任何 | 使用任何可用的协议(默认) | | 动态主机配置协议 | 使用 DHCP | | 引导程序协议 | 使用 BOOTP | | 怪怪的 | 使用 RARP | | 两者 | 使用 BOOTP 或 RARP,但不要使用 DHCP |
表 17-3
ip=内核参数
|田
|
描述
|
默认
| | --- | --- | --- | | ip 客户端 | 客户端的 IP 地址 | 自动配置 | | ip 服务器 | NFS 服务器的 IP 地址,仅 NFS 根目录需要 | 自动配置 | | gw-ip | 服务器的 IP 地址(如果在单独的子网上) | 自动配置 | | 网络掩码 | 本地 IP 地址的网络掩码 | 自动配置 | | 主机名 | 要提供给 DHCP 的主机名 | 客户端 IP 地址 | | 设备 | 要使用的接口的名称 | 当有多个可用时,autoconf | | 自动配置 | 自动配置方法 | 任何的 |
随着内核的交换和配置恢复到安全选项,现在应该可以启动紧急内核了。登陆救援。
要将系统恢复到正常状态,您需要遵循以下步骤:
-
将
kernel.img改名为kernel_emergency.img(为了以后的救援)。 -
将
kernel.bak重命名为kernel.img(恢复您的正常内核)。 -
如有必要,恢复/更改您的
config.txt配置。 -
如有必要,恢复/更改您的
cmdline.txt配置。
此时,您可以使用原来的内核和配置重新启动。