当前位置:首页 >> 信息与通信 >>

嵌入式Linux初级实验s2410


嵌入式 Linux 初级实验教程

1

前言
背景
随着计算机技术、微处理器技术、电子技术、通信技术、集成电路技术的发展,嵌入式 系统已成为计算机技术和计算机应用领域的一个重要组成部分, 嵌入式产品在人们的日常生 活中也扮演着越来越重要的角色。 近年来,Linux 在嵌入式领域的成功应用引起了广泛的兴趣和热烈的回应,越

来越多的 开发者开始学习和研究嵌入式 Linux 系统。但是嵌入式 Linux 的入门却不简单,进行嵌入式 Linux 的开发需要具备完善的知识结构,不仅要了解嵌入式设备相关的硬件知识,比如常用 嵌入式处理器的体系结构,接口技术等,还需要一定的 Linux 操作系统基础。 目前针对嵌入式 Linux 开发的书籍相当多,也不乏经典。然而大多数书中介绍的实例依 赖平台却又脱离平台, 使得其可操作性反而不强; 互联网的发展使得共享的网络资源琳琅满 目,面对这么多的书籍,资料,刚入门的开发者们往往无可是从。 本书面向那些想要在未来或者目前的计划中使用 Linux 的有一定经验的嵌入式系统设 计者,以及想要熟悉嵌入式 Linux 系统开发工具和技术但没有经验的嵌入式系统开发者,以 现在嵌入式领域使用相当广泛的 ARM 处理器为开发平台, 在一个具体的 S3C2410 开发板上, 从开发平台介绍,开发环境搭建,Linux 系统移植,到最终成功运行一个应用实例,带领读 者一步一步掌握嵌入式 Linux 的开发过程。 本书的作者具有多年的嵌入式开发经验,了解嵌入式 Linux 的开发过程,又熟悉 ARM 的体系结构及底层硬件接口电路。特别地,笔者在编写本书之前针对 S3C2410 做过很多的 实例开发,解决了不少在开发过程中遇到的问题,也积累了很多自己的体会,因此笔者希望 借助本书与大家分享这些经验与体会, 目的只是为了让大家在嵌入式 Linux 这条路上少栽几 个跟斗,少拐几个弯。 为了让本书更加贴近初学者,笔者根据自己的经验,精心设计了一系列的实验范例,并 选定了一个具体的开发平台——深圳旋级力通有限公司的 Super-ARM 实验教学平台。书中 所有实验范例的开发都在该平台上完成。之所以选择 Super-ARM 平台,是因为该平台的处 理器及其接口电路等都很具有代表性。 笔者专门安排了一章来介绍这个平台, 只是为了让读 者在充分了解平台的基础上更好地理解书中的实例, 这样当读者面对其他平台的时候更能够 举一反三。另外,本书的所有实验范例都经过多位初学者的再三验证,这足以证明本书实例 的可操作性。

预备知识
本书编写依赖三个假定,假定读者已经具备一定的 Linux 基础,包括 Linux 的安装,一 些基本命令的使用以及在 PC 的 Linux 环境下用 C 或者 C++开发简单的应用程序; 假定读者 对 ARM 的体系结构有所了解,包括 ARM 处理器的工作原理和接口技术,如 I/O,中断与异 常机制等, 同时对设备驱动程序的开发以及嵌入式图形界面的开发有一定认识。 假定读者有 一定硬件电路基础,能看懂一些简单的接口电路,如 LED,数码管等。

本书内容及组织方式
本书分为 4 篇,共 17 章,组织如下:

第一篇:开发环境篇

嵌入式 Linux 初级实验教程

2

本篇包括第 1 章到第 4 章,介绍如何搭建嵌入式开发的软硬件环境。 第 1 章:概述 本章主要介绍在嵌入式 Linux 开发过程中会涉及到的一些基本概念,基础知识等。 第 2 章:开发平台介绍 本章主要介绍本书实例使用的 Super-ARM 实验教学平台,使读者对开发平台的硬件资 源有一定的了解。 第 3 章:ADS 开发环境搭建 本章主要讲解 ADS 开发环境的安装过程,并结合一个简单实例介绍其使用方法,为后 续开发中 BootLoader 移植做好准备。 第 4 章:嵌入式 Linux 开发环境搭建 本章介绍主机 Linux 开发环境的安装,包括系统的安装,相关开发工具的配置等。

第二篇:系统移植篇
本篇包括第 5 章到第 7 章,介绍 Linux 系统的移植过程。 第 5 章:BootLoader 移植 本章主要介绍 BootLoader 的一些基础知识以及 U-Boot 的详细移植过程。 第 6 章:内核移植 本章主要介绍 Linux 内核的编译,配置及安装过程。 第 7 章:文件系统移植 本章主要讲解根文件系统的制作、移植和访问以及 NFS 文件系统的挂载。

第三篇:基础实验篇
本篇包括第 8 章到第 14 章,主要介绍一些简单硬件的驱动程序编写、移植及测试。 第 8 章:Linux 设备驱动概述 本章主要介绍 Linux 设备驱动的相关概念,包括设备驱动的作用、分类及特点,以及驱 动模块的加载与卸载等。 第 9 章:LED 实例 本章结合 LED 驱动实例介绍简单字符设备驱动的程序结构,并编写简单的应用程序对 设备驱动进行测试,通过本章,读者可以了解开发驱动程序的大致流程,为以后学习其他设 备驱动程序的开发打下基础。 第 10 章:按键中断实例 本章介绍 S3C2410 的中断机制及嵌入式 Linux 中断驱动程序的结构。通过按键驱动实 例的开发,带领大家一步一步实现该驱动程序的设计与测试过程。 第 11 章: 数码管实例 本章主要介绍数码管驱动的开发过程。 通过本章, 读者可以了解数码管的显示原理及其 驱动程序的设计方法。

嵌入式 Linux 初级实验教程

3

第 12 章:矩阵键盘实例 本章主要介绍键盘驱动的开发及测试。通过本章,读者可以了解键盘扫描的原理,从而 为自己的系统添加键盘设备驱动程序。 第 13 章:LCD 实例 本章主要介绍 LCD 显示设备的工作原理以及在 Linux 中移植 LCD 设备驱动的过程。 第 14 章:触摸屏实例 本章主要介绍触摸屏的工作原理,以及在 Linux 中移植触摸屏输入设备驱动的过程。

第四篇:图形应用篇
本篇包括第 15 章到第 17 章,主要介绍 QT/Embeded 的安装和编译,并通过开发一个 简单的 QT 实例,使学生逐步了解嵌入式图形界面编程。最后完成本书的一个综合实例 第 15 章:嵌入式 QT 环境搭建 本章首先对嵌入式 GUI 编程做个简单介绍,然后在宿主机上完成 QT/Embeded 开发环 境的搭建。 第 16 章:嵌入式 QT 之 HelloWorld 本章指导学生编写一个最简单的 QT 程序:在一个主窗口中添加一个按钮,点击该按钮 会弹出一个对话框,让该程序分别运行在桌面 PC 和实验箱上。 第 17 章:综合实例 作为本书的最后一章,本章结合基础实验篇中的一些实例,用 QT/Embedded 编写一个 简单图片浏览程序。该程序具有如下功能: (1)能读取文件系统系统所有目录下的图片,在实验箱的 LCD 屏幕上显示出来。 (2)具有单张查看和循环播放两种模式。 (3)在循环播放模式下,可以通过实验箱的数码管显示播放时间间隔(以秒为单位) 。 (4)在单张查看模式下可以通过点击触摸屏切换到下一张,上一张。

附件
为方便读者更高效地理解并完成本书的实例, 笔者为部分章节提供了相关的源代码, 工 程文件以及参考资料等。以附件的形式发布在随书光盘中。

作者
本书第一篇由徐成,谭曼琼,徐署华,刘豪和朱雪庆编写,第二篇由徐成,谭曼琼和朱 雪庆编写,第三篇由谭曼琼编写,第四篇由谭曼琼,朱雪庆和邱金波编写。全书由谭曼琼整 理和统稿。最后由李仁发教授主审。 徐成教授是多年从事嵌入式系统教学的老师,有非常丰富的嵌入式系统开发和教学经 验,徐署华、刘豪、谭曼琼等作者也从事嵌入式开发和教学多年,本书是所有作者教学与开 发经验的积累和总结。 本书的所有内容和实例都经过作者的仔细编排与验证。这里要特别感谢刘冬,张嵎桐, 张泰忠,曾娟丽等人的无私帮助,他们本着认真负责的态度对本书的内容,特别是实例部分

嵌入式 Linux 初级实验教程

4

进行了验证,并提出了宝贵的意见。尽管我们再三校对,但书中肯定还存在错误和不足,恳 请读者批评指正。您宝贵的意见和建议是我们的期待,也是我们继续前进的动力。我们的联 系方式:xu_cheng@yeah.net, heima251210490@163.com。

嵌入式 Linux 初级实验教程

1

目 录
第一篇 开发环境篇
第 1 章 概述 ............................................................................................................... 2
1.1 基本概念 .............................................................................................................................. 2 1.1.1 嵌入式 Linux ................................................................................................................ 2 1.1.2 ARM 处理器................................................................................................................. 3 1.1.3 宿主机和目标机 ........................................................................................................... 5 1.1.4 交叉编译....................................................................................................................... 7 1.1.5 内核............................................................................................................................... 9 1.1.6 根文件系统 ................................................................................................................... 9 1.1.7 系统引导程序(BootLoader) .................................................................................. 10 1.2 嵌入式 LINUX 开发过程简介 ............................................................................................ 11

第 2 章 开发平台介绍 ............................................................................................. 13
2.1 SUPER-ARM 整体结构及资源........................................................................................... 13 2.1.1 Super-ARM 整体结构 ................................................................................................ 13 2.1.2 Super-ARM 教学系统主要资源 ................................................................................ 14 2.2 SUPER-ARM 各模块简介................................................................................................... 16 2.2.1 底板............................................................................................................................. 16 2.2.2 主板............................................................................................................................. 17 2.2.3 核心板......................................................................................................................... 19 2.2.4 LCD 模块 .................................................................................................................... 20 2.2.5 JTAG 仿真器 ProbeICE.............................................................................................. 20 2.2.6 连接电缆及配件 ......................................................................................................... 21

第 3 章 ADS 开发环境搭建 .................................................................................... 22
3.1 搭建硬件开发环境 ............................................................................................................ 22 3.1.1 Super-ARM 供电线路连接 ........................................................................................ 22 3.1.2 JTAG 连接 .................................................................................................................. 23 3.2 搭建软件开发环境 ............................................................................................................ 23 3.2.1 ProbeICE-ARM 服务器配置...................................................................................... 23 3.2.2 ProbeICE-ARM 仿真器配置...................................................................................... 26 3.3 新建工程及仿真调试 ........................................................................................................ 29 3.3.1 新建工程..................................................................................................................... 29 3.3.2 编译及连接 ................................................................................................................. 34 3.3.3 仿真调试..................................................................................................................... 34

第 4 章 嵌入式 LINUX 开发环境搭建 .................................................................. 37
4.1 安装 LINUX 操作系统 ........................................................................................................ 37

嵌入式 Linux 初级实验教程

2

4.1.1 在 Windows 中安装虚拟机........................................................................................ 37 4.1.3 在虚拟机上安装 Ubuntu ............................................................................................ 40 4.2 宿主机 LINUX 系统中基本环境的配置与安装 ................................................................ 43 4.2.1 网络配置..................................................................................................................... 43 4.2.2 更新 Linux 操作系统 ................................................................................................. 45 4.2.3 安装一些相关工具和程序库 ..................................................................................... 45 4.2.4 实际项目工作空间目录的安排 ................................................................................. 45 4.2.5 配置 Linux 下的 minicom .......................................................................................... 46 4.2.6 配置 Linux 下的 TFTP 服务器 .................................................................................. 52 4.3 在主机 LINUX 系统中建立交叉编译环境 ........................................................................ 53 4.3.1 准备工具链软件 ......................................................................................................... 53 4.3.2 建立交叉编译工具链 ................................................................................................. 53

第二篇 系统移植篇 第二篇 系统移植篇
第 5 章 BOOTLOADER 移植 ................................................................................ 58
5.1 系统引导程序基础 ............................................................................................................ 58 5.1.1 Boot Loader 的安装媒介(Installation Medium) .................................................. 58 5.1.2 BootLoader 工作模式................................................................................................. 59 5.1.3 BootLoader 的启动过程 ............................................................................................ 59 5.1.4 BootLoader 与宿主机之间进行文件传输所用的通信设备及协议 ........................ 61 5.1.5 几种常用的 Boot Loader ............................................................................................ 61 5.2 移植 U-BOOT ...................................................................................................................... 63 5.2.1 U-Boot 源码结构 ........................................................................................................ 63 5.2.2 U-Boot 移植过程详解 ................................................................................................ 64 5.2.3 烧写 U-Boot................................................................................................................ 74 5.3 U-BOOT 使用 ...................................................................................................................... 74 5.3.1 U-Boot 命令 ................................................................................................................ 75 5.3.2 U-Boot 命令使用实例 ................................................................................................ 76 5.3.3 U-Boot 引导内核 ........................................................................................................ 79 5.4 U-BOOT 的环境变量 ......................................................................................................... 80 5.4.1 查看环境变量 ............................................................................................................. 80 5.4.2 设置环境变量 ............................................................................................................. 81 5.4.3 保存环境变量 ............................................................................................................. 82

第 6 章 LINUX 内核移植 ....................................................................................... 83
6.1 选择 LINUX 内核 ................................................................................................................ 83 6.2 LINUX 内核移植前准备 ..................................................................................................... 84 6.2.1 Linux 内核源码 .......................................................................................................... 85 6.2.2 内核配置及方法 ......................................................................................................... 86 6.2.3 图形化内核配置选项 ................................................................................................. 87 6.2.4 构建内核映像 ............................................................................................................. 88 6.2.5 构建模块..................................................................................................................... 89 6.2.6 安装内核及内核模块 ................................................................................................. 89 6.3 LINUX 内核移植实例 ......................................................................................................... 90

嵌入式 Linux 初级实验教程

3

6.3.1 配置编译内核的过程 ................................................................................................. 90 6.3.2 从 NandFlash 引导内核 ............................................................................................. 93 6.3.3 网络引导内核 ............................................................................................................. 94

第 7 章 根文件系统移植 ......................................................................................... 96
7.1 文件系统概述 .................................................................................................................... 96 7.1.1 文件系统..................................................................................................................... 96 7.1.2 根文件系统 ................................................................................................................. 98 7.2 制作根文件系统 ................................................................................................................ 99 7.2.1 Busybox 工具 ............................................................................................................. 99 7.2.2 根文件系统制作实例 ............................................................................................... 100 7.3 配置 NFS 服务 ................................................................................................................. 107 7.3.1 NFS 文件系统简介 .................................................................................................. 107 7.3.2 在 Linux 下配置 NFS 服务器 .................................................................................. 109 7.4 目标机挂载 NFS 根文件系统 ......................................................................................... 112 7.4.1 移植网卡驱动 ........................................................................................................... 113 7.4.2 挂载 NFS 根文件系统 ............................................................................................. 115 7.5 HELLO WORLD 测试程序 ................................................................................................. 119 7.6 文件系统移植 .................................................................................................................. 120 7.6.1 配置内核命令行参数 ............................................................................................... 121 7.6.2 制作 cramfs 文件系统 .............................................................................................. 121 7.6.3 将根文件系统烧写到 NandFlash ............................................................................ 122

第三篇 基础实验篇 第三篇 基础实验篇
第 8 章 LINUX 设备驱动概述 ............................................................................. 125
8.1 设备驱动的角色 .............................................................................................................. 125 8.2 设备驱动和操作系统 ...................................................................................................... 126 8.2.1 无操作系统时的设备驱动 ....................................................................................... 126 8.2.2 有操作系统时的设备驱动 ....................................................................................... 128 8.3 LINUX 设备驱动 ............................................................................................................... 129 8.3.1 Linux 设备的分类及特点 ........................................................................................ 129 8.3.2 不同设备的驱动设计概述 ....................................................................................... 130 8.3.3 Linux 设备文件的创建 ............................................................................................ 133 8.3.4 Linux 驱动程序的加载和卸载 ................................................................................ 134 8.3.5 学习 Linux 驱动程序的基础及方法 ....................................................................... 135

第 9 章 LED 实例 ................................................................................................ 136
9.1 字符设备驱动程序的结构 ................................................................................................ 136 9.1.1 常用的头文件 ........................................................................................................... 136 9.1.2 主次设备号 ............................................................................................................... 137 9.1.3 cdev 结构体 .............................................................................................................. 137 9.1.4 分配和释放设备号 ................................................................................................... 139 9.1.5 File_operation 结构体 .............................................................................................. 139

嵌入式 Linux 初级实验教程

4

9.1.6 字符设备驱动程序一般结构 ................................................................................... 141 9.2 LED 设备驱动实例.......................................................................................................... 143 9.2.1 实验目的................................................................................................................... 143 9.2.2 实验原理................................................................................................................... 143 9.2.3 实验任务................................................................................................................... 145 9.2.4 实验步骤................................................................................................................... 145

第 10 章 按键中断实例 ......................................................................................... 153
10.1 S3C2410 中断机制......................................................................................................... 153 10.1.1 中断向量表............................................................................................................. 153 10.1.2 中断控制器............................................................................................................. 154 10.2 嵌入式 LINUX 中断处理程序架构 ................................................................................ 160 10.2.1 Linux 中断处理程序的上半部与下半部机制 ...................................................... 160 10.2.2 Linux 中断编程 ...................................................................................................... 160 10.3 按键中断驱动实例 ........................................................................................................ 163 10.3.1 实验目的................................................................................................................. 163 10.3.2 实验原理................................................................................................................. 163 10.3.3 实验任务................................................................................................................. 164 10.3.4 实验步骤................................................................................................................. 164

第 11 章 数码管实例.............................................................................................. 172
11.1 数码管显示原理............................................................................................................. 172 11.1.1 数码管简介 ............................................................................................................. 172 11.1.2 数码管显示原理 ..................................................................................................... 173 11.1.3 数码管驱动电路设计 ............................................................................................. 174 11.2 数码管设备驱动实例..................................................................................................... 176 11.2.1 实验目的 ................................................................................................................. 177 11.2.2 实验原理 ................................................................................................................. 177 11.2.3 实验任务 ................................................................................................................. 178 11.2.4 实验步骤 ................................................................................................................. 178

第 12 章 4*4 矩阵键盘实例 .................................................................................. 189
12.1 键盘接口概述 ................................................................................................................ 189 12.1.1 键盘的分类............................................................................................................. 189 12.1.2 键盘的扫描............................................................................................................. 190 12.1.3 键盘的防抖............................................................................................................. 191 12.1.4 键盘的缓冲算法 ..................................................................................................... 191 12.2 4*4 键盘驱动实例 ......................................................................................................... 192 12.2.1 实验目的................................................................................................................. 192 12.2.2 实验原理................................................................................................................. 192 12.2.3 实验任务................................................................................................................. 194 12.2.4 实验步骤................................................................................................................. 195

第 13 章 LCD 驱动实例 ........................................................................................ 209
13.1 LCD 的硬件原理 ........................................................................................................... 209

嵌入式 Linux 初级实验教程

5

13.1.1 LCD 的显像原理 .................................................................................................... 209 13.1.2 LCD 的分类 ............................................................................................................ 210 13.1.3 TFT LCD 的工作时序及参数设置 ........................................................................ 210 13.2 S3C2410 的 LCD 控制器及 IO 配置 ............................................................................ 213 13.2.1 LCD 控制器 ............................................................................................................ 214 13.2.2 LCD 控制器的寄存器设置 .................................................................................... 214 13.2.3 S3C2410 的 LCD 接口及配置 .............................................................................. 217 13.3 基于帧缓冲(FRAMEBUFFER)的 LCD 驱动分析 ...................................................... 218 13.3.1 FrameBuffer 设备驱动分析 ................................................................................... 218 13.3.2 基于 FrameBuffer 的 LCD 驱动分析 ................................................................... 223 13.3.3 FrameBuffer 驱动与 LCD 驱动之间的关系 ........................................................ 230 13.4 LCD 驱动移植实例 ....................................................................................................... 231 13.4.1 实验目的................................................................................................................. 231 13.4.2 实验原理................................................................................................................. 231 13.4.3 实验任务................................................................................................................. 231 13.4.4 实验步骤................................................................................................................. 231

第 14 章 触摸屏实例 ............................................................................................. 235
14.1 触摸屏的硬件原理 ........................................................................................................ 235 14.2 S3C2410 的触摸屏控制................................................................................................. 236 14.2.1 S3C2410 的 ADC 及触摸屏接口原理................................................................... 236 14.2.2 S3C2410 的 ADC 和触摸屏接口模式................................................................... 238 14.2.3 S3C2410 的 ADC 及触摸屏控制寄存器............................................................... 239 14.2.4 S3C2410 的触摸屏中断控制 ................................................................................. 240 14.3 LINUX 输入子系统 ....................................................................................................... 241 14.3.1 Input 子系统架构 ................................................................................................... 241 14.3.2 Input 子系统数据结构 ........................................................................................... 241 14.3.3 Input 设备驱动编写 ............................................................................................... 242 14.3.4 Input 设备驱动范例 ............................................................................................... 243 14.4 触摸屏驱动移植实例 .................................................................................................... 243 14.4.1 实验目的................................................................................................................. 243 14.4.2 实验原理................................................................................................................. 244 14.4.3 实验任务................................................................................................................. 250 14.4.4 实验步骤................................................................................................................. 250

第四篇 图形应用篇 第四篇 图形应用篇
环境搭建 第 15 章 嵌入式 QT 环境搭建.............................................................................. 255
15.1 嵌入式 GUI 简介 ........................................................................................................... 255 15.1.1 MiniGUI .................................................................................................................. 256 15.1.2 OpenGUI ................................................................................................................. 257 15.1.3 Qt/Embedded .......................................................................................................... 257 15.2 QT 开发环境搭建 ........................................................................................................ 259 15.2.1 Ubuntu 下安装 QT 开发环境 ................................................................................ 259 15.2.2 Qt Assistant ............................................................................................................. 260

嵌入式 Linux 初级实验教程

6

15.2.3 Qt Designer ............................................................................................................. 262 15.2.4 QDevelop ................................................................................................................ 262 15.3 QT/EMBEDDED 环境的安装 .......................................................................................... 264 15.3.1 安装 tslib ................................................................................................................. 264 15.3.2 安装 Qt/Embedded.................................................................................................. 265 15.3.3 环境配置及触摸屏校准 ......................................................................................... 267

第 16 章 嵌入式 QT 之 HELLOWORLD ........................................................... 269
16.1 QT/E 信号与插槽机制 ................................................................................................... 269 16.1.1 信号和插槽机制 ..................................................................................................... 269 16.1.2 信号和插槽机制的实现 ......................................................................................... 270 16.2 HELLOWORLD 实例 ....................................................................................................... 273 16.2.1 实验目的................................................................................................................. 273 16.2.2 实验任务................................................................................................................. 273 16.2.3 实验步骤................................................................................................................. 274

第 17 章 综合实例 ................................................................................................. 281
17.1 实验目的.................................................................................................................... 281 17.2 实验任务.................................................................................................................... 281 17.3 实验步骤.................................................................................................................... 282

参考文献 ................................................................................................................... 296

嵌入式 Linux 初级实验教程

1

第一篇

