Intel Assabet(SA-1110 评估板)内核构建、RedBoot 引导与 JFFS2 实战指南
【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux
本文以 Linux 内核官方文档 Documentation/arch/arm/sa1100/assabet.rst 为主线,系统讲解 Intel StrongARM SA-1110 微处理器评估板 Assabet 的完整使用流程:从内核编译、引导加载程序(Bootloader)选择与安装,到 RedBoot 下烧写内核镜像、挂载 JFFS2 根文件系统、编写自动化引导脚本,最后结合当前仓库源码(arch/arm/mach-sa1100/assabet.c、arch/arm/configs/assabet_defconfig、drivers/mtd/parsers/redboot.c 等)深入剖析其底层实现。读完本文,你将能够独立完成 Assabet 平台的交叉编译、RedBoot 环境初始化和从 Flash 启动 Linux 的全过程。
Assabet 平台与文档背景
Assabet 是 Intel 官方推出的 StrongARM SA-1110 微处理器开发板(评估板),在 Linux ARM 生态早期扮演了重要的参考平台角色。SA-1110 集成了一颗 StrongARM 处理器核心,片上集成了 LCD 控制器、串口、USB、PCMCIA 等外设,配合 Neponset(SA-1111)扩展板可进一步扩展 I/O 能力。
在内核源码树中,Assabet 的平台支持代码集中在 arch/arm/mach-sa1100/assabet.c,其机器类型描述如下(见 assabet.c):
MACHINE_START(ASSABET, "Intel-Assabet") .atag_offset = 0x100, .fixup = fixup_assabet, .map_io = assabet_map_io, .nr_irqs = SA1100_NR_IRQS, .init_irq = assabet_init_irq, .init_time = sa1100_timer_init, .init_machine = assabet_init, .init_late = sa11x0_init_late, .restart = sa11x0_restart, MACHINE_END从 arch/arm/mach-sa1100/Kconfig 可以看到,SA11x0 平台目前已被标记为DEPRECATED(已废弃),且明确提示“Support for these machines will go away in 2027, unless there are any remaining users that speak up”(若无现存用户发声,该平台支持将于 2027 年移除)。因此本文内容对 ARM 早期平台移植和嵌入式 Linux 引导流程的研究、教学与历史梳理具有重要价值。
需要说明的是,本文以当前仓库(即 Linux 内核源码树)的实际代码和文档为准,涉及的命令行、配置与工具链描述适用于 Assabet 平台及其对应的内核版本。
编译 Assabet 内核镜像
三步构建流程
根据官方文档,使用默认配置构建 Assabet 内核只需三条命令:
make assabet_defconfig make oldconfig make zImagemake assabet_defconfig:加载 Assabet 的默认内核配置。该配置文件位于 arch/arm/configs/assabet_defconfig,是本文档所述流程的直接依据。make oldconfig:基于现有.config交互式确认新增/变更的配置项,确保配置与当前内核版本一致。make zImage:编译生成压缩内核镜像。
构建完成后,内核镜像位于linux/arch/arm/boot/zImage。
默认配置的关键选项
arch/arm/configs/assabet_defconfig 中的核心配置与本文档的引导流程一一对应,值得逐项解读:
| 配置项 | 值 | 含义与引导流程关联 |
|---|---|---|
CONFIG_ARCH_SA1100 | y | 启用 SA11x0 平台支持 |
CONFIG_SA1100_ASSABET | y | 启用 Assabet 板级支持 |
CONFIG_ATAGS | y | 使用 ATAGS 向内核传递启动参数 |
CONFIG_CMDLINE | "mem=32M console=ttySA0,38400n8 initrd=0xc0800000,3M root=/dev/ram" | 默认内核命令行:32M 内存、串口控制台(38400 波特率,8 数据位无校验)、initrd 起始地址与大小、根文件系统为 ramdisk |
CONFIG_BLK_DEV_INITRD | y | 支持 initrd/ramdisk 启动,对应文档中“加载 ramdisk 镜像”一节 |
CONFIG_MTD | y | 启用 MTD(Memory Technology Device)层,是 JFFS2 的基础 |
CONFIG_MTD_REDBOOT_PARTS | y | 启用 RedBoot FIS 分区表解析,对应文档中 Linux 显示 “Using RedBoot partition definition” 的输出 |
CONFIG_MTD_BLOCK | y | 提供/dev/mtdblockN块设备接口,对应文档中root=/dev/mtdblock2的使用 |
CONFIG_MTD_CFI | y | 启用 CFI(Common Flash Interface)探测,对应 “SA1100 flash: probing 32-bit flash bus” |
CONFIG_MTD_SA1100 | y | SA1100 平台 Flash 映射驱动 |
CONFIG_JFFS2_FS | y | 启用 JFFS2 日志型闪存文件系统 |
CONFIG_SERIAL_SA1100_CONSOLE | y | SA1100 串口作为内核控制台 |
CONFIG_FB_SA1100 | y | SA1100 LCD 帧缓冲驱动 |
CONFIG_PCMCIA_SA1100、CONFIG_PCMCIA_PCNET | y | PCMCIA 及 PCnet 网卡支持,配合文档中“使用 CF 网卡进行 TFTP 传输” |
CONFIG_NFS_FS | y | NFS 根文件系统支持,对应文档中“通过 NFS 启动根文件系统” |
值得关注的是,配置中的CONFIG_MTD_REDBOOT_PARTS直接对应 Linux 内核启动时读取 RedBoot 维护的 FIS(Flash Image System)目录并自动生成 MTD 分区表的行为,这与文档第五节中 Linux 输出 5 个 MTD 分区的现象完全吻合。
引导加载程序(Bootloader)的选择
Assabet 上可用的 Linux 引导加载程序有三类,各有特点:
| Bootloader | 来源/背景 | 特点 |
|---|---|---|
| BLOB | LART 项目的引导程序,社区贡献补丁加入 Assabet 支持 | 轻量、简单,但无网络功能 |
| Compaq Bootldr | Compaq 为 iPAQ Pocket PC 开发的引导程序,John Dorsey 提供 Assabet 与 JFFS 支持补丁 | 面向 PDA,带 JFFS 文件系统支持 |
| RedBoot | Red Hat 基于 eCos RTOS HAL 开发的引导程序 | 支持众多硬件平台,唯一具备网络支持,维护最活跃,是当时推荐选择 |
官方文档明确指出:
RedBoot is currently the recommended choice since it's the only one to have networking support, and is the most actively maintained.
由于 RedBoot 是文档推荐方案且具备网络(TFTP)能力,以下引导与烧写流程均以 RedBoot 为主线展开。
RedBoot 固件安装
在开始使用之前,需要先将预编译好的 RedBoot 二进制写入 Assabet 的 Flash。文档给出的预编译 RedBoot 二进制(文件名形如redboot-assabet*.tgz,并附有安装说明redboot-assabet*.txt)存放于如下 FTP 站点:
ftp://ftp.netwinder.org/users/n/nico/ftp://ftp.arm.linux.org.uk/pub/linux/arm/people/nico/ftp://ftp.handhelds.org/pub/linux/arm/sa-1100-patches/
硬件注意事项:若使用 CF 网卡(文档作者 Assabet 套件附带 Socket Communications 的 CF+ LP-E 网卡)进行 TFTP 文件传输,必须在 RedBoot 运行之前插入,因为 RedBoot 无法动态检测 CF 网卡。
RedBoot 初始化配置
RedBoot 提供两类持久化配置:
初始化 Flash 目录
fis init -f该命令用于初始化 Flash Image System(FIS)目录,-f表示强制操作(会清除现有的 FIS 目录区域)。FIS 是 RedBoot 维护的一张 Flash 镜像目录表,内核侧的 drivers/mtd/parsers/redboot.c 正是解析这张表来生成 MTD 分区的。
初始化非易失性网络配置
fconfig -ifconfig -i进入交互式配置模式,用于设置 BOOTP 动态获取 IP 还是静态 IP 等网络参数,以及脚本超时等选项。这些非易失性设置保存在 Flash 的 “RedBoot config” 区域中(后续fis list输出中可见)。
RedBoot 分区结构(源码视角)
从内核侧看,RedBoot FIS 目录中的镜像描述符结构定义于 drivers/mtd/parsers/redboot.c:
struct fis_image_desc { unsigned char name[16]; // Null terminated name u32 flash_base; // Address within FLASH of image u32 mem_base; // Address in memory where it executes u32 size; // Length of image u32 entry_point; // Execution entry point u32 data_length; // Length of actual data unsigned char _pad[256 - (16 + 7 * sizeof(u32))]; u32 desc_cksum; // Checksum over image descriptor u32 file_cksum; // Checksum over image data };每个字段(镜像名、Flash 基址、内存加载地址、长度、入口点、数据长度、校验和)与fis list输出的各列一一对应。解析器通过CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK确定的目录块位置读取整块擦除块,并逐个检查镜像描述符的校验和来构建分区表(见 redboot.c)。
将内核镜像写入 Flash
第一步:将 zImage 加载到 RAM
内核镜像必须先加载到内存中才能烧写。两种方式:
方式一:TFTP 网络加载(前提是 RedBoot 配置好了网络且 CF 网卡已插入):
load zImage -r -b 0x100000方式二:串口 Y-Modem 上传:
load -m ymodem -r -b 0x100000参数说明:
-r:将镜像加载到 RAM(raw load)。-b 0x100000:指定加载到 RAM 的物理地址0x100000(1MB 处)。
第二步:写入 Flash
fis create "Linux kernel" -b 0x100000 -l 0xc0000fis create将 RAM 中0x100000处、长度0xc0000(768KB)的数据写入 Flash,并登记为名为 “Linux kernel” 的 FIS 镜像。
启动内核与加载文件系统
加载 ramdisk
内核本身还需要一个文件系统才能完成启动。使用 TFTP 加载 ramdisk 镜像:
load ramdisk_image.gz -r -b 0x800000若改用串口 Y-Modem 上传,将文件名替换为-y ymodem:
load -y ymodem -r -b 0x800000从 Flash 取出内核并执行
fis load "Linux kernel" exec -b 0x100000 -l 0xc0000fis load:将 Flash 中名为 “Linux kernel” 的镜像读回 RAM(默认加载地址即创建时记录的内存地址)。exec -b 0x100000 -l 0xc0000:从地址0x100000处、长度0xc0000执行(即跳转启动内核)。
文档特别指出:ramdisk 也可以烧入 Flash,但针对“在 Flash 上存放可写文件系统”这一需求,JFFS2 是更优解,详见下一节。
使用 JFFS2 构建可写的 Flash 根文件系统
JFFS2 与 MTD 的关系
JFFS2(The Second Journalling Flash File System,第二代日志型闪存文件系统)是当时在 Flash 上存放可写文件系统最便捷的方案。它必须与 MTD(Memory Technology Device)层配合使用——MTD 负责底层的 Flash 管理(探测、擦除、读写、坏块处理等),JFFS2 则在其上提供日志型文件系统语义。
从配置看,arch/arm/configs/assabet_defconfig 同时启用了CONFIG_MTD、CONFIG_MTD_SA1100、CONFIG_MTD_CFI、CONFIG_MTD_BLOCK与CONFIG_JFFS2_FS,正是 JFFS2 方案所需的完整依赖链。
加载示例 JFFS2 镜像
示例 JFFS2 镜像(sample_img.jffs2)可从与预编译 RedBoot 相同的 FTP 站点获取。加载到 RAM:
load sample_img.jffs2 -r -b 0x100000预期输出(文件实际加载的大小随镜像不同而变化):
RedBoot> load sample_img.jffs2 -r -b 0x100000 Raw file loaded 0x00100000-0x00377424即镜像从0x00100000加载到0x00377424。
查询可用 Flash 空间
fis free示例输出:
RedBoot> fis free 0x500E0000 .. 0x503C0000注意:上述地址可能因文件系统大小和 Flash 类型不同而变化,以下计算仅作为示例,实际使用务必替换为自己的数值。
计算烧写参数
size of unallocated flash: 0x503c0000 - 0x500e0000 = 0x2e0000 size of the filesystem image: 0x00377424 - 0x00100000 = 0x277424- 未分配 Flash 区域大小:
0x2e0000(约 2.875MB) - 文件系统镜像实际大小:
0x277424(约 2.48MB)
设计目标:镜像必须能放进去,同时将剩余全部Flash 空间都划给该文件系统分区。
解锁、擦除、写入并创建 FIS 条目
fis unlock -f 0x500E0000 -l 0x2e0000 fis erase -f 0x500E0000 -l 0x2e0000 fis write -b 0x100000 -l 0x277424 -f 0x500E0000 fis create "JFFS2" -n -f 0x500E0000 -l 0x2e0000逐步解析:
fis unlock -f:解锁目标 Flash 区域(Flash 写入前通常需解锁)。fis erase -f:擦除整个目标区域(擦除是 Flash 写入的强制前置步骤)。fis write:将 RAM 地址0x100000处、长度0x277424的数据写入 Flash 地址0x500E0000。fis create "JFFS2" -n:-n表示不复制数据,仅为该区域在 FIS 目录中登记名为 “JFFS2” 的镜像条目(数据已由上一步写入)。
验证:fis list 与 Linux 侧 MTD 分区
烧写完成后,fis list显示完整的 Flash 布局:
RedBoot> fis list Name FLASH addr Mem addr Length Entry point RedBoot 0x50000000 0x50000000 0x00020000 0x00000000 RedBoot config 0x503C0000 0x503C0000 0x00020000 0x00000000 FIS directory 0x503E0000 0x503E0000 0x00020000 0x00000000 Linux kernel 0x50020000 0x00100000 0x000C0000 0x00000000 JFFS2 0x500E0000 0x500E0000 0x002E0000 0x00000000而在 Linux 侧,得益于CONFIG_MTD_REDBOOT_PARTS,启动时内核解析同一份 FIS 目录并打印:
SA1100 flash: probing 32-bit flash bus SA1100 flash: Found 2 x16 devices at 0x0 in 32-bit mode Using RedBoot partition definition Creating 5 MTD partitions on "SA1100 flash": 0x00000000-0x00020000 : "RedBoot" 0x00020000-0x000e0000 : "Linux kernel" 0x000e0000-0x003c0000 : "JFFS2" 0x003c0000-0x003e0000 : "RedBoot config" 0x003e0000-0x00400000 : "FIS directory"这条输出的前两行与 Assabet 板级 Flash 驱动直接对应。从源码看,arch/arm/mach-sa1100/assabet.c 中定义了两种 Flash 硬件布局:
- Phase 4 Assabet:Bank 0 中两块 Intel 28F160B3 Flash(每块 2MB 级),引导区为
0x00020000; - Phase 5 Assabet:Bank 0 中两块 Intel 28F128J3A Flash(每块 16MB 级),引导区为
0x00040000。
同时,assabet.c 使用cfi_probe作为映射名,并将两块 Flash 内存资源(SA1100_CS0_PHYS与SA1100_CS1_PHYS,各 32MB)注册给 MTD 层——这解释了启动日志中 “probing 32-bit flash bus / Found 2 x16 devices” 的探测行为。
从 Flash 直接启动 JFFS2 根文件系统
重要的是理解分区的顺序:Linux 侧第三个分区才是 “JFFS2”,它对应块设备/dev/mtdblock2。因此从 Flash 启动内核 + JFFS2 根文件系统的完整命令为:
fis load "Linux kernel" exec -b 0x100000 -l 0xc0000 -c "root=/dev/mtdblock2"-c参数将内核命令行设置为root=/dev/mtdblock2,指示内核将第三个 MTD 块设备作为根文件系统。
其他文件系统方案
文档也指出,除 JFFS 外还可选用其他文件系统:
- cramfs:只读压缩文件系统,适合存放不可变数据;
- NFS 根文件系统:通过
root=/dev/nfs配合网络启动; - 直接在 Linux 内烧写 Flash:在 ramdisk 或 NFS 引导的系统下,使用 Linux MTD 工具(如
flash_erase、mkfs.jffs2、mount)直接对刚擦除的分区挂载 JFFS2 并拷贝文件——这种方法有时更为便捷。
RedBoot 脚本化自动引导
每次重启都手动输入上述命令显然不现实,RedBoot 的脚本能力可完全自动化引导过程。以下示例脚本实现从网络 TFTP 服务器加载内核与 ramdisk 后自动启动:
RedBoot> fconfig Run script at boot: false true Boot script: Enter script, terminate with empty line >> load zImage -r -b 0x100000 >> load ramdisk_ks.gz -r -b 0x800000 >> exec -b 0x100000 -l 0xc0000 >> Boot script timeout (1000ms resolution): 3 Use BOOTP for network configuration: true GDB connection port: 9000 Network debug at boot time: false Update RedBoot non-volatile configuration - are you sure (y/n)? y配置项逐一说明:
| 配置项 | 值 | 含义 |
|---|---|---|
Run script at boot | false true | 改为true启用开机自动执行脚本 |
Boot script | 3 条命令 | 依次加载内核、加载 ramdisk、执行内核;空行结束输入 |
Boot script timeout | 3 | 脚本执行前的倒计时(单位 1000ms,即 3 秒),期间可按任意键中断进入交互模式 |
Use BOOTP for network configuration | true | 使用 BOOTP 自动获取网络配置 |
GDB connection port | 9000 | RedBoot GDB 调试连接端口 |
Network debug at boot time | false | 开机时不进入网络调试模式 |
保存配置后,重启 Assabet 只需等待登录提示符出现即可——整个引导过程完全自动化。
外设支持状态与硬件细节
文档附录记录了截至 2001 年 10 月,-rmk内核树中 Assabet 及 Neponset 外设的支持状态,可作为评估该平台能力的权威参考:
Assabet 本体
串口(Serial ports):
| 端口 | 状态 |
|---|---|
| Radio | TX、RX、CTS、DSR、DCD、RI 可用;PM 未测试 |
| COM | TX、RX、CTS、DSR、DCD、RTS、DTR、PM 可用;PM 未测试 |
| I2C | 已实现,未完全测试 |
| L3 | 完全测试通过(pass) |
| PM | 未测试 |
视频(Video):
| 项 | 状态 |
|---|---|
| LCD | 完全测试通过(注意:连接 Neponset 时 LCD 不喜欢被 blanked 熄灭) |
| Video out | 未完全测试 |
音频(Audio):
- UDA1341:播放完全测试通过;录音已实现未测试;PM 未测试。
- UCB1200:音频播放/录音、电信音频播放/录音均已实现但未重度测试;POTS 控制不支持;触摸屏支持;PM 未测试。
从源码可以印证 UCB1200 的接入方式:assabet.c 注册了 UCB1x00 平台数据(含复位回调与唤醒支持),并通过 MCP(Multimedia Communications Port,sa11x0_register_mcp)以11981000Hz 的 SCLK 时钟连接 codec;assabet.c 中的assabet_codec_reset展示了 UCB1x00 与 UDA1341 共享复位信号的细节——该复位线同时接到三个器件(UCB1x00、UDA1341、ADV7171),复位任一器件都会影响其余两者,且会使 ADV7171 消耗约 100mA 电流,超过 MAX846 锂电充电器的预算,若未接锂电池会导致 Assabet 崩溃——这正是注释中保留的硬件设计约束。
其他(Other):
| 项 | 状态 |
|---|---|
| PCMCIA(LPE) | 完全测试通过 |
| USB | 不支持 |
| IRDA(SIR / FIR) | 均完全测试通过;PM 未测试 |
Neponset 扩展板
| 项 | 状态 |
|---|---|
| 串口 COM1、COM2 | TX、RX、CTS、DSR、DCD、RTS、DTR 可用;PM 未测试 |
| USB | 已实现,未重度测试 |
| PCMCIA | 已实现,未重度测试 |
| CF | 已实现,未重度测试 |
Neponset 的板级支持代码位于 arch/arm/mach-sa1100/neponset.c,且在内核配置中由CONFIG_ASSABET_NEPONSET(见 arch/arm/mach-sa1100/Kconfig)控制,该选项依赖SA1100_ASSABET并自动选择SA1111。
启动时探测 Neponset
Assabet 的一大特殊之处在于必须在paging_init()之前探测 Neponset 是否存在,以正确确定可用 RAM 数量。因此 assabet.c 在fixup_assabet阶段先手动映射 GPIO 寄存器,再通过get_assabet_scr()读取系统配置字节:
static void __init get_assabet_scr(void) { unsigned long scr, i; GPDR |= 0x3fc; /* Configure GPIO 9:2 as outputs */ GPSR = 0x3fc; /* Write 0xFF to GPIO 9:2 */ GPDR &= ~(0x3fc); /* Configure GPIO 9:2 as inputs */ for(i = 100; i--; ) /* Read GPIO 9:2 */ scr = GPLR; GPDR |= 0x3fc; /* restore correct pin direction */ scr &= 0x3fc; /* save as system configuration byte. */ SCR_value = scr; }该方法通过 GPIO 9:2 的上下拉采样得到系统配置字节(SCR),若检测到 Neponset 则打印 “Neponset expansion board detected”。同一扫描逻辑也用于 zImage 解压阶段设置串口输出状态消息(见注释中引用的arch/arm/boot/compressed/head-sa1100.S)。此外,assabet.c 中的ASSABET_BCR_DB1110/ASSABET_BCR_DB1111分别定义了未接/接入 Neponset 时板控寄存器(BCR)的默认值,并在assabet_init_irq中按探测结果初始化(见 assabet.c)。
总结
通过本文,你可以完整掌握 Assabet(Intel SA-1110 评估板)从零构建内核到 Flash 引导的完整链路:
- 构建:
make assabet_defconfig && make oldconfig && make zImage,产出arch/arm/boot/zImage;默认配置 arch/arm/configs/assabet_defconfig 中CONFIG_MTD_REDBOOT_PARTS、CONFIG_MTD_BLOCK、CONFIG_JFFS2_FS等选项与引导流程深度耦合。 - 引导程序:RedBoot 是具备网络支持、维护最活跃的推荐选择。
- 烧写:通过
fis init -f、fconfig -i初始化环境,用 TFTP/Y-Modem 加载镜像,用fis create写入 Flash。 - 文件系统:JFFS2 + MTD 是 Flash 可写文件系统的最便捷方案,
fis list(RedBoot 侧)与 MTD 分区(Linux 侧)一一对应,root=/dev/mtdblock2完成从 Flash 直接启动。 - 自动化:RedBoot
fconfig脚本可实现开机自动从 TFTP 引导,配合 BOOTP 实现无人值守启动。
当前仓库中,板级代码 arch/arm/mach-sa1100/assabet.c、平台配置 arch/arm/mach-sa1100/Kconfig 以及 MTD 解析器 drivers/mtd/parsers/redboot.c 为上述全部流程提供了源码级支撑,是深入研究 ARM 早期平台移植、RedBoot 引导机制与 MTD/JFFS2 分区的绝佳参考。需要注意的是,该平台支持已进入废弃倒计时(预计 2027 年移除),本文内容更适合作为嵌入式 Linux 引导技术的历史档案与学习素材。
【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考