嵌入式 Linux 内核驱动开发【The first day: 36093万字】_linux嵌入式内核及驱动开发
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
嵌入式 Linux 内核驱动开发【1】
由于篇幅太大以章分块按天写
嵌入式 Linux 内核驱动开发前言
本篇主要讲述嵌入式 Linux 产品开发过程中的内核/驱动开发部分相关内容包括
Linux 内核裁剪定制、驱动编写和驱动移植
等。进行嵌入式 Linux 驱动开发一些特定外设需要从零开始编写驱动
然而很多外设基本都有可参考驱动在实际工作中仅需进行移植本篇特 意给出了 3个驱动移植实例。
本篇一共分 11 章各章标题和内容概要如下
第 1 章
Linux 内核裁剪和定制
首先介绍了几种内核源码查看工具
然后对内核目录树
和相关文件进行介绍接着给出了内核配置详情
以及裁剪实例
第 2 章Linux 设备驱动基础
由浅入深的介绍了 Linux驱动编写相关知识点从内核模块、字符设备驱动
到平台设备驱动
都有详细讲解并给出了相应的范例代码
第 3 章LED 子系统和驱动
分析了内核中的 LED 子系统并给出了相关实现实 例
第 4 章GPIO 驱动
分析了内核中的GPIOLIB
子系统并给出了相关实现实例
第 5 章输入子系统和按键驱动
分析了内核中的输入子系统并给出了按键驱动 实现范例
第 6 章I2C 总线和外设驱动
分析了内核中的 I2C 子系统并给出了I2C 接口 EEPROM 驱动实现范例
第 7 章SPI总线和外设驱动
简要分析了 SPI 总线驱动并实现了两种典型 SPI 设备驱动
第 8 章UART 和 SC16IS752驱动
简析了 UART 驱动子系统并对 SC16IS752 的驱动实现进行了详细分析
第 9 章SGTL5000声卡驱动移植
介绍 SGTL5000 在i.MX283 平台
的移植过程
第 10 章AP6181 无线网卡驱动移植
介绍 AP6181 无线网卡在i.MX283
平台的移植过程
第 11 章SIM6360-PCIE 模块驱动移植
介绍SIM6360-PCIE 模块驱动移植和PPP 拨号上网
的过程。
本篇的内容涵盖了嵌入式 Linux 产品开发过程中底层开发的大部分工作给出的实例也都具有很强的参考意义。
第1章 Linux 内核裁剪和定制
【1】Linux 内核开发简介
这里所说的“Linux 内核开发”仅仅是指嵌入式 Linux 产品开发中内核和驱动相关开发工作与 Linus所领导的内核开发团队的内核开发有很大不同。 产品开发中对内核进行二次开发需要开发人员具备如下一些基本技能和背景知识
-
具备操作系统的基本知识理解操作系统原理最好了解 ~~Linux 操作系统~~
-
内核绝大部分都是 C 语言编写的~~C 语言~~ 是必备技能
-
内核是用 ~~GNU C 编写的~~ 尽管符合 ISO C89 标准但还是使用了一些 GNU 扩展所以对 GNU C 的一些扩展也必须有所了解
-
对 ~~Linux 内核源码~~ 基本分布有大致了解
-
产品级的内核开发通常还包括一些内核驱动工作对~~外设工作原理和驱动编写~~ 也必须有一定的了解。
【2】 Linux 源码阅读工具
俗话说“
工欲善其事必先利其器
”面对几百兆的 Linux 内核代码要阅读、查看或者搜索其中的代码大部分初次接触到 Linux 内核代码的开发人员都有无从下手的感觉。
下面推荐几个源码阅读和索引工具能为后续内核开发提供一些便利。
【1.2.1】Source Insight
Source Insight 是 Windows 平台下一款流行度极高的源码阅读和编辑工具。不少 Linux开发人员还是习惯于在 Windows 下进行源码编辑甚至查看和编辑 Linux 内核源码依然在 Source Insight 中完成。
注意蓝色字体的超链接是我改过的为了好看而已
安装 Source Insight 软件后新建一个工程取名并指定数据存放位置如图 1.1 所示。
然后添加源码。浏览选中 Linux 内核源码文件夹后点击“Add Tree”按钮将内核源码树的全部文件添加到工程中如图 1.3 所示。
添加完成即可在 Source Insight 中进行源码阅读和编辑了如图 1.4 所示。
【1.2.2 Eclipse】
Eclipse 是一个跨平台 IDE既能运行于 Windows 平台也能在 Linux 下运行。不少习惯于
图形界面操作的开发人员
在Linux 下则习惯于用 Eclipse 来查看和编辑 Linux 源码
。 如果仅仅是在 Eclipse 中查看 Linux 内核源码则可以不必事先安装交叉编译器否则 则须事先安装好交叉编译器。
创建内核源码工程。点击 FileNewProject开始创建工程在工程创建界面选择创建 C 工程如图 1.5 所示。
点击 Next在 C Project 界面的 Project name 栏中填写工程名称去掉“Use default location”的勾点击 Browse 将 Location 设置为 Linux 内核源码目录如图 1.6 所示。如果不在 Eclipse中编译内核则使用 Linux GCC 即可否则请使用安装好的 Cross GCC
然后点击 Finish完成 Linux 内核源码导入在 Eclipse 中即可进行代码阅读和编辑了如图 1.7 所示。
在 Eclipse 中进行源码跟踪只需选择函数、变量或者宏定义后按
F3
即可。更多的操作可在Navigate
中找到。
【1.2.3】 vim+ctags+cscope
Vi/Vim 是一个文本编辑器在 Vim 中能高效的实现代码编辑。但 Vim 的功能不仅仅是一个文本编辑器借助
ctags
和cscope
的配合Vim 能实现堪比图形 IDE 环境
的源码编辑和阅读功能在某种程度上甚至比图形 IDE 更方便。 Vi/Vim 的安装不再介绍了。如果不是通过远程登录在远程服务器上工作而是在本地桌面系统操作还可以用gvim 启动 Vi 编辑器
。
1. Taglist
Taglist 是 Vim 的一个源码浏览插件可从http://www.vim.org 网站获得。下载到压缩包后在本地解压然后将解压得到目录中的
plugin 目录复制到~/.vim 目录
。如果用户主目录 下没有.vim目录则建立命令mkdir .vim
一个这样的目录即可。
2. Ctags
Ctags 是一个用于产生 tags 文件的软件可以下载源码进行编译安装在 Ubuntu 下 可通过 apt-get 进行安装
$ sudo apt-get install exuberant-ctags
3. 源码阅读和跟踪
进入准备查看的源码所在目录首先生成 tags 文件
$ ctags -R
执行时间长短取决于源码数量的多少执行完毕在当前目录下可看到一个 tags 文件。 源码越多执行时间越长产生的 tags文件也越大。
注意
如果修改了源码代码行号发生了变化需要重新生成 tags 文件。
1查看函数等定义。用 Vi/Vim 打开一个 C 文件。若想知道某个函数、变量、结构 或者宏定义在什么地方定义先将光标移动到函数变量、结构或者宏定义上然后按
CTRL+]
即可。查看后按CTRL+o
可回到原来所在位置。
2查看文件函数列表。打开C 文件后在Vi/Vim的命令状态下输入:TlistToggleVi/Vim的命令输入支持补全
在 Vi/Vim 左边就会出现函数列表侧栏如图 1.8 所示。按CTRL+ww
2 次> w可在列表和代码查看区间切换。
如果在本地桌面用Gvim
打开 C 文件使用起来比较接近 IDE 集成环境。用鼠标双击函数即可跳转到函数定义
的地方CTRL+鼠标右键
即可回退到原来所在位置。更多实用特性还需要在实际操作中体验。
【1.2.4】 LXR
LXR 是 Linux Cross Referencer 的缩写是一个比较流行的
Linux 源码查看工具
当然也不仅仅局限于查看 Linux 源码。LXR 的下载地址为http://lxr.sourceforge.net参考该网站
的安装说明很容易在本机搭建一个本地 LXR 用于源码查看。
如果不想搭建本地 LXR可以直接浏览已经搭好的 LXR 网站推荐两个网站一个是开源中国网站提供的 Linux 源码在线阅读
http://lxr.oss.org.cn另一个是http://lxr.free-electrons.com 网站前者速度较快但是提供的 Linux 内核版本较少后者则提供的版本较多。网站提供了源码阅读、关键字搜索和自由文本搜索功能。两者的网页快照分别如图 1.9 和图 1.10 所示。
【3】Linux 内核源码
【1.3.1 目录树概览】
解压 Linux 内核源码压缩包将得到内核源码。内核源码很复杂包含多级目录形成 一个庞大的树状结构通常称为 Linux源码目录树。进入源码所在目录可以看到目录树顶 层通常包含如下目录和文件
各个目录文件的简要说明如表 1.1 所列。
目录 | 内容 |
---|---|
arch/ | 包含各体系结构特定的代码如 arm、x86、ia64、mips 等在每个体系结构目录下通常都有 -boot 内核需要的特定平台代码 -kernel 体系结构特有的代码 -lib 通用函数在特定体系结构的实现 -math-emu 模拟 FPU 的代码在 ARM 中使用 mach-xxx 代替 -mm 特定体系结构的内存管理实现 -include 特定体系的头文件 |
block/ | 存放块设备相关代码 |
crypto/ | 存放加密、压缩、CRC 校验等算法相关代码 |
Documentation/ | 存放相关说明文档很多实用文档包括驱动编写 等 |
drivers/ | 存放 Linux 内核设备驱动程序源码 。驱动源码在 Linux 内核源码中站了很大比例常见外设几乎都有可参考源码对驱动开发而言该目录非常重要。该目录包含众多驱动目录按照设备类别进行分类如 char、block、input、i2c、spi、pci、usb 等 |
firmware/ | 存放处理器 相关的一些特殊固件 |
fs/ | 存放所有文件系统代码如 fat、ext2、ext3、ext4、ubifs、nfs、sysfs 等 |
include/ | 存放内核所需、与平台无关的头文件与平台相关的头文件已经被移动到 arch 平台的include 目录 如 ARM 的头文件目录<arch/arm/include/asm/> |
init/ | 包含内核初始化代码 |
ipc/ | 存放进程间通信 代码 |
kernel/ | 包含 Linux 内核管理 代码 |
lib/ | 库文件 代码实现 |
mm/ | 存放内存管理 代码 |
net/ | 存放网络 相关代码 |
samples/ | 存放提供的一些内核编程范例如 kfifo 后者相关用户态编程范例如 hidraw |
srcipts/ | 存放一些脚本文件如 menuconfig 脚本 |
security/ | 存放系统安全性相关代码 |
sound | 存放声音、声卡 相关驱动 |
tools/ | 编译过程中一些主机必要工具 |
usr/ | cpio 相关实现 |
virt/ | 内核虚拟机 KVM |
Linux 内核源码数量很庞大解压后大约好几百兆字节要能在如此庞大的源码中找到 有效代码熟悉 Linux 源码目录树的结构是基本要求。每个目录所包含的代码量差异也很大 下面是从 http://www.kernel.org 下载的一份源码解压后的统计结果其中
drivers
目录几乎占了源 码总量的一半arch
目录也差不多有 1/4
【1.3.2】 快速确定主板关联代码
拿到一份源码和一块评估板如何快速找到与这块板相关的源码是很多研发人员都曾遇到过的问题。如果对内核源码结构有大概了解要完成这些事情也不难通常可按照
基础代码、驱动代码和其它代码
等方面来梳理。
1. 基础代码
Linux
移植通常分为体系结构级别移植、处理器级别移植和板级移植
各级别移植难易程度差异很大工作量和调试方式也各不相同。一般的产品开发人员所进行的内核移植通常都是板级移植
这是几个级别中最简单的。
从代码层面来看通常把能让一个主板最小系统能运行的代码称为基础代码这部分代码通常包含体系结构移植代码、处理器核心代码以及板级支持包的部分代码。理清了这部分代码对于了解和掌握整个主板相关代码具有重要意义。
确定主板名称和默认配置文件。
例如对于
EPC-28x 工控板
其对应的默认内核配置 文件为<arch/arm/configs/ EPC-M28x_defconfig
。通常来说一个评估板的内核默认配置文件名称与评估板的名称相同或者有关联。确定了配置文件后可用任何文本编辑器打开该配 置文件可以对配置的选项进行查看或者进行make menuconfig
配置进入配置界面查看。
确定对应的主板文件。
在 ARM Linux 移植代码中每个评估板通常都有一个对应的主 板文件在
<arch/arm/mach-xxx/>
目录下。大多数主板文件都以“board-
”开头采用 “board-xxx.c
”这样的文件名例如<arch/arm/mach-omap2/board-am335xevm.c>
也有以 “mach-
”开头的如<arch/arm/mach-mxs/mach-mx28evk.c>
。通常来说一个评估板的主板 文件名称与评估板的名称相同或者有关联。
如果遇到名称特征不是很明显不能确定的情况则建议打开默认配置文件找到“
CONFIG_MACH_XXX=y
”这一行确定主板对应的配置开关变量。然后打开<arm/arm/mach -xxx/Makefile>
文件根据配置开关变量来确定主板文件。例如<arch/arm/mach-pxa/Makefile>
文件中有如下内容
# Intel/Marvell Dev Platforms
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
obj-$(CONFIG_MACH_ZYLONITE300) += zylonite.o zylonite_pxa300.o
可以看到这几个主板文件命名都既不是以“
board-
”开头也不是以“mach-
”开头 对于这种情况通过Makefile文件
来确定一下是比较好的做法。特别是对于主板开关变量 对应非单一文件的更需要查看 Makefile来确定关联文件否则有可能遗漏某个文件造 成代码阅读理解上的障碍。如CONFIG_MACH_ZYLONITE300 对应着 zylonite.c 和 zylonite _pxa300.c 两个 C 文件
。
2. 驱动代码
Linux 内核源码中接近一半的代码量是驱动对某一个特定主板的系统而言驱动也占据很大的比例底层开发的很大一部分是驱动相关工作。掌握从众多驱动中找到正确的驱动 源码文件并根据产品的实际需求进行修改调整的方法能有效促进产品开发的进度。
Linux 内核源码树 drivers
目录很复杂包含了各种外设的驱动
。对嵌入式 Linux 开发而 言通常需要关注的目录如表 1.2 所列。
熟悉各类驱动在源码树中的大概位置能帮助在开发过程中快速进行驱动源码查找和定位。一个系统到底用了哪些代码与系统本身外设相关也与主板配置文件相关。
【4】 Linux 内核中的 Makefile 文件
本节不对内核的 Makefile 文件进行深入展开更多语法和说明请阅读
<Documentation /kbuild/makefiles.txt>文件
。
【1.4.1】 顶层 Makefile
源码目录树顶层 Makefile 是整个内核源码管理的入口对整个内核的源码编译起着决定性作用。编译内核时顶层 Makefile 会按规则递归历遍内核源码的所有子目录下的Makefile 文件完成各子目录下内核模块的编译。熟悉一下该 Makefile对内核编译等方面会有所帮助。
1. 内核版本号
打开顶层 Makefile开头的几行记录了内核源码的版本号通常如下所示
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 35
EXTRAVERSION =3
说明代码版本为 2.6.35.3编译得到的内核在目标板运行后输入
uname -a
命令可以得 到印证
# uname -a
Linux boy 2.6.35.3-571-gcca29a0-gd431b3d-dirty #22 PREEMPT Tue Oct 27 20:12:33 CST 2015 armv5tejl
GNU/Linux
2. 编译控制
- 1体系结构
Linux 是一个支持众多体系结构的操作系统在编译过程中需指定体系结构以与实际 平台对应。在
顶层 Makefile
中通过变量ARCH
来指定
ARCH ?= $(SUBARCH)
如果没有在编译命令行中指定 ARCH 参数系统将会进行本地编译通过获取本机信 息来自动指定
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ -e s/parisc64/parisc/ \
-e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-e s/sh[234].*/sh/ )
如果进行 ARM 嵌入式 Linux 开发则必须指定 ARCH 为 arm注意大小写须与 arch/ 目录下的 arm 一致如
$make ARCH=arm
当然也可以修改 Makefile将修改为 ARCH ?= $(SUBARCH)修改为
ARCH = arm
在 命令行直接 make即可。
- 2编译器
如果不是进行本地编译则须指定交叉编译器通过
CROSS_COMPILE
来指定。Makefile 中与交叉编译器的指定如下
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
……
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) –E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
CONFIG_CROSS_COMPILE
是一个配置选项可在内核配置时候指定。如果在配置内核时候没有指定 CONFIG_CROSS_COMPILE也没有在编译参数指定CROSS_COMPILE
则会采用本地编译器进行编译。
进行 ARM 嵌入式 Linux 开发必须指定交叉编译器可以在内核配置通过
CONFIG _CROSS_COMPILE
指定交叉编译器也可以通过 CROSS_COMPILE 指定。假定使用的交 叉编译器是arm-linux-gnueabihf-gcc
则指定CROSS_COMPILE 为 arm-linux-gnueabihf-
$ make ARCH=arm CROSS_COMPILE= arm-linux-gnueabihf-
或者在 Makefile 中直接指定 CROSS_COMPILE 的值
CROSS_COMPILE = arm-linux-gnueabihf-
注意
CROSS_COMPILE 指定的交叉编译器必须事先安装并正确设置系统环境变量如果没有设置环境变量则需使用绝对地址
例如
CROSS_COMPILE =/home/ctools/linux-devkit/bin/arm-linux-gnueabihf-
如果同时指定了
ARCH
和CROSS_COMPILE
则在编译的时候只需简单的 make 就可以了。
【1.4.2】 子目录的 Makefile
在内核源码的子目录中几乎每个子目录都有相应的 Makefile 文件管理着对应目录下的代码。对该目录的文件或者子目录的编译控制Makefile 中有两种表示方式一种是默认选择编译用
obj-y
表示如
obj-y += usb-host.o # 默认编译 usb-host.c 文件
obj-y += gpio/ # 默认编译 gpio 目录
另一种表示则与内核配置选项相关联编译与否以及编译方式取决于内核配置例如
obj-$(CONFIG_WDT) += wdt.o # wdt.c 编译控制
obj-$(CONFIG_PCI) += pci/ # pci 目录编译控制
是否编译
wdt.c
文件或者以何种方式编译取决于内核配置后的变量CONFIG_WDT
值如果在配置中设置为[*]
则静态编译到内核
如果配置为[M]
则编译为wdt.ko 模块
否则不编译。
说明受控目标是一个目录
obj-y
并不直接决定受控目录的文件以及子目录的文件仅仅是与受控目录Makefile 交互
实际编译控制在受控子目录的 Makefile 中。例如“obj-y += gpio/
”最终 gpio 目录下哪些文件被编译完全取决于 gpio 目录下的Makefile
。“obj-$(CONFIG_PCI) += pci/”的含义同理。
【5】 Linux 内核中的 Kconfig 文件
本节不对内核的 Kconfig 文件进行深入展开更多 Kconfig 语法和说明请阅读
<Documentation/kbuild/kconfig-language.txt>
和<Documentation/kbuild/kconfig.txt>
。内核源码树每个目录下都还包含一个
Kconfig 文件
用于描述所在目录源代码相关的内核配置菜单各个目录的 Kconfig文件构成了一个分布式的内核配置数据库
。通过make menuconfigmake xconfig 或者 makegconfig
命令配置内核的时候从 Kconfig 文件读取菜 单配置完毕保存到文件名为.config
的内核配置文件中供Makefile 文件在编译内核时使用。
【1.5.1】 Kconfig 基本语法
如程序清单 1.1 所示代码摘自
<drivers/char/Kconfig>
文件是一个比较典型的 Kconfig文件片段包含了 Kconfig 的基本语法。
menu "Character devices"
source "drivers/tty/Kconfig"
config DEVKMEM
bool "/dev/kmem virtual device support"
default y
help
Say Y here if you want to support the /dev/kmem device. The
/dev/kmem device is rarely used, but can be used for certain
kind of kernel debugging operations.
When in doubt, say "N".
……
endmenu
1. 子菜单
通过
menu
和endmenu
来定义一个子菜单程序清单 1.1 所示代码定义了一个“Character devices
”子菜单子菜单在界面中用“—>”表示如图 1.11 所示。
子菜单的菜单项则由config
来定义随后的“bool”、“default”、“help”
等都是该菜单项的属性
config DEVKMEM
bool "/dev/kmem virtual device support"
这两行语句定义了一个
bool选项
在.config
中的配置变量名称为CONFIG_DEVKMEM
选项提示信息为“/dev/kmem virtual device support”
在内核配置界面的实际表现为
[*] /dev/kmem virtual device support
由于设置其
默认属性 default 为 y
所以该选项默认选中。
help 引出帮助信息在内核配置界面选择选项后通过<Help>
可以查看帮助信息。
2. 属性
类型定义每个菜单项都必须定义类型可选类型有
bool、tristate、string、hex 和 int
各类型描述如表 1.3所列。
定义选项的类型后面可以加菜单信息用引号“”给出留空则不加提示信息。
对于布尔型选项在配置界面用[ ]表示
[*] /dev/kmem virtual device support
[*]表示选中对应 CONFIG_XXX=y[ ]则表示未选中。
对于三态选项在配置界面用< >表示
<*> Kernel .config support
<*>
表示选中对应CONFIG_XXXx=y
<M>
表示编译为模块
对应CONFIG_XXX=m
< >表示未选中
。 子菜单也可同时设置类型如下列代码在定义PWM
菜单的同时定义了菜单属性为三态
menuconfig GENERIC_PWM
tristate "PWM Support"
default n
help
Enables PWM device support implemented via a generic
framework. If unsure, say N.
在配置界面表现为
< > PWM Support --->
说明
子菜单的配置值会影响其子选项的可能值。例如三态子菜单配置为则其三 态子选项依旧可有 3种可能值即可配置为、或者不选中而三态子菜单配置为 则其子选项只有和不选中两种状态可用。
默认值
有写选项可以设置默认值无论是哪种类型都可以通过default
设置其默认值例如
config ARM
bool
default y
select HAVE_AOUT
选中
前面这个示例的select
表示了一种选中关系即选中某个选项后会自动选中 某个或者某些选项。
前面这个示例表明选中ARM
后会自动选中HAVE_AOUT
。 依赖关系如果一个选项能否生效与否与其它选项的设置有关则必须通过depends on
来声明这种依赖关系。例如只有使能了SMP
才能设置 CPU 个数变量NR_CPUS
在Kconfig
中则写成
config NR_CPUS
int "Maximum number of CPUs (2-32)"
range 2 32
depends on SMP
default "4"
帮助
通过 help 关键字引入帮助帮助的正文必须另起一行。
菜单选项属性的每个关键字必须用TAB 键
与行首隔开
不能用等数的空格替代。
3. 目录层次迭代
通过
source
可以直接引用下级目录的Kconfig 文件
形成新的菜单项或者子菜单这样方便每个目录独立管理各自的配置内容。“source "drivers/tty/Kconfig"
”就是直接引用<drivers/tty/Kconfig>
文件形成更多菜单项。
【1.5.2】 配置项和配置开关
通过
config
定义的菜单配置项在内核配置后会产生一个以“CONFIG_”开头的配置开关变量该开关变量可在·Makefile
中或者源代码中使用。
例如“config BAR”
将会产生一个开关变量 CONFIG_BAR
在 Makefile 中可以这么使用
obj-$(CONFIG_BAR) += file_bar.o
在源代码中可用这个开关变量来进行一些条件处理例如
#if defined (CONFIG_BAR)
实际处理代码
#endif
如果定义的 BAR 是三态变量则还可以根据需要这样使用
#if defined (CONFIG_BAR) || defined (CONFIG_BAR_MODULE)
实际处理代码
#endif
【6】 配置和编译 Linux 内核
对内核进行正确配置后才能进行编译。配置不当的内核很有可能编译出错或者不能正确运行。
【1.6.1】 快速配置内核
进入 Linux 内核源码数
顶层目录
输入make menuconfig
命令可进入如图 1.12 所示的基于 Ncurses
的 Linux 内核配置主界面注意
主机须安装 ncurses 相关库才能正确运行该 命令并出现配置界面。如果没有在Makefile
中指定ARCH
则须在命令行中指定
$ make ARCH=arm menuconfig
配置完毕将光标移动到配置界面末尾选中“
Save an Alternate Configuration File
”后回车保存当前内核配置默认配置文件名为.config如图 1.13 所示。
保存完毕选择退出内核配置界面回到终端命令行。
当然也可以将配置文件命名为其它文件名如 config-bak 等但该配置不会被 Makefile
文件使用Makefile 默认使用文件名为.config 的配置文件所以重新命名配置文件通常在保留或者备份内核配置信息时使用。 也可以不用“Save an Alternate Configuration File”操作连按 ESC 或选择退出内核配置界面将会出现如图 1.14 所示的保存配置提示信息选择后回车内核配置将会被保存为.config 文件。
备份内核配置在命令行下将.config 文件复制为其它文件名来得更简单快捷
$ cp .config config-bak
装载某个配置文件可在配置界面选中“Load an Alternate Configuration File”然后填 入已存在的配置文件名称。也可在命令行下将配置文件复制为.config
$ cp config-bak .config
在
<arch/arm/configs/>
目录下有很多*_defconfig
文件这些都是内核的预设配置文件分别对应各种不同的参考板。如果要使用其中的配置文件作为内核编译配置可用“make xxx_defconfig”
命令来完成。对于已经设定好的内核配置也可以命名为某个文件名放到<arch/arm/configs/>
目录下在以后直接用make
来调用该配置即可。例如将当前配置命名为 m3352_defconfig 并放到<arch/arm/configs/>目录下后续只需执行下列命令即可使用当前配 置
$ make m3352_defconfig 或者
$ make ARCH=arm CROSS_COMPILE= arm-linux-gnueabihf- m3352_defconfig
【1.6.2】 内核配置详情
Linux 内核配置菜单比较复杂下面对一些比较重要的配置界面进行介绍更多的详细配置建议进行实际操作。另外由于 Linux 内核版本差异实际看到的内核配置界面可能与本节的介绍有所差异。
图 1.12 所示的内核配置主界面实际包含了如表 1.4 所列的各项一级菜单。
一级菜单下的每一项几乎都有复杂的下级子菜单各自的配置选项也很丰富每项的意义也各不相同如果逐一进行描述将会是一件非常繁琐的事。而实际产品开发中并不需要完全了解内核的每一个配置项通常只需要了解其中一些相关项即可。
1. 通用设置
进入
General setup
是内核通用设置菜单界面菜单选项众多通常可以关注表 1.5 所列 选项。
2. 内核特性
Kernel Features
是内核特性配置菜单常用选项介绍如表 1.6 所列。
3. 启动选项
启动选项一般关心内核启动参数设置即可可设置默认启动参数和内核参数类型。 默认启动参数通过“
Default kernel command string
”设置例如
(root=/dev/mmcblk0p2 rootwait console=ttyO0,115200) Default kernel command string
内核参数类型通过 Kernel command line type 来设置可选值
( ) Use bootloader kernel arguments if available
( ) Extend bootloader kernel arguments
( ) Always use the default kernel command string
如果设置为“
Always use the default kernel command string
”则只能使用默认内核启动参数通常会设置为“Use bootloader kernel arguments if available
”可接受Bootloader
传递的参数启动。
4. 网络支持
网络支持部分包括了以太网、CAN、红外、蓝牙、无线等各种网络的支持配置选项。 网络选项配置。从
Networking support Networking options
可进入网络选项配置界面 网络的配置很复杂常用的一些配置选项和说明如表 1.7 所列。
通常来说使用Linux
的系统都会用到网络
而使用网络又往往离不开TCP/TP
故建 议在配置中选中 TCP/IP选项并选中下级全部选项配置后的 TCP/IP 选项如程序清单 1.2 所示。
程序清单 1.2 TCP/IP 配置
[*] TCP/IP networking
[*] IP: multicasting
[*] IP: advanced router
[*] FIB TRIE statistics
[*] IP: policy routing
[*] IP: equal cost multipath
[*] IP: verbose route monitoring
[*] IP: kernel level autoconfiguration
[*] IP: DHCP support
[*] IP: BOOTP support
[*] IP: RARP support
<*> IP: tunneling
<*> IP: GRE demultiplexer
<*> IP: GRE tunnels over IP
[*] IP: broadcast GRE over IP
[*] IP: multicast routing
[*] IP: multicast policy routing
[*] IP: PIM-SM version 1 support
[*] IP: PIM-SM version 2 support
[*] IP: ARP daemon support
[*] IP: TCP syncookie support
<*> IP: AH transformation
<*> IP: ESP transformation
<*> IP: IPComp transformation
<*> IP: IPsec transport mode
<*> IP: IPsec tunnel mode
<*> IP: IPsec BEET mode
<*> Large Receive Offload (ipv4/tcp)
<*> INET: socket monitoring interface
[*] TCP: advanced congestion control --->
[*] TCP: MD5 Signature Option support (RFC2385) (EXPERIMENTAL)
<M> The IPv6 protocol --->
这些配置中三态选项也可以配置为
<M>
在需要的时候再插入模块
。
对于IPv6
现在已经有不少应用需求建议配置为并选中配置菜单中的全部选项在需要的时候再插入模块。
特别说明一下CAN
的配置选项。CAN-Bus 相关协议支持以及 CAN 设备驱动配置项都在这里并没有将 CAN 设备驱动放在 drivers 配置菜单中。CAN-Bus
子系统配置界面如图
1.15 所示。
其中的“CAN Device Drivers
”子菜单下可选择具体的CAN
设备如图 1.16 所示。具体选择哪个 CAN 设备驱动与具体的硬件平台相关。
5. 设备驱动
Linux 内核支持众多外设设备驱动程序很多配置界面也很复杂有众多配置项如 表 1.8 所列。
6. 文件系统
进入 File systems是内核文件系统配置界面可以看到很多文件系系统配置选项如 图 1.17 所示。
一个完整的嵌入式 Linux 系统往往会支持多种文件系统但绝非“File systems”菜单下的全部。这里仅对当前主流系统比较常用的一些文件系统配置项进行介绍如表 1.9 所列。
【1.6.3】 编译内核
内核配置完成输入
make
命令即可开始编译内核。如果没有修改Makefile
文件并指定ARCH
和CROSS_COMPILE
参数则须在命令行中指定
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
目前大多数主机都是多核处理器为了加快编译进度可以开启多线程编译在 make 的时候加上“-jN”即可N 的值为处理器核心数目的 2倍。例如对于 I7 4 核处理器可将 N 设置为 8
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- -j8
采用多线程编译的优点是能加快编译进度缺点是如果内核中有错误某个编译线程遇到错误终止了编译而其它编译线程却还在继续出错线程的错误提示通常会被其它编译线 程的输出信息淹没不利于排查。对于这种情况则建议改为单线程编译直到错误排除。
如果编译不出错编译完成会生成 vmlinux、Image、zImage 等文件各文件说明如 表 1.10 所列。
1. zImage
zImage
是通常情况下默认的压缩内核可以直接加载到内存地址并开始执行。它从<arch/arm/boot/compressed/vmlinux>
文件经过objcopy
处理得到。在ARM Linux
下最终生成zImage
的各个参数记录在<arch/arm/boot/.zImage.cmd>
文件中。AM3352 内核
生成zImage
的
实际参数为
cmd_arch/arm/boot/zImage := /home/ctools/i686-arago-linux/usr/bin/arm-linux-gnueabihf-objcopy -O binary
-R .comment -S arch/arm/boot/compressed/vmlinux arch/arm/boot/zImage
说明 1路径信息与实际具体编译环境有关。
说明 2如果在 64 位 ubuntu 下编译 Linux 内核在编译过程中很有可能出现
“arm-fsl-linux-gnueabi/bin/as: error while loading shared libraries: libz.so.1: cannot open shared object file: No such file or directory”这样的错误这是因为没有正确安装libz库所致
可“sudo apt-get install zlib1g:i386
”命令安装解决。
2. uImage
对于
ARM Linux
系统大多数采用U-Boot
引导很少直接使用 zImage 映像实际上更多的是 uImage。uImage 是 U-Boot 默认采用的内核映像文件它是在 zImage 内核映像之前加上了一个长度为 64 字节信息头的映像。这 64 字节信息头包括映像文件的类型、加载位置、生成时间、大小等信息可参考 U-Boot 源码<include/image.h>
文件的image_header_t
数据结构定义。进入<arch/arm/boot/>
目录用 ls 命令查看uImage 文件大小比 zImage 大 64字节
$ cd arch/arm/boot
$ ls -la Image zImage uImage
-rwxrwxr-x 1 chenxibing chenxibing 6460852 Jul 25 09:24 Image
-rw-rw-r-- 1 chenxibing chenxibing 3135544 Jul 25 09:24 uImage
-rwxrwxr-x 1 chenxibing chenxibing 3135480 Jul 25 09:24 zImage
在 U-Boot 下通过 bootm 命令可以引导 uImage 映像文件启动。
3. mkimage 工具
从
zImage
生成uImage
需要 用到mkimage
工具。该工具可在编译 U-Boot 源码后从 tools 目录下获得复制到系统/usr/bin
目录即可对于 Ubuntu 系统还可用sudo apt-get install u-boot-tools
命令安装得到。进入 mkimage 文件所在目录执行该文件或者在安装 mkimage 工具后直接在终端输入 mkimage 命令可以得到 mkimage 工具的用法
$ ./mkimage 或者 mkimage
Usage: ./mkimage -l image
-l ==> list image header information
./mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
-A ==> set architecture to 'arch'
-O ==> set operating system to 'os'
-T ==> set image type to 'type'
-C ==> set compression type 'comp'
-a ==> set load address to 'addr' (hex)
-e ==> set entry point to 'ep' (hex)
-n ==> set image name to 'name'
-d ==> use image data from 'datafile'
-x ==> set XIP (execute in place)
./mkimage [-D dtc_options] -f fit-image.its fit-image
./mkimage -V ==> print version information and exit
使用 mkimage 工具根据 zImage 制作 uImage 映像文件的命令如下
$ mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
命令参数中需要指定体系结构、操作系统类型、压缩方式和入口地址等信息各参数说明如表 1.11 所列。
对于
EPC-28x
处理器内存起始地址为0x40000000
从 zImage 生成 uImage 映像文件的命令实际操作范例
$ mkimage -A arm -O linux -T kernel -C none -a 0x40008000 -e 0x40008000 -n 'Linux-2.6.35' -d
arch/arm/boot/zImage arch/arm/boot/uImage
说明内存地址与处理器相关在不同处理器上可能有差异。
mkimage 除了可以制作 uImage 映像文件之外还可以查看一个 uImage 映像文件的文件头信息用法
$ mkimage -l uImage_file
例如用 mkimage 工具查看 EPC-28x 工控主板的 uImage 内核映像可以得到如下信息
$ mkimage -l uImage
Image Name: Linux-2.6.35.3-571-gcca29a0-g191
Created: Tue Nov 17 11:57:47 2015
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2572336 Bytes = 2512.05 kB = 2.45 MB
Load Address: 40008000
Entry Point: 40008000
如果只有
zImage
内核映像文件需要转换成 uImage 映像文件则只能通过上述命令来实现。但是如果有内核源码那生成 uImage 的方法就简单很多。实际上Linux 内核已经支持直接生成 uImage 格式映像文件在<arch/arm/boot/Makefile>
文件中给出了uImage
的生
成规则
quiet_cmd_uimage = UIMAGE $@
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
-C none -a $(LOADADDR) -e $(STARTADDR) \
-n 'Linux-$(KERNELRELEASE)' -d $< $@
生成 uImage 的编译命令为 make uImage
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- -j8 uImage
在 ARM Linux 下最终生成
uImage
的各个参数记录在<arch/arm/boot/.uImage.cmd>
文件中。对于在EPC-28x
的 Linux 内核实际参数为
cmd_arch/arm/boot/uImage := /bin/bash /home/vmuser/prj/m28x/kernel/linux-2.6.35.3/scripts/mkuboot.sh -A arm
-O linux -T kernel -C none -a 0x40008000 -e 0x40008000 -n 'Linux-2.6.35.3-571-gcca29a0-g1914ba0' -d
arch/arm/boot/zImage arch/arm/boot/uImage
4. 编译内核模块
如果内核中有配置为
<M>
的模块或者驱动需要在编译内核后再通过make modules
命 令编译这些模块或者驱动
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- modules
编译得到的内核模块文件以“
.ko
”结尾这些可以通过insmod
命令插入到运行的内核中。
有的模块编译得到单一的“.ko”文件且不依赖于其它模块这样的模块可以直接用insmod 命令插入系统而不会出现错误。
有的模块则可能编译后得到多个“.ko”文件或者依赖于其它模块文件且各文件插入还有顺序要求这就是常说的模块依赖。对于这样的情况用 insmod 命令手工尝试得到依赖关系然后按顺序插入也是可以的但不推荐这样做毕竟很麻烦。
建议编译模块后再通过make modules_install
命令安装模块可将编译得到的全部模块安装到某一目录下并且还会生成模块的依赖关系文件。默认情况下会将内核模块安装到编译机器的“/”目录下这一方面需要root
权限另一方面容易与主机文件混淆。建议通过INSTALL_MOD_PATH
参数指定模块安装路径
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabiINSTALL_MOD_PATH=/home/chenxibing/work/rootfs
modules_install
安装后将在安装目录下生成“
lib/modules/
内核版本/”目录该目录下通常有下列文件 和目录
所有的内核模块都在
kernel
目录下modules.dep
是全部模块的依赖关系文件。将“lib/modules/
内核版本/”复制到目标系统后根目录后就可以用modprobe
命令进行模块安装而不用手工逐一加载各个模块。该文件内容多少与内核模块多少相关现在摘取一个实例片段进行说明
kernel/drivers/net/bonding/bonding.ko: (1)
kernel/drivers/usb/serial/usbserial.ko: (2)
kernel/drivers/usb/serial/ftdi_sio.ko:kernel/drivers/usb/serial/usbserial.ko (3)
每行开头至冒号
(:)
之前的表示一个内核模块冒号之后的表示该模块所依赖的其它模块 必须先加载后面的模块才能加载该模块文件。冒号后面为空则表示该模块没有依赖关系。 第(1)行表示模块文件bonding.ko
没有依赖关系可以直接用insmod
命令加载到内核中
# insmod kernel/drivers/net/bonding/bonding.ko
用 insmod 加载模块必须指明文件路径否则不能加载。用 modprobe 命令加载则无需 带路径
# modprobe bonding
第(2)和(3)则共同说明了模块文件
ftdi_sio.ko
依赖于usbserial.ko
文件usbserial.ko
没有依赖文件。用insmod
命令用法如下
# indmod kernel/drivers/usb/serial/usbserial.ko
# insmod kernel/drivers/usb/serial/ftdi_sio.ko
用 modprobe 命令就简单了
# modprobe ftdi_sio
1.6.4 运行内核
得到
uImage
映像文件后将 uImage 加载到内存地址ep-0x40
处通过bootm
命令即可 运行内核
# tftp 40007fc0 uImage
# bootm 40007fc0
uImage 启动会打印文件头信息并进行校验和计算校验通过后开始内核自解压并运行
## Booting kernel from Legacy Image at 40007fc0 ...
Image Name: Linux-2.6.35.3-571-gcca29a0-gd43
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2653928 Bytes = 2.5 MB
Load Address: 40008000
Entry Point: 40008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
……
以下省略
【7】 Linux 内核裁剪实例
从零开始配置内核是不明智的建议在某一个默认配置的基础上进行修改以达到自己 产品的实际需求。 裁剪和配置内核的基本原则
基于某一个最接近的主板配置来修改
必须的、能确定的选项选中
不能确定的则不要改变原来配置
可选可不选的建议根据 help 信息决定或者不选
一次改动不要太多渐进式修改和验证
注意及时备份配置文件出现意外可以回退恢复。
下面给出一些常见功能的配置裁剪实例很多功能与所采用的主板硬件相关与其它不 同主板的内核配置上不一定完全相同但还是有一些参考意义。
【1.7.1】 GPIO 子系统配置
Linux 2.6 以上内核引入了子系统
GPIO
子系统将全部 GPIO 的操作接口都通过“/sys/class/gpio/”
目录导出非常方便用户使用。 输入下列命令进入内核配置菜单
$ make ARCH=arm menuconfig
在主菜单界面中选择“Device Drivers”
[*] Networking support --->
Device Drivers --->
File systems --->
Kernel hacking --->
进入“Device Drivers”界面选择并进入“GPIO Support”
[*] SPI support --->
PPS support --->
PTP clock support
-*- GPIO Support --->
<*> PWM Support --->
在“GPIO Support”中选中“/sys/class/gpio…”
--- GPIO Support
[*] /sys/class/gpio/... (sysfs interface)
*** Memory mapped GPIO drivers: ***
配置后重新编译内核使用新内核的系统即可通过“/sys/class/gpio/”访问系统的 GPIO了。
【1.7.2 】LED 子系统配置
Linux LED
子系统提供了“/sys/class/leds/”
的访问接口启用 LED 子系统能很方便地 操作系统的 LED 资源。
在“Device Drivers”配置界面选中“LED Support”支持
<*> MMC/SD/SDIO card support --->
< > Sony MemoryStick card support (EXPERIMENTAL) --->
[*] LED Support --->
[ ] Accessibility support --->
进入“LED Support”子菜单选中 LED 类支持和 LED 触发器支持并根据需要设置触发器
--- LED Support
[*] LED Class Support
*** LED drivers ***
...
[*] LED Trigger support
*** LED Triggers ***
<*> LED Timer Trigger
<*> LED Heartbeat Trigger
< > LED backlight Trigger
<*> LED GPIO Trigger
<*> LED Default ON Trigger
只要将系统的 LED 设备驱动添加到
LED
子系统中即可通过“/sys/class/leds/”
接口来进行访问。
【1.7.3】 串口配置
串口是嵌入式 Linux 必不可少的外设默认控制台通常就是串口所以必须在内核中使能串口以及串口控制台支持。
在“Device Drivers”配置界面选择“Character devices”
Input device support --->
Character devices --->
-*- I2C support --->
进入“
Character devices
”配置菜单选择“Serial drivers
”
[*] /dev/kmem virtual device support
Serial drivers --->
[ ] ARM JTAG DCC console
进入“
Serial drivers
”在配置界面进行串口控制器配置。嵌入式 Linux 默认控制台是串口所以还需使能串口控制台支持。串口控制器与具体处理器相关需要根据硬件进行选择很多处理器移植代码会默认选中自身的串口驱动支持例如EPC-28x
已经默认选中了“i.MXS Application serial port support
”
<M> 8250/16550 and compatible serial support
*** Non-8250 serial port support ***
<*> i.MXS debug serial port support
<*> i.MXS Application serial port support
【1.7.4】 USB Host 驱动配置
USB 可以外接多种设备不同设备的驱动配置也是不同的。下面以常用的 U 盘、USB鼠标键盘配置为例进行介绍。
1. 使用 U 盘
U 盘在
Linux
系统下被认为是SCSI
设备所以必须在内核中选择支持 SCSI。在主菜单 界面选择“Device Drivers
”进入设备驱动配置界面选择“SCSI device support
”
[*] Block devices --->
[*] Misc devices --->
SCSI device support --->
< > Serial ATA and Parallel ATA drivers --->
进入“SCSI device support”配置界面进行如下配置
< > RAID Transport Class
<*> SCSI device support
< > SCSI target support
[*] legacy /proc/scsi/ support
*** SCSI support type (disk, tape, CD-ROM) ***
<*> SCSI disk support
< > SCSI tape support
< > SCSI OnStream SC-x0 tape support
然后在驱动中配置 USB 控制器。进入“Device Drivers”选中“USB support”
< > Sound card support --->
[ ] HID Devices --->
[*] USB support --->
<*> MMC/SD/SDIO card support --->
进入“
USB support
”菜单选中“Support for Host-side USB
”并根据处理器的控制器 情况配置 USB 控制器。下面是EPC-28x
处理器 USB 控制器的配置
--- USB support
<*> Support for Host-side USB
[*] USB device filesystem (DEPRECATED)
[*] USB device class-devices (DEPRECATED)
[*] USB runtime power management (suspend/resume and wakeup)
<*> EHCI HCD (USB 2.0) support
[*] Support for Freescale controller
[*] Support for Host1 port on Freescale controller
[*] Support for DR host port on Freescale controller
[*] Root Hub Transaction Translators
使用 U 盘必须使能 USB 大容量类支持选中“
USB Mass Storage support
”
…
<*> USB Mass Storage support
[ ] USB Mass Storage verbose debug
大多数情况下U 盘都在用 FAT 格式为了能正常使用 U 盘还需在内核中使能
FAT
支持。菜单路径和配置如下
File systems --->
DOS/FAT/NT Filesystems --->
<*> MSDOS fs support
<*> VFAT (Windows-95) fs support
(437) Default codepage for FAT
(iso8859-1) Default iocharset for FAT
< > NTFS file system support
保存配置重新编译内核基于新内核的系统就能使用 U 盘了。
2. 使用 USB 键盘和鼠标
使用 USB 键盘或者鼠标需要在内核中使能 HID 支持。在“
Device Drivers
”菜单界面选中“HID Devices
”
<*> Sound card support --->
[*] HID Devices --->
[*] USB support --->
<*> MMC/SD/SDIO card support --->
进入“
HID Devices
”选中“USB Human Interface Device (full HID) support
”
--- HID Devices
-*- Generic HID support
[ ] /dev/hidraw raw HID device support
*** USB Input Devices ***
<*> USB Human Interface Device (full HID) support
[ ] PID device support
[ ] /dev/hiddev raw HID device support
Special HID drivers --->
另外还需使能
Event
支持。在“Device Drivers
”配置界面选择“Input device support
”
< > Telephony support --->
Input device support --->
Character devices --->
-*- I2C support --->
进入“
Input device support
”选中“Event interface
”
< > Joystick interface
<*> Event interface
< > Event debugging
`当然还需要 USB Host 支持参考前面“使用 U 盘”配置部分配置好 USB 控制器。
保存配置并编译内核使用新内核的系统即可支持 USB 键盘和鼠标。`
【1.7.5】 USB Gadget 驱动配置
USB Gadget 能通过
USB Device
实现诸如 U 盘模拟、USB 串口、USB 网卡等多种功能。 首先在内核配置使能“USB Gadget Support
”
Device Drivers --->
[*] USB support --->
<*> USB Gadget Support --->
然后进入“
USB Gadget Support
”根据实际情况选择 USB 控制器如下是AM335x
的USB
控制器选择
<*> USB Peripheral Controller (Inventra HDRC USB Peripheral (TI, ADI, ...)) --->
最后在配置菜单中根据实际需要选择配置相应的功能。对于 USB Gadget 的功能建议编译为模块在需要的时候插入模块用完后将模块卸载
<M> USB Gadget Drivers
< > Gadget Zero (DEVELOPMENT)
< > Audio Gadget (EXPERIMENTAL)
<M> Ethernet Gadget (with CDC Ethernet support)
[*] RNDIS support
...
<M> File-backed Storage Gadget (DEPRECATED)
[ ] File-backed Storage Gadget testing version
<M> Mass Storage Gadget
< > Serial Gadget (with CDC ACM and CDC OBEX support)
【1.7.6】 SD/MMC 驱动配置
在“Device Drivers”菜单中使能“MMC/SD/SDIO card support”
Device Drivers --->
<*> MMC/SD/SDIO card support --->
进入“
MMC/SD/SDIO card support
”使能“MMC block device driver
”。在“MMC/SD/SDIO Host Controller Drivers
”下选择处理器对应的SD/MMC
控制器
--- MMC/SD/SDIO card support
...
*** MMC/SD/SDIO Card Drivers ***
<*> MMC block device driver
(8) Number of minors per block device
[*] Use bounce buffer for simple hosts
< > SDIO UART/GPS class support
< > MMC host test driver
*** MMC/SD/SDIO Host Controller Drivers ***
...
[*] Freescale i.MX Secure Digital Host Controller Interface
<*> MXS MMC support
另外还需根据
SD/MMC
卡的文件系统格式在内核中配置相应的文件系统支持。如果是FAT 格式请参考前面“使用U 盘”中 VFAT
的配置如果采用Ext2/3/4
格式则进行如下配置
File systems --->
<*> Second extended fs support
<*> Ext3 journalling file system support
<*> The Extended 4 (ext4) filesystem
【1.7.7】 网卡驱动配置
配置网卡首先要在主菜单中使能网络即选中“Networking support”
Power management options --->
[*] Networking support --->
Device Drivers --->
File systems --->
为了正常使用网络通常还需在“`Networking options`”中配置 `TCP/IP`
[*] Networking support --->
Networking options --->
<*> Packet socket
<*> Unix domain sockets
< > PF_KEY sockets
[*] TCP/IP networking
[*] IP: multicasting
[ ] IP: advanced router
[*] IP: kernel level autoconfiguration
[*] IP: DHCP support
[*] IP: BOOTP support
[*] IP: RARP support
只有开启“
Networking support
”支持后才能在“Device Drivers
”菜单中看到“Network device support
”子菜单
Device Drivers --->
[ ] Multiple devices driver support (RAID and LVM) --->
< > Generic Target Core Mod (TCM) and ConfigFS Infrastructure --->
[*] Network device support --->
[ ] ISDN support --->
< > Telephony support --->
Input device support --->
选中“
Network device support
”并进入根据主板实际硬件在“Ethernet driver support
”中配置物理网卡。如下是基于 EPC-28x
的主板网卡配置示例
[*] --- Ethernet (10 or 100Mbit) --->
…
<*> FEC ethernet controller (of ColdFire and some i.MX CPUs)
[*] Second FEC ethernet controller (on some ColdFire CPUs)
【1.7.8】 NFS Client 配置
使用
NFS 文件系统
首先需要保证网卡可用且在内核已经配置了网卡。在“File system
”配置界面使能“Network File Systems
”并进行配置
File systems --->
[*] Network File Systems --->
<*> NFS client support
[*] NFS client support for NFS version 3
[*] NFS client support for the NFSv3 ACL protocol extension
[*] NFS client support for NFS version 4
[*] NFS client support for NFSv4.1 (EXPERIMENTAL)
[*] Root file system on NFS
选中“
Root file system on NFS
”能够通过NFS 挂载服务器
上的根文件系统这点在裁剪文件系统中特别有用。
【1.7.9】 PPP 拨号配置
PPP 拨号配置在“
Device Drivers
”的“Network device support
”菜单下。选中并使能“PPP (point-to-point protocol) support
”及子选项即可使用 PPP 拨号功能。这里以模块方式编译
Device Drivers --->
[*] Network device support --->
<M> PPP (point-to-point protocol) support
<M> PPP BSD-Compress compression
<M> PPP Deflate compression
[*] PPP filtering
<M> PPP MPPE compression (encryption) (EXPERIMENTAL)
[*] PPP multilink support (EXPERIMENTAL)
<M> PPP over Ethernet (EXPERIMENTAL)
<M> PPP support for async serial ports
<M> PPP support for sync tty ports
编译内核后通过
make modules
编译模块在<drivers/net/ppp/>
目录下会生成slhc.ko、pppox.ko、pppoe.ko
等模块。将这些模块复制到目标系统中然后按照下列顺序依次插入模块
#insmod slhc.ko
#insmod ppp_generic.ko
#insmod pppox.ko
#insmod pppoe.ko
插入模块后生成/dev/ppp 设备节点通过 ppp 拨号脚本即可进行拨号了。
【1.7.10】 MTD 配置
在内核配置主菜单界面进入“
Device Drivers
”界面选择“Memory Technology Device (MTD) support
”
< > Connector - unified userspace <-> kernelspace linker --->
<*> Memory Technology Device (MTD) support --->
Device Tree and Open Firmware support --->
< > Parallel port support --->
并进入“Memory Technology Device (MTD) support”进行如下配置
--- Memory Technology Device (MTD) support
< > MTD tests support (DANGEROUS)
< > RedBoot partition table parsing
[*] Command line partition table parsing
...
<*> Direct char device access to MTD devices
-*- Common interface to block layer for MTD 'translation layers'
<*> Caching block device access to MTD devices
…
<*> NAND Device Support --->
进入“NAND Device Support”对系统 NAND 控制器进行选择
--- NAND Device Support
[ ] Verify NAND page writes
[ ] Support software BCH ECC
[ ] Enable chip ids for obsolete ancient NAND devices
< > GPIO NAND Flash driver
<*> NAND Flash device on OMAP2, OMAP3 and OMAP4
保存配置编译内核。采用新内核启动的系统在驱动无误的情况下可以看到系统的MTD 分区信息。如下是 EPC-28x 进入系统后可通过/proc/mtd 文件查看
[root@M283 ~] # cat /proc/mtd
dev: size erasesize name
mtd0: 00c00000 00020000 "reserve"
mtd1: 00080000 00020000 "reserve"
mtd2: 00080000 00020000 "reserve"
mtd3: 00080000 00020000 "reserve"
mtd4: 00080000 00020000 "reserve"
mtd5: 04000000 00020000 "rootfs"
mtd6: 02e00000 00020000 "opt"
【1.7.11】 UBIFS 文件系统配置
UBIFS
是工作于 UBI 子系统之上的文件系统而 UBI 又工作于MTD
设备上所以首先需要在 MTD 中使能UBI
Device Drivers --->
<*> Memory Technology Device (MTD) support --->
<*> Enable UBI - Unsorted block images --->
进入“Enable UBI - Unsorted block images”对 UBI 进行配置
--- Enable UBI - Unsorted block images
(4096) UBI wear-leveling threshold
(1) Percentage of reserved eraseblocks for bad eraseblocks handling
< > MTD devices emulation driver (gluebi)
[ ] UBI debugging
其中“Percentage of reserved eraseblocks for bad eraseblockshandling”设置用于坏块管理 的保留块的百分比默认是 1%可以适当调整大一些不过必须与 U-Boot 中的设置一致。 还需在文件系统设置中使能和配置 UBIFS
File systems --->
[*] Miscellaneous filesystems --->
<*> UBIFS file system support
[*] Extended attributes support
[*] Advanced compression options
[*] LZO compression support (NEW)
[*] ZLIB compression support (NEW)
【1.7.12】 CAN 驱动配置
前面已经提到过CAN 设备驱动的配置路径不在“Devie Drivers”下而是在“
Networking support
”中。进入内核配置主菜单选择“Networking support
”
Power management options --->
[*] Networking support --->
Device Drivers --->
File systems --->
选中或者模块编译“CAN bus subsystem support”
--- Networking support
Networking options --->
[ ] Amateur Radio support --->
<*> CAN bus subsystem support --->
< > IrDA (infrared) subsystem support --->
进入“CAN bus subsystem support”选中“Raw CAN Protocol”和“Broadcast Manager CAN Protocol”
--- CAN bus subsystem support
<*> Raw CAN Protocol (raw access with CAN-ID filtering)
<*> Broadcast Manager CAN Protocol (with content filtering)
< > CAN Gateway/Router (with netlink configuration) (NEW)
CAN Device Drivers --->
然后进入“CAN Device Drivers”对 CAN 设备驱动进行配置如下
CAN Device Drivers --->
<*> Virtual Local CAN Interface (vcan) (NEW)
<> Serial / USB serial CAN Adaptors (slcan) (NEW)
< > Platform CAN drivers with Netlink support (NEW)
<*> Freescale FlexCAN
【8】 EPC-28x 平台内核快速编译
从 EPC-28x光盘内获取内核源码包EPC-28x.xxxxx.tar.bz2然后把它拷贝到Ubuntu 下面执行如下步骤
1. 解压缩
vmuser@Linux-host ~$ tar -vxjf EPC-28x.xxxxx.tar.bz2
解压后产生内核目录 linux-2.6.35.3。
2. 编译内核
EPC-28x
内核源码的Makefile
文件内已经配置好了ARCH
和CROSS_COMPILE
所以 在 make 时无需指定ARCH
和CROSS_COMPILE
。EPC-28x
的源码已经包含配置好的.config
文件无需makemenuconfig
配置即可使用默 认配置除非需要改动内核配置。
vmuser@Linux-host ~$ cd linux-2.6.35.3
vmuser@Linux-host ~/ linux-2.6.35.3$ make uImage
编译完成将得到内核文件
<arch/arm/boot/uImage>
。 另外在执行make distclean
或者make mrproper
之前请先将.config 配置文件备份 如
vmuser@Linux-host ~/ linux-2.6.35.3$cp .config config-bak
第二章等你