开发环境篇

本篇内容
概述 ★ 开发平台介绍 ★ ADS 开发环境搭建 ★ 嵌入式 Linux 开发环境搭建 ★

本篇目标
了解嵌入式 Linux 开发过程中会涉及到的一些基本概念 ★ 了解本书实例所使用的硬件开发平台 ★ 熟悉 ADS 开发环境的安装过程及使用方法 ★ 掌握主机 LINUX 开发环境中虚拟机的安装方法及相关开发工具详细配置过程 ★

本篇实例
实例一:ADS 相关开发工具的安装及使用 ★ 实例二:虚拟机上 Linux 工作站的安装及配置 ★ 实例三:Minicom 及 TFTP 的安装配置 ★ 实例四:交叉编译工具链的制作 ★

嵌入式 Linux 初级实验教程

2

第1章

概述

好的,开始吧。 本书的目的就是带领读者你完成一个任务——在一块空的嵌入式开发板上移植一个基 于 Linux 的应用程序实例。在进行我们的嵌入式 Linux 开发过程之前,也许你心中正在问: “嵌入式 Linux” ,这究竟是一个怎样的世界?从这一刻开始,让我们一起步入这个世界吧。 当你已经拿到本书的出版物的时候, 不管你是未过门的还是刚入门的, 我想你一定是对 “嵌入式 Linux”感兴趣的,所以假定你已经知道什么是嵌入式系统了,套用现在流行的定 义“嵌入式系统是以应用为中心,以计算机技术为基础,软硬件可裁剪,对功能、可靠性、 成本、功耗、体积等有严格要求的专用计算机系统” ,而且我们几乎天天在跟嵌入式设备打 交道,别不承认,你有几天离开过你的手机?你一个人听歌或者听英语的时候是不是要 Mp 3 呢?还有,我们的公交车上,银行里几乎都存在嵌入式设备。同样,我也认为你已经知道 Linux 是什么了,甚至还在自己的 PC 上安装过 Linux,进行过 Linux 的开发。在此,我就不 多费口舌介绍“什么是 Linux”了。至于“什么是嵌入式 Linux” ,恐怕很多读者都想得到答 案,笔者在接下来的基本概念中将做简单介绍。 本章接下来向大家介绍嵌入式 Linux 开发中的一些基本概念, 以及嵌入式 Linux 的开发 过程,让读者对在开发过程中遇到的一些术语不至于感到陌生,同时也对嵌入式 Linux 的开 发有个大致的了解。当然,你读完这一章之后对于某些概念,可能还是不甚理解,不妨先把 疑问留下,相信随着开发过程的深入,你一定会得到答案的,到时候再回过头来阅读这些概 念,便会明了了。

1.1
1.1.1 嵌入式 Linux

基本概念

嵌入式 Linux(Embedded Linux)是指对标准 Linux 经过小型化裁剪处理之后,能够固 化在容量只有几 KB 或者几 MB 字节的存储器芯片(如 Flash)或者单片机中,是适合于特 定嵌入式应用场合的专用 Linux 操作系统。 嵌入式 Linux 同 Linux 一样,具有低成本、高性能、支持多种硬件平台和良好的网络支 持等优点。另外,嵌入式 Linux 为了更好地适应嵌入式领域的开发,还在 Linux 基础上做了 不少改进,例举部分如下: (1)改善的内核结构 整个 Linux 内核是一个单独的、非常大的程序,这种整体式结构虽然能够使系统的各个 部分直接沟通,提高系统响应速度,但与嵌入式系统存储容量小、资源有限的特点不符合。 因此, 嵌入式系统中经常采用的是一种称为微内核的体系结构, 即内核本身只提供一些最基 本的操作系统功能,如任务调度、内存管理、中断处理等,而类似于文件系统和网络协议等 附加功能则运行在用户空间中, 并且可以根据实际需要进行裁剪。 这样就大大减小了内核的 体积,便于维护和移植。 (2)提高的系统实时性 由于现有的 Linux 是一个通用的操作系统, 虽然它也采用了许多技术来加快系统的运行 和响应速度,但从本质上来说并不是一个嵌入式实时操作系统。因此,利用 Linux 作为底层 操作系统,在其上进行实时化改造,从而构建出一个具有实时处理能力的嵌入式系统,如 R T-Linux 已经成功地应用于航天飞机的空间数据采集、科学仪器测控和电影特技图像处理等 各种领域。

嵌入式 Linux 初级实验教程

3

嵌入式 Linux 同 Linux 一样,也有众多的版本,主要有以下这些: 版本 简单介绍 开放源码的嵌入式 Linux 的典范之作。它主要是针对目标处理器没有存储 管理单元 MMU,其运行稳定,具有良好的移植性和优秀的网络功能,对 各种文件系统有完备的支持,并提供标准丰富的 API。 由美国墨西哥理工学院开发的嵌入式 Linux 硬实时操作系统。它已有广泛 的应用。 根据嵌入式应用系统的特点重新设计的 Linux 发行版本。 它提供了超过 25 种的 Linux 系统服务, 包括 Web 服务器等。 此外还推出了 Embedix 的开发 调试工具包、基于图形界面的浏览器等。可以说,Embedix 是一种完整的 嵌入式 Linux 解决方案。 采用了“超字元集”专利技术,使 Linux 内核不仅能与标准字符集相容, 还涵盖了 12 个国家和地区的字符集。因此,XLinux 在推广 Linux 的国际 应用方面有独特的优势。 它可以提供跨操作系统并且构造统一的、标准化的和开放的信息通信基础 结构,在此结构上实现端到端方案的完整平台。 由北京中科院红旗软件公司推出的嵌入式 Linux,它是国内做得较好的一 款嵌入式操作系统。目前,中科院计算机研究所自行开发的开放源码的嵌 入式操作系统——Easy Embedded OS(EEOS)也已经开始进入实用阶段。
表 1-1-1 嵌入式 Linux 的主要版本

uCLinux

RT-Linux

Embedix

XLinux

PoketLinux

红旗嵌入式 Linux

表 1-1-1 所列出的嵌入式 Linux 的不同版本分别是针对不同的需要在内核等方面加入了 特定的机制而定制的,在很多嵌入式 Linux 应用中,开发者一般在标准发行版 Linux 内核的 基础上直接为自己的硬件平台定制裁剪嵌入式 Linux 系统。 正如上面所说,在“嵌入式开发”的语境中,嵌入式 Linux 通常指一个针对特定硬件 设备的完整的系统;而在“嵌入式 Linux 厂商”的语境中,嵌入式 Linux 用于表示以嵌入 式系统为需求对象的发行套件,如“嵌入式 Linux 发行套件”指的是为嵌入式系统与开发 工具量身定制的软件套件,以便建立一个完整的系统。嵌入式 Linux 发行套件所提供的开 发工具可能包括: 交叉编译器、 调试器、 引导映像生成器等等 (你可能对这些概念感到陌生, 笔者将在开发中陆续介绍) 。

1.1.2

ARM 处理器

(1)ARM 简介 ARM(Advanced RISC Machines) ,既可以认为是一个公司的名字,也可以认为是对一 类微处理器的通称,还可以认为是一种技术的名字。 ARM 公司主要出售芯片设计技术的授权。目前,采用 ARM 技术知识产权(IP)核的 微处理器,即我们通常所说的 ARM 处理器,已遍及工业控制、消费类电子产品、通信系统、 网络系统、 无线系统等各类产品市场, 基于 ARM 技术的微处理器应用占据 32 位 RISC 微处 理器 75%以上的市场份额。

嵌入式 Linux 初级实验教程

4

ARM 公司是专门从事基于 RISC 技术芯片设计开发的公司,作为知识产权供应商,它 本身不直接从事芯片生产,靠转让设计许可,由合作公司生产各具特色的芯片,世界各大半 导体生产商从 ARM 公司购买其设计的 ARM 处理器核,根据各自不同的应用领域,加入适 当的外围电路,从而形成自己的 ARM 处理器芯片进入市场。目前,全世界有几十家大半导 体公司都使用 ARM 公司的授权,因此既使得 ARM 技术获得更多的第三方工具、制造、软 件的支持,又使整个系统成本降低,从而使产品更容易进入市场被消费者所接受,更具有竞 争力。 (2)ARM 处理器的应用领域及特点 到目前为止,ARM 处理器及技术的应用几乎已经深入到各个领域,并会在将来取得更 加广泛的应用。 工业控制领域: 作为 32 位的 RISC 架构, 基于 ARM 核的微控制器芯片不但占据了 高端微控制器市场的大部分份额, 同时也逐渐向低端微控制器应用领域扩展, ARM 微控制器的低功耗、高性价比,向传统的 8 位/16 位微控制器提出了挑战。 无线通信领域:目前已有 85%以上的无线通信设备采用了 ARM 技术,ARM 以其 高性能和低成本的特点,在该领域的地位日益巩固。 网络应用:随着宽带技术的推广,采用 ARM 技术的 ADSL 芯片正逐步获得竞争优 势。此外,ARM 在语音及视频处理上进行了优化,并获得广泛支持,也对 DSP 的 应用领域提出了挑战。 消费类电子产品:ARM 技术在目前流行的数字音频播放器、数字机顶盒和游戏机 中得到广泛采用。 ARM 处理器一般具有如下特点。 体积小、低功耗、低成本、高性能; 支持 Thumb(16 位)/ARM(32 位)双指令集,能很好地兼容 8 位/16 位器件; 大量使用寄存器,指令执行速度更快; 大多数数据操作都在寄存器中完成; 寻址方式灵活简单,执行效率高; 指令长度固定。 (3)ARM 处理器系列 下面所列的是 ARM 处理器的几个系列,以及其他厂商基于 ARM 体系结构的处理器, 这些处理器除了具有 ARM 体系结构的共同特点以外,每一个系列的 ARM 处理器都有各自 的特点和应用领域。 ARM7 系列 ARM9 系列 ARM9E 系列 ARM10E 系列 SecurCore 系列 Intel 的 Xscale Intel 的 StrongARM 其中,ARM7、ARM9、ARM9E 和 ARM10 为 4 个通用处理器系列,每一个系列提供一 套相对独特的性能来满足不同应用领域的需求。如 SecurCore 系列专门为安全要求较高的应 用而设计。 下面详细介绍 ARM7 处理器及 ARM9 处理器的特点。

嵌入式 Linux 初级实验教程

5

ARM7 处理器 ARM7 系列微处理器为低功耗的 32 位 RISC 处理器,最适合用于对价位和功耗要求较 高的消费类应用。ARM7 微处理器系列具有如下特点: 具有嵌入式 ICE-RT 逻辑,调试开发方便。 极低的功耗,适合对功耗要求较高的应用,如便携式产品。 能够提供 0.9MIPS/MHz 的三级流水线结构。 代码密度高并兼容 16 位的 Thumb 指令集。 对操作系统的支持广泛,包括 Windows CE、Linux、Palm OS 等。 指令系统与 ARM9 系列、ARM9E 系列和 ARM10E 系列兼容,便于用户的产 品升级换代。 主频最高可达 130MIPS,高速的运算处理能力能胜任绝大多数的复杂应用。 ARM7TDMI、 ARM7TDMI-S、 ARM720T、 ARM7 系列微处理器包括如下几种类型的核: ARM7EJ。其中,ARM7TMDI 是目前使用最广泛的 32 位嵌入式 RISC 处理器,属低端 ARM 处理器核。TDMI 的基本含义为: T:支持 16 位压缩指令集 Thumb; D:支持片上 Debug; M:内嵌硬件乘法器(Multiplier); I:嵌入式 ICE,支持片上断点和调试点。 ARM9 处理器 ARM9 系列微处理器在高性能和低功耗特性方面提供最佳的性能。具有以下特点: 5 级整数流水线,指令执行效率更高。 提供 1.1MIPS/MHz 的哈佛结构。 支持 32 位 ARM 指令集和 16 位 Thumb 指令集。 支持 32 位的高速 AMBA 总线接口。 全性能的 MMU,支持 Windows CE、Linux、Palm OS 等多种主流嵌入式操作 系统。 MPU 支持实时操作系统。 支持数据 Cache 和指令 Cache,具有更高的指令和数据处理能力。 ARM9 系列微处理器包含 ARM920T、ARM922T 和 ARM940T 三种类型,以适用于不 同的应用场合。本书的开发平台上使用的处理器就是 ARM920T。

1.1.3

宿主机和目标机

宿主机其实就是我们的开发主机, 大多数时候指的就是我们日常使用的 PC 机, 我们在 宿主机上进行应用程序的开发;而目标机就是我们的开发板,也叫做目标板,它为应用程序 提供运行环境。 在开发过程中,宿主机与目标机必须进行信息交互,如在调试过程中,宿主机要向目标 机发送调试控制命令,目标机则需要向宿主机返回调试状态信息,开发完成后,宿主机需要 将代码下载到目标机上。为了实现信息交互,宿主机与目标机之间必须存在物理的连接,连 接方式依交互方式的不同而改变,主要包括 JTAG 连接,串口连接,网络连接,USB 连接。 (1)JTAG 连接 JTAG 主 要 用 来 实现 程 序 的 下 载以 及仿 真, 在 嵌 入式 Linux 开 发中 也用 来移 植 BootLoader,它一般通过 USB 或者并口将宿主机与目标机连接在一起。针对本书中使用的

嵌入式 Linux 初级实验教程

6

Super-ARM 平台的 JTAG 连接方式将在第三章中描述,这里先不讲述。 (2)串口连接 串口在调试过程中占有重要地位, 它与串口调试工具 (如 Windows 下的超级终端和 Linux 下的 minicom)相结合便组成一个调试控制台,该控制台可以获取用户从键盘输入的控制命 令,并显示出来,然后将控制命令通过串口传送到目标机上;同时,该控制台还可以通过串 口获取目标机返回的调试信息,也将其显示出来,供用户查看。当然你也可以用串口来传输 文件,但是速度太慢了,不推荐使用。 串口有 9 针和 25 针两种,现在的 PC 机上一般只有 9 针的串口,而嵌入式开发中通常 也都使用 9 针串口进行通信。所谓 9 针串口就是指串口有 9 个引脚,对应 9 根信号线,如下 表: 引脚号 1 2 3 4 5 6 7 8 9 功能描述 数据载波检测 接收数据 发送数据 数据终端准备 信号地 数据设备准备好 请求发送 清除发送 振铃指示
表 1-1-2 9 针串口信号引脚列表

字母代号 DCD RXD TXD DTR GND DSR RTS CTS DELL

不过,在实际通信过程中这 9 根信号线并不都需要,通常只要将 RXD 、TXD、 GND 这 3 个信号连接起来就足够了, 这也就是我们常说的串口的三线制接法。 至于信号之间具体 是怎么连接的,那是硬件工程师的事情(当然这个很简单,有兴趣的也可以去了解一下) 。 而我们现在需要做的就是找到 Super-ARM 实验箱中的串口线缆,将它的一端插座实验箱的 串口 1 上,另一端插在 PC 机上就可以了。 (3)网络连接 网络,现在已经成为我们生活中相当重要的一部分,其优点自不必多说。 在嵌入式系统中涉及到的大批量数据传输,如视频、图像等都是通过网络实现。而在嵌 入式的开发过程中, 也常常将宿主机和目标机组建成一个网络, 方便宿主机和目标机之间的 文件传输。比如,在宿主机上运行 TFTP 服务器,可以将内核和文件系统烧写到目标机的 Flash 存储器中;也可以在宿主机上启动 NFS(网络文件系统)服务,挂载一个网络文件系 统,方便目标机访问宿主机的数据。 网络的连接需要完成以下几项工作,以 PC,Super-ARM 为例:

嵌入式 Linux 初级实验教程

7

首先,用网络交叉线(Super-ARM 实验箱有提供)直接将 PC 机和 Super-ARM 相连; 或者用两根网络直连线(平常用的网线)和一个交换机,一根将 PC 和交换机连接,一根将 Super-ARM 和交换机连接。这样就完成了宿主机和目标机的物理连接。 然后,需要配置宿主机和目标机的 IP,子网掩码和默认网关,使宿主机和目标机在同一 网段。 (4)USB 连接 USB 接口支持热插拔,即插即用,而且传输速度快,这些优点使得 USB 无处不见。无 论 PC 机还是嵌入式设备,几乎都留有 USB 接口。USB 现在有两个规范,一个是 USB1.1, 一个是 USB2.0,前者最高传输率是 12Mbps,后者最高达到 480Mbps。 USB 也广泛应用在嵌入式开发中,如很多厂商提供的仿真器使用的是 USB 接口;嵌入 式系统通过挂载 USB 接口的可移动存储设备,访问设备中的数据。

1.1.4

交叉编译

(1)为什么需要交叉编译 当我们需要从源代码编译出一个能运行在 ARM 架构上的程序的时候,可以有两种方 法。 第一种是像平常一样, 使用相同架构机器上的编译器, 编译出运行在同一架构上的程序。 在嵌入式系统领域,这是较难实现的。嵌入式系统是专用的计算机系统,它对系统的成本, 功耗,体积等有严格的要求,因此大部分嵌入式设备都没有鼠标,键盘,显示器,大容量硬 盘等外设, 这些硬件的特殊性决定了嵌入式系统往往没有足够的硬件资源支持安装发行版的 Linux、运行相应的开发工具和调试工具,所以,通常嵌入式系统的软件开发采用一种交叉 编译的方式。 (2)什么是交叉编译 什么是交叉编译呢?简单地来说,交叉编译就是在一个平台上(如 PC)生成另一个平 台上(如 ARM)可运行代码的编译技术。在嵌入式开发中,由于宿主机和目标机的处理器 架构一般不相同,宿主机(如 PC)为 Intel 处理器,而目标机(如 Super-ARM 实验箱)为 三星 S3c2410 处理器, 因此在宿主机上可以运行的代码却不一定能在目标机上运行。 要解决 这个问题,就需要在宿主机上生成目标机上运行的代码,也叫做目标代码,这一过程就是嵌 入式系统中的交叉编译。 (3)什么是交叉编译工具链 要完成程序编译并生成可执行代码,都要经过一系列的处理,这一系列处理包括:预编 译,高级语言编译,汇编,连接及重定位。这些处理过程需要一系列的编译链接工具和相关 的库,包括 gcc 编译器、ld 连接器、gas 解释器、ar 打包器,还包括 C 程序库 glibc 以及 gdb 调试器,这些工具的集合组成了一套编译工具链。 一般的情况下,工具链的运行环境和它产生的目标代码的环境是一致的。例如在 VC 中 编译一个程序,工具链在 x86 平台上运行,编译产生的也是运行在 x86 平台上的目标代码。 但实际上, 工具链编译产生的目标代码的运行平台可以与工具链本身运行的环境不一致, 这 种工具链,称为交叉工具链(cross-compiler tool chain),使用这种工具链的编译过程对应地被 称为交叉编译(cross-compile)。 理论上来说,交叉工具链可以用在任何两种异构的系统中, 例如,可以构建出 PowerPC-ARM 工具链,Sun Sparc-x86 工具链等等。在基于 ARM 的嵌入 式系统开发中,一般会使用 x86 架构的计算机系统作为宿主机,故最为常用的是 x86-ARM 交叉工具链。 宿主机上安装了发行版的 Linux,它包含了一整套完整的工具链,这套工具链在嵌入式 开发中又称为本地工具链;在嵌入式 Linux 开发中,拥有一套完善的工具链也相当重要,这 套工具链被称为交叉编译工具链。 交叉编译工具链的每个工具名字都加了一个前缀, 用来区

嵌入式 Linux 初级实验教程

8

别本地的工具链(例如:arm-linux-gcc,arm-linux-ar 等) ,除了体系结构相关的编译选项以 外, 它的使用方法与宿主机上的 gcc 相同。 所以 Linux 编程技术对于嵌入式 Linux 同样适用。 (4)工具链相关软件 目前市场上存在着各种各样不用的 x86-ARM 交叉工具链,常用的交叉工具链有开发 和商业两种类型,商业类型的有 ARM 公司自家在 RVDS 开发工具中整合的 armcc,有 Microsoft 在 Platform Builder 中的 armv4I 编译器等。一般来说,这些由商业公司提供的工具 链,都不会附有工具链相关的源代码和制作方法,灵活性不足,并且它们一般都与整套开发 系统捆绑销售使用,成本较高。开放类型的典型代表是 GNU 工具链,目前已经能支持 x86、 PowerPC、ARM 等处理器。为了更好的理解这种技术和降低成本,获得更好的灵活性,市 场上有不少的公司使用国际开源组织 GNU 开发的工具链来作为他们的产品开发工具。 Linux 软件从一开始就使用 GNU 的工具链。这些 GNU 的工具和软件都是开放源码的, 可以免费下载源码编译。 但是并不能以为任何一个版本拿来都能用, 各种软件包存在版本匹 配问题,并且不同版本都有一些补丁。 GNU 的工具链软件源码包可以从 GNU 网站 http://www.gnu.org 下载。这个站点有很 多 GNU 软件,其中 Linux 使用的工具链软件是:binutils、gcc、glibc 和 gdb。通过这些软件 包,可以生成 gcc、g++、ar、as、ld 等编译链接工具,还可以生成 glibc 库和 gdb 调试器。 下面简单介绍一下这些工具链软件。 binutils 是二进制程序处理工具,包括连接器、汇编器等目标程序处理的工具。 gcc(GNU Compiler Collection)是编译器,不但能够支持 C/C++语言的编译,而且 能够支持 Fortran、 Java、 Ada 等编程语言。 不过, 一般不需要配置其他语言的选项, 需要支 也可以避免编译其他语言功能而导致的错误。 对于 C/C++语言的完整支持, 持 glibc 库。 glibc 是应用程序编程的函数库软件包,可以编译生成静态库和共享库。完整的 gcc 需要支持 glibc。 gdb 是调试工具,可以读取可执行程序中的符号表,对程序进行源码调试。 (5)如何构建交叉编译工具链 理论上讲,要构建出一个交叉工具链,需要解决三个问题。一是这个工具链必须是可以 运行在宿主机平台上的; 二是需要更换一个与目标平台对应的汇编器, 使得工具链能产生对 应的目标代码; 三是要更换一套与目标平台对应的二进制库, 使得工具链在连接时能找到正 确的二进制库。解决了这三个问题,交叉编译工具链也就建立起来了。 但是, 建立交叉编译工具链是一个微妙而又相当复杂的过程, 它需要你了解工具链软件 的版本、补丁、为各种架构调整各种工具链组件等难懂的知识,这些知识不仅分散在许多地 方,并因软件的版本而有所不同。一个刚入门(或甚至是已有些经验)的嵌入式 Linux 系 统建构者当然无法独自应付。 如果不想自己经历复杂繁琐的编译过程, 那么最简单的方法就是直接从网上下载已经制 作 好 的 可 用 的 交 叉 编 译 工 具 链 。 如 cross-2.95.3 这 个 工 具 链 可 以 在 ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/ 站点获得。 当然, 如果你真的很勇敢或者刚好你手上有许多空闲的时间, 而且你渴望学习交叉工具 链构建程序的整个细节, 我强烈建议自己手动构建交叉编译工具链, 你可以参考 “Cross Linux From Scratch”项目(http://trac.cross-lfs.org)的做法。这种手动制作的方法就是要指导大家 从选定各个软件的版本,下载这些软件版本的源码包和补丁开始,到编译各个软件包,一步 一步地编译出自己的交叉编译器。 决定采用这种方法之前, 你还是做好心理准备, Dan Kegel (Crosstool 的主要作者)对“手动建构交叉工具链”所做的描述: “构建一个交叉工具链供 嵌入式系统开发使用是一个令人恐惧的景象,需要钢铁般的意志,需要几天(如果不是几个 星期)的功夫,需要具备许多的 Unix 和 GNU 知识……” 虽然你绝对能够手动完成工具链的构建,但笔者还是推荐使用 crosstool 工具自动完成

嵌入式 Linux 初级实验教程

9

交叉工具链的构建。关于 crosstool 工具以及如何利用该工具构建交叉编译工具链,在本章 后续内容中,将详细介绍。其中用到的软件和版本组合都是经过预先测试的,它们是能够替 特定的架构产生可用工具链的已知组合。这让刚入门的嵌入式 Linux 系统开发者(或许就 是你)能够轻易构建出可用的工具链,而不需要变成了解各种工具链软件版本状态的专家。

1.1.5

内核

内核 (kernel) 是所有 Linux 系统的主要软件组件。 它的责任是管理目标系统中的硬件, 以免系统上各种软件组件之间为了使用硬件资源而一团混乱。 基本上, 可以说内核是一个资 源中介。由它负责安排特定 Linux 系统中现有硬件资源的使用以及调解硬件资源的存取。 内核所管理的资源包括提供给程序的系统处理器时间、现有 RAM 的使用,以及间接存取 的大量硬件设备。 应用程序可以通过内核所提供的各种软件概念存取系统资源, 而不需要直 接与硬件沟通。 Linux 内核的功能取决于内核构建时所设定的配置。 内核的配置可以让你移除非必要的 支持或者永远不会被用到的功能。 例如, 你可以从不支持网络的嵌入式设备移除对许多不同 网络文件系统的支持。相反的,你可以特别对所选用目标系统独有的周边设备提供支持。此 外,许多功能还可以被构建成选项、执行期载入、模块化组件。这样可以在需要特定功能时 载入它们。 嵌入式设备的 Linux 内核开发,通常依处理器的架构进行划分。例如,Russell King 领 导了一群开发者致力于将 Linux 移植到 ARM 的开发板上(http://www.arm.linux.org.uk/) , 这些 ARM 开发者的工作基础是 Linus Torvalds 所发行的官方 Linux 内核,并且为它开发 出了 ARM 专属的补丁文件。这些源代码补丁文件的作用包括启用新的硬件支持、修正官 方内核中会影响 ARM 架构的既有漏洞等,而这些补丁文件也会并入官方的内核。因此, 我们通常直接使用官方 Linux 内核。 官方 Linux 内核可以到 http://www.kernel.org/ 下载。

1.1.6

根文件系统

Linux 内核在系统启动期间所进行的最后一项操作就是挂载根文件系统。 根文件系统或 者可以认为是一组特定的目录结构,不同的目录里面存放了不通名称,不同用途的文件,方 便系统及用户应用程序查找及调用, (1) 根文件系统的基本结构 根文件系统中各顶层目录,均有其特殊的用法和目的。表 1-1-3 提供了根文件系统各顶 层目录的完整清单。 目录 bin boot dev etc home 必要的用户命令(二进制文件) 引导加载程序所使用的静态文件 设备文件和其他特殊文件 系统配置文件,包括启动文件 用户主目录 内容

嵌入式 Linux 初级实验教程

10

lib media mnt opt proc root sbin sys tmp usr var

必要的程序库(例如 C 程序库)以及内核模块 挂载点,用于可移除媒体 挂载点,用于临时挂载的文件系统 附加的软件套件 用于提供内核与进程信息的虚拟文件系统 root 用户的主目录 必要的系统管理员命令(二进制文件) 系统信息与控制(总线、设备以及驱动程序)的虚拟文件系统 临时文件 在第二层包含了对大多数用户有用的大量应用程序和文件,包括 X 服务器 用于存放服务程序和工具程序的可变资料
表 1-1-3 根文件系统各顶层目录

如果你在桌面 PC 上安装了发行版的 Linux,并且经常使用它,那么你应该已经熟悉其 中一些目录了。不过在嵌入式 Linux 系统中,所有与多用户环境有关的目录,例如 /home、 /mnt、/opt 和 /root,都可以省略;其余的目录/bin、/dev、/etc、/lib、/proc、/sbin 和 /usr 则是不可或缺的;有时候,如果将内核配置成不支持相应的虚拟文件系统的话,/proc 和/sys 也可以省略;/usr 和 /var 这两个顶层目录,与根目录非常像,它们自己有预定的层次结构。 (2)NFS 根文件系统 网络文件系统(NFS,Network File System)最早是 SUN 开发的一种文件系统。NFS 允 许一个系统在网络上共享目录和文件。 通过使用 NFS,用户和程序可以像访问本地文件一样访问远程系统上的文件,这样, 本地工作站使用更少的磁盘空间, 因为通常的数据可以存放在一台机器上而且可以通过网络 访问到,这极大地简化了信息共享。 Linux 系统支持 NFS,并且可以配置启动 NFS 网络服务。而网络文件系统的优点正好 适合嵌入式 Linux 系统开发。目标板没有足够的存储空间,Linux 内核挂接网络根文件系 统可以避免使用本地存储介质,快速建立 Linux 系统。这样可以方便运行和调试应用程序。 如何配置 NFS 及在开发过程中如何使用 NFS 在后续篇章中将被讨论到。

1.1.7

系统引导程序(BootLoader)

BootLoader 是在系统上电之后, 操作系统内核运行之前执行的一段程序, 主要负责载入 系统内核。尽管它在系统启动期间执行的时间非常短,但它却是非常重要的系统组件。任何 运行 Linux 核心的系统几乎都需要用到 bootloader。但是嵌入式系统通常会有进一步的限 制,使得启动过程跟典型的桌面型 Linux 开发系统有些不同。 由于 BootLoader 必须与硬件打交道,而嵌入式处理器的种类较多,不同处理器架构区

嵌入式 Linux 初级实验教程

11

别较大,就算相同架构的不同电路板之间也有很大差异,而 BootLoader 的选用,设置及配 置与所使用的硬件有很大关系,所以没有通用的 BootLoader。这需要开发人员在了解 BootLoader 工作原理的基础上,根据自己的开发板的硬件结构,自行完成 BootLoader 设计 与实现。 嵌入式 Linux 系统有许多 BootLoader 可用,如 LILO、ROLO、Etherboot、U-Boot 等等, 本书的开发范例中使用的是 U-Boot,因为它支援各式各样的系统,而且是针对嵌入式应用 从头开始设计而成的。 U-Boot,全称 Universal BootLoader,被认为是功能最多、最具弹性以及开发最积极的 BootLoader,它是遵循 GPL 条款的开放源码项目。其源码目录、编译形式与 Linux 内核很相 似。它目前是由 DENX Software Engineering(位于德国慕尼黑之外)的 Wolfgang Denk 所 维护,并且受到各种开发者的支援。 之所以在 Boot Loader 前面加个 Universal,主要体现在以下两个方面:在操作系统的支 持方面,U-Boot 不仅仅支持嵌入式 Linux 系统的引导,当前,它还支持 NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS 嵌入式操作系统;在处理器支持方面,U-Boot 除了支持 PowerPC 系列的处理器外,还能支持 MIPS、x86、ARM、NIOS、XScale 等诸多常用系列的 处理器。这两个特点正是 U-Boot 项目的开发目标,即支持尽可能多的嵌入式处理器和嵌入 式操作系统。就目前来看,U-Boot 对 PowerPC 系列处理器支持最为丰富,对 Linux 的支持 最完善。 此外,U-Boot 还具备使用 TFTP 通过网络从 IDE 、 USB 以及从各式各样的 Flash 装置启动核心的能力。U-Boot 支援一系列的文件系统,包括 Cramfs(Linux、ext2(Linux) 、 FAT(Microsoft)以及 JFFS2(Linux) 。 U-Boot 源码包及最新版本可以从 http://sourceforge.net/projects/u-boot/下载。

1.2

嵌入式 Linux 开发过程简介

Linux 功能强大, 又可裁剪, 可定制, 所以它可以在很多的硬件平台上运行,如 x86, PPC, ARM 等,无论什么平台,嵌入式 Linux 开发都要经过以下过程: (1)在宿主机上安装发行版的 Linux 操作系统,如 Fedora、OpenSuse、Ubuntu 等。一 般情况下,都是在宿主机上直接安装 Linux 系统;如果宿主机的内存和硬盘容量允许,也可 ,然后在虚拟机工作站中安装 以先在 Windows 下安装虚拟机工作站(VMWare Workstation) Linux 系统。 这个装好的 Linux 系统就是应用软件开发的基本平台,它提供了程序的编辑, 编译及连接工具,如 Vim、GCC 等;也提供了与开发板进行通信的工具,如 MINICOM、 TFTP 等。 (2)在宿主机的 Linux 系统中安装交叉编译环境。通过网络下载相应的 GCC 交叉编译 器进行安装(比如 arm-linux-gcc) ,或者安装产品厂家提供的交叉编译器。 (3)配置开发主机。包括串口调试工具,如 Linux 下的 MINICOM 或者 Windows 下的 超级终端,作为调试嵌入式开发板信息输出的监视器和键盘输入的工具;还包括 TFTP 服务 器,用来实现宿主机与目标机之间的文件传输。 (4) 引导装载程序 BootLoader, 从网络上下载一些公开源代码的 BootLoader, U-Boot、 如 BLOB、VIVI、LILO、ARM-Boot、RED-Boot 等,根据开发板上的核心芯片类型进行移植 修改。有些芯片没有内置引导装载程序,比如三星的 ARM7、ARM9 系列芯片,这就需要自 行编写将引导程序烧写到开发板 Flash 的代码。 网上有免费下载的 Windows 下通过 JTAG 并 口简易仿真器烧写 ARM 外围 Flash 芯片的程序,也有 Linux 下公开源代码的 J-Flash 程序。 当然,如果你需要迅速开发应用程序,最好直接购买开发板厂商提供的仿真器,这可以极大 地提高开发速度,但是不能了解其中的核心技术。

嵌入式 Linux 初级实验教程

12

(5)下载 Linux 操作系统,如 uCLinux、ARM-Linux、PPC-Linux 等,如果有专门针对 你所使用的 CPU 而移植好的 Linux 操作系统那是再好不过了,下载后再添加特定硬件的驱 动程序,进行调试修改。 (6)建立根文件系统,从 www.busybox.net 下载 BusyBox 软件对 Linux 文件系统进行 功能裁减,产生一个最基本的根文件系统,再根据自己的应用需要添加其他的程序。默认的 启动脚本一般都不会符合应用的需要, 所以就要修改根文件系统中的启动脚本, 它的存放位 置位于/etc 目录下,包括:/etc/init.d/rc.S,/etc/profile,/etc/.profile 等,自动挂装文件系统的 配置文件/etc/fstab,具体情况会随系统不同而不同。根文件系统在嵌入式系统中一般设为只 读,需要使用 mkcramfs、genromfs 等工具产生烧写映象文件。 (7)建立应用程序的 Flash 磁盘分区,一般使用 JFFS2 或 YAFFS 文件系统,这需要 在内核中提供这些文件系统的驱动,有的系统使用 NOR Flash,有的系统使用 NAND Flash, 有的两个同时使用,需要根据应用规划 Flash 的分区方案。 (8)开发应用程序,可以下载到根文件系统中,也可以放入 YAFFS、JFFS2 文件系统 中,有的应用程序不使用根文件系统,而是直接将应用程序和内核设计在一起,这有点类似 于 UCOS-II 的方式。 (9)烧写最终调试通过的内核,根文件系统,应用程序到开发板中。 (10)发布产品。 以 上是 嵌入式 Linux 的应 用程 序开 发过 程, 本书 接下 来将 从安装开发环境到在 Super-ARM 实验箱上运行一个最简单的应用程序,以图文并茂的方式向读者展示这整个过 程。

嵌入式 Linux 初级实验教程

13

第2章

开发平台介绍

好啦,不管你是否理解了第 1 章提到的那些抽象的概念,我们都暂且把它们丢在一边。 如果把嵌入式 Linux 的开发过程比作建造一栋房子的话, 那么首先应该找个风水先生选择一 块风水宝地,这块风水宝地呢,自然就是我们的目标开发平台了。我们将从这一章开始,走 入我们的风水宝地,开始进行“嵌入式 Linux 开发”这栋房子的建造。 言归正传, 本章首先带领大家熟悉我们的目标开发平台——Super-ARM 实验教学平台。 Super-ARM 是深圳旋极公司推出的以 ARM 处理器为基础的针对嵌入式教学、 开发而专门设 计的平台。通过本章,读者可以熟悉该平台的大体结构及其配备的硬件资源。

2.1
2.1.1

Super-ARM 整体结构及资源

Super-ARM 整体结构

Super-ARM 教学系统采用模块化设计。所有硬件模块及配件都安放在一个便携式 Supe r-ARM 中。

图 2-1-1

Super-ARM 结构

如图 2-1-1 所示,Super-ARM 主要包括以下几个组成部分: 箱体 交流输入插口,实验箱可直接接到 220V 交流电 底板(含键盘和数码管等) 主板 核心模块 LCD 模块 扩展板(可选)

嵌入式 Linux 初级实验教程

14

ProbeICE 仿真器 各种连接电缆及配件

2.1.2

Super-ARM 教学系统主要资源

(1)ARM 处理器 系统采用三星公司的处理器 S3C2410X(ARM9)。该处理器是基于 ARM920T 内核,主 频高达 203MHz,带 MMU(内存管理单元) ,片上资源丰富,性价比极高,是目前 ARM9 处理器中,使用较多的一种。其结构图如图 2-1-2 所示:

图 2-1-2

S3C2410 处理器结构图

S3C2410 集成的片上功能如下: 内核工作电压为1.8/2.0V、存储器供电电压3.3V、外部I/O设备的供电电压3.3V; 16KB的指令Cache和16KB的数据Cache;

嵌入式 Linux 初级实验教程

15

LCD控制器,最大可支持4K色STN和256色TFT; 4通道的DMA请求; 3通道的UART(IrDA1.0、16字节TxFIFO、16字节RxFIFO) ,2通道的SPI接口; 2通道的USB(Host/Slave) ; 4路PWM和1个内部时钟控制器; 117个通用I/O,24路外部中断; 272Pin FBGA封装; 16位的看门狗定时器; 1通道的IIC/IIS控制器; 带有PLL片上时钟发生器; S3C2410 ARM 处理器支持大/小端模式存储字数据,其寻址空间可达 1GB,每个 Bank 为 128MB,对于外部 I/O 设备的数据宽度,可以是 8/16/32 位,所有的存储器 Bank(共有 8 个)都具有可编程的操作周期,而且支持 NOR/NAND Flash、EEPROM 等多种 ROM 引导 方式。 (2)存储器 4M Flash、64M NandFlash 及 64M SDRAM (3)接口资源 主/从USB接口 RS232接口2个 SM卡/SD卡 多功能I/O扩展接口 4 x 4小键盘和4位8段数码管 外中断输入 LCD/触摸屏接口 A/D输入 IIC 、IIS及音频输入/输出接口 JTAG调试接口 VGA 以太网口 总线扩展接口3个 PS/2键盘、鼠标接口 话音输入输出(拾音器、扬声器)

嵌入式 Linux 初级实验教程

16

2.2
2.2.1 底板

Super-ARM 各模块简介

底板安装在箱体上,用于固定并连接其他模块。如图 2-2-1 所示:

图 2-2-1

底板

底板上除了安装主板,LCD 模块以外,还提供以下资源: 220V交流开关及电源指示。 4X4小键盘、4位8段数码管。 系统配置拨码开关,用于控制键盘及数码管。 5V直流电源插口。 调试接口,包括ARM JTAG和CPLD JTAG。 模拟输入接口,用于A/D转换实验。 拾音器(MIC)和扬声器,用于IIS 实验话音输入/输出。 VGA接口,可以与普通电脑显示器相接。 PS/2 键盘、鼠标接口。 这里介绍一下与本书实例相关的数码管和键盘接口。 (1)4位8段数码管 底板上设有数码管和键盘,便于与传统单片机输入输出实验接轨。数码管有4位,每位8 段,采用硬件解码驱动,即输入BCD 码,输出相应的字符。可显示带小数点的0-9十个数字 和几个特殊字符 数码管共有4位,从右至左,分别为第0、1、2、3 位。LED 采用共阳极驱动,每位有8 段,其中A、B、C、D、E、F、G 7 段由一片专用BCD 解码显示芯片来驱动,小数点H 则 用一晶体管Q5 单独驱动。控制哪一位点亮则由一片2 – 4译码器通过4个晶体管来完成。

嵌入式 Linux 初级实验教程

17

(2)4 x 4 矩阵键盘 底板上设计了4行4列共16个按键的矩阵键盘。 每个按键并没有固定定义, 用户可自行设 计。键盘按照从左到右,从上到下排列如下: S11 S12 S13 S14 S21 S22 S23 S24 S31 S32 S33 S34 S41 S42 S43 S44 4 x 4 键盘扫描电路采用了一种节省 I/O 资源的巧妙电路来实现,共用到4 个I/O,1个 中断,它们来自主板通用I/O 扩展接口。如果有某一键按下,将会产生一个键盘中断,启动 键盘扫描程序。CPU 接收到键盘中断后(也可以用查询的办法) ,可通过“一条线输出多条 线输入”方法扫描其键值,从而确定按键的位置。

2.2.2

主板

如图2-2-2所示,主板提供了丰富的外设接口以及扩展接口。其中通用多功能 I/O中断、 A/D输入、彩色/单色LCD、ARM/CPLD 调试接口、音频输入/输出等接口已连接到底板上, 这些接口即可通过底板访问,也可通过主板访问。另外串口、USB接口、以太网口、SD卡、 硬盘接口 (IDE) 以及总线扩展等接口只能在主板上使用。 还有中断输入按键、 FLASH、 CPLD、 IIC、直流输入及控制、复位、系统配置控制等资源同样只能在主板上使用。

图 2-2-2

主电路板及接口资源

下面具体介绍一下与本书实例相关的接口资源。 (1)串口 主板设有2 个符合RS232-C标准的通用异步串口(UART) ,均为DTE(数据终端设备) , 采用DB-9 型针式插座。其中串口0为核心板的UART0,串口1默认为UART1。其定义参见表 2-2-1。 (2)调试接口

嵌入式 Linux 初级实验教程

18

Super-ARM 主板上有2 个调试接口,一个是20 针的ARM-JTAG,用于主板和整个系统 的调试,另一个是10 针的CPLD-JTAG,用于主板上CPLD芯片的编程。本书并不需要用到 CPLD调试,这里仅介绍JTAG接口。JTAG接口定义如表2-2-2所示。 (3)以太网口 Super-ARM 主板的以太网接口是通过外扩电路实现的,符合10BASE-T 标准。扩展芯 片选用CIRRUS LOGIC 公司的CS8900,网口通过RJ-45 插座引出。

图2-2-3

RS232接口

图 2-2-4

JTAG接口

引脚号 1 2 3 4 5 6,7,8,9

引脚定义 NC RXD TXD NC GND NC 表 2-2-1 RS232接口定义

描述 无连接 接收数据 发送数据 无连接 信号地 无连接

引脚号 1 3 5 7 9 11 13 15 17 19

引脚定义 Vref nTRST TDI TMS TCK TDO nRST -

描述 引脚号 参考电压(3.3V) 2 JTAG 复位 4 JTAG 数据输入 6 JTAG 模式选择 8 JTAG 时钟 10 12 JTAG 数据输出 14 复位 16 18 20 表 2-2-2

引脚定义 VDD GND GND GND GND GND GND GND GND GND

描述 3.3V 电源 地 地 地 地 地 地 地 地 地

JTAG接口定义

(4)LCD 及触摸屏接口 主板设有两个 LCD 及触摸屏控制接口。其中一个为50PIN 彩色接口,支持TFT彩屏, 另一个为20PIN 接口,支持16 级灰度LCD。二者都带有触摸屏控制器(4 线电阻式) 。它 们的引脚定义如图2-2-5和表2-2-3所示。

图 2-2-5

LCD/触摸屏接口

嵌入式 Linux 初级实验教程

19

单色LCD 接口采用的是4bit 单扫描方式,可用于16 级灰度显示。只能与ARM7核心板 配合使用。当系统为ARM9 时,该接口无效。 彩色LCD 接口支持TFT 真彩,采用的是16 位显示模式,只能与ARM9 核心板配合使 用,当系统配置成ARM7 时,该接口无效。其三基色数据宽度之比为: R:G:B=5:6:5 其他显示模式不可用。 引脚 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 核心板 VDD33 VDD33 nRESET VD3 VD5 VD7 VD11 VD12 VD14 VD20 VD22 GND VFRAME VCLK XMON AIN7 YMON AIN5 TFT VDD33 VDD33 nRESET B0 B2 B4 G1 G2 G4 R1 R3 GND VSYNC VCLK XMON AIN7 YMON AIN5 描述 3.3V 电源 3.3V 电源 复位 蓝色 bit0 蓝色 bit2 蓝色 bit4 绿色 bit1 绿色 bit2 绿色 bit4 红色 bit1 红色 bit3 地 帧同步 像素时钟 X 公共端 Y 轴坐标 Y 公共端 X 轴坐标
表 2-2-3

引脚 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50

核心板 VDD33 GND VD4 VD6 VD10 GND VD13 VD15 VD19 VD21 VD23 LCD_PWR VM VLEN LEND GND nXPON GND nYPON GND

TFT VDD33 GND B1 B3 G0 GND G3 G5 R0 R2 R4 LCD_PWR VDEN HSYNC LEND GND nXPON GND nYPON GND

描述 3.3V 电源 地 蓝色 bit1 蓝色 bit3 绿色 bit0 地 绿色 bit3 绿色 bit5 红色 bit0 红色 bit2 红色 bit4 LCD 电源 数据使能 行同步 行结束 地 X 位置端 地 Y 位置端 地

彩色LCD/触摸屏接口定义

2.2.3

核心板

Super-ARM 可以配置两种不同的核心板,以提供不同的性能和功能。其一是ARM9核 ,另一款是ARM7 核心板(S3C44B0x) 。它们与主板的接口是相同的。 心板(S3C2410x) ARM9 核心板提供64M NandFlash 及64M SDRAM(容量皆可扩展) 。系统可以从 NandFlash 启动,也可以从主板上的Flash 启动(主板设有启动方式选择) 。ARM7 核心板 提供8M SDRAM、 128K RAM 和2M FLASH。 由于S3C44B0x没有MMU (存储器管理单元) , 不能运行Linux,所以我们选择ARM9核心板。如图 2-2-6 所示。

嵌入式 Linux 初级实验教程

20

图2-2-6

ARM9核心板

2.2.4

LCD 模块

Super-ARM 可以根据核心模块的不同配置两种不同的 LCD,彩色 LCD 为 320 X 240 (或 240 X 320)TFT 屏(图 2-2-7),与 ARM9 核心板配套使用。单色 LCD 为 320 X 24 0(或 240 X 320)灰度屏,与 ARM7 核心板配套使用。

图 2-2-7

彩色 LCD

2.2.5

JTAG 仿真器 ProbeICE

ProbeICE 是与 SDT251 或 ADS1.2 配套使用的 JTAG 仿真器, 支持 ARM7/ARM9/XSCA L 等系列 ARM 内核。图 2-2-8 是该仿真器的实物图。

图 2-2-8

JTAG 仿真器

嵌入式 Linux 初级实验教程

21

2.2.6

连接电缆及配件
交流电源线 1 根 20pin JTAG 扁平电缆 1 根 20/14 转换头 1 个 DB25 型并口电缆 1 根 DB9 型 RS232 延长线 1 根 DB9 型 RS232 交叉线 1 根 USB 电缆 1 根 RJ45 网口电缆 1 根 5V 直流电缆 2 根 ProbeICE 使用手册 开发光盘

嵌入式 Linux 初级实验教程

22

第3章

ADS 开发环境搭建

第 2 章带领大家将我们的风水宝地参观了一番,现在是为我们的房子打地基的时候了。 不论做什么样的开发,建立一个良好可用的开发环境是首先要做的,最基础的,也是相当重 ,另一种是“嵌 要的一项工作。本书中会提到两种“开发环境” ,一种是“ADS 开发环境” 入式 Linux 开发环境” ,前者是本章要跟大家介绍的,后者在下一章中讲述。 开发环境包括硬件开发环境和软件开发环境。 要针对目标机进行开发, 首先要搭建针对 目标机的硬件开发环境, 硬件开发环境主要包括宿主机, 目标机, 还有其他相关硬件设备 (如 仿真仿真器) 之间的连接以及正确的配置。 软件开发环境则主要是指在宿主机上配置相应的 开发环境以及安装相关的开发工具,这些开发工具可能是开发用的,也可以是调试用的,还 有下载用的。比如本章要介绍的 ADS 开发工具,就是用来完成程序编辑、编译、调试、仿 真、代码生成等功能的集成开发环境,而下一章要介绍的 Linux 下的 Minicom,TFTP 等工 具则是在嵌入式 Linux 开发中经常用到的调试和下载工具。 如果你之前没有接触过嵌入式 ARM 设计,有可能还没听过 ADS 这个名称。ADS 全称 为 ARM Developer Suite。是 ARM 公司推出的新一代 ARM 集成开发工具。现在 ADS 的最 新版本是 1.2, 它取代了早期的 ADS1.1 和 ADS1.0。 它除了可以安装在 Windows NT4, Windows 2000,Windows 98 和 Windows 95 操作系统下,还支持 Windows XP 和 Windows Me 操作系 统。ADS 由命令行开发工具、ARM 时实库、GUI 开发环境(Code Warrior 和 AXD)、实用程 序和支持软件组成。 利用这些组件, 用户就可以为 ARM 系列的 RISC 处理器编写和调试自 己的开发应用程序。 ADS 在嵌入式 ARM 开发中是一个比较常用的工具,不过在很多嵌入式 Linux 开发中, 并不一定要用到它,只是本书中有个“烧写 BootLoader”的实例需要用到 ADS,所以笔者 就花这么一章的篇幅向大家介绍一下这个工具的用法, 中间结合了一个具体的实例, 希望通 过这个实例的讲解,能让不知道 ADS 的读者朋友也顺便学习了一把,如果你已经对 ADS 的操作了如指掌了,那关于 ADS 的部分你就跳过吧。 本章首先会介绍如何搭建基本的硬件开发环境, 然后以图文并茂的方式向大家展示仿真 器的使用和 ADS 工具的安装与使用方法。

3.1

搭建硬件开发环境

硬件开发环境包括 PC 机,Super-ARM, MULTI-ICE 仿真器。

3.1.1

Super-ARM 供电线路连接

每一块开发板都离不开电源,所以供电线路的连接是必不可少的,而且也不容马虎,下 面列出 Super-ARM 的供电线路连接步骤,一个简单的过程,笔者却将其列得仔细是希望引 起大家也包括自己的重视,因为笔者曾经犯过不少因供电线路的连接不正确而导致的失误。 (1)将交流电源线插入 Super-ARM 的电源插座,连接 220V 交流电。 (2)用一根 5V 直流电缆连接底板 5V 直流供电插座(底板右侧)和主板直流输入插 座。 (3)打开交流电源开关(底板右侧中部),开关上指示灯亮。 (4)打开主板电源开关,电源指示灯亮。 连接示意图如图 3-1-1 所示:

嵌入式 Linux 初级实验教程

23

图 3-1-1

设备连接图

3.1.2

JTAG 连接

如果要进行程序仿真,则需要使用 ProbeICE,在使用之前,需在实验箱断电的情况下 按下述步骤连接: (1)取出 ProbeICE,将 20pin JTAG 扁平电缆一端连接仿真器 JTAG 口,另一端连接 底板调试接口(底板右侧上部)中的 ARM 调试口。 (2)将 DB25 型并口电缆一端与仿真器并口相连,另一端连接计算机打印口。 (3)通过 5V 直流电缆连接底板 5V 直流供电插座(底板右侧)和仿真器直流输入口 (4)打开交流开关和直流开关。 注:使用仿真器时电源开启应先开 ProbeICE-ARM 电源,再开目标板电源,关机时则 带电插拔可能会对仿真 遵循相反的顺序; 务必在断电情况下连接 ProbeICE-ARM 和目标板。 器造成永久损害! 请使用仿真器配套的专用直流电源, 其他电源可能导致意想不到的问题出 现! RS232 串口电缆、USB 电缆和 RJ45 网口电缆,在后续开发中根据需要进行连接。它们 的连接方式及其简单,几乎不需要用脑,只要你用眼用手就可以办到。只是千万记住,一定 不要在系统带电的情况下对串口线进行拔插。

3.2

搭建软件开发环境

ADS1.2 集成了程序编辑、编译、生成、调试等工具。而程序仿真则要用到 ProbeICEARM 仿真器,该仿真器使用之前须安装服务器(Server) 。ProbeICE-ARM 使用与 Multi-IC E 2.2 兼容的服务器软件 ProbeICE-Server。 ADS1.2 和 Multi-ICE 2.2 的安装过程比较简单,笔者不做介绍,不过本章附件中也提供 了它们的安装说明。本小节主要介绍这两个软件的配置。

3.2.1

ProbeICE-ARM 服务器配置

服务器(Server)和编译调试环境(ADS1.2 )安装完成以后,需要启动服务器并正确

嵌入式 Linux 初级实验教程

24

配置以后才能进行下一步的开发,配置过程如下: (1)将本章附件中 ARM920T.cfg 文件复制到 Multi-ICE 的安装目录下。 (2)确认仿真器与主机和目标板已按图 3-1-1 连接好。 (3)确认仿真器电源和目标板电源已开启。 (4)确认仿真器电源指示灯‘PWR’亮。 (5)从 Windows 开始菜单中选择 Multi-ICE Server ,如图 3-2-21 所示:

图 3-2-1

从 Windows 启动 Multi-ICE Server

(6)从 Windows 开始菜单运行 Multi-ICE Server,如下图示:

图 3-2-2

Multi-ICE Server 运行界面

嵌入式 Linux 初级实验教程

25

(7)点击 File | Load Configuration,出现图 3-2-3 所示的对话框,打开 ARM920T.cf g,如果连接和配置正常,会出现如图 3-2-4 所示的画面,表明服务器已经识别目标板 A RM 内核并准备好为它服务。至此,开发环境已经准备完必,接下来可以进行软件的开 发与调试了。

图 3-2-3

选择 Multi-ICE Server 的配置文件

图 3-2-4

Multi-ICE Server 正常运行界面

嵌入式 Linux 初级实验教程

26

3.2.2

ProbeICE-ARM 仿真器配置

(1)参照 3.2.3 节描述的步骤运行 Multi-ICE Server。 (2)从 Windows 开始菜单启动 AXD Debugger,如图 3-2-5。得到如图 3-2-6 的 AXD 调试界面。

图 3-2-5

从 Windows 启动 AXD

图 3-2-6

AXD 调试界面

嵌入式 Linux 初级实验教程

27

(3)点击 Options | Configure Target,选择仿真器,如图 3-2-7。

图 3-2-7

选择仿真器界面

(4)点击 Add,在 MultiICE 安装目录下找到 Multi-ICE.dll,如图 3-2-28 界面。

图 3-2-8

添加 Multi-ICE.dll

(5)点击“打开” ,得到如图 3-2-9 添加成功界面;

嵌入式 Linux 初级实验教程

28

图 3-2-9

添加 Multi-ICE.dll 成功

(6)选中 Multi-ICE 项,双击出现如图 3-2-10 所示的界面。

图 3-2-10

配置仿真器

(7)点击“确定” ,仿真器配置完毕。

嵌入式 Linux 初级实验教程

29

3.3

新建工程及仿真调试

开发环境准备好以后,接下来,本小节将以一个 LED 实验为例,用详细的图文描述如 何在 ADS1.2 集成开发环境中新建一个工程,并利用 Multi-ICE 仿真器在目标板上调试该工 程。 本章附件中的 project 文件夹下包含所有与该工程有关的源文件,本次实验并不要求读 懂这些源代码,重点在于熟悉整个开发过程。

3.3.1

新建工程

(1)从 Windows 开始菜单运行 ADS1.2 的 CodeWarrior for ARM Developer Suit,选中 File | New 菜单, 在出现的对话框中选中 Project | ARM Executable Image,如图 3-3-1 所示, 在 Project name 项输入工程名,如 Newdemo,在 Location 项设置工程 1 路径,如 G:\book\chapter_3\project。点击“确定”后一个新的工程就建好了。此时,ads1.2 会自动在 project 目录下建立一个 NewDemo 的文件夹,这个文件夹用来保存所有的工程文件。

图 3-3-1

新建一个工程

(2)选中工具栏中的 DebugRel Settings 按钮,对工程进行设置。界面如图 3-3-2 所示。

图 3-3-2

选中工具栏中的 DebugRel Settings 按钮

嵌入式 Linux 初级实验教程

30

(3)选中 Target Settings,设置 Post-linker 为 ARM fromELF。如图 3-3-3。

图 3-3-3 设置 Post-linker

(4)选中 Access Paths,点击 add, 添加所有与工程相关的文件路径,如图 3-3-4 所示。 这项设置可以将一些不在工程目录下的文件与工程关联起来。比如我们需要用到一个 def.h 的头文件,但该文件在 G:\book\chapter_3\project\include 目录下,那么我们就要将这个目录 添加进来。

图 3-3-4

设置与工程相关的文件路径

嵌入式 Linux 初级实验教程

31

图 3-3-5 为 ARM 汇编器选择处理器

(5)为编译器选择处理器类型。选中 ARM Assembler,在 Target 栏,Archtecture or Processor 项中选择 ARM920T,其他设置不变。如图 3-3-5 所示;在 ARM C Complier 一项 中作同样的设置,如图 3-3-6 所示。

图 3-3-6 为 C 编译器选择处理器

嵌入式 Linux 初级实验教程

32

图 3-3-7

ARM linker 中 Output 栏设置

(6) ARM linker 设置。选中 ARM Linker,在 Output 栏,RO Base 项中填入 0x3010 0000,如图 3-3-7 所示;在 Layout 栏,Object/Symbol 项中填入 init.o,Section 项中填入 init, 如图 3-3-8 所示。

图 3-3-8

ARM linker 中 Layout 栏设置

嵌入式 Linux 初级实验教程

33

图 3-3-9 添加文件

(7) 添加文件到工程中。在工程的空白处点击右键,选中 Add Files...,将本章附件中 project\source 目录下的所有文件添加进来,如图 3-3-9 所示。

图 3-3-10 make

嵌入式 Linux 初级实验教程

34

3.3.2

编译及连接

点击工具栏中的 make 按钮,对所有添加到工程中的文件进行编译、连接,如图 3-3-10 所示。如果编译有错,会弹出一个 Errors & Warnings 对话框,对话框中有错误提示信息, 这时只要双击错误提示行, 就可以找到出错的位置。 然后根据错误提示信息对程序进行修改, 再编译,直到编译通过,Errors & Warnings 对话框中提示 0 个错误为止。

3.3.3

仿真调试

(1)配置服务器(参考 3.2.4 ProbeICE-ARM 仿真器配置) (2)如图 3-3-11 所示,点击工具栏中的 Debug 按钮启动 AXD。

图 3-3-11 Debugger

(3)AXD 调试界面,如图 3-3-12 所示。

图 3-3-12 AXD 调试界面

嵌入式 Linux 初级实验教程

35

(4)点击 System Views | Command Line Interface 启动命令行接口。如图 3-3-13。

图 3-3-13

(5) 本章附件中的 wtk2410.ads 文件复制到工程目录下的 Newdemo\DebugRel 中, D 在 ebug>后面输入:obey wtk2410.ads,出现如 3-3-14 所示界面。

图 3-3-14

(6)点击工具栏中的 Go 按钮,开始运行程序,如图 3-3-15:

嵌入式 Linux 初级实验教程

36

图 3-3-15 开始运行程序

(7)运行这个程序时,可以看到实验箱上的 LED 灯一闪一灭。要想看程序每一步的运 行状态,也可以对程序实行单步调试,或者在程序中设置断点等。 到此, 我们完成了 ADS 开发环境的搭建, 虽然我们并不是要在 ADS 环境下进行嵌入式 开发,不过本书后面的实例中将用 ADS 工具进行 U-boot 的烧写。

嵌入式 Linux 初级实验教程

37

第4章

嵌入式 Linux 开发环境搭建

上一章主要介绍的是 ADS 开发环境搭建以及使用, 本章将在宿主机上搭建嵌入式 linux 开发环境,主要介绍 Linux 操作系统的安装及网络等环境的配置,如何使用实际的项目工作 空间,minicom、tftp 等相关服务的安装和配置,交叉编译工具链的制作。如果读者对 Linux 系统比较熟悉,可以根据自身的情况选择跳过本章的某些小节。

4.1

安装 Linux 操作系统

目前,主流的 Linux 操作系统有 Canonical 的 Ubuntu,Novell 的 OpenSuse 以及 Red Hat 的 Fedora。Ubuntu 无论是在消费者当中或者商业领域都拥有非常好的口碑,成为最受欢迎 风靡欧洲, 现在也已经开始进入美国市场。 的 Linux 发行版本。 OpenSuse 凭借其业务基础, 至于 Red Hat,凭借 Fedora,他已经发展成为社区 Linux 操作系统中的龙头企业。 本书选用 Ubuntu 8.04 作为开发环境,其稳定性一直备受业内人士推崇,采用 2.6 版的 linux 内核,有桌面版和服务器版本之分,笔者安装的是桌面版。 安装 ubuntu8.04 的宿主机,其性能要求如下: CPU:高于奔腾 500M,推荐高于赛扬 1.7 内存:大于 256M,推荐高于 512M; 硬盘:大于 20G,推荐高于 40G。 现在大家使用的主机基本都能达到这个配置,当然,如果你的宿主机有更好的配置,也 可以考虑先在你的宿主机上安装 Windows 系统,然后在 Windows 系统中安装一个虚拟机工 作站,再在虚拟机工作站上安装 Linux 系统。这样就可以在 Windows 中使用 Linux,避免在 两个系统间切换时反复地关机、重启。笔者为了方便实验调试,文稿撰写,采用的是这种方 式。笔者的硬件配置如下: CPU:64 位 AMD 速龙双核; 内存:2G; 硬盘:300G。 直接在宿主机上安装 Ubuntu 8.04 和在宿主机的虚拟机工作站上安装 Ubuntu 8.04 只是两 种不同的安装方式,对用户使用 Linux 操作系统几乎没有影响,开发过程也完全一样。下面 介绍一下虚拟机的安装方式。

4.1.1

在 Windows 中安装虚拟机

首先安装虚拟机工作站,笔者使用的虚拟机工作站是 VMware_WorkStation_6.5,可以 去 VMware 的官方网站(http://www.vmware.com)下载该工具,它的安装过程很简单,笔者 就不多费笔墨了。 下面主要介绍一下在虚拟机工作站中新建一个虚拟机的以及在虚拟机上安装 Linux 系 统的过程。 在这之前, 首先要下载 Ubuntu 8.04 的光盘映像文件 ubuntu-8.04-alternate-i386.iso, 下载地址为 http://releases.ubuntu.com/8.04/。 (1)首先运行虚拟机工作站,如图 4-1-1。 (2)点击 New Virtual Machine 的图标,出现图 4-1-2 所示界面。

嵌入式 Linux 初级实验教程

38

4-1-1 虚拟机工作站

4-1-2 新建虚拟机向导

(3)选择 Typical,点击 Next,在出现的界面(图 4-1-3)中点击 Browse,选中所要安装 系统的光盘映像文件(ubuntu-8.04-alternate-i386.iso) 。 (4)点击 Next,设置用户名和密码,如图 4-1-4 所示。

4-1-3 选择安装映像

4-1-4 设置用户名和密码

(5)点击 Next,设置虚拟机的名称,默认为 Ubuntu,你可以根据自己的喜好设置,再 点击 Browse,设置 Ubuntu 的安装目录, 比如, 笔者将 Ubuntu 安装在 D 盘的 “Heima_Ubuntu” 文件夹下。要确保该目录所在的磁盘有足够的空间(最好 8G 以上)来容纳我们新安装的 Ubuntu 系统。如图 4-1-5 所示。 (6)点击 Next,设置虚拟机占用的最大硬盘空间,默认 8G,如果你的主机硬盘容量 够大,可以适当设大一点,免得开发过程受硬盘空间限制,比如后面编译 QT 的时候需要好 几 G 的空间,如果空间不够,可能会出错。笔者就设了 20G,如图 4-1-6 所示。

嵌入式 Linux 初级实验教程

39

4-1-5 设置安装目录

4-1-6 设置虚拟机硬盘最大容量

(7)点击 Next,进入 4-1-7 所示的界面,可以看到,现在的硬盘容量是 20G,默认的 内存大小是 512M,网络连接方式选择的是 NAT,还有 CD/DVD 驱动,软盘,USB 控制器 等,如果不需要更改这些配置或者增加其他的硬件设备,到这一步就可以点击“Finish”了。

4-1-7 配置向导完成界面

4-1-8 内存配置

如果你还要更改配置(如改变内存大小) ,或者增加一个硬件设备(如串口) ,那就点击 “Customize Hardware” ,这时会出现如图 4-1-8 所示的配置界面,笔者将各部分的配置截图 说明如下: 内存配置 内存配成 512M 差不多了,不过要配得比你主机的内存小,笔者主机的内存是 2G,这 里配 1G 左右。如图 4-1-8 所示。 在虚拟机的光驱中加入虚拟机系统的安装映像 在虚拟机的光驱中加入虚拟机系统的安装映像就和在物理主机的光驱中插入系统安装 ( , 光盘是一个概念。 笔者安装的 Linux 系统是 Ubuntu-8.04 映像 ubuntu-8.04-alternate-i386.iso) 如果你想安装其他版本的 Ubuntu 或者其他的 Linux 系统,需要下载这些系统的安装映像文 件。这一步还要注意勾上“Connect at power on”选项,如图 4-1-9 所示。

嵌入式 Linux 初级实验教程

40

4-1-9 安装映像配置

4-1-10 网络连接方式配置

配置虚拟机的网络连接方式 网络连接方式共有四种方式可以选择,先选择 NAT,如图 4-1-10 所示。至于这几种方 式具体怎么配置,用在什么样的场合,笔者在后面会详细介绍。 增加一个串口设备 点击“Add...”选项,然后选中"Serial Port",点击“Next” ,选中“Use physical serial port on the host”选项 (图 4-1-11) ,再点击“Next” 在 Physical serial port“那一栏选择“COM1” , , 点击“Finish” (图 4-1-12) 。就为虚拟机增加了一个串口设备,这个设备使得虚拟机系统可 以使用宿主机的串口 1 与目标机进行通信。

4-1-11 串口配置 1

4-1-12 串口配置 2

其他的几项配置(USB Controller、Display、Processors)一般都不用更改,点击图 4-1-7 界面中的 “Finish” 完成新建虚拟机的过程。 就可以进入 Linux 系统的安装了。

4.1.3

在虚拟机上安装 Ubuntu

(1)进入 Ubuntu 的安装过程,首先出现的是选择语言的界面。在该界面上点击一下鼠 标,就可以通过键盘的“↓”和 “↑”键进行语言的选择,默认为 English,我建议你也选 用 English。选中以后按 Enter 键就会进入下一步(以后都是按 Enter 键确认当前选项并进入 下一步) ,这时可能你会发现你的鼠标不见了,不用慌,同时按下 Ctrl 和 Alt 就出来了。

嵌入式 Linux 初级实验教程

41

(2)接着选择国家,没有 China,就选 Hong Kong 吧。下一步是问你要不要做键盘检 测,选“NO” ,不做,没关系的。然后连续选择两个 USA,就会进入 CD-ROM 的检测,如 果检测不到 CD-ROM 中的映像文件,就会提示 Incorrect CD-ROM detected(如图 4-1-13), 这时你需要回过头去检查一下你的 CD-ROM 驱动器中的映像文件是否正确或者映像文件是 否存在。如果能检测成功就顺利进入下一步。

4-1-13 检测 CD-ROM 失败

(3) CD-ROM 检测完以后就开始检测网络硬件及配置, 接下来的几个步骤都可以默认, 包括 Host Name 的设置(如图 4-1-14) ,直到进入磁盘分区的界面(如图 4-1-15) 。

4-1-14 配置主机在网络中的名字

(4)开始进行磁盘分区(Partition disks) ,这里的磁盘就是虚拟机的磁盘,也就是下图 显示的 SCSI3(0,0,0) (sda) ,其容量在前面已经设置好了。

4-1-15 磁盘分区

嵌入式 Linux 初级实验教程

42

选中图 4-1-15 中“SCSI3(0,0,0) (sda)……”那一行,按 Enter 键,就会出现一个 对话框,提示你是不是要在该磁盘上创建一个空的分区。选择“YES” ,就会出现如图 4-1-16 所示的界面,表示在虚拟机的磁盘上新建了一个自由的空间。

4-1-16 在磁盘上新建一个自由空间

选中“……FREE SPACE”那行,按 Enter 键,就会在新建的空间上进行分区,用自动 分区的方式就可以了,分区完了以后选择“Finish partitioningr and write changes to disk”,将 更改写入磁盘。具体的安装截图如图 4-1-17 和图 4-1-18 所示。

4-1-17 自动分区

4-1-18 完成分区并写入磁盘

嵌入式 Linux 初级实验教程

43

(5)接着就是“Installing the base system” 。设置用户名和密码,相信大家都会了。紧 跟着会弹出一个要求设置代理服务器的对话框, 先空着不设。 再接下去就是安装系统软件了。 这些过程都是自动的,不用管,只是需要等二十分钟左右,整个系统就安装完成了。

4-1-19 系统安装过程

(6)重启系统,如果出现熟悉的登录对话框,恭喜你,Ubuntu 安装成功!输入用户名 和密码,登入 Ubuntu,开始你的 Ubuntu 开发之旅吧。

4.2

宿主机 Linux 系统中基本环境的配置与安装

Linux 操作系统安装完以后,我们面对的还是一个没有安装相关开发工具的空系统。所 以我们首先需要配置系统的网络(包括 IP 地址、网关、DNS 服务器等) 、更新系统、安装 一些基本的工具(包括一些编译工具,调试工具、程序库等) ,为我们后续的开发做准备。 另外,在进行项目开发之前,一个比较好的习惯是为我们的项目规划一个工作空间,所以这 一小节还涉及到项目工作空间的规划。笔者接下来将一一介绍。

4.2.1

网络配置

正确配置 Linux 系统的网络,以实现 Linux 系统接入 Internet,下载开发过程中需要的 各种开发工具的源码包或者其他相关资源。 虚拟机有四种网络连接方式:Bridged(网络桥接)方式,NAT 方式,Host-only 方式, 以及 Custom 方式。一般来说,后面两种方式用户很少用到,这里只介绍一下前两种方式的 的使用场合和配置方法。不管是哪一种方式,都会涉及到 3 方面的设置:主机系统(本书对 应 Windows 系统) ,虚拟机,虚拟系统(本书对应 Linux 系统) 。

嵌入式 Linux 初级实验教程

44

(1)Bridged 方式 如果你的真实主机在一个以太网中,这种方法是将你的虚拟机接入网络最简单的方法。 虚拟机就像一台新增加的、 与真实主机有着同等物理地位的电脑, 桥接模式可以享受所有可 用的服务;包括文件服务、打印服务等等。 当虚拟机配置成这种方式时,要实现 Linux 系统连入 Internet,需要设置 Linux 系统的 IP 和 Windows 系统的 IP 在同一个网段,比如 Windows 系统的 IP 为 10.62.85.1,那么 Linux 系统的 IP 就要设置成 10.62.85.x(x = 2~254) 。具体操作包括以下几步: 设置 Windows 的 IP 地址为 10.62.85.1。 设置虚拟机的网络连接方式为 Bridged,如图 4-2-1 所示。 在 Linux 系统的启动栏中,执行“System”—>“Administration”—>“Network” 在弹出的“Network Settings”对话框中,选中“Wired connection”项,然后点击 “Properities”,在弹出的“eth0 properities”对话框中设置 Ubuntu 的 IP 地址为 10.62.85.2,子网掩码和网关的设置与 Windows 下面的一样。如图 4-2-2 。

4-2-1 选择 Bridged 连接方式

4-2-2 配置 IP,子网掩码,网关

这样设置以后在 Linux 中启动浏览器,看看是不是可以连入 Internet,如果不行,可能 还需要配置代理服务器(如果你的 Windows 系统是通过代理服务器连入 Internet 的) ,执行 “System”—>“preferrences”—>“Network Proxy” ,设置代理服务器的 IP 地址及端口。 (2)NAT 方式 NAT(networkaddresstranslation)模式可以方便地使虚拟机连接到公网,代价是桥接模 式下的其他功能都不能享用。使用这种模式的配置相当简单,只要真实主机连接到 Internet, 将虚拟机的网络连接方式设置为 NAT(图 4-2-3) ,然后将 Linux 系统中的网络设置为 DHCP 方式(图 4-2-4) ,这时 Linux 系统就可以接入 Internet 了。如果你的 Windows 系统是通过代 理服务器连入 Internet 的,那么同样要配置代理服务器。

4-2-3 选择 NAT 连接方式

4-2-4 配置 DHCP 模式

嵌入式 Linux 初级实验教程

45

在嵌入式 Linux 开发中,如果宿主机 Linux 系统需要连接 Internet,那么可以按照上面 介绍的方法将虚拟机设置成 Bridged 方式或者 NAT 方式;但是,如果要实现宿主机 Linux 系统和目标机进行网络通信的话,必须将虚拟机的网络连接方式配置成 Bridged,然后设置目 标机的 IP 与宿主机上 Linux 系统的 IP 在同一个网段。

4.2.2

更新 Linux 操作系统

配置好 Linux 系统的网络,就可以对系统进行更新,获取最新的软件列表并安装。这部 分 内 容 可 以 参 考 Ubuntu 官 方 网 站 的 “ Ubuntu 8.04 LTS 速 配 指 南 ” 网 址 是 : , 。这个速配指南关于怎 “http://wiki.ubuntu.org.cn/index.php?title=Qref/Hardy&variant=zh-cn” 么设置系统更新源、更新软件列表以及安装更新都写得简单明了。

4.2.3

安装一些相关工具和程序库

在宿主机上安装 bison(语法分析器) 、flex(词法分析器) 、build-essential (C/C++编译 环境,包括编译 C/C++程序需要的软件包,相关工具等) 、patch(linux 下的补丁工具) 、 libncurses5-dev 库(调用 ncurses 图形库时需要用的,比如,在执行 make menuconfig 时必须 安装这个库) ,安装命令如下: sudo apt-get install bison sudo apt-get install flex sudo apt-get install build-essential sudo apt-get install patch sudo apt-get install libncurses5-dev

4.2.4

实际项目工作空间目录的安排

在为目标机开发及定制软件的过程中, 最好在宿主机上规划一个综合的、 容易使用的目 录结构,组织各种软件包和项目组件,表 4-2-1 是本书范例使用的目录安排方式,你可以自 行修改此目录结构以符合你的需要。 目录 bootloader source debugtool doc image kernel project rootfs sysapp tmp crosstool 目标板的引导加载程序 存放构建交叉编译工具链所需要用到的软件源码包 调试工具以及所有相关套件 项目将会用到的所有文件 准备使用在目标板上的引导加载程序和内核的二进制映像,以及根文件系统 存放内核 项目配置文件等 目标系统的内核在执行期间所看到的根文件系统 存放系统应用程序 存放临时文件 存放交叉编译工具链以及 C 程序库
表 4-2-1 本书范例所用的项目目录安排方式

内容

这个项目工作区要放在何处,由个人自己决定,不过最好不要放在 /usr 或 /usr/local 等目录下。我将它放在我的用户主目录(/home/hm)下,当然在用户主目录下,为了与其他

嵌入式 Linux 初级实验教程

46

项目的目录分开,我新建了一个子目录(book2410)来存放该工作空间,以下是我的目录结 构: ls -l /home/hm/book2410 total 44 drwxr-xr-x 2 hm drwxr-xr-x 2 hm drwxr-xr-x 2 hm drwxr-xr-x 2 hm drwxr-xr-x 2 hm drwxr-xr-x 2 hm drwxr-xr-x 2 hm drwxr-xr-x 2 hm drwxr-xr-x 2 hm drwxr-xr-x 2 hm drwxr-xr-x 2 hm

hm hm hm hm hm hm hm hm hm hm hm

4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096

2009-08-01 2009-08-01 2009-08-01 2009-08-01 2009-08-01 2009-08-01 2009-08-01 2009-08-01 2009-08-01 2009-08-01 2009-08-01

22:21 22:21 22:21 22:21 22:21 22:21 22:21 22:21 22:21 22:21 22:21

bootloader crosstool debugtool doc image kernel project rootfs source sysapp tmp

如何创建这些目录?我相信只要接触过 linux 的读者对于 mkdir 这个命令一定不陌生。 举例来说,我要在我/home/hm 目录下面创建 book2410 目录,只需要打开 Linux 的终端,敲 入以下命令: mkdir /home/hm/book2410 现在聪明的你肯定知道怎么在 book2410 目录下面创建 bootloader 以及其他子目录了。 看到这里,有些读者,特别是初学者,一定还不清楚现在建立的这些目录与以后的开发 过程究竟有什么样的关联,看到表 4-2-1 中的一些概念,比如“交叉编译工具链”“根文件 、 系统”“内核”等,也难免会觉得很抽象,不用担心,你现在只需要先把这些目录建立起来 、 就好了,心中存留的这些疑问会在你学习与实践的过程中会一个一个地得到答案的。

4.2.5

配置 Linux 下的 minicom

minicom 是 Linux 下的一个串口调试工具, Windows 下的超级终端功能相似。 与 在以后 的章节当中经常要用到 minicom 来查看键盘输入信息和调试输出信息。本小节将介绍 minicom 的安装和配置过程,详细过程如下: (1)安装 minicom。 sudo apt-get install minicom (2)运行 minicom。 sudo minicom 出现如图 4-2-5 所示的界面:

嵌入式 Linux 初级实验教程

47

图 4-2-5

minicom 配置前的界面

(3)先按下 Ctrl + A, 放开, 再按 O, 出现配置菜单。

图 4-2-6

进入配置菜单

(4)选择 Serial port setup 项, 出现如下界面:

嵌入式 Linux 初级实验教程

48

图 4-2-7

配置前的界面

(5)键入“A”,可修改串口在 Linux 中对应的设备,串口 COM1 对应 ttyS0, COM2 对 应 ttyS1, 这一项配置完以后敲回车键退出, 可以进入其他项的配置; 键入“E”,设置为 115200 8N1 (波特率 115200,奇偶校验无, 停止位 1),这是根据 Super-ARM 的参数配置的,当然, 不同的开发板参数可能不一样,要根据自己的情况来定,该项配置完后回车;分别键入 “F”“G”,配置硬/软件流控制,都选 NO。所有项配置完成后的界面如下图:

图 4-2-8

配置后的界面

(6)在确认配置正确之后,敲回车键进入配置菜单的界面,将其保存为默认配置(即

嵌入式 Linux 初级实验教程

49

选择 save setup as dfl 项) 。如图 4-2-9 所示。

图 4-2-9

保存为默认配置

(7)保存成功,出现如下图界面。

图 4-2-10

配置被保存

(8)选择 Exit 项,返回上级界面;如图 4-2-11:

嵌入式 Linux 初级实验教程

50

图 4-2-11

Exit 选项

(9)Ctrl + A, 放开, 再按 Q,退出 minicom,在出现的界面中选择“Yes” ,保存设置。

图 4-2-12

退出 minicom

(10)重启 minicom,配置生效,如图 4-2-13:

嵌入式 Linux 初级实验教程

51

图 4-2-13

配置生效后重启 minicom

(11)用串口线将宿主机和目标机相连,如果此时目标机向宿主机发送数据,就会在 minicom 中显示。比如下图是笔者在开发过程中截取的一张图片,该图片上显示的是从目标 机发送到宿主机的信息。当然读者现在面对的目标机可能还是个空板子,就算把线接上了, 也肯定不会有信息传到主机上来,没关系,只要你跟着笔者一步步走下去,总有一天你会看 到的。

图 4-2-14

在 minicom 中显示目标板发送过来的信息

嵌入式 Linux 初级实验教程

52

4.2.6

配置 Linux 下的 TFTP 服务器

TFTP 协议是简单文件传输协议,基于 UDP 协议而实现,它可以看作是一个 FTP 协议 的简化版本,与 FTP 协议相比,它的最大区别在于没有用户管理的功能。它的传输速度快, 可以通过防火墙,使用方便快捷,因此在嵌入式的文件传输中广泛使用。 同 FTP 一样,TFTP 分为客户端和服务器端两种。通常,首先在宿主机上安装并开启 TFTP 服务器端服务,设置好 TFTP 的根目录内容(也就是供客户端下载的文件) ,接着,在 目标机上开启 TFTP 的客户端程序。 这样,把目标机和宿主机相连,并且配置好 IP,子网 掩码和默认网关之后,就可以通过 TFTP 协议传输可执行文件了。 下面介绍如何在 Linux(针对 Ubuntu 8.04)下面安装配置以及使用 TFTP 服务器。 (1)安装 tftpd(服务端) ,tftp(客户端) ,xinetd sudo apt-get install tftpd tftp xinetd (2)在 Linux 下,不管使用的是哪一种服务器端服务:inetd 或者 xinetd,默认情况下 TFTP 服务是禁用的, 所以要修改文件来开启服务。在/etc/xinetd.d/下建立一个配置文件 tftp, 主要是设置 TFTP 服务器的根目录,开启服务。 sudo gedit /etc/xinetd.d/tftp 在文件中输入以下内容: service tftp { socket_type = dgram protocol = udp wait = yes user = root server = /usr/sbin/in.tftpd server_args = -s /home/hm/book2410/debugtool/tftpboot disable = no per_source = 11 cps = 100 2 flags = IPv4 } 保存退出。 其中 server_args = -s 参数设置 TFTP 服务器的根目录, 该目录就是用来存放 在后续开发过程中生成的内核及文件系统映像, 以供 tftp 客户端下载。 本书范例中使用的 tftp 根目录放在 4.2.4 节中安排的目录/home/hm/book2410/debugtool/下。 (3)建立 tftp 服务器文件目录 (这个目录就是在第二步中对 server_args = -s 设置的值) , 并且更改其权限,命令如下(读者需要根据自己的设置修改命令) : sudo mkdir /home/hm/book2410/debugtool/tftpboot sudo chmod 777 /home/hm/book2410/debugtool/tftpboot -R (4)重新启动服务 sudo /etc/init.d/xinetd restart

嵌入式 Linux 初级实验教程

53

4.3

在主机 Linux 系统中建立交叉编译环境

我们在第一章的概述中已经介绍了什么是交叉编译, 什么是交叉编译工具链, 以及制作 交叉编译工具链的几种方法。在本小节中,笔者将向读者展示利用 crosstool 工具制作交叉 编译工具链,为目标机应用程序建立交叉编译环境。

4.3.1

准备工具链软件

构建工具链的第一个步骤就是选择 gcc、glibc 与 binutils 这些软件的版本。而版本的匹 配是个大麻烦, 因为这些软件的维护与发行是彼此独立的, 当一个软件的所有版本与其他软 件的各种版本组合在一起时, 并非都能顺利完成建构。 读者可以尝试使用每一个软件的最新 版本,但此一组合是否可行也未可知。 如欲选择正确的版本, 读者朋友必须测试某个组合是否适合自己的宿主机和目标机。 如 果你很幸运,能够找到一个之前测试过的组合,那是最好不过了。如果没有,那么就可以从 每个套件最新的稳定版本开始测试, 若构建失败, 那么就需要一个接着一个地换成较旧的版 本进行测试。因此,假定现在的 gcc 最新版本是 gcc4.2.2,而 gcc4.2.2 编译失败,则可以尝试 gcc 4.2.1。如果再失败,便尝试 4.2,依此类推。然而,也不能永无止境地这样下去,因为 一些软件的最新版本会对其他软件提供了哪些功能是预定的。 因此, 如果其他软件完全无法 编译成功,可能回头使用这些软件的较旧版本就能编译成功。 一般情况下,用于处理二进制包的工具包 binutils 是可以独立安装的,它不需要更改, 就能编译成功。 此外,有些软件的版本还需要打一些补丁,才能成功完成编译。 要寻找软件版本的补丁以及合适的软件版本组合,可以参看下面列出的一些网站: http://www.debian.org/distrib/packages 上可以找到 Debian Linux 发行的源码包; http://cross-lfs.org/view/1.0.0 所提供的“Cross Compiled Linux From Scratch” (Linux 交 叉编译从零开始)文件; “CrossTool build matrix” http://www.kegel.com/crosstool/crosstool-0.43/buildlogs 所提供的 (交叉工具建构矩阵) 。这里可以很容易找到针对不同架构的已经测试通过的版本组合。 每当发现到一个可以编译成功的新版本组合,务必测试其所产生的工具链的确可以使 用。有些版本组合或许可以编译成功,但是使用的时候仍旧会失败。 本章接下来将使用表 4-3-1 中的软件版本组合来构建交叉工具链: 软件版本 binutils-2.16.1 gcc-3.3.6 gcc-4.1.1 glibc-2.3.2 gdb-6.5 linux-2.6.24 linux-libc-headers-2.6.12.0 crosstool-0.43 下载地址 ftp://ftp.gnu.org ftp://ftp.gnu.org ftp://ftp.gnu.org ftp://ftp.gnu.org ftp://ftp.gnu.org http://www.kernel.org http://ep09.pld-linux.org/~mmazur/linux-libc-headers/ http://kegel.com/crosstool/crosstool-0.43.tar.gz
表 4-3-1 本书范例所用的软件版本组合

4.3.2

建立交叉编译工具链

本书向大家介绍的是利用 crosstool 工具自动建立交叉编译工具链的方法。crosstool 是

嵌入式 Linux 初级实验教程

54

一组命令脚本,可用于替 glibc 所支援的大部分架构建立与测试多个 gcc 与 glibc 版本。 crosstool 甚至会替你下载源码包及相应补丁。 它最初是个命令脚本,Bill Gatliff 称之为 crossgcc,后来由 Dan Kegel 一般化及修改 成现在的样子。 crosstool 为工具链组件准备了一组补丁,这是建构交叉工具链组合所必须的。它支援 Alpha、ARM、i686、ia64、MIPS、PowerPC、PowerPC64、SH4、SPARC、SPARC64、s390 以及 x86_64 架构。 crosstool 具移植性,其所构建的交叉工具链可执行在 Linux、Mac OS X、Solaris 和 Cygwin 之上,可用于构建出 Linux 二进制文件。 下面是利用 crosstool 工具自动建立交叉编译工具链的具体过程: (1)下载工具链软件 将表 4-3-1 中所列的软件包从相应的站点下载下来,放在/home/hm/book2410/source 目 录下。 (2)解压 crosstool-0.43 cd /home/hm/book2410/source tar -xvzf crosstool-0.43.tar.gz cd crosstool-0.43/ (3)修改 demo-arm.sh gedit demo-arm.sh 修改下面两个地方 第一处 TARBALLS_DIR=/home/hm/book2410/source RESULT_TOP=/home/hm/book2410/crosstool 第二处 将文件最后"echo Done."前面一行"eval `cat arm.dat gcc-4.1.0-glibc-2.3.2-tls.dat` sh all.sh --notest"注释掉,并添加一行:"eval `cat arm.dat gcc-4.1.1-glibc-2.3.2.dat` sh all.sh --notest": #eval `cat arm.dat gcc-4.1.0-glibc-2.3.2-tls.dat` sh all.sh --notest eval `cat arm.dat gcc-4.1.1-glibc-2.3.2.dat` sh all.sh --notest echo Done. (3)编辑 gcc-4.1.1-glibc-2.3.2.dat 打开 crosstool-0.43 目录下 gcc-4.1.1-glibc-2.3.2.dat 文件 gedit gcc-4.1.1-glibc-2.3.2.dat 在该文件中写入如下内容(将原来的内容覆盖) : BINUTILS_DIR=binutils-2.16.1 GCC_CORE_DIR=gcc-3.3.6 GCC_DIR=gcc-4.1.1 GLIBC_DIR=glibc-2.3.2 LINUX_DIR=linux-2.6.24 注:进入源码目录 注:解压 crosstool-0.43 注:进入 crosstool-0.43 目录

嵌入式 Linux 初级实验教程

55

LINUX_SANITIZED_HEADER_DIR=linux-libc-headers-2.6.12.0 GLIBCTHREADS_FILENAME=glibc-linuxthreads-2.3.2 GDB_DIR=gdb-6.5 (4)编辑 arm.dat gedit arm.dat 在该文件中写入如下内容(将原来的内容覆盖) : KERNELCONFIG=`pwd`/arm.config TARGET=arm-linux TARGET_CFLAGS="-O" (5)修改 all.sh 将下面几行注释掉(57 行左右) ,便可以以 root 身份编译。 case x$USER in xroot) abort "Don't run all.sh or crosstool.sh as root, it's dangerous" ;; *) ;; esac (6)修改 glibc-2.3.2/csu 目录下的 Makefile 解压 source 目录下的 glibc-2.3.2.tar.bz2,打开 glibc-2.3.2/csu 目录下的 Makefile,修改文 件末尾 2 处 echo,命令如下: cd /home/hm/book2410/source tar -xvjf glibc-2.3.2.tar.bz2 cd glibc-2.3.2/csu gedit Makefile 第一处 echo "\"Compiled on a $$os $$version system" \ "on `date +%Y-%m-%d`.\\n\"" ;; \ 改为: echo "\"Compiled on a $$os $$version system" \ "on `date +%Y-%m-%d`.\\\\n\"" ;; \ 第二处 echo "\"Available extensions:\\n\"";\ 改为: echo "\"Available extensions:\\\\n\"";\ 将 glibc-2.3.2 重新压缩为 glibc-2.3.2.tar.bz2 , 覆盖 source 目录下原来的 glibc-2.3.2.tar.bz2 命令如下: cd /home/hm/book2410/source rm glibc-2.3.2.tar.bz2

嵌入式 Linux 初级实验教程

56

tar -cvzf glibc-2.3.2.tar.bz2 glibc-2.3.2 (7)修改宿主机 gcc 版本为 gcc-3.4 由于宿主机上的 gcc 版本在系统更新完以后安装的是当前的最新版本, 编译时有可能会 报错,现将其换成 gcc-3.4。命令如下: sudo apt-get install gcc-3.4 cd /usr/bin sudo rm gcc sudo ln -s gcc-3.4 gcc (8)执行 demo-arm.sh 以 root 用户的权限进行编译,避免编译过程因为一些文件的读、写、执行权限问题而 终止。命令如下: sudo su cd /home/hm/book2410/source/crosstool-0.43/ ./demo-arm.sh (9)建立成功 如果执行过程中没有错误, 那么说明交叉编译工具链建立成功。 交叉编译工具链建立成 功后, 进入/home/hm/book2410/crosstool/gcc-4.1.1-glibc-2.3.2/arm-linux/bin 目录下面可以看到 如 arm-linux-gcc 等一系列工具,这些工具就是目标板应用程序的编译调试工具。这些工具 的具体使用方法会在后面章节的“hello,world”范例中介绍。 hm@ubuntu804:~/book2410/crosstool/gcc-4.1.1-glibc-2.3.2/arm-linux/bin$ ls arm-linux-addr2line arm-linux-g++ arm-linux-ld arm-linux-size arm-linux-ar arm-linux-gcc arm-linux-nm arm-linux-strings arm-linux-as arm-linux-gcc-4.1.1 arm-linux-objcopy arm-linux-strip arm-linux-c++ arm-linux-gccbug arm-linux-objdump fix-embedded-paths arm-linux-c++filt arm-linux-gcov arm-linux-ranlib arm-linux-cpp arm-linux-gprof arm-linux-readelf hm@ubuntu804:~/book2410/crosstool/gcc-4.1.1-glibc-2.3.2/arm-linux/bin$ 现在,有了这些基础和准备工作,读者就可以正式开始嵌入式 Linux 开发了。在下一篇 章中,笔者将详细介绍怎样部署嵌入式 Linux 系统,如:U-boot 的烧写、内核以及文件系统 的移植等,带领读者朋友更深入的掌握嵌入式 Linux 的开发过程。

嵌入式 Linux 初级实验教程

57

第二篇

系统移植篇

本篇内容
BootLoader 移植 ★ 内核移植 ★ 根文件系统移植 ★

本篇目标
了解 BootLoader 的一些基础知识以及 u-boot 的移植过程 ★ 掌握 Linux 内核的编译,配置及安装过程 ★ 掌握根文件系统的制作、移植过程 ★ 学会挂载及使用 NFS 文件系统 ★

本篇实例
实例一:u-boot-1.1.6 的移植 ★ 实例二:内核移植 ★ 实例三:根文件系统制作 ★ 实例四:NFS 文件系统挂载 ★ 实例五:hello world ★

嵌入式 Linux 初级实验教程

58

第5章

BootLoader 移植

前面几章主要介绍在宿主机上建立基本的开发环境,为“嵌入式 Linux 开发”打好了地 基。从本章开始,笔者将正式带领大家为“嵌入式 Linux 开发”添砖加瓦。 对于计算机系统来说, 从开机上电到操作系统启动需要一个引导过程。 嵌入式 Linux 系 统同样离不开引导程序, 这个引导程序就叫作 Bootloader, 它的功能在于加载启动整个系统。 本章首先介绍 Bootloader 的一些基础知识,然后针对 U-Boot 的移植及使用做详细介绍。

5.1

系统引导程序基础

在第一章的概述中,笔者曾经介绍过: “BootLoader 是在系统上电之后,操作系统内核 运行之前执行的一段程序,主要负责载入系统内核” 。在嵌入式 Linux 中,BootLoader 需要 完成必要的硬件设备初始化, 将操作系统内核与它支持的设备加载到存储器, 以及着手执行 内核。Bootloader 所进行的典型任务包括选择内核(比如,回忆一下我们桌面型 Linux 系 统的启动过程,在引导初期你按下了一个按键,系统会提供一份内核清单,让你选择内核) 以及加载一个 initial RAM-based 文件系统(可以是 initrd、initramfs 或其他) 。RAM-based 文件系统中所包含的环境足以挂载根文件系统, 以及着手正常的启动程序 (启动系统监控程 序以及进行诸如此类的工作) 。一般的桌面型系统具有广泛的系统固件(如 PC 机的 BIOS) , 其所提供的信息包括硬件设备的配置、中断路由,以及 Linux 需要用到的其他信息。然而, 嵌入式 Linux 系统通常没有这类固件, 事实上, 它们都是通过 Bootloader 来执行这些任务。 因此,嵌入式 Linux 系统的 Bootloader 不仅必须将内核映像加载到系统存储器,它还必须 设定存储器控制器、初始化处理器高速缓存区、启用各种硬件设备、直接实现网络引导基础 设备的支持,以及从事各式各样的其他活动。 前面也介绍过,因为嵌入式硬件的特殊性,嵌入式领域没有通用的 BootLoader。不同的 CPU 体系结构都有不同的 BootLoader。有些 BootLoader 也支持多种体系结构的 CPU。除 了依赖于 CPU 的体系结构外, BootLoader 实际上也依赖于具体的目标机的配置。 这也就是 说,对于两块不同的目标机而言,即使它们是基于同一种 CPU 而构建的,要想让运行在一 块板子上的 Boo Loader 程序也能运行在另一块板子上,通常都需要修改 BootLoader 的源 程序。这就要求开发人员在了解 BootLoader 工作原理的基础上,根据自己的开发板的硬件 结构,自行完成 BootLoader 设计与实现。 接下来笔者将会介绍一些与 BootLoader 相关的基础知识,这些知识在网上或者其他类 似参考书上都会提到,如果你对这些知识已经很清楚了,就可以跳过。

5.1.1

Boot Loader 的安装媒介(Installation Medium)

通常来说,系统加电或复位后,所有的 CPU 通常都会从某个由 CPU 制造商预先设定 的地址上取指令。 例如, 在本书范例中所使用的 ARM 处理器, 它复位时是从地址 0x00000000 读取第一条指令。而基于 CPU 构建的嵌入式系统通常都将某种类型的固态存储设备(比如: ROM、EEPROM 或 FLASH 等)映射到这个预先安排的第一条指令的地址上。

图 5-1-1 典型的固态存储设备的空间分布图

对于大部分的含有 CPU 的嵌入式系统,固态存储设备的空间分布都与图 5-1-1 类似。 如 Super-ARM 有一块 64M 的 NandFlash,其上的 BootLoader、内核、文件系统的分布也是 参考上图。这里给大家看一下笔者对 Super-ARM 上 NandFlash 的具体布局。

嵌入式 Linux 初级实验教程

59

文件 BootLoader 内核 根文件系统 用户的其他文件系统
表 5-1-1

起始地址 0x0 0x30000 0x200000 0x2000000

大小(字节) 192 K 1856 K 30M 32M

Super-ARM 的 NandFlash 文件映射表

从表 5-1-1 可以看出, BootLoader 程序占据着 0x0 位置, 也就是说, 在系统加电后, CPU 将首先执行 BootLoader 程序。

5.1.2

BootLoader 工作模式

BootLoader 一般有两种工作模式, “启动加载” (bootloading)模式和“下载” (down loading)模式,这种区别仅对于开发人员才有意义。从最终用户的角度看,Boot Loader 的 作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。 启动加载模式:这种模式也称为"自主"(Autonomous)模式。即 BootLoader 从目标机 上的某个固态存储设备上将操作系统加载到 RAM 中运行,整个过程并没有用户的介入。 这种模式是 BootLoader 的正常工作模式, 因此在嵌入式产品发布的时侯, BootLoader 显然 必须工作在这种模式下。 下载模式:在这种模式下,目标机上的 Boot Loader 将通过串口连接或网络连接等通信 手段从宿主机下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常 首先被 BootLoader 保存到目标机的 RAM 中,然后再被 BootLoader 写到目标机上的 Flash 类固态存储设备中。BootLoader 的这种模式通常在第一次安装内核与根文件系统时被使用; 此外,以后的系统更新也会使用 BootLoader 的这种工作模式。工作于这种模式下的 Boot Loader 通常都会向它的终端用户提供一个简单的命令行接口。 如笔者在下面的章节中将要介绍的 U-Boot,通常同时支持以上两种工作模式,而且允 许用户在这两种模式之间进行切换。U-Boot 在启动时处于正常的启动加载模式,但是它会 延时一段时间(通常是几秒,用户可以自行设置)等待用户按下任意键而将 U-Boot 切换到 下载模式。如果在这段时间内用户没有按键,U-Boot 就开始自动引导内核。

5.1.3

BootLoader 的启动过程

通常多阶段的 BootLoader 能提供更为复杂的功能,以及更好的可移植性。从固态存储 设备上启动的 BootLoader 大多都是2个阶段的启动过程,也即启动过程可以分为 stage 1和 stage 2 两部分。依赖于CPU体系结构的代码(如CPU初始化代码等)通常都放在阶段1中, 且通常用汇编语言实现,而阶段2则通常用C语言来实现,这样可以实现复杂的功能,而且 有更好的可读性和移植性。 阶段1主要完成系统入口的定义,设置异常向量表,CPU 工作模式和工作频率以及一些 寄存器的值和堆栈空间等,还要完成代码从 NandFlash 到 RAM 的搬运过程。通常包括以 下步骤(以执行的先后顺序): (1)硬件设备初始化。 屏蔽所有的中断 设置 CPU 的速度和时钟频率 RAM 初始化 初始化 LED 关闭 CPU 内部指令/数据 Cache (2)为加载 BootLoader 的 step2 准备 RAM 空间。

嵌入式 Linux 初级实验教程

60

除了阶段 2 可执行映象的大小外,还必须把堆栈空间也考虑进来 必须确保所安排的地址范围的确是可读写的 RAM 空间 (3)拷贝 BootLoader 的 step2 到 RAM 空间中。 (4)设置好堆栈。 (5)跳转到 step2 的 C 入口点。 阶段2主要完成一系列的初始化,包括Flash,内存,环境变量,以及外围设备等,最后 进入命令行模式,以获取用户输入的命令,与用户进行交互。通常包括以下步骤(以执行的 先后顺序): (1)初始化本阶段要使用到的硬件设备。 初始化至少一个串口,以便和终端用户进行 I/O 输出信息 初始化定时器等 (2)检测系统内存映射(memory map)。 内存映射的描述 内存映射的检测 (3)将 kernel 映像和根文件系统映像从 Flash 上读到 RAM 空间中。 规划内存占用的布局:内核映像和根文件系统所占用的内存范围 从 Flash 上拷贝映象文件 (4)为内核设置启动参数。 标 记 列 表 (tagged list) 的 形 式 来 传 递 启 动 参 数 , 启 动 参 数 标 记 列 表 以 标 记 ATAG_CORE 开始,以标记 ATAG_NONE 结束 嵌 入 式 Linux 系 统 中, 通 常 需 要 由 Boot Loader 设 置 的 常见 启 动参 数有: ATAG_CORE、 ATAG_MEM、 ATAG_CMDLINE、 ATAG_RAMDISK、 ATAG_INITRD (5)调用内核。 CPU 寄存器的设置: R0=0; R1=机器类型 ID;关于机器类型号,可以参见: Linux/arch/arm/tools/mach-types。 R2=启动参数标记列表在 RAM 中起始基地址; CPU 模式: 必须禁止中断(IRQs 和 FIQs) ; CPU 必须 SVC 模式; Cache 和 MMU 的设置: MMU 必须关闭; 指令 Cache 可以打开也可以关闭; 数据 Cache 必须关闭; 读者如果想要深入研究 U-Boot 的启动过程或者工作原理,建议阅读 U-Boot 的源码。

嵌入式 Linux 初级实验教程

61

5.1.4

BootLoader 与宿主机之间进行文件传输所用的通信设备及协议

最常见的情况就是,目标机上的 BootLoader 通过串口与宿主机之间进行文件传输,传 输协议通常是 xmodem/ymodem/zmodem 协议中的一种。但是,串口传输的速度是有限 的,因此通过以太网连接并借助 TFTP 协议来下载文件是个更好的选择。 此外,在论及这个话题时,宿主机所用的软件也要考虑。比如,在通过以太网连接和 TFTP 协议来下载文件时,宿主机必须有一个软件用来提供TFTP 服务,这时候,上一章介 绍的——在宿主机Linux系统中安装tftp 服务器——就要派上用场了。

5.1.5

几种常用的 Boot Loader

嵌入式 Linux 系统有许多 BootLoader 可用,如 LILO、ROLO、Etherboot、U-Boot 等等, 限于篇幅,本章不可能逐一介绍。笔者只会简单介绍几种经常被提到的 Bootloader,然后将 会专注于 U-Boot, 因为 U-Boot 支援各式各样的系统, 而且是针对嵌入式应用从头开始设计 而成的。 (1) LILO LInux LOader(简称 LILO)是由 Werner Almesberger 于 Linux 草创时期所提出,而 且目前某些 x86 系统仍然会通过它启动内核。LILO 目前由 John Coffman 负责维护,可以 到 http://lilo.go.dyndns.org/ 下载最新的版本。 LILO 具有非常完善的文件。例如,LILO 套件随附有使用手册(user manual)和参考 。此外,你还可以在 LDP 的《LILO mini-HOWTO》以及《Running 手册(internals manual) Linux》 (O'Reilly 出版)的第五章找到 LILO 的使用指南。 笔者不准备详细说明 LILO,因为它已经具有非常完善的文件,而且它已经不再是 bootloader 的事实标准,它只会被使用在配备了 PC BIOS 的 x86 PC 类型的系统上。 (2) GRUB GRand Unified Bootloader( 简 称 GRUB) 是目 前 x86 系 统上 最受 欢 迎的 Linux bootloader, 并常见于基于 x86 “PC”的嵌入式电路板上。 如果你所开发的嵌入式 Linux 系统, 大体上基于标准的 PC 硬件,那么你用的应该是 GRUB,而不是其他的 BootLoader。 GRUB 最初是由 Erich Boleyn 为 GNU Mach 的操作系统所撰写的 bootloader。后来由 继续维护和开发 GRUB。 你可以 Gordon Matzigkeit 和 Okuji Yoshinori 接替 Erich 的工作, 从 GRUB 项目的网站 http://www.gnu.org/software/grub/ ) ( 下载最新的 GRUB 稳定版套件, 也可以在该网站上找到对 GRUB 套件的使用有广泛探讨的《GRUB manual》文件。或者你 可以使用 CVS 获取 GRUB 的源码包。 GRUB 能够使用 TFTP 和 BOOTP 或 DHCP 通过网络来引导,这在开发过程中相当 有用。另外,GRUB 有能力辨识各种标准的文件系统(并支持 tab 键的文件名路径补全功 能) ,因此无须对配置进行永久性的变更,这大为简化了测试的工作。 要进一步了解 GRUB, 你可以浏览该项目的网站, 以及使用任何的 基于 x86 的桌面型 Linux 系统来实验它。 (3) BLOB Blob 是 Boot Loader Object 的缩写,是一款功能强大的 Bootloader。它遵循 GPL,源代 码完全开放。Blob 既可以用来简单的调试,也可以启动 Linux kernel。Blob 最初是 Jan-Derk Bakker 和 Erik Mouw 为一块名为 LART(Linux Advanced Radio Terminal)的板子写的, 该板使 用的处理器是 StrongARM SA-1100。 现在 Blob 已经被移植到了很多 CPU 上, 包括 S3C44B0。 Blob 编译后的代码定义最大为 64KB,并且这 64KB 又分成两个阶段来执行。第一阶段 的代码在 start.S 中定义,大小为 1KB,它包括从系统上电后在 0x00000000 地址开始执行的

嵌入式 Linux 初级实验教程

62

部分。这部分代码运行在 Flash 中,它包括对 S3C44B0 的一些寄存器的初始化和将 Blob 第 二阶段代码从 Flash 拷贝到 SDRAM 中。除去第一阶段的 1KB 代码,剩下的部分都是第二 阶段的代码。第二阶段的起始文件为 trampoline.s,被复制到 SDRAM 后,就从第一阶段跳 转到这个文件开始执行剩余部分代码。第二阶段最大为 63KB,在这个程序中进行一些 BSS 段设置、堆栈的初始化等工作后,最后跳转到 main.c 进入 C 函数。 (4) ARMboot 是为基于 ARM 或者 StrongARM CPU ARMboot 是一个基于 ARM 平台的开源固件项目, 的嵌入式系统所设计的。它所支持的处理器构架有 StrongARM ,ARM720T ,PXA250 等。 ARMboot 发布的最后版本为 ARMboot-1.1.0,2002 年 ARMboot 终止了维护,其发布网址 为:http://sourceforge.net/projects/armboot。 ARMboot 的目标是成为通用的、容易使用和移植的引导程序,非常轻便地运用于新的平 台上。ARMboot 是 GPL 下的 ARM 固件项目中唯一支持 Flash 闪存,BOOTP、DHCP、TFTP 网络下载,PCMCLA 寻线机等多种类型来引导系统的。特性为: 支持多种类型的 FLASH 允许映像文件经由 BOOTP、DHCP、TFTP 从网络传输; 支持串行口下载 S-record 或者 binary 文件 允许内存的显示及修改 支持 jffs2 文件系统等 ARMboot 对 S3C44B0 板的移植相对简单,在经过删减完整代码中的一部分后,仅仅需要 完成初始化、串口收发数据、启动计数器和 FLASH 操作等步骤,就可以下载引导 uClinux 内 核完成板上系统的加载。总得来说,ARMboot 介于大、小型 Boot Loader 之间,相对轻便,基本 功能完备,缺点是缺乏后续支持。 (5) Redboot Redboot 是 Redhat 公司随 eCos 发布的一个 BOOT 方案,是一个开源项目。当前 Redboot 的 最 新 版 本 是 Redboot-2.0.1,Redhat 公 司 将 会 继 续 支 持 该 项 目 , 其 官 方 发 布 网 址 为:http://sources.redhat.com/redboot/。 Redboot 支持的处理器构架有 ARM,MIPS,MN10300,PowerPC, Renesas SHx,v850,x86 等, 是一个完善的嵌入式系统 Boot Loader。 Redboot 是在 ECOS 的基础上剥离出来的,继承了 ECOS 的简洁、轻巧、可灵活配置、稳 定可靠等品质优点.它可以使用 X-modem 或 Y-modem 协议经由串口下载,也可以经由以太网 口通过 BOOTP/DHCP 服务获得 IP 参数,使用 TFTP 方式下载程序映像文件,常用于调试支持 和系统初始化(Flash 下载更新和网络启动).Redboot 可以通过串口和以太网口与 GDB 进行通 信,调试应用程序,甚至能中断被 GDB 运行的应用程序.Redboot 为管理 FLASH 映像,映像下 载,Redboot 配置以及其他如串口、以太网口提供了一个交互式命令行接口,自动启动 后,REDBOOT 用来从 TFTP 服务器或者从 Flash 下载映像文件加载系统的引导脚本文件保存 在 Flash 上。当前支持单板机的移植版特性有: 支持 ECOS,Linux 操作系统引导 在线读写 Flash 支持串行口 kermit,S-record 下载代码 监控(minitor)命令集:读写 I/O,内存,寄存器、 内存、外设测试功能等 Redboot 是标准的嵌入式调试和引导解决方案,支持几乎所有的处理器构架以及大量的 外围硬件接口,并且还在不断地完善过程中。 (6) ViVi

嵌入式 Linux 初级实验教程

63

ViVi 是由 mizi 公司设计为 ARM 处理器系列设计的一个 bootloader,因为 ViVi 目前只支 持使用串口和主机通信,所以您必须使用一条串口电缆来连接目标板和宿主机. 它有如下作用: 把内核(kernel)从 flash 复制到 RAM,然后启动它 初始化硬件 下载程序并写入 flash(一般是通过串口或者网口先把内核下载到 RAM 中,然后再 写入到 flash) 检测目标板(bootloader 会有一些简单的代码用以测试目标板硬件的好坏) (7) U-Boot U-Boot,全称 Universal BootLoader,被认为是功能最多、最具弹性以及开发最积极的 BootLoader,它是遵循 GPL 条款的开放源码项目。目前由 DENX Software Engineering(位 于德国慕尼黑之外)的 Wolfgang Denk 所维护,并且受到各种开发者的支援。 U-Boot 是基于早先的 PPCBoot 项目(为 PowerPC 系统所撰写的 bootloader)和 ARMBoot 项目。PPCBoot 本身基于 8xxrom 的源码,而 ARMBoot 则是 Sysgo Gmbh 将 PPCBoot 移植到 ARM 的成果。 之所以在 Boot Loader 前面加个 Universal,主要体现在以下两个方面:在操作系统的支 持方面,U-Boot 不仅仅支持嵌入式 Linux 系统的引导,当前,它还支持 NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS 嵌入式操作系统;在处理器支持方面,U-Boot 除了支持 PowerPC 系列的处理器外,还能支持 MIPS、x86、ARM、NIOS、XScale 等诸多常用系列的 处理器。这两个特点正是 U-Boot 项目的开发目标,即支持尽可能多的嵌入式处理器和嵌入 式操作系统。就目前来看,U-Boot 对 PowerPC 系列处理器支持最为丰富,对 Linux 的支持 最完善。 此外,U-Boot 还具备使用 TFTP 通过网络连线从 IDE 或 SCSI 磁盘、从 USB 以及 从各式各样的 flash 设备启动内核的能力。U-Boot 支持一系列的文件系统,包括 Cramfs (Linux、ext2(Linux) 、FAT(Microsoft)以及 JFFS2(Linux) 。 U-Boot 具备广泛可设定的命令集以及许多能力。它还拥有相当完善的文件,如 u-boot 源 码 包 中 的 Manual 提 供 有 如 何 使 用 U-Boot 的 详 细 说 明 。 你 可 以 从 http://denx.de/wiki/U-Boot/WebHome 的 DENX wiki 上找到大量的文件、邮件论坛的信息、 讨论内容等。 U-Boot 源码包及最新版本可以从 http://sourceforge.net/projects/u-boot/下载。

5.2

移植 U-Boot

上一节中笔者介绍了关于 BootLoader 的相关知识,其中也简单介绍了 U-Boot。在本小 节,我会以 Super-ARM 为平台,介绍如何将 U-Boot 移植到该平台上。 U-Boot 作为一种在嵌入式领域广泛使用的 BootLoader,可以支持几十种处理器和数百 种开发板。其源码是值得开发者们学习和研究的。尽管本书的目的不是要求读者对 U-Boot 的源代码进行深入探讨,事实上,现在已经有不少专门探讨 U-Boot 的书籍,但是为了更好 地理解 U-Boot 的移植过程,在进行 U-Boot 移植之前还是有必要介绍一下它的源码结构的。 本书针对 u-boot-1.1.6 进行移植, 读者也可以对 U-Boot 其他版本进行类似的移植。移植 U-Boot 的一般步骤是:先下载 U-Boot 源码包,并根据开发板的具体情况来进行配置,然后 将配置好的 U-Boot 源码编译,最后通过 JTAG 等工具烧写到目标板。

5.2.1

U-Boot 源码结构

从网上下载 u-boot-1.1.6 的源码包,解压以后就可以看到全部的 U-Boot 源代码,结构如

嵌入式 Linux 初级实验教程

64

表 5-2-1 所示: 目 录 board cpu lib_ppc lib_arm lib_i386 include common lib_generic Net Fs Post drivers Disk Rtc Dtt examples tools Doc 特 性 平台依赖 平台依赖 平台依赖 平台依赖 平台依赖 通 用 通 用 通 用 通 用 通 用 通 用 通 用 通 用 通 用 通 用 应用例程 工 具 文 档 解 释 说 明 存放电路板相关的目录文件,例如:RPXlite(mpc8xx)、 smdk2410(arm920t)、sc520_cdp(x86)等目录 存放 CPU 相关的目录文件,例如:mpc8xx、ppc4xx、arm720t、 arm920t、xscale、i386 等目录 存放对 PowerPC 体系结构通用的文件,主要用于实现 PowerPC 平台通用的函数 存放对 ARM 体系结构通用的文件,主要用于实现 ARM 平台通 用的函数 存放对 X86 体系结构通用的文件,主要用于实现 X86 平台通用 的函数 头文件和开发板配置文件,所有开发板的配置文件都在 configs 目录下 通用的多功能函数实现 通用库函数的实现 存放网络的程序 存放文件系统的程序 存放上电自检程序 通用的设备驱动程序,主要有以太网接口的驱动 硬盘接口程序 RTC 的驱动程序 数字温度测量器或者传感器的驱动 一些独立运行的应用程序的例子,例如 helloworld 存放制作 S-Record 或者 U-Boot 格式的映像等工具, 例如 mkimage 开发使用文档
表 5-2-1 U-Boot 顶层目录说明

整个 U-Boot 文件夹下所包含的文件非常多,对于特定的开发板,配置编译过程只需要 其中部分程序,因此,我们对 U-Boot 源代码进行修改的时候,只要针对自己使用的 CPU 和 开发板进行特定修改就可以了。具体到本书的范例,由于我们使用的处理器是 S3c2410,而 U-Boot 下已提供的实验平台 smdk2410 也是采用此款芯片,我们可以借鉴这个平台的设计, 针对自己的实验平台特征进行相应修改。

5.2.2

U-Boot 移植过程详解

U-Boot 源码包的 README 文档中广泛地说明了 U-Boot 的用法,它还探讨了源码的 布局、可用的构建选项、U-Boot 的命令集以及 U-Boot 特有的环境变量。如果要深入探讨 U-Boot,最好将 U-Boot 所提供的 README 副本打印出来,随时参考。 接下来笔者将详细介绍在 Super-Arm 上移植 u-boot-1.1.6 的过程。笔者一边介绍移植的 步骤的同时,一边进行相应的解析,希望读者充分理解整个移植过程,这样,当读者面对其 它开发板时同样可以做到得心应手。 (1)首先下载 u-boot-1.1.6.tar.bz2 源码包,放在工作空间的 bootloader 目录下,解压, 并进入该目录: cd ~/book2410/bootloader tar -jxvf u-boot-1.1.6.tar.bz2

嵌入式 Linux 初级实验教程

65

cd u-boot-1.1.6 (2)修改顶层 Makefile U-Boot 是通过 gcc 和 Makefile 组织编译的。顶层目录下的 Makefile 可以设置开发板的 定义,然后递归地调用各级子目录下的 Makefile,最后把编译过的代码连接成 u-boot 映像。 每个目标板都要在 U-Boot 的 Makefile 中设定一行配置选项 boardname_config ,用来 定义目标板处理器的架构及类型,进而替目标板设定 U-Boot 的构建配置。U-Boot 为相当 多的开发板预先设定了一些配置, 所以许多目标系统可能已经存在预先设好的配置或者类似 的配置,以 Super-ARM 为例,U-Boot 里面有个 smdk2410 的配置 smdk2410_config ,在这 个配置的基础上,只要对 U-Boot 源代码做少量修改就可以为 Super-ARM 平台(这里我们暂 且将 Super-ARM 平台命名为 SuperARM2410)所用。 所以在顶层 Makefile 中,你只要找到 smdk2410_config 这一行: smdk2410_config:unconfig @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0 然后参考上面一行增加 SuperARM2410_config,如下: SuperARM2410_config:unconfig @$(MKCONFIG) $(@:_config=) arm arm920t SuperARM2410 NULL s3c24x0 解释一下这行配置中各项的意思: arm: CPU 的架构(ARCH) arm920t: CPU 的类型(CPU),其对应于 cpu/arm920t 子目录。 SuperARM2410: 开发板的类型,对应于 board/ SuperARM2410 目录。 NULL: 开发者/或经销商(vender)。 s3c24x0: 片上系统(SOC)。 在顶层 Makefile 中还要定义交叉编译器,这里就使用我们在第四章中构建的交叉编译 器。 ifeq ($(ARCH),arm) CROSS_COMPILE = arm-linux交叉编译器的前缀配置成 arm-linux-,前面需要加上交叉编译器的绝对路径,或者将该 路 径 加 到 宿 主 机 的 PATH 环 境 变 量 中 。 比 如 , 笔 者 的 交 叉 编 译 器 的 绝 对 路 径 是 /home/hm/book2410/crosstool/gcc-4.1.1-glibc-2.3.2/arm-linux/bin/, 这时我可以将它直接添加到 arm-linux-前面,如图 5-2-1 所示:

图 5-2-1 配置交叉编译器

或者打开/etc/profile 文件,在文件的末尾添加下面两行: PATH=$PATH:/home/hm/book2410/crosstool/gcc-4.1.1-glibc-2.3.2/arm-linux/bin/ export PATH 然后保存退出, 这样就将交叉编译器的路径加入到系统的环境变量当中, 这样系统就能 通过这个路径自动找到交叉编译器, 不过设置完这个文件以后需要重启系统才能生效, 当然, 也有办法让它马上生效,只要在终端敲入下面的命令:

嵌入式 Linux 初级实验教程

66

source /etc/profile (3)为 Super-ARM 平台新建一个目录 Super-ARM 是参考 smdk2410 开发板的配置,在 smdk2410 平台的基础上进行移植的。 不过为了不破换 U-Boot 本身的代码,我们在 board 目录下将 smdk2410 文件夹复制为 SuperARM2410,并将该目录下的 smdk2410.c 重命名为 SuperARM2410.c cd board cp -r smdk2410 SuperARM2410 cd SuperARM2410 mv smdk2410.c SuperARM2410.c (4)为 Super-ARM 平台配置头文件 每块开发板都有一个头文件,位于 include/configs 目录下,它是为开发板定义配置选项 和参数的,如 smdk2410 开发板对应的头文件是 smdk2410.h。 这个头文件中主要定义了两类变量,一类是选项,前缀是 CONFIG_,用来选择处理器, 命令,参数等。如: #define CONFIG_S3C2410 1 一类是参数,前缀是 CFG_,用来定义总线参数,串口波特率,flash 地址等。如: #define CFG_LOAD_ADDR 0x30008000 接下来,我们将参考 smdk2410.h,进行适当的修改,为 Super-ARM 来设定相关的选项 和配置。首先进入 include/configs 目录,复制 smdk2410.h 为 SuperARM2410.h 需要做的修改有以下几处: 第一处:在“#define CONFIG_SMDK2410 #define CONFIG_S3C2410_NAND_BOOT 1 #define STACK_BASE 0x33f00000 #define STACK_SIZE 0x8000 #define UBOOT_RAM_BASE 0x33f80000 其中第一行是配置目标板从 NandFlash 启动, 第二行和第三行配置堆栈的基地址和堆栈 空间的大小,第四行配置 U-Boot 在 RAM 中的基地址。 第二处:增加配置命令 CFG_CMD_NAND 1”这一行下面添加以下几行:

图5-2-2 修改 SuperARM2410.h(1)

嵌入式 Linux 初级实验教程

67

该配置用来增加操作 NandFlash 的相关命令, 如读写 (nand read, nand write) 擦除(nand , erase)等操作命令。 第三处:配置 u-boot 环境变量,这些环境变量也可以在 u-boot 烧写到 Flash 以后再 配置,在这里,笔者暂时不介绍这些环境变量的具体含义,把它放到后面“U-Boot 环境变量”这一小节进行介绍。

图5-2-3 修改 SuperARM2410.h(2)

第四处:配置命令提示符(command prompt) ,这个属于个性化配置范畴了,你可 以根据自己的喜好配,也可以用默认的。

图5-2-4 修改 SuperARM2410.h(3)

第五处:配置装载地址为0x30008000

图5-2-5 修改 SuperARM2410.h(4)

这两个装载地址是 U-Boot 通过 Flash 启动或者 TFTP 引导内核时的默认装载地址, 这样 说读者或许还不太明白,先暂且放着不管,后面用到这个参数的时候笔者还会介绍,那时就 容易理解了。 第六处:在文件末尾处,#endif 之前进行如下修改 注释掉下面两行: #defineCFG_ENV_IS_IN_FLASH 1 #define CFG_ENV_SIZE0x10000 /* Total Size of Environment Sector */ 增加如下代码: #define CFG_ENV_IS_IN_NAND 1 #define CFG_ENV_SIZE 0x4000/* Total Size of Environment Sector */ #define CFG_ENV_OFFSET (0x04000000-0x8000) /*********define mach_type ***********/ #define CONFIG_ARCH_SMDK2410 1 /* define nand command support */ #if (CONFIG_COMMANDS & CFG_CMD_NAND)

嵌入式 Linux 初级实验教程

68

#define CFG_NAND_LEGACY 1 #define CFG_NAND_BASE 0x4E000000 #define CFG_MAX_NAND_DEVICE 1 #define SECTORSIZE 512 #define NAND_SECTOR_SIZE SECTORSIZE #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1) #define ADDR_COLUMN 1 #define ADDR_PAGE 3 #define ADDR_COLUMN_PAGE 4 #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 #define NAND_MAX_CHIPS 1 #define WRITE_NAND_COMMAND(d, adr) do {rNFCMD = d;} while(0) #define WRITE_NAND_ADDRESS(d, adr) do {rNFADDR = d;} while(0) #define WRITE_NAND(d, adr) do {rNFDATA = d;} while(0) #define READ_NAND(adr) (rNFDATA) #define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));} #define NAND_DISABLE_CE(nand) {rNFCONF |= (1<<11);} #define NAND_ENABLE_CE(nand) {rNFCONF &= ~(1<<11);} #define NAND_CTL_CLRALE(nandptr) #define NAND_CTL_SETALE(nandptr) #define NAND_CTL_CLRCLE(nandptr) #define NAND_CTL_SETCLE(nandptr) #define CONFIG_MTD_NAND_VERIFY_WRITE 1 #endif /* CONFIG_COMMANDS & CFG_CMD_NAND*/ #ifdef CONFIG_S3C2410_NAND_BOOT #define rNFCONF (*(volatile unsigned int *)0x4e000000) #define rNFCMD (*(volatile unsigned char *)0x4e000004) #define rNFADDR (*(volatile unsigned char *)0x4e000008) #define rNFDATA (*(volatile unsigned char *)0x4e00000c) #define rNFSTAT (*(volatile unsigned int *)0x4e000010) #define rNFECC (*(volatile unsigned int *)0x4e000014) #define rNFECC0 (*(volatile unsigned char *)0x4e000014) #define rNFECC1 (*(volatile unsigned char *)0x4e000015) #define rNFECC2 (*(volatile unsigned char *)0x4e000016) #define NF_CMD(cmd) {rNFCMD=cmd;} #define NF_ADDR(addr) {rNFADDR=addr;} #define NF_nFCE_L() {rNFCONF&=~(1<<11);} #define NF_nFCE_H() {rNFCONF|=(1<<11);} #define NF_RSTECC() {rNFCONF|=(1<<12);} #define NF_RDDATA() (rNFDATA) #define NF_WRDATA(data) {rNFDATA=data;} #define NF_WAITRB() {while(!(rNFSTAT&(1<<0)));} #endif 上面这些配置选项都是与 NandFlash 有关的,太多了,笔者不一一介绍,如果你有兴趣 了解,可以直接查阅 U-Boot 的 README 文件。接下来涉及到的 nand.c,start.S,env_nand.c

嵌入式 Linux 初级实验教程

69

文件的修改大部分是与 NandFlash 相关,这些文件的修改只是针对 Super-ARM 的,鉴于各 个开发板上 NandFlash 的特殊性,这些修改不一定适合你的开发板,因此,笔者不打算对其 中的代码进行详细分析。 (5)在 SuperARM2410 目录下增加 nand.c 文件,文件内容如下: #include <common.h> #include <s3c2410.h> #include <config.h> #define TACLS0 #define TWRPH03 #define TWRPH10 #define U32 unsigned int extern unsigned long nand_probe(unsigned long physadr); static void NF_Reset(void) { int i; NF_nFCE_L(); NF_CMD(0xFF); for(i=0;i<10;i++); NF_WAITRB(); NF_nFCE_H(); } void NF_Init(void) { rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)\ |(TWRPH1<<0); NF_Reset(); } int nand_read_whole(unsigned char *buf, unsigned long start_addr, int size) { int i, j; if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) { return 1; } NF_nFCE_L(); for(i=0; i<10; i++); i = start_addr; while(i < start_addr + size) { rNFCMD = 0; rNFADDR = i & 0xff; rNFADDR = (i >> 9) & 0xff; rNFADDR = (i >> 17) & 0xff; rNFADDR = (i >> 25) & 0xff; NF_WAITRB(); for(j=0; j < NAND_SECTOR_SIZE; j++, i++) { *buf = (rNFDATA & 0xff); buf++; }

嵌入式 Linux 初级实验教程

70

} NF_nFCE_H(); return 0; } void nand_init(void) { NF_Init();/* nand_reset();*/ printf ("%4lu MB\n", nand_probe((unsigned long)CFG_NAND_BASE) >> 20); } (6)修改 SuperARM2410 目录下的 Makefile 注释掉: COBJS:= smdk2410.o flash.o 再增加一行: COBJS:= SuperARM2410.o nand.o flash.o 这是因为前面将 smdk2410.c 改成 SuperARM2410.c, 而且新增加了个 nand.c 文件, 所以 要在 Makefile 中告诉编译器将 SuperARM2410.c 及 nand.c 文件分别编译链接成 nand.o 及 SuperARM2410.o 这两个目标文件。 (7)修改 cpu/arm920t 目录下的 start.S 文件 第一处(165行左右) :在“#ifndef CONFIG_SKIP_RELOCATE_UBOOT”这一行 后面增加: #ifdef CONFIG_S3C2410_NAND_BOOT /* relocate uboot from NAND Flash instead of NOR Flash */ bl copy_myself #else 在 187 行左右 ble copy_loop 后面增加: #endif /* CONFIG_S3C2410_NAND_BOOT */ 第二处(230行左右) :在_start_armboot:.word start_armboot 这一行下面增加如下 内容: #ifdef CONFIG_S3C2410_NAND_BOOT copy_myself: mov r10, lr ldr sp, DW_STACK_START mov fp, #0 bl NF_Init @read UBOOT from Nand Flash to RAM ldr r0, =UBOOT_RAM_BASE mov r1, #0x0 mov r2, #0x20000 bl nand_read_whole tst r0, #0x0

嵌入式 Linux 初级实验教程

71

beq ok_nand_read 1: b 1b ok_nand_read: mov r0, #0x00000000 ldr r1, =UBOOT_RAM_BASE mov r2, #0x400 go_next: ldr r3, [r0], #4 ldr r4, [r1], #4 teq r3, r4 bne notmatch subs r2, r2, #4 beq done_nand_read bne go_next notmatch: 1: b 1b done_nand_read: mov pc, r10 #endif /* CONFIG_S3C2410_NAND_BOOT */ 第三处:在文件末尾增加下面几行内容: #ifdef CONFIG_S3C2410_NAND_BOOT .align 2 DW_STACK_START: .word STACK_BASE + STACK_SIZE - 4 #endif (8)修改 common 目录下的 env_nand.c 文件 第一处: 将“#include <nand.h>”这一行去掉,然后添加下面的内容 #if (CONFIG_COMMANDS & CFG_CMD_NAND) #ifdef CFG_NAND_LEGACY #include <linux/mtd/nand_legacy.h> extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; extern int curr_device; extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs, size_t len, int clean); extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start, size_t len, size_t *retlen, u_char *buf); extern void nand_print(struct nand_chip *nand); extern void nand_print_bad(struct nand_chip *nand); extern int nand_read_oob(struct nand_chip *nand, size_t ofs, size_t len, size_t *retlen, u_char *buf); extern int nand_write_oob(struct nand_chip *nand, size_t ofs, size_t len, size_t *retlen, const u_char *buf); struct nand_chip* nand = &nand_dev_desc[0]; #else /* !CFG_NAND_LEGACY */ #include <linux/mtd/nand.h>

嵌入式 Linux 初级实验教程

72

#include <nand.h> #endif /* !CFG_NAND_LEGACY */ #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ 第二处:找到下面几行内容,注释掉。 int nand_legacy_rw (struct nand_chip* nand, int cmd, size_t start, size_t len, size_t * retlen, u_char * buf); /* info for NAND chips, defined in drivers/nand/nand.c */ extern nand_info_t nand_info[]; 第三处:该文件中有两个 int saveenv(void)函数,我们修改第二个,即"#else /* ! CFG_ENV_OFFSET_REDUND */"这一行后面的 int saveenv(void)函数, 将该函数体 中的内容更改如下: int saveenv(void) { int ret = 0; #ifndef CFG_NAND_LEGACY ulong total; puts ("Erasing Nand..."); if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE)) return 1; puts ("Writing to Nand... "); total = CFG_ENV_SIZE; ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr); #else ulong off = CFG_ENV_OFFSET; ulong size = CFG_ENV_SIZE; puts ("Erasing Nand Environment..."); ret = nand_legacy_erase (nand,off, size, 1); printf("%s\n", ret ? "ERROR\n" : "OK\n"); if (ret!=0) return ret; puts ("Writing new Environment Variables to Nand..."); int total; ret = nand_legacy_rw (nand, 0x0, off, size,(size_t *)&total,(u_char*)env_ptr); #endif /* CFG_NAND_LEGACY */ if (ret || total != CFG_ENV_SIZE){ puts("undone!!!\n"); return 1; } puts ("done\n"); return ret; } 第四处:该文件中有两个 void env_relocate_spec (void)函数,我们也是修改第二个, 即 "#else /* ! CFG_ENV_OFFSET_REDUND */ */" 这 一 行 后 面 的 void env_relocate_spec (void),将该函数体中的内容更改如下: void env_relocate_spec (void)

嵌入式 Linux 初级实验教程

73

{ #if !defined(ENV_IS_EMBEDDED) #ifndef CFG_NAND_LEGACY ulong total; int ret; total = CFG_ENV_SIZE; ret = nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr); if (ret || total != CFG_ENV_SIZE) return use_default(); if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) return use_default(); #else ulong total; int ret; ret = nand_legacy_rw(nand, 1, CFG_ENV_OFFSET, CFG_ENV_SIZE, (size_t *)&total, (u_char*)env_ptr); if (ret || total != CFG_ENV_SIZE) return use_default(); if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) return use_default(); #endif /* CFG_NAND_LEGACY*/ #endif /* ! ENV_IS_EMBEDDED */ } (9)修改 common 目录下的 cmd_boot.c 文件。 第一处: 找到头文件下面的几行, 注释掉 “#if defined(CONFIG_I386)” “#endif” 和 : //#if defined(CONFIG_I386) DECLARE_GLOBAL_DATA_PTR; //#endif 第二处:在60行左右的“#if !defined(CONFIG_NIOS)”这一行下面添加如下几行: if(argc==2) rc = ((ulong (*)(int, char *[]))addr) (0, gd->bd->bi_arch_number); else (10)上述文件修改完毕以后,进入顶层目录执行 make SuperARM2410_config 命令。 (11)执行 make 命令,开始对 U-Boot 进行编译,编译完成之后,顶层目录下面增加 了 u-boot 各种格式的映像文件和符号表。如表 5-2-2 所示: 文件名 u-boot.map u-boot u-boot.bin u-boot.srec 说明 U-Boot 的符号对映 U-Boot 可执行文件,采用 ELF 二进制格式 U-Boot 原始二进制映像,可以被写入引导储存设备 U-Boot 映像的 S-Recoad 格式
表 5-2-2 U-Boot 编译生成的映像文件

嵌入式 Linux 初级实验教程

74

5.2.3

烧写 U-Boot

U-Boot 编译完成之后,就可以将 u-boot 目录下的 u-boot.bin 烧 写 到 目 标 机 的 NandFlash 中。u-boot.bin 的烧写需要使用一个硬件烧录装置,例如 Flash 烧录器或 JTAG 仿 真器。Super-ARM 实验箱的 U-Boot 烧写,在 WINDOWS 下进行,依赖第 3 章中所安装的 ADS 开发环境,过程如下: (1) 用 Super-ARM 实验箱中配置的并口线将 PC 机并口 (DB25 口) 与仿真器 Probe ICE 的 DB25 口连接;用 20Pin 扁平电缆线将仿真器 Probe ICE 的 ARM-JTAG 口与实验 箱的 JTAG 口相连接。打开系统电源。 (2)运行 Multi-ICE Server(参看第三章的相关章节) (3) 将本章附件中名为“u-boot 烧写”的文件夹复制到 PC 机的某个目录下,将新编译成 功的 u-boot.bin 拷贝到该目录下。“u-boot 烧写”文件夹包含了 downUBoot.bat、WriteDwn.bat 等批处理文件。这里需要了解一下 downUBoot.bat 文件的作用,文件内容如下: @echo off set FILE=u-boot.bin if not exist %FILE% goto error call writedwn %FILE% 116880 0x80000000 12 goto quit :error echo file: %FILE% NOT found! :quit 暂且不管这个文件中的语法,只重点解释一下标为斜体的两行: “set FILE=u-boot.bin”:这一行的意思是设置即将要烧写的文件名为 u-boot.bin; “call writedwn %FILE% 116880 0x80000000 12”:这一行的意思是调用 WriteDwn.bat 批 处理文件将 u-boot.bin 烧写到 NandFlash 的 0x0000000 地址。 其中“116880”是 u-boot.bin 文件 的大小(单位字节) ;“0x80000000”表示 u-boot.bin 存放的起始地址为 NandFlash 的第 0 块 (Super-ARM 实验箱的 NandFlash 的容量为 64M 字节,分 4096 块,每一块大小为 16K 字 节) ,也就是 0x0000000 地址(最前面的 8 表示操作的是 NandFlash,后面数字表示 NandFlash 的块地址,比如 0x80000002,则表示 u-boot.bin 存放的起始地址为 NandFlash 的第 2 块,也 就是 0x0008000 地址) ;“12”表示 u-boot.bin 文件的大小不能超过 NandFlash 的 12 块。 理解了 downUBoot.bat 文件的几个重要参数以后,可以根据实际情况(u-boot.bin 大小, 计划烧写到 NandFlash 的地址)更改文件中的参数。然后双击运行 downUBoot.bat。 当 Super-ARM 核心板上面 IO 口的红绿灯常亮的时候则表示 bootloader 烧写成功(如果 灯一直在闪, 则可能烧写失败, 要重新烧写)。 这样就把 U-Boot 通过 Probe ICE 烧写到 Nand Flash 中了。

5.3

U-Boot 使用

将 U-Boot 烧写到目标机的 Flash 之后,用串口线将目标机与宿主机连接起来,进入宿 主机 Linux 系统,运行 minicom,再打开目标机电源,如果 U-Boot 烧写成功,会看到下面 的提示信息: U-Boot 1.1.6 (Oct 19 2009 - 03:01:55) DRAM: 64 MB

嵌入式 Linux 初级实验教程

75

Flash: 512 kB NAND: 64 MB In: serial Out: serial Err: serial Hit any key to stop autoboot: 0 从上面的提示信息可以知道,U-Boot 首先会打印出版本信息,然后提供与硬件有关的 若干细节。U-Boot 一运行便会有一个可设定的计时器在输出的最后一行开始倒数计时。如 果在所设定的秒数内未按下任何键,U-Boot 就会根据预设的配置开始引导内核。如果在该 时间之内有按下一个键,你会看到一个提示符号: SuperARM # 这个命令提示符就是在上一小节中配置的。 这时你可以在命令提示符的后面输入一定的 命令来完成你想要完成的任务,比如配置目标机的 ip 地址,通过 tftp 的方式下载内核和根 文件系统等。

5.3.1

U-Boot 命令

在命令行提示符后面输入 help 可以查看 U-Boot 的所有命令 SuperARM # help ? - alias for 'help' autoscr - run script from memory base - print or set address offset bdinfo - print Board Info structure boot - boot default, i.e., run 'bootcmd' bootd - boot default, i.e., run 'bootcmd' bootelf - Boot from an ELF image in memory bootm - boot application image from memory bootp - boot image via network using BootP/TFTP protocol bootvx - Boot vxWorks from an ELF image cmp - memory compare coninfo - print console devices and information cp - memory copy crc32 - checksum calculation date - get/set/reset date & time dcache - enable or disable data cache echo - echo args to console erase - erase FLASH memory flinfo - print FLASH memory information go - start application at address 'addr' help - print online help icache - enable or disable instruction cache iminfo - print header information for application image imls - list all images found in flash itest - return true/false on integer compare loadb - load binary file over serial line (kermit mode) loads - load S-Record file over serial line loady - load binary file over serial line (ymodem mode)

嵌入式 Linux 初级实验教程

76

loop - infinite loop on address range md - memory display mm - memory modify (auto-incrementing) mtest - simple RAM test mw - memory write (fill) nand - legacy NAND sub-system nboot - boot from NAND device nfs - boot image via network using NFS protocol nm - memory modify (constant address) printenv- print environment variables protect - enable or disable FLASH write protection rarpboot- boot image via network using RARP/TFTP protocol reset - Perform RESET of the CPU run - run commands in an environment variable saveenv - save environment variables to persistent storage setenv - set environment variables sleep - delay execution for some time tftpboot- boot image via network using TFTP protocol version - print monitor version U-Boot 替每个命令提供了辅助说明,要使用某个命令之前可以通过查看这些辅助说明 来了解该命令的用法,如要想知道 cp 命令的作用及使用方法,便可以输入 help cp 查看: SuperARM # help cp cp [.b, .w, .l] source target count - copy memory 当 U-Boot 在命令之后附加 [.b, .w, .l] 表达式时, 代表你需要根据所调用的命令版本在 命令之后附加相应的字符串。例如,cp 命令的三个版本 cp.b、cp.w 和 cp.l 分别可用于复 制 byte、word 和 long 类型的数据。 U-Boot 对自变量的格式有严格的要求。它会将大部分的自变量视为十六进制的数值。 以 cp 命令为例,这代表源位置、目的地址和字节计数等参数都必须是十六进制的数值。你 不必为这些数值前置或附加任何特殊的符号,例如 0x 或 h。举例来说,如果你的来源地址 是 0x40000000,只须键入 40000000。 U-Boot 允许你使用代表唯一命令的子字符串来启动该命令。举例来说,如果你想要使 用 tftpboot 命令,你可以只键入 tftp,因为以 tftp 起头的命令只有 tftpboot 。相对而言,你 不可以键入 lo,因为有四个命令以这两个字母起头:loadb、loads、loady 和 loop。

5.3.2

U-Boot 命令使用实例

限于篇幅,笔者不打算将 U-Boot 的所有命令都介绍一遍,事实上也没这个必要。接下 来笔者会挑几个在开发过程中经常会用到的命令,对这些命令的参数,用法等,辅以实例进 行讲解。 (1)tftpboot SuperARM # help tftpboot tftpboot [loadAddress] [bootfilename] 这条命令是使用 TFTP 协议通过网络下载文件,按照二进制文件格式下载。另外使用 这个命令,必须配置好相关的环境变量。例如 serverip 和 ipaddr(参看下一小节“设置环

嵌入式 Linux 初级实验教程

77

境变量”。 ) 第一个参数 loadAddress 是下载到的内存地址。 第二个参数是要下载的文件名称,该文件必须放在 TFTP 服务器相应的目录下。 使用 tftpboot 命令的具体的实例就是通过 tftp 方式从宿主机的 tftp 服务器根目录中下载 内核或者文件系统映像。比如我们将内核映像 zImage 放在宿主机的 tftp 服务器根目录(在 上一章中,笔者的设置是工作空间的 debugtool/tftpboot 目录)下: hm@ubuntu804:~/book2410/debugtool/tftpboot$ ls zImage 若 loadAddress 为 0x30008000(是不是很熟悉呢,在前一小节中找到它,一会你就明白 它是做什么的了),则敲入“tftp 0x30008000 zImage”这条命令,这时 U-Boot 就会从宿主机 上下载 zImage 文件,将其放在目标机以 0x30008000 为首地址的内存(RAM)区中。下面 就是笔者在开发过程中执行 “tftp 0x300080000 zImage”命令后输出的内容: SuperARM # tftp 0x300080000 zImage TFTP from server 210.43.111.211; our IP address is 210.43.111.212 Filename 'zImage'. Load address: 0x80000 Loading: ################################################################# ################################################################# ################################################################# ################################################################# ################################################ done Bytes transferred = 1576704 (180f00 hex) 这里最后一行还可以看到下载文件的大小, 这个参数很有用, 如果你要将这个文件写到 NandFlash 中,就必须知道文件的大小,那时就需要参考这个参数。 (2)nand SuperARM # help nand nand info - show available NAND devices nand device [dev] - show or set current device nand read[.jffs2[s]] addr off size nand write[.jffs2] addr off size - read/write `size' bytes starting at offset `off' to/from memory address `addr' nand erase [clean] [off size] - erase `size' bytes from offset `off' (entire device if not specified) nand bad - show bad blocks nand read.oob addr off size - read out-of-band data nand write.oob addr off size - read out-of-band data nand 下面列了很多的子命令,如 nand info,nand read,nand write,nand erase,nand bad 等。这些命令都是用来操作 NandFlash 的。分别解释如下: SuperARM # nand info Device 0: Samsung unknown 64Mb at 0x4e000000 (64 MB, 16 kB sector)

嵌入式 Linux 初级实验教程

78

执行 nand info 命令,输出上面一行,这里列出了 Super-ARM 上 NandFlash 的容量、段 大小等详细信息。 SuperARM # nand bad Device 0 bad blocks: 执行 nand bad 命令,用来检查目标机上 NandFlash 有没有坏块 SuperARM # nand erase 0x30000 0x190000 NAND erase: device 0 offset 196608, size 1638400 ... OK nand erase 命令是用来擦除一片 NandFlash 区的, 第一个参数是待擦除区域的起始地址, 第二个参数是待擦除区域的大小。比如执行“nand erase 0x30000 0x190000”命令以后会将 NandFlash 的从 0x30000 开始,大小为 0x190000 的这一块内容给擦除掉。 SuperARM # nand write 0x30008000 0x30000 0x190000 NAND write: device 0 offset 196608, size 1638400 ... 1638400 bytes written: OK nand write 命令用来将内存中的内容写到 NandFlash,第一个参数是待写内容在内存中 的起始地址,第二个参数待写 NandFlash 的起始地址,第三个参数是待写 NandFlash 区域的 大小。不过要注意每次在写 NandFlash 之前都要擦除。 举例来说,在执行了“tftp 0x300080000 zImage”和“nand erase 0x30000 0x190000”命 令后,再执行“nand write 0x30008000 0x30000 0x190000”便会将内核写到 NandFlash 的从 0x30000 开始,大小为 0x190000 的区域。这里的 0x190000 参数就是参考内核的大小写的, (如 180f00 hex) 那么在擦除 NandFlash , 通过 tftpboot 命令我们能够得到 zImage 文件的大小 时就要擦除一片比该文件大的区域,而且这块区域的大小必须是 NandFlash 的块大小 (Super-ARM 的是 16KB)的整数倍。 SuperARM # nand read 0x30008000 0x30000 0x190000 NAND read: device 0 offset 196608, size 1638400 ... 1638400 bytes read: OK nand read 命令与 nand write 命令的参数是同样的意思,只是 nand read 是从 NandFlash 读到内存中。 (3)go SuperARM # help go go addr [arg ...] - start application at address 'addr' passing 'arg' as arguments go 命令可以执行应用程序。第一个参数是要执行程序的入口地址。第二个可选参数是 传递给程序的参数,可以不用。 使用 go 命令可以用来引导内核,比如在执行完 tftp 0x30008000 zImage 命令以后,内核 映像已经在内存的 0x30008000 地址了,这时我们执行 go 0x30008000 这条命令,U-Boot 就 会跳到这个地址开始执行,实现了内核的引导。 (4)bootm

嵌入式 Linux 初级实验教程

79

SuperARM # help bootm bootm [addr [arg ...]] - boot application image stored in memory passing arguments 'arg ...'; when booting a Linux kernel, 'arg' can be the address of an initrd image bootm 命令可以引导存储在内存中的程序映像。这些内存包括 RAM 和可以永久保存 这个程序映像必须转换成 U-Boot 的格式。 的 Flash。第一个参数 addr 是程序映像的地址, 第二个参数对于引导 Linux 内核有用,通常作为 U-Boot 格式的 RAMDISK 映像存储地 址;也可以是传递给 Linux 内核的参数(缺省情况下传递 bootargs 环境变量给内核) 。 (5)printenv SuperARM # help printenv printenv - print values of all environment variables printenv name ... - print value of environment variable 'name' printenv 命令打印环境变量。可以打印全部环境变量,也可以只打印参数中列出的环境 变量。 (6)setenv SuperARM # help setenv setenv name value ... - set environment variable 'name' to 'value ...' setenv name - delete environment variable 'name'

setenv 命令可以设置环境变量。第一个参数是环境变量的名称。第二个参数是要设置 的值,如果没有第二个参数,表示删除这个环境变量。
(7)saveenv saveenv 命令将环境变量写到 NandFlash 中。

5.3.3

U-Boot 引导内核

用 U-Boot 引导内核有以下两种方式: (1)网络引导方式 这种方式跟无盘工作站有点类似,在开发板不需要配置较大的存储介质。U-Boot 通过 以太网接口远程下载 Linux 内核映像或者文件系统。 使用这种方式的前提条件就是目标机有串口、 以太网接口或者其他连接方式。 串口一般 作为控制台, 以太网接口作为通用的互连设备, 一般的目标机都可以配置 10M 以太网接口。 另外,需要在服务器上配置启动相关网络服务。U-Boot 下载文件可以通过 TFTP 网络 协议。TFTP 服务为 U-Boot 客户端提供文件下载功能,把内核映像和其他文件放在宿主机 的/tftpboot 目录下。这样 U-Boot 可以通过简单的 TFTP 协议远程下载内核映像到内存。 读者回顾一下刚刚介绍的 tftpboot 命令, 就知道 U-Boot 通过 tftp 引导内核的操作过程了。 总结起来就是下面两条简单的命令(这是针对 Super-ARM 的,读者朋友理解以后类推就可 以了) :

嵌入式 Linux 初级实验教程

80

tftp 0x30008000 zImage go 0x30008000 (2)Flash 启动方式 大多数嵌入式系统上都使用 Flash 存储介质。 Flash 有很多类型, 包括 NOR Flash、 NAND Flash 等。其中,NOR Flash(也就是线性 Flash)使用最为普遍。NOR Flash 可以支持随机 访问, 所以代码是可以直接在 Flash 上执行的。 以 Super-ARM 为例,用 U-Boot 从 Flash 引导内核,可以归结为以下两条命令: nand read 0x30008000 0x30000 0x190000 go 0x30008000 回顾一下刚刚介绍的 nand 命令,再参照 NandFlash 的文件映射表(表 5-1-1) ,相信大 家对于 Flash 启动方式已经理解了。

5.4
5.4.1 查看环境变量

U-Boot 的环境变量

U-Boot 启动和执行之后, 可以通过设定适当的环境变量来设定它的配置。 U-Boot 环境 变量的使用与 Unix shell(例如 bash)中环境变量的使用非常类似。可以使用 printenv 命 令查看当前目标系统上环境变量的值。下面是 Super-ARM 开发板上环境变量的内容: UB=>printenv bootdelay=5 baudrate=115200 ethaddr=08:00:3e:26:0a:5b bootfile="elinos-lart" bootcmd=nand read 0x30008000 0x30000 0x180000; go 0x30008000 bootargs=root=/dev/nfs nfsroot=210.43.111.211:/armnfs stdin=serial stdout=serial stderr=serial fileaddr=30008000 netmask=255.255.255.0 ipaddr=210.43.111.212 serverip=210.43.111.211 Environment size: 335/16380 bytes 表 5-4-1 列出了各个环境变量的含义及作用。 环境变量 bootdelay 解释说明 定义执行自动引导内核的等候秒数。U-Boot 执行完以后,如果在 bootdelay 时 间内按下一个键,就进入前面所说的 U-Boot 下载模式,在该模式下执行一些 U-Boot 命令,修改环境变量等。如果在 bootdelay 时间内未按下一个键,则开 始引导内核。 串口控制台的波特率 定义默认的下载文件名,比如将其设为 zImage,那么在使用 tftpboot 命令时,

baudrate bootfile

嵌入式 Linux 初级实验教程

81

fileaddr bootcmd

bootargs

stdin stdout stderr ethaddr netmask serverip ipaddr

如果没有写第二个参数,就会默认为 zImage。 定义下载文件存到内存中的起始地址,比如将其设为 0x30008000,那么在使用 tftpboot 命令时,如果没有写第一个参数,就会默认为 0x30008000 定义自动引导内核时执行的几条命令,可以参考“U-Boot 引导内核” (5.3.3 小 节 ) 中 提 供 的 命 令 。 如 “ nand read 0x30008000 0x30000 0x190000; go 0x30008000” ,这里有两条 U-Boot 命令,中间需要用“; ”号隔开。 定义传递给 Linux 内核的命令行参数,如 Super-ARM 所设置的“root=/dev/nfs nfsroot=210.43.111.211:/armnfs” ,将告诉内核系统通过 nfs 的方式挂载根文件系 统,根文件系统放在 IP 地址为 210.43.111.211 的宿主机(该机器必须配置了 NFS 服务)的/armnfs 目录下。这个你可能还看不懂,第 7 章再详细介绍。 定义标准输入设备,一般是串口 定义标准输出设备,一般是串口 定义标准错误显示设备,一般是串口 定义以太网接口的 MAC 地址 定义以太网接口的掩码 定义 tftp 服务器端的 IP 地址,就是宿主机的 IP 定义本地的 IP 地址,需要与宿主机的 IP 设在同一个网段
表 5-4-1 U-Boot 环境变量的解释说明

5.4.2
置。

设置环境变量

使用 setenv 命令可以用来修改或者添加相应的环境变量。下面举例说明环境变量的配 (1)设置 TFTP 服务器的 IP 地址: setenv serverip 210.43.111.211 (2)设置本地 IP 地址: setenv ipaddr 210.43.111.212 (3)设置启动命令: flash 启动方式: setenv bootcmd nand read 0x30008000 0x30000 0x180000\; go 0x30008000 网络 tftp 启动方式: setenv bootcmd tftp 0x30008000 zImage\; go 0x30008000 (注意“; ”号前面的“\”号,这是告诉 U-Boot 不要将“; ”号当成特殊符号处理) (4)设置下载文件名: setenv bootfile zImage (5)设置启动参数: setenv bootargs root=/dev/nfs nfsroot=210.43.111.211:/armnfs

嵌入式 Linux 初级实验教程

82

5.4.3

保存环境变量

环境变量修改完以后可以通过 saveenv 命令来保存环境变量: UB=>saveenv Saving Environment to NAND... Erasing Nand Environment...OK Writing new Environment Variables to Nand...done

嵌入式 Linux 初级实验教程

83

第6章

Linux 内核移植

上一章我们一起学习了 BootLoader,并进行了 U-Boot 的移植,同时还探讨了 U-Boot 的使用及其环境变量的设置。其中多处提到了内核,内核映像等,因为 BootLoader 本身就 承担着引导内核的任务。那么本章就和大家一起来了解 Linux 内核,学习 Linux 内核移植, 包括如何配置、编译内核以及制作 Linux 内核映像等。 所谓 Linux 内核移植就是把 Linux 操作系统针对具体的目标机做必要裁剪之后, 安装到 目标机使其正确的运行起来。这个概念目前在嵌入式开发领域流传比较广泛。嵌入式 Linux 移植是指对 Linux 经过小型化裁剪后,能够固化在容量只有几 K 字节或几十 K 字节的存储 器芯片或单片机中,应用于特定嵌入式场合的专用 Linux 操作系统。 本章将从嵌入式 Linux 内核移植相关知识入手, 介绍内核移植中可能涉及的一些概念和 基础。通过在 Super-ARM 开发平台上实例移植来向读者展现具体的 Linux 内核移植过程和 详细步骤。

6.1 选择 Linux 内核
正如概述中所说,内核(kernel)是所有 Linux 系统的主要软件组件。内核既是操作系 统的心脏,也是它的大脑,因为内核控制着基本的硬件。内核是操作系统的核心,具有很多 最基本功能,如虚拟内存、多任务和 TCP/IP 网络等功能。 Linux 内核的起源可追溯到 1991 年芬兰大学生 Linus Torvalds 编写和第一次公布 Linux 的日子。 尽管到目前为止 Linux 系统早已远远发展到了 Torvalds 本人之外的范围, Torvalds 但 仍保持着对 Linux 内核的控制权,并且是 Linux 名称的唯一版权所有人。自发布 Linux 0.12 版起,Linux 就一直依照 GPL(通用公共许可协议)自由软件许可协议进行授权。 Linux 内核本身并不是操作系统, 它是一个完整操作系统的组成部分。Red Hat、Novell、 Debian 和 Gentoo 等 Linux 发行商都采用 Linux 内核,然后加入更多的工具、库和应用程序 来构建一个完整的操作系统。 开始熟习 Linux 之后,你将很快发现,可供使用的 Linux 内核版本不只一种。官方 Linux 内核可以到 http://www.kernel.org/ 下载。 官方内核有好几种版本可供下载。目前,编号以 2.6.x 或 2.6.x.y 开头的版本是最新的 系列,它们通常会被用于部署新的 Linux 系统。较旧的 2.4 系列仍被使用在许多设备中, 而且有时会发行修订版,但是所有新的发展都只出现在 2.6 系列。 (1) 嵌入式 Linux 内核 嵌入式设备的 Linux 内核开发,一般会根据处理器的架构进行划分。例如,以 Russell King 为首的一群开发者专注于将 Linux 移植到以 ARM 架构为基础的目标平台。这些 ARM 开发者的工作基础是 Linus Torvalds 所发行的官方 Linux 内核,并且为它开发出了 ARM 专属的补丁文件。这些源代码补丁文件的作用包括启用新的硬件支持、修正官方内核 中会影响 ARM 架构的既有漏洞,等等。 构建 Linux 内核时,你首先应该知道的是目标机的架构,然后找到替该架构维护内核 的个人(或团体)的网站—例如,Russell 的 ARM Linux 网站或是 Paul Mackerras 的 PowerPC Linux 网站。即使你可能不需要使用任何特殊的内核版本,不过知道去什么地方寻 找资料是很重要的。

嵌入式 Linux 初级实验教程

84

(2) 2.4 系列内核 2.4 系列 Linux 内核,套用现在流行的说法,已经“out”了,因为它早已被 2.6 系列 所取代。2.6 系列内核为资源有限的嵌入式设备加入了一套丰富的配置选项。尽管使用 2.6 系列内核有许多优点,但是嵌入式开发者要做到轻松地使用 2.6 系列,还是需要花很多时 间去摸索的。 现在,我们并不鼓励使用 2.4 Linux 内核来构建嵌入式系统,因为旧版内核的支持正在 衰退中,再加上后续的开发工作完全是针对新版的 2.6 系列内核。这意味着,小漏洞的修 正很可能多半是针对 2.6 系列内核,而非较旧的系列。 (3) 2.6 系列内核 获取主流的 2.6 系列 Linux 内核源代码的方式通常有两种: 下载并解压特定内核版本的压缩文件。比如,你可以在名为 linux-2.6.20.tar.bz2 的 文件中获得 2.6.20 版的内核源代码。 使用 git 内核“软件配置管理“(Software Configuration Management,简称 SCM) 工具追踪每日的发展以及官方所发行的内核版本。 你还可以使用各种的 git 附加工 具以视觉化方式追踪每日的内核发展。 与 Linux2.4 系列相比,Linux 2.6 无论对相当大的系统还是相当小的系统的支持都有很 大提升。 能够支持相当广泛的硬件平台,是采用 Linux 作为内核的操作系统的优势之一。 Linux 自 1.2 版就开始包含对新的处理器类型和特性的支持, 最新的 Linux 2.6 内核 发布版本也不例外。 使用了新的调度器算法 采纳了内核抢占的补丁,大大减小了用户交互、多媒体等应用程序的调度延迟。这 一特性对实时系统和嵌入式系统来说特别有用。 新的线程模型,能够支持 NPTL 线程库 在文件系统的支持上也有很大的改进,特别是对扩展属性以及 POSIX 标准的访问 控制的支持。 加强了对多播网络的支持,使得由一台计算机发出的数据包可以被多台计算机接 收。 在用户界面层, 对帧缓冲控制台子系统的支持有了不少改进, 也对近乎所有可接入 输入设备的支持,包括触摸屏,各种鼠标,甚至盲人用设备等。 创建了一个统一的设备模型, 通过维持大量的数据结构, 囊括了几乎所有的设备结 构和系统,可以改进设备的电影管理和简化设备相关的任务管理。 涉及新嵌入式设备的设计时, 通常倾向于使用官方内核。嵌入式开发者会选定某个版本 的 Linux 内核,而且在产品的整个生命周期(或至少首次发行期间)内不再更换。基于以 上讨论,在本书的范例中,我们选择 2.6 系列的内核。

6.2

Linux 内核移植前准备

对于嵌入式 Linux 系统来说,有各种体系结构的处理器和硬件平台,并且用户需要根 据需求自己定制硬件板。只要是硬件平台发生变化,即使非常小,可能也需要做一些移植工 作。内核移植是嵌入式 Linux 系统中最常见的一项工作。 当然,移植嵌入式 Linux 系统并不意味着该内核使用了任何特定的链接库或用户工具, 建立嵌入式系统并不需要特别的内核。 嵌入式系统中使用的内核与工作站或服务器上使用的

嵌入式 Linux 初级实验教程

85

内核主要的不同在于内核的配置方面。Linux 内核移植是在 Linux 原内核基础上,通过对平 台的选择设计来实现针对特定系统的内核版本。 Linux 内核的移植包含启动代码的修改、内核的链接及装入、参数传递、内核引导几个 部分。其基本过程如下: (1)首先,获取某一版本的 Linux 内核源码,根据具体目标平台对源码进行必要的改 写(主要是修改体系结构相关部分); (2)然后添加一些外设的驱动(如网卡驱动,USB 驱动),打造一款适合于目标平台 (可以是嵌入式便携设备也可以是其它体系结构的 PC 机)的新操作系统,也就是常说的内 核配置或内核定制; (3)对该系统进行针对目标平台的交叉编译,生成一个内核映象文件(如 zImage, uImage,bzImage); (4)最后通过一些手段(如 TFTP)把该映象文件烧写到目标平台中。 本节将对 Linux 内核移植的一些相关概念、知识进行介绍,希望读者可以对 Linux 内核 的移植理解得更透彻。

6.2.1

Linux 内核源码

Linux 内核移植工作主要是修改跟硬件平台

相关文章:
ARM2410-S_linux实验指导书_图文
ARM2410-S_linux实验指导书_计算机软件及应用_IT/计算机_专业资料。博创科技 ...293 1 博创科技 第一章 嵌入式 LINUX 开发基础知识目前 Linux 已广泛应用于...
嵌入式linux实验报告_图文
嵌入式linux实验报告_工学_高等教育_教育专区。嵌入式操作系统 Linux 实验报告 ...实验代码 注释 shell #定义两个变量 PREFIX=uptech TARGETDIR=/arm2410s clear...
嵌入式Linux实验手册——基于ARM9 S3C2410实验平台
嵌入式Linux实验手册——基于ARM9 S3C2410实验平台_计算机软件及应用_IT/计算机_...? cpu/arm920t/start.S _start: b reset ldr pc, _undefined_instruction ...
LINUX嵌入式实验报告
LINUX嵌入式实验报告_计算机软件及应用_IT/计算机_专业资料。LINUX 嵌入式实验...[root@zxt/]#cd/arm2410s/exp/basic/05_ad/ [root@zxt04_ad]#make arm...
嵌入式系统 实验二 嵌入式Linux系统的编程
嵌入式系统 实验嵌入式Linux系统的编程_计算机软件及应用_IT/计算机_专业资料。二、嵌入式LINUX系统的编程 1、实验目的 熟悉UP-TECHPXA270-S下Linux的开发环境...
嵌入式系统实验报告
嵌入式实验报告熟悉 Linux 开发环境 1、 实验步骤: cd /arm2410s/exp/basic/01_hello 进入目录 make clean 清除之前编译生成的文件 make 编译 telnet 192.168...
嵌入式Linux系统开发教程实验报告
掌握常用的 Linux 下 shell 命令 二实验设备及工具硬件:UP-NETARM2410-S 嵌入式实验仪、PC 机 pentumn500 以上、硬盘 40G 以上、内存大于 256M。 软件:PC 机...
实验一 嵌入式Linux 教程 手册 编程开发环境基础
三,预备知识 C 语言的基础知识,程序调试的基础知识和方法,Linux 的基本操作. 四,实验设备及工具硬件:UP-NETARM2410-S 嵌入式实验平台,PC 机Pentium 500 以上,...
嵌入式Linux系统开发教程实验报告
二、实验内容对嵌入式 Linux 系统进行裁剪、配置和编译,生成自己需要的操作系统映像 文件,并将其烧写到 flash 中。 三、实验设备及工具硬件:UP-NETARM2410-S ...
linux嵌入式实验报告---
Linux 嵌入式系统概论实验报告 组员:王浩(0945532135) 沈诚(0945532128) 专业:...将 5V 电源线的连到 UP-NETARM2410-S 的电源接口; b、连接串口线,一端...
更多相关标签:
嵌入式linux实验报告 | 嵌入式linux实验 | s3c2410 linux | 基于s3c2410与linux | linux s3c2410 spi | 博创2410实验箱 | s3c2410的键盘实验 | 嵌入式linux |