2023年8月2日发(作者:)

二 Linux内核移植实验指导书

1 Linux内核移植前准备

对于嵌入式Linux系统来说,有各种体系结构的处理器和硬件平台,并且用户需要根据需求自己定制硬件板。只要是硬件平台发生变化,即使非常小,可能也需要做一些移植工作。内核移植是嵌入式Linux系统中最常见的一项工作。当然,移植嵌入式 Linux系统并不意味着该内核使用了任何特定的链接库或用户工具,建立嵌入式系统并不需要特别的内核。嵌入式系统中使用的内核与工作站或服务器上使用的内核主要的不同在于内核的配置方面。Linux 内核移植是在 Linux原内核基础上,通过对平台的选择设计来实现针对特定系统的内核版本。 Linux内核的移植包含启动代码的修改、内核的链接及装入、参数传递、内核引导几个部分。其基本过程如下:

(1)首先,获取某一版本的Linux内核源码,根据具体目标平台对源码进行必要的改写(主要是修改体系结构相关部分);

(2)然后添加一些外设的驱动(如网卡驱动,USB驱动),打造一款适合于目标平台(可以是嵌入式便携设备也可以是其它体系结构的 PC 机)的新操作系统,也就是常说的内核配置或内核定制;

(3)对该系统进行针对目标平台的交叉编译,生成一个内核映象文件(如 zImage,uImage,bzImage);

(4)最后通过一些手段(如TFTP)把该映象文件烧写到目标平台中。

本实验将对 Linux 内核移植的一些相关概念、知识进行介绍,希望学员可以对 Linux 内核的移植理解得更透彻。

1.1 Linux内核源码

Linux内核移植工作主要是修改跟硬件平台相关的代码,一般不涉及 Linux 内核通用的程序,移植的难度也取决于两种硬件平台的差异。通常对 Linux 源码的改写工作难度较大,它要求你不仅对 Linux内核结构要非常熟悉,还要求你对目标平台的硬件结构非常熟悉。同时还要求你对相关版本的汇编语言较熟悉因为与体系结构相关的部分源码往往是用汇编写

的。

本小节虽然并不对具体的内核代码进行修改, 但是与其相关的一些基础和概念还是有必

要简单介绍一下。

(1)BSP包开发

Linux对于特定的硬件平台的软件就叫作 BSP(Board Support Package)。基于上面描

述的困难,这部分工作一般由目标平台提供商来完成。比如说针对目前嵌入式系统中最流行

的 ARM平台,它的这部分工作就是由英国ARM公司的工程师完成的,我们所要做的就是从其网站上下载相关版本Linux内核的补丁(Patch)。把它打到我们的Linux内核上,再进行后续操作就行。针对某些特定的硬件平台可能并没有平台开发商提供的BSP,这就需要我们自己参考类似的BSP来开发程序。

所幸的是,Linux内核已经支持了各种体系结构的很多种目标板,我们很容易从中找到

跟自己硬件类似的目标板。参考内核已经支持的目标板来移植BSP,就如同使用模板开发程序一样。当然,我们选择的参考板不能仅凭兴趣或爱好来选取,选择参考板也有一定的原

则。具体的原则如下:

■ 参考板与开发板具有相同的处理器,至少类似的处理器;

■ 参考板和开发板具有相同的外围接口电路,至少基本接口相同;

■ Linux内核已经支持参考板,至少有非官方的补丁或者BSP;

■ 参考板Linux设备驱动工作正常,至少已经驱动基本接口。

找到了参考板后,还要仔细分析内核代码以及参考板的BSP,分析平台相关的部分代码实现;分析内核编译组织方式;分析内核启动的初始化程序;分析驱动程序的实现;弄清楚

哪些设备有驱动程序,哪些还没有等等。然后才能开始动手修改内核源代码。

(2)内核源码分析

1 我们需要进行 Linux内核移植,那么首先,我们得下载一个干净的内核源码树,这里实验下载的内核源代码版本为 Linux2.6.24.4。解压后,先来看看Linux内核源代码目录树结构。

(2)内核源码分析

我们需要进行 Linux内核移植,那么首先,我们得下载一个干净的内核源码树,这里本实验下载的内核源代码版本为 Linux2.6.24.4。解压后,先来看看 Linux内核源代码目录树结构。

表1-1 Linux内核子目录结构

目录名

arch

block

crypto

drivers

描述

存放各种与硬件体系结构相关的代码,每种体系结构一个相应的目录,每个目录下都包括了该体系结构相关的代码,包括内存管理,启动代码,浮点数仿真等等。

部分块设备驱动程序。

常用加密和散列算法(如 AES、SHA等) ,还有一些压缩和 CRC 校验算法。

所有的设备驱动程序,里面每一个子目录对应一类驱动程序,比如drivers/block/为块设备驱动程序,drivers/char/为字符设备驱动程序,drivers/mtd/为NOR Flash、NAND Flash等存储设备的驱动程序。

fs

include

提供对各种文件系统的支持。每个子目录对应一种文件系统,比如fs/fat32/

内核头文件,有基本文件(存放在include/linux/目录下)、各种驱动或功能部件的头文件(比如include/media/、include/mtd/、include/net/)、各种体系相关的头文件(比如include/asm-arm/)。当配置内核后,include/asm/是某个include/asm-xxx/(比如include/asm-arm/)的链接。

init

ipc

kernel

lib

mm

net

scripts

sound

usr

内核的初始化代码(不是系统的引导代码),其中的main.c文件中的star_kernel函数是内核引导后运行的第一个函数

进程间通信的代码

内核的最核心部分,包括进程调度、定时器等,和平台相关的一部分代码放在arch/*/kernel

目录下。

各种库文件代码。

内存管理代码,和平台相关的一部分代码放在 arch/*/mm目录下。

网络相关代码,实现了各种常见的网络协议。

用于配置内核文件的脚本文件

音频设备的驱动程序

用户代码

在以上布局中,linux内核主要分为特定于体系结构的部分和与体系结构无关的部分。

在 Linux启动的第一阶段,内核与体系结构相关部分(arch目录下)首先执行,在这部分它要做的工作有:内核解压缩、解压缩内核重定位;内存硬件初始化检测;参数表的分析;初始化页表目录的制作等工作,然后把控制权转给内核中与系统结构无关部分。所以操作系统内核移植中要改动的代码主要集中在与体系结构相关的启动初始化部分。 从上面的目录结构介绍可知,如果要添加新的开发板或者寻找体系结构相关的文件首先就是到 arch 目录下去寻找。在 arch 目录中我们可以看到有许多子目录,它们往往是用芯片命名的,表示是针对该芯片体系结构的代码。为 ARM系列芯片编译内核,就应修改 ARM目录下的相关文件。 Linux 移植过程中内容非常多,涉及的知识量也很大,而且由于平台的不同,和内核版本的不同所涉及的内容往往也有很大不同。所以以上给出内容也仅作为读者参考之用。具体操作时还应收集相关平台及内核版本的详细资料,才能展开相应工作。限于篇幅本实验也无法做更深入的介绍。

1.2 图形化内核配置选项

在 Linux源码的顶层目录运行 make menuconfig,便会出现如下图所示的图形化配置菜单:

2

Documentation

内核文档

图1-1 内核配置选项主菜单

上图显示的是一个主菜单,主菜单中还包含了很多子菜单,通过敲键盘的↑、↓键可以

选择不同的子菜单,再敲回车键,进入这些子菜单,可以看到该子菜单下的一些功能选项,如我们进入

System Type这个子菜单,便可以看到如图 1-2 所示的界面:

图1-2 内核配置选项子菜单

在对各个选项进行配置时,有三种方式,它们分别代表的含义如下:

Y:将该功能编译进内核;

3 N:不将该功能编译进内核;

M:将该功能编译成可以在需要时动态插入到内核中的模块 。

至于某个选项具体配置成哪一种方式,可以通过空格键进行选取。所有选项前都有一个

括号,有的是中括号,有的是尖括号,还有圆括号。用空格键选择时可以发现,中括号里要么是空,要么是"*",而尖括号里可以是空,"*"和"M"这表示前者对应的项要么不要,要么编译到内核里;后者则多一样选择,可以编译成模块。而圆括号的内容是要你在所提供的几个选项中选择一项。

内核配置好后,读者可以通过 Esc 键或是 Exit 选项离开内核配置菜单。内核配置系统

将会提示是否要储存新的配置。选择Yes,离开内核配置系统的时候,会将新的配置储存到

新的.config文件。这除了会建立.config文件,也会建立一些的头文件和符号链接。选择 No,

离开内核配置系统的时候,并不会储存任何变更。除了主要的配置选项,内核所支持的架构通常会包含特定开发板的标准样版配置。比如ARM开发板,以 s3c2410为例,在 arch/arm/configs目录下便有一个s3c2410_defconfig的配置文件,运行 make s3c2410_defconfig命令,内核配置系统将自动调用该配置文件,并且将该文件中各选项的配置存储到.config文件中去,下次执行 make menuconfig时就会载入这些配置。

2 Linux内核移植

2.1 获取linux源码

linux-2.6.24.4的内核源码可以从上下载。

将2拷贝到/gdut2410/kernel/目录下,解压,就可以得到完整的Linux内核源码包:

进入/gdut2410/kernel目录下

[root@BC /]# cd /gdut2410/kernel

2.2 解压内核源代码

解压内核

[root@BC kernel]# tar -jxvf 2

进入内核目录

[root@BC kernel]# cd linux-2.6.24.4

2.3 指定交叉编译器

修改顶层目录的 Makefile,执行命令:

[root@BC linux-2.6.24.4]# vi Makefile

找到193行设置下面两行:

ARCH := arm

CROSS_COMPILE := /gcc-3.4.6-glibc-2.3.6/arm-linux/bin/arm-linux-

这两行表示接下来将对嵌入式 ARM系统上使用的 Linux内核进行交叉编译。

2.4 移植 Nand 驱动并更改分区信息

设置Nand Flash的分区信息表是为内核启动以后加载文件系统用的,可以将Nand Flash看成我们PC机的硬盘,对 Nand Flash的分区看成是对硬盘的分区,硬盘可以分成C盘,D盘之类,而 Nand Flash则可以分成很多块,每块有不同的名字、大小和用途。下面是对Super-ARM实验箱的Nand Flash进行分区的情况:

■ 第 0 块命名为"uboot",它用来存放 映像,起始地址是 Nand Flash 的0x000000,最大0x80000 个字节;

■ 第 1 块命名为"kernel",用来存放内核,起始地址是 Nand Flash 的 0x80000,最大0x200000 个字节;

■ 第2 块命名为"rootfs",用来存放根文件系统,起始地址是 Nand Flash的 0x280000,最大 60M字节;

至于具体要怎么分,这样根据你的目标机的Nand Flash来定,不能一概而论。分区的方法就是修改

arch/arm/plat-s3c24xx目录下的 common-smdk.c文件:

执行命令

4 [root@BC linux-2.6.24.4]# vi arch/arm/plat-s3c24xx/common-smdk.c

在第109行找到:static struct mtd_partition smdk_default_nand_part[],在其中填入下面的内容(将原来的内容覆盖),如代码清单 2-1-1所示:

代码清单 2-3-1 NandFlash分区信息

static struct mtd_partition smdk_default_nand_part[] = {

[0] = {

.name = "u-boot",

.size = 0x80000,

.offset = 0,

},

[1] = {

.name = "kernel",

.offset = 0x80000,

.size = 0x200000,

},

[2] = {

.name = "rootfs",

.offset = SZ_2M + 0x80000,

.size = SZ_2M*30,

},

};

2.5 添加 devfs 文件系统支持

为了我们的内核支持devfs,以及在启动时能自动挂载/dev。编辑 fs/Kconfig:

[root@BC linux-2.6.24.4]# vi fs/Kconfig

在907 行menu "Pseudo filesystems"下面添加如下代码:

config DEVFS_FS

bool "/dev file system support (OBSOLETE)"

default y

config DEVFS_MOUNT

bool "Automatically mount at boot"

default y

depends on DEVFS_FS

2.6 关于内核配置菜单中选项

首先拷贝smk2410开发板配置文件到linux-2.6.24.4

[root@BC linux-2.6.24.4]# cp -a arch/arm/configs/s3c2410_defconfig ./

执行 make s3c2410_defconfig 命令,获取 s3c2410_defconfig文件中给定的配置。

[root@BC linux-2.6.24.4]# make s3c2410_defconfig

然后执行make menuconfig命令,出现内核的配置界面:

[root@BC linux-2.6.24.4]# make menuconfig

5

图2-6-1 内核配置界面

在smdk2410_defconfig基础上,增删以下内核配置项:在配置菜单中,选择system

type-->s3c2410 machines中的smdk2410,其他的arch-machines全部取消。

图2-6-2 内核配置选项(1)

6

图2-6-3 内核配置选项(2)

至于所有其他的选项都默认 s3c2410_defconfig 给定的配置,这里暂时不做修改。在后续实验中,需要添加相应的功能时再对相关选项重新进行配置。 重新保存为.config并退出。

图2-6-4 保存内核配置选项(1)

7

图2-6-5 保存内核配置选项(2)

2.7 移植 LCD显示驱动

(1)进入内核顶层目录,修改arch/arm/mach-s3c2410/mach-smdk2410.c文件

[root@BC linux-2.6.24.4]# vi arch/arm/mach-s3c2410/mach-smdk2410.c

▶第一处:在56行后添加下面的头文件

#include

▶第二处:在92行后添加 s3c2410fb_display 结构

static struct s3c2410fb_display s3c2410_lcd_cfg __initdata = {

.lcdcon5 = S3C2410_LCDCON5_FRM565 |

S3C2410_LCDCON5_INVVLINE |

S3C2410_LCDCON5_INVVFRAME |

S3C2410_LCDCON5_PWREN |

S3C2410_LCDCON5_HWSWP,

.type = S3C2410_LCDCON1_TFT,

.width = 240,

.height = 320,

.pixclock = 98619, // 10.1

.xres = 240,

.yres = 320,

.bpp = 16,

.left_margin =16,

.right_margin = 7,

.hsync_len = 14,

.upper_margin = 2,

.lower_margin = 3,

.vsync_len = 2,

};

xres = LINEVAL + 1

yres = HOZVAL + 1

pixclock = (1/hclk) ×1012 其中Super-ARM的hclk 是10.14Mhz

left_margin = HFPD + 1

8 right_margin = HBPD + 1

hsync_len = HSPW+1

upper_margin = VBPD +1

lower_margin = VFPD+1

vsync_len = VSPW+1

▶ 第三处:113行后添加 s3c2410fb_mach_info 结构

static struct s3c2410fb_mach_info s3c2410_fb_info __initdata = {

.displays = &s3c2410_lcd_cfg,

.num_displays = 1,

.default_display = 0,

.gpccon = 0xaaa556a9,

.gpccon_mask = 0xfff003fc,

.gpcup= 0x0000ffff,

.gpcup_mask= 0xffffffff,

.gpdcon = 0xaa95aaa5,

.gpdcon_mask = 0xffc0fff0,

.gpdup = 0x0000ffff,

.gpdup_mask = 0xffffffff,

.lpcsel = 0x4,

};

▶ 第四处:在函数 smdk2410_init()中加入下面一行

s3c24xx_fb_set_platdata(&s3c2410_fb_info);

我跟大家分析一下添加这些代码的具体作用。首先看 smdk2410_fb_info(第三处),它是

s3c2410fb_mach_info 类型的结构体,这个结构体有一个 displays 的成员变量,它指向s3c2410fb_display

类型的指针。之前说过,一个系统有多少个显示设备就对应多少个s3c2410fb_display 的结构,Super-ARM

只有一个 LCD 显示设备,所以就只定义了一个

s3c2410fb_display结构体 smdk2410_lcd_cfg(第二处) ,那么 displays就指向这个结构体,同时将

num_displays 赋值 1。最后通过 s3c24xx_fb_set_platdata 函数将smdk2410_fb_info 传递给底层 LCD 驱动。

把所给的s3c2410fb.c s3c2410fb.h放在/gdut2410/kernel/linux-2.6.24.4/drivers/video/下。

(2)重新配置内核:执行 make menuconfig,添加下面两项配置

▶ 第一项:添加 S3C2410 LCD 驱动支持

进入 Device drivers-->Graghics support-->Support for frame buffer devices , 出现下面的界面,选中

S3C2410 LCD framebuffer support和S3C2410 lcd debug messages 两个选项。

9

图2-7-1 配置LCD选项(1)

图2-7-2 配置LCD选项(2)

▶第二项:Bootup logo

10

图2-7-3 配置Bootup logo选项

配置 Bootup logo是为了在内核加载完 LCD 驱动后在 LCD 屏上看到一个小企鹅。

进入 Device drivers-->Graghics support-->Bootup logo, 出现下面的界面, 三个不同的 logo选项对应不同的小企鹅图片,可以到内核的 drivers/video/logo目录下找到对应的图片,读者可以根据自己的喜好随便选择一个。

(3)编译内核,并将重新编译生成的 zImage文件复制到 tftp 根目录下

[root@BC linux-2.6.24.4]# make

(4)启动Super-ARM,加载内核和文件系统,看看LCD 屏上是不是出现了小企鹅

2.8 移植触摸屏驱动

以下操作都在内核主目录下进行。

(1)修改drivers/input/touchscreen/Makefile文件:

[root@BC linux-2.6.24.4]# vi drivers/input/touchscreen/Makefile

在文件中添加:

obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o

图2-8-1 修改触摸屏Makefile

11 (2)修改drivers/input/touchscreen/Kconfig文件:

[root@BC linux-2.6.24.4]# vi drivers/input/touchscreen/Kconfig

在文件中136行后添加:

config TOUCHSCREEN_S3C2410

tristate "S3C2410 Touchscreen"

depends on ARCH_SMDK2410 && INPUT && INPUT_TOUCHSCREEN

(3)重新配置内核:

[root@BC linux-2.6.24.4]# make menuconfig

进入Device drivers-->Input device support-->,出现下面的界面,将Horzontal设置为240,Vertical 设置为320,选中<*>Event interface、<*>Event debugging和 [*] Touchscreens选项。进入[*] Touchscreens选项以后,选中我们在Kconfig文件中设置的<*> Samsung S3C2410 touchscreen input driver 和 [*]Samsung

S3C2410 touchscreen debug messages。

图2-8-2 配置触摸屏(1)

12

图2-8-3 配置触摸屏(2)

(4)修改arch/arm/mach-s3c2410/mach-smdk2410.c文件

[root@BC linux-2.6.24.4]# vi arch/arm/mach-s3c2410/mach-smdk2410.c

▶ 第一处:在 map_desc smdk2410_iodesc结构前面添加 s3c2410_ts_mach_info结构:

static struct s3c2410_ts_mach_info s3c2410_ts_cfg __initdata = {

.delay = 10000, // delay 是AD 转换的延时时间

//.delay = 200000,

.presc = 49, // presc将被写入ADCCON 的PRESVL字段,用来配置AD 转换速率

.oversampling_shift = 2, //一次触摸动作需要进行4(1<<2)次AD 转换后取平均值作为最后的坐标值

};

s3c2410_ts_mach_info 结构中的 delay 是 AD 转换的延时时间,在触摸屏驱动中将被写入 ADCDLY

寄存器中, presc将被写入 ADCCON 的 PRESVL字段, 用来配置AD 转换速率。oversampling_shift将传给 s3c2410_ts的 shift 成员,该值为2,说明一次触摸动作需要进行4(1<<2)次 AD 转换后取平均值作为最后的坐标值。

▶ 第二处:在 static struct platform_device *smdk2410_devices[] __initdata = {中添加:

&s3c_device_ts,

▶ 第三处: 在 static void __init smdk2410_map_io(void)函数中添加:

set_s3c2410ts_info(&s3c2410_ts_cfg);

▶ 第四处:在53行后添加头文件

#include

(5)添加s3c2410_ts.h:

[root@BC linux-2.6.24.4]# vi include/asm-arm/arch-s3c2410/s3c2410_ts.h

在空白的s3c2410_ts.h添加如下代码

#ifndef __ASM_ARM_S3C2440_TS_H

13 #define __ASM_ARM_S3C2440_TS_H

struct s3c2410_ts_mach_info {

int delay; // delay 是AD 转换的延时时间

int presc;// ,presc将被写入ADCCON 的PRESVL字段,用来配置AD 转换速率

int oversampling_shift;

//一次触摸动作需要进行4(1<<2)次AD 转换后取平均值作为最后的坐标值

};

void __init set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info);

#endif /* __ASM_ARM_S3C2440_TS_H */

(6)修改regs-adc.h添加宏定义

[root@BC linux-2.6.24.4]# vi include/asm-arm/plat-s3c/regs-adc.h

在44行后添加以下宏定义

//add by mh

/* For touchscreen */

#define S3C2410_ADCTSC_XY_PST_N (0x0<<0)

#define S3C2410_ADCTSC_XY_PST_X (0x1<<0)

#define S3C2410_ADCTSC_XY_PST_Y (0x2<<0)

#define S3C2410_ADCTSC_XY_PST_W (0x3<<0)

//add end

//对触摸屏控制寄存器 的状态选择位 宏定义

(7)修改include/asm-arm/plat-s3c24xx/devs.h文件:

[root@BC linux-2.6.24.4]# vi include/asm-arm/plat-s3c24xx/devs.h

在#include 文件32行后添加下面的内容:

extern struct platform_device s3c_device_ts;

图2-8-4 添加s3c_device_ts

(8)修改arch/arm/plat-s3c24xx/devs.c文件:

[root@BC linux-2.6.24.4]# vi arch/arm/plat-s3c24xx/devs.c

▶ 第一处:在37行后添加新增加的头文件

#include

▶ 第二处:在约191行后(即 /* NAND Controller */前)添加如下代码

/* Touchscreen */

static struct s3c2410_ts_mach_info s3c2410ts_info;

void __init set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info){

memcpy(&s3c2410ts_info, hard_s3c2410ts_info, sizeof(struct s3c2410_ts_mach_info));

}

14

EXPORT_SYMBOL(set_s3c2410ts_info);

struct platform_device s3c_device_ts = {

.name = "s3c2410-ts",

.id = -1,

.dev = {

.platform_data = &s3c2410ts_info,

}

};定义一个平台设备

EXPORT_SYMBOL(s3c_device_ts);

(9)添加drivers/input/touchscreen/s3c2410_ts.c 文件

该文件是开源的,可以直接从网上下载(需做适当修改),本实验提供已修改过的s3c2410_ts.c。

(10)编译内核,并将重新编译生成的 zImage文件复制到 tftp 根目录下

[root@BC linux-2.6.24.4]# make

(11)启动 Super-ARM,加载内核和文件系统。

在内核启动信息中可以看到

“input: s3c2410 Touchscreen as /class/input/input0 ” 。

2.9 移植网卡驱动

2.9.1 移植CS8900网卡驱动

CS8900 芯片是 Cirrus Logic 公司生产的一种局域网处理芯片,在嵌入式领域中使

用非常常见。它的封装是 100-pin TQFP,内部集成了在片 RAM、10BASE-T 收发滤波器,并且提供 8 位和 16 位两种接口。在本实验介绍的开发板中采用的就是 CS8900芯片。下面介绍移植网卡驱动的实验过程。(以下操作在/gdut2410/kernel/linux-2.6.24 目录下进行)

(1)修改Makefile

[root@BC linux-2.6.24.4]# vi drivers/net/arm/Makefile

在文件末尾添加一行:

obj-$(CONFIG_ARM_CS8900) += cs8900.o

(2)修改Kconfig文件

[root@BC linux-2.6.24.4]# vi drivers/net/arm/Kconfig

在文件末尾添加下面这一段:

config ARM_CS8900

tristate "CS8900 support"

depends on NET_ETHERNET && ARM && ARCH_SMDK2410

help

support for cs8900 chipset based Ethernet cards , if you have a network card of this type

(3)修改mach-smdk2410.c文件

[root@BC linux-2.6.24.4]# vi arch/arm/mach-s3c2410/mach-smdk2410.c

在60行处static struct map_desc smdk2410_iodesc[] __initdata里面添加如下内容(如图所示):

vSMDK2410_ETH_IO,

pSMDK2410_ETH_IO,

SZ_1M,

MT_DEVICE

15

图2-9-1 添加s3c_device_ts

并将下一步骤中创建的头文件添加进来,在54行后添加:

#include

(4)创建smdk2410.h文件

[root@BC linux-2.6.24.4]# vi include/asm-arm/arch-s3c2410/smdk2410.h

在文件中添加如下内容:

#ifndef __ASM_ARCH_SMDK2410_H

#define __ASM_ARCH_SMDK2410_H

#define pSMDK2410_ETH_IO __phys_to_pfn(0x19000000)

#define vSMDK2410_ETH_IO 0xE0000000

#define SMDK2410_ETH_IRQ IRQ_EINT9

#define __IRQT_FALEDGE IRQ_TYPE_EDGE_FALLING

#define __IRQT_RISEDGE IRQ_TYPE_EDGE_RISING

#define __IRQT_LOWLVL IRQ_TYPE_LEVEL_LOW

#define __IRQT_HIGHLVL IRQ_TYPE_LEVEL_HIGH

#define IRQT_NOEDGE (0)

#define IRQT_RISING (__IRQT_RISEDGE)

#define IRQT_FALLING (__IRQT_FALEDGE)

#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE)

#define IRQT_LOW (__IRQT_LOWLVL)

#define IRQT_HIGH (__IRQT_HIGHLVL)

#define IRQT_PROBE IRQ_TYPE_PROBE

#endif

(5)复制 cs8900.h 和 cs8900.c 两个文件到/drivers/net/arm 目录下,网上可以下载这两个文件,但是需要做些修改才能为 Super-ARM 所用。

(6)配置内核

[root@BC linux-2.6.24.4]# make menuconfig

增加对cs8900 的支持: Device drivers ----> Network device support ---> Ethernet (10 or 100 Mbit)----->

<*> CS8900 Support 。配置界面如下图所示:

16

图2-9-2 配置网卡(1)

图2-9-3 配置网卡(2)

2.9.2 添加对 NFS 文件系统的支持

第一项:Networking--->Networking options --->

该选项配置网络环境,选中 IP: kernel level autoconfiguration、TCP/IP networking IP:RARP support 三项界面如图 2-9-4 所示:

17

图2-9-4 配置支持NFS文件系统(1)

第二项:File system ---> Network File System --->

该选项配置内核的文件系统,选中 NFS file system support、Provide NFSv3 client support和 Root file

system on NFS三项,使其支持网络文件系统,界面如下图所示:

图2-9-5 配置支持NFS文件系统(2)

2.10 配置USB 键盘、扫描器和鼠标

(1) 在内核源代码目录的终端输入:make menuconfig,依次选择如下子菜单项:

18 Device Drivers --->

[*] HID Devices --->

出现如图内核配置菜单:

图2-10-1 配置支持USB键盘和鼠标

按空格键选中“USB Human Interface Device (full HID) support” ,这样就配置好了USB键盘和鼠标项。

提示:这里的配置选项对应的内核源代码目录是:linux-2.6.24.4/drivers/hid/usbhid,其中USB键盘和条码扫描器的原理是一样的,因此它们的代码是相同的。

(2) 修改ohci-s3c2410.c

[root@BC linux-2.6.24.4]# vi drivers/usb/host/ohci-s3c2410.c

在28行后添加如下代码

#include

#include

unsigned long upllvalue = (0x78<<12)|(0x02<<4)|(0x03); //add

然后修改约48行处的s3c2410_start_hc函数,在函数里面(66行后面)添加

while (upllvalue != __raw_readl(S3C2410_UPLLCON))

{

__raw_writel(upllvalue, S3C2410_UPLLCON);

mdelay(1);

}

19

图2-10-2 修改后的s3c2410_start_hc函数

附录 制作uImage格式镜像

(1) 进入uboot-1.3.2/tools,找到mkimage可执行文件,将其拷贝到linux2.6.24.4目录下。

(2) 制作脚本make_uImage

[root@BC linux-2.6.24.4]# vi make_uImage

[root@BC linux-2.6.24.4]#chmod +x make_uImage

内容如下所示

#! /bin/bash

#make uImage

./mkimage -A arm -T kernel -C none -O linux -a 0x30008000 -e 0x30008040 -d arch/arm/boot/zImage -n

'Linux-2.6.24.4' uImage

cp -arf uImage /mnt/hgfs/linux_lucky/

最后一行表示把uImage拷贝到共享目录linux_lucky(根据自己实际路径设置)供TFTP下载。

//更改权限为可执行

20

2023年8月2日发(作者:)

二 Linux内核移植实验指导书

1 Linux内核移植前准备

对于嵌入式Linux系统来说,有各种体系结构的处理器和硬件平台,并且用户需要根据需求自己定制硬件板。只要是硬件平台发生变化,即使非常小,可能也需要做一些移植工作。内核移植是嵌入式Linux系统中最常见的一项工作。当然,移植嵌入式 Linux系统并不意味着该内核使用了任何特定的链接库或用户工具,建立嵌入式系统并不需要特别的内核。嵌入式系统中使用的内核与工作站或服务器上使用的内核主要的不同在于内核的配置方面。Linux 内核移植是在 Linux原内核基础上,通过对平台的选择设计来实现针对特定系统的内核版本。 Linux内核的移植包含启动代码的修改、内核的链接及装入、参数传递、内核引导几个部分。其基本过程如下:

(1)首先,获取某一版本的Linux内核源码,根据具体目标平台对源码进行必要的改写(主要是修改体系结构相关部分);

(2)然后添加一些外设的驱动(如网卡驱动,USB驱动),打造一款适合于目标平台(可以是嵌入式便携设备也可以是其它体系结构的 PC 机)的新操作系统,也就是常说的内核配置或内核定制;

(3)对该系统进行针对目标平台的交叉编译,生成一个内核映象文件(如 zImage,uImage,bzImage);

(4)最后通过一些手段(如TFTP)把该映象文件烧写到目标平台中。

本实验将对 Linux 内核移植的一些相关概念、知识进行介绍,希望学员可以对 Linux 内核的移植理解得更透彻。

1.1 Linux内核源码

Linux内核移植工作主要是修改跟硬件平台相关的代码,一般不涉及 Linux 内核通用的程序,移植的难度也取决于两种硬件平台的差异。通常对 Linux 源码的改写工作难度较大,它要求你不仅对 Linux内核结构要非常熟悉,还要求你对目标平台的硬件结构非常熟悉。同时还要求你对相关版本的汇编语言较熟悉因为与体系结构相关的部分源码往往是用汇编写

的。

本小节虽然并不对具体的内核代码进行修改, 但是与其相关的一些基础和概念还是有必

要简单介绍一下。

(1)BSP包开发

Linux对于特定的硬件平台的软件就叫作 BSP(Board Support Package)。基于上面描

述的困难,这部分工作一般由目标平台提供商来完成。比如说针对目前嵌入式系统中最流行

的 ARM平台,它的这部分工作就是由英国ARM公司的工程师完成的,我们所要做的就是从其网站上下载相关版本Linux内核的补丁(Patch)。把它打到我们的Linux内核上,再进行后续操作就行。针对某些特定的硬件平台可能并没有平台开发商提供的BSP,这就需要我们自己参考类似的BSP来开发程序。

所幸的是,Linux内核已经支持了各种体系结构的很多种目标板,我们很容易从中找到

跟自己硬件类似的目标板。参考内核已经支持的目标板来移植BSP,就如同使用模板开发程序一样。当然,我们选择的参考板不能仅凭兴趣或爱好来选取,选择参考板也有一定的原

则。具体的原则如下:

■ 参考板与开发板具有相同的处理器,至少类似的处理器;

■ 参考板和开发板具有相同的外围接口电路,至少基本接口相同;

■ Linux内核已经支持参考板,至少有非官方的补丁或者BSP;

■ 参考板Linux设备驱动工作正常,至少已经驱动基本接口。

找到了参考板后,还要仔细分析内核代码以及参考板的BSP,分析平台相关的部分代码实现;分析内核编译组织方式;分析内核启动的初始化程序;分析驱动程序的实现;弄清楚

哪些设备有驱动程序,哪些还没有等等。然后才能开始动手修改内核源代码。

(2)内核源码分析

1 我们需要进行 Linux内核移植,那么首先,我们得下载一个干净的内核源码树,这里实验下载的内核源代码版本为 Linux2.6.24.4。解压后,先来看看Linux内核源代码目录树结构。

(2)内核源码分析

我们需要进行 Linux内核移植,那么首先,我们得下载一个干净的内核源码树,这里本实验下载的内核源代码版本为 Linux2.6.24.4。解压后,先来看看 Linux内核源代码目录树结构。

表1-1 Linux内核子目录结构

目录名

arch

block

crypto

drivers

描述

存放各种与硬件体系结构相关的代码,每种体系结构一个相应的目录,每个目录下都包括了该体系结构相关的代码,包括内存管理,启动代码,浮点数仿真等等。

部分块设备驱动程序。

常用加密和散列算法(如 AES、SHA等) ,还有一些压缩和 CRC 校验算法。

所有的设备驱动程序,里面每一个子目录对应一类驱动程序,比如drivers/block/为块设备驱动程序,drivers/char/为字符设备驱动程序,drivers/mtd/为NOR Flash、NAND Flash等存储设备的驱动程序。

fs

include

提供对各种文件系统的支持。每个子目录对应一种文件系统,比如fs/fat32/

内核头文件,有基本文件(存放在include/linux/目录下)、各种驱动或功能部件的头文件(比如include/media/、include/mtd/、include/net/)、各种体系相关的头文件(比如include/asm-arm/)。当配置内核后,include/asm/是某个include/asm-xxx/(比如include/asm-arm/)的链接。

init

ipc

kernel

lib

mm

net

scripts

sound

usr

内核的初始化代码(不是系统的引导代码),其中的main.c文件中的star_kernel函数是内核引导后运行的第一个函数

进程间通信的代码

内核的最核心部分,包括进程调度、定时器等,和平台相关的一部分代码放在arch/*/kernel

目录下。

各种库文件代码。

内存管理代码,和平台相关的一部分代码放在 arch/*/mm目录下。

网络相关代码,实现了各种常见的网络协议。

用于配置内核文件的脚本文件

音频设备的驱动程序

用户代码

在以上布局中,linux内核主要分为特定于体系结构的部分和与体系结构无关的部分。

在 Linux启动的第一阶段,内核与体系结构相关部分(arch目录下)首先执行,在这部分它要做的工作有:内核解压缩、解压缩内核重定位;内存硬件初始化检测;参数表的分析;初始化页表目录的制作等工作,然后把控制权转给内核中与系统结构无关部分。所以操作系统内核移植中要改动的代码主要集中在与体系结构相关的启动初始化部分。 从上面的目录结构介绍可知,如果要添加新的开发板或者寻找体系结构相关的文件首先就是到 arch 目录下去寻找。在 arch 目录中我们可以看到有许多子目录,它们往往是用芯片命名的,表示是针对该芯片体系结构的代码。为 ARM系列芯片编译内核,就应修改 ARM目录下的相关文件。 Linux 移植过程中内容非常多,涉及的知识量也很大,而且由于平台的不同,和内核版本的不同所涉及的内容往往也有很大不同。所以以上给出内容也仅作为读者参考之用。具体操作时还应收集相关平台及内核版本的详细资料,才能展开相应工作。限于篇幅本实验也无法做更深入的介绍。

1.2 图形化内核配置选项

在 Linux源码的顶层目录运行 make menuconfig,便会出现如下图所示的图形化配置菜单:

2

Documentation

内核文档

图1-1 内核配置选项主菜单

上图显示的是一个主菜单,主菜单中还包含了很多子菜单,通过敲键盘的↑、↓键可以

选择不同的子菜单,再敲回车键,进入这些子菜单,可以看到该子菜单下的一些功能选项,如我们进入

System Type这个子菜单,便可以看到如图 1-2 所示的界面:

图1-2 内核配置选项子菜单

在对各个选项进行配置时,有三种方式,它们分别代表的含义如下:

Y:将该功能编译进内核;

3 N:不将该功能编译进内核;

M:将该功能编译成可以在需要时动态插入到内核中的模块 。

至于某个选项具体配置成哪一种方式,可以通过空格键进行选取。所有选项前都有一个

括号,有的是中括号,有的是尖括号,还有圆括号。用空格键选择时可以发现,中括号里要么是空,要么是"*",而尖括号里可以是空,"*"和"M"这表示前者对应的项要么不要,要么编译到内核里;后者则多一样选择,可以编译成模块。而圆括号的内容是要你在所提供的几个选项中选择一项。

内核配置好后,读者可以通过 Esc 键或是 Exit 选项离开内核配置菜单。内核配置系统

将会提示是否要储存新的配置。选择Yes,离开内核配置系统的时候,会将新的配置储存到

新的.config文件。这除了会建立.config文件,也会建立一些的头文件和符号链接。选择 No,

离开内核配置系统的时候,并不会储存任何变更。除了主要的配置选项,内核所支持的架构通常会包含特定开发板的标准样版配置。比如ARM开发板,以 s3c2410为例,在 arch/arm/configs目录下便有一个s3c2410_defconfig的配置文件,运行 make s3c2410_defconfig命令,内核配置系统将自动调用该配置文件,并且将该文件中各选项的配置存储到.config文件中去,下次执行 make menuconfig时就会载入这些配置。

2 Linux内核移植

2.1 获取linux源码

linux-2.6.24.4的内核源码可以从上下载。

将2拷贝到/gdut2410/kernel/目录下,解压,就可以得到完整的Linux内核源码包:

进入/gdut2410/kernel目录下

[root@BC /]# cd /gdut2410/kernel

2.2 解压内核源代码

解压内核

[root@BC kernel]# tar -jxvf 2

进入内核目录

[root@BC kernel]# cd linux-2.6.24.4

2.3 指定交叉编译器

修改顶层目录的 Makefile,执行命令:

[root@BC linux-2.6.24.4]# vi Makefile

找到193行设置下面两行:

ARCH := arm

CROSS_COMPILE := /gcc-3.4.6-glibc-2.3.6/arm-linux/bin/arm-linux-

这两行表示接下来将对嵌入式 ARM系统上使用的 Linux内核进行交叉编译。

2.4 移植 Nand 驱动并更改分区信息

设置Nand Flash的分区信息表是为内核启动以后加载文件系统用的,可以将Nand Flash看成我们PC机的硬盘,对 Nand Flash的分区看成是对硬盘的分区,硬盘可以分成C盘,D盘之类,而 Nand Flash则可以分成很多块,每块有不同的名字、大小和用途。下面是对Super-ARM实验箱的Nand Flash进行分区的情况:

■ 第 0 块命名为"uboot",它用来存放 映像,起始地址是 Nand Flash 的0x000000,最大0x80000 个字节;

■ 第 1 块命名为"kernel",用来存放内核,起始地址是 Nand Flash 的 0x80000,最大0x200000 个字节;

■ 第2 块命名为"rootfs",用来存放根文件系统,起始地址是 Nand Flash的 0x280000,最大 60M字节;

至于具体要怎么分,这样根据你的目标机的Nand Flash来定,不能一概而论。分区的方法就是修改

arch/arm/plat-s3c24xx目录下的 common-smdk.c文件:

执行命令

4 [root@BC linux-2.6.24.4]# vi arch/arm/plat-s3c24xx/common-smdk.c

在第109行找到:static struct mtd_partition smdk_default_nand_part[],在其中填入下面的内容(将原来的内容覆盖),如代码清单 2-1-1所示:

代码清单 2-3-1 NandFlash分区信息

static struct mtd_partition smdk_default_nand_part[] = {

[0] = {

.name = "u-boot",

.size = 0x80000,

.offset = 0,

},

[1] = {

.name = "kernel",

.offset = 0x80000,

.size = 0x200000,

},

[2] = {

.name = "rootfs",

.offset = SZ_2M + 0x80000,

.size = SZ_2M*30,

},

};

2.5 添加 devfs 文件系统支持

为了我们的内核支持devfs,以及在启动时能自动挂载/dev。编辑 fs/Kconfig:

[root@BC linux-2.6.24.4]# vi fs/Kconfig

在907 行menu "Pseudo filesystems"下面添加如下代码:

config DEVFS_FS

bool "/dev file system support (OBSOLETE)"

default y

config DEVFS_MOUNT

bool "Automatically mount at boot"

default y

depends on DEVFS_FS

2.6 关于内核配置菜单中选项

首先拷贝smk2410开发板配置文件到linux-2.6.24.4

[root@BC linux-2.6.24.4]# cp -a arch/arm/configs/s3c2410_defconfig ./

执行 make s3c2410_defconfig 命令,获取 s3c2410_defconfig文件中给定的配置。

[root@BC linux-2.6.24.4]# make s3c2410_defconfig

然后执行make menuconfig命令,出现内核的配置界面:

[root@BC linux-2.6.24.4]# make menuconfig

5

图2-6-1 内核配置界面

在smdk2410_defconfig基础上,增删以下内核配置项:在配置菜单中,选择system

type-->s3c2410 machines中的smdk2410,其他的arch-machines全部取消。

图2-6-2 内核配置选项(1)

6

图2-6-3 内核配置选项(2)

至于所有其他的选项都默认 s3c2410_defconfig 给定的配置,这里暂时不做修改。在后续实验中,需要添加相应的功能时再对相关选项重新进行配置。 重新保存为.config并退出。

图2-6-4 保存内核配置选项(1)

7

图2-6-5 保存内核配置选项(2)

2.7 移植 LCD显示驱动

(1)进入内核顶层目录,修改arch/arm/mach-s3c2410/mach-smdk2410.c文件

[root@BC linux-2.6.24.4]# vi arch/arm/mach-s3c2410/mach-smdk2410.c

▶第一处:在56行后添加下面的头文件

#include

▶第二处:在92行后添加 s3c2410fb_display 结构

static struct s3c2410fb_display s3c2410_lcd_cfg __initdata = {

.lcdcon5 = S3C2410_LCDCON5_FRM565 |

S3C2410_LCDCON5_INVVLINE |

S3C2410_LCDCON5_INVVFRAME |

S3C2410_LCDCON5_PWREN |

S3C2410_LCDCON5_HWSWP,

.type = S3C2410_LCDCON1_TFT,

.width = 240,

.height = 320,

.pixclock = 98619, // 10.1

.xres = 240,

.yres = 320,

.bpp = 16,

.left_margin =16,

.right_margin = 7,

.hsync_len = 14,

.upper_margin = 2,

.lower_margin = 3,

.vsync_len = 2,

};

xres = LINEVAL + 1

yres = HOZVAL + 1

pixclock = (1/hclk) ×1012 其中Super-ARM的hclk 是10.14Mhz

left_margin = HFPD + 1

8 right_margin = HBPD + 1

hsync_len = HSPW+1

upper_margin = VBPD +1

lower_margin = VFPD+1

vsync_len = VSPW+1

▶ 第三处:113行后添加 s3c2410fb_mach_info 结构

static struct s3c2410fb_mach_info s3c2410_fb_info __initdata = {

.displays = &s3c2410_lcd_cfg,

.num_displays = 1,

.default_display = 0,

.gpccon = 0xaaa556a9,

.gpccon_mask = 0xfff003fc,

.gpcup= 0x0000ffff,

.gpcup_mask= 0xffffffff,

.gpdcon = 0xaa95aaa5,

.gpdcon_mask = 0xffc0fff0,

.gpdup = 0x0000ffff,

.gpdup_mask = 0xffffffff,

.lpcsel = 0x4,

};

▶ 第四处:在函数 smdk2410_init()中加入下面一行

s3c24xx_fb_set_platdata(&s3c2410_fb_info);

我跟大家分析一下添加这些代码的具体作用。首先看 smdk2410_fb_info(第三处),它是

s3c2410fb_mach_info 类型的结构体,这个结构体有一个 displays 的成员变量,它指向s3c2410fb_display

类型的指针。之前说过,一个系统有多少个显示设备就对应多少个s3c2410fb_display 的结构,Super-ARM

只有一个 LCD 显示设备,所以就只定义了一个

s3c2410fb_display结构体 smdk2410_lcd_cfg(第二处) ,那么 displays就指向这个结构体,同时将

num_displays 赋值 1。最后通过 s3c24xx_fb_set_platdata 函数将smdk2410_fb_info 传递给底层 LCD 驱动。

把所给的s3c2410fb.c s3c2410fb.h放在/gdut2410/kernel/linux-2.6.24.4/drivers/video/下。

(2)重新配置内核:执行 make menuconfig,添加下面两项配置

▶ 第一项:添加 S3C2410 LCD 驱动支持

进入 Device drivers-->Graghics support-->Support for frame buffer devices , 出现下面的界面,选中

S3C2410 LCD framebuffer support和S3C2410 lcd debug messages 两个选项。

9

图2-7-1 配置LCD选项(1)

图2-7-2 配置LCD选项(2)

▶第二项:Bootup logo

10

图2-7-3 配置Bootup logo选项

配置 Bootup logo是为了在内核加载完 LCD 驱动后在 LCD 屏上看到一个小企鹅。

进入 Device drivers-->Graghics support-->Bootup logo, 出现下面的界面, 三个不同的 logo选项对应不同的小企鹅图片,可以到内核的 drivers/video/logo目录下找到对应的图片,读者可以根据自己的喜好随便选择一个。

(3)编译内核,并将重新编译生成的 zImage文件复制到 tftp 根目录下

[root@BC linux-2.6.24.4]# make

(4)启动Super-ARM,加载内核和文件系统,看看LCD 屏上是不是出现了小企鹅

2.8 移植触摸屏驱动

以下操作都在内核主目录下进行。

(1)修改drivers/input/touchscreen/Makefile文件:

[root@BC linux-2.6.24.4]# vi drivers/input/touchscreen/Makefile

在文件中添加:

obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o

图2-8-1 修改触摸屏Makefile

11 (2)修改drivers/input/touchscreen/Kconfig文件:

[root@BC linux-2.6.24.4]# vi drivers/input/touchscreen/Kconfig

在文件中136行后添加:

config TOUCHSCREEN_S3C2410

tristate "S3C2410 Touchscreen"

depends on ARCH_SMDK2410 && INPUT && INPUT_TOUCHSCREEN

(3)重新配置内核:

[root@BC linux-2.6.24.4]# make menuconfig

进入Device drivers-->Input device support-->,出现下面的界面,将Horzontal设置为240,Vertical 设置为320,选中<*>Event interface、<*>Event debugging和 [*] Touchscreens选项。进入[*] Touchscreens选项以后,选中我们在Kconfig文件中设置的<*> Samsung S3C2410 touchscreen input driver 和 [*]Samsung

S3C2410 touchscreen debug messages。

图2-8-2 配置触摸屏(1)

12

图2-8-3 配置触摸屏(2)

(4)修改arch/arm/mach-s3c2410/mach-smdk2410.c文件

[root@BC linux-2.6.24.4]# vi arch/arm/mach-s3c2410/mach-smdk2410.c

▶ 第一处:在 map_desc smdk2410_iodesc结构前面添加 s3c2410_ts_mach_info结构:

static struct s3c2410_ts_mach_info s3c2410_ts_cfg __initdata = {

.delay = 10000, // delay 是AD 转换的延时时间

//.delay = 200000,

.presc = 49, // presc将被写入ADCCON 的PRESVL字段,用来配置AD 转换速率

.oversampling_shift = 2, //一次触摸动作需要进行4(1<<2)次AD 转换后取平均值作为最后的坐标值

};

s3c2410_ts_mach_info 结构中的 delay 是 AD 转换的延时时间,在触摸屏驱动中将被写入 ADCDLY

寄存器中, presc将被写入 ADCCON 的 PRESVL字段, 用来配置AD 转换速率。oversampling_shift将传给 s3c2410_ts的 shift 成员,该值为2,说明一次触摸动作需要进行4(1<<2)次 AD 转换后取平均值作为最后的坐标值。

▶ 第二处:在 static struct platform_device *smdk2410_devices[] __initdata = {中添加:

&s3c_device_ts,

▶ 第三处: 在 static void __init smdk2410_map_io(void)函数中添加:

set_s3c2410ts_info(&s3c2410_ts_cfg);

▶ 第四处:在53行后添加头文件

#include

(5)添加s3c2410_ts.h:

[root@BC linux-2.6.24.4]# vi include/asm-arm/arch-s3c2410/s3c2410_ts.h

在空白的s3c2410_ts.h添加如下代码

#ifndef __ASM_ARM_S3C2440_TS_H

13 #define __ASM_ARM_S3C2440_TS_H

struct s3c2410_ts_mach_info {

int delay; // delay 是AD 转换的延时时间

int presc;// ,presc将被写入ADCCON 的PRESVL字段,用来配置AD 转换速率

int oversampling_shift;

//一次触摸动作需要进行4(1<<2)次AD 转换后取平均值作为最后的坐标值

};

void __init set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info);

#endif /* __ASM_ARM_S3C2440_TS_H */

(6)修改regs-adc.h添加宏定义

[root@BC linux-2.6.24.4]# vi include/asm-arm/plat-s3c/regs-adc.h

在44行后添加以下宏定义

//add by mh

/* For touchscreen */

#define S3C2410_ADCTSC_XY_PST_N (0x0<<0)

#define S3C2410_ADCTSC_XY_PST_X (0x1<<0)

#define S3C2410_ADCTSC_XY_PST_Y (0x2<<0)

#define S3C2410_ADCTSC_XY_PST_W (0x3<<0)

//add end

//对触摸屏控制寄存器 的状态选择位 宏定义

(7)修改include/asm-arm/plat-s3c24xx/devs.h文件:

[root@BC linux-2.6.24.4]# vi include/asm-arm/plat-s3c24xx/devs.h

在#include 文件32行后添加下面的内容:

extern struct platform_device s3c_device_ts;

图2-8-4 添加s3c_device_ts

(8)修改arch/arm/plat-s3c24xx/devs.c文件:

[root@BC linux-2.6.24.4]# vi arch/arm/plat-s3c24xx/devs.c

▶ 第一处:在37行后添加新增加的头文件

#include

▶ 第二处:在约191行后(即 /* NAND Controller */前)添加如下代码

/* Touchscreen */

static struct s3c2410_ts_mach_info s3c2410ts_info;

void __init set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info){

memcpy(&s3c2410ts_info, hard_s3c2410ts_info, sizeof(struct s3c2410_ts_mach_info));

}

14

EXPORT_SYMBOL(set_s3c2410ts_info);

struct platform_device s3c_device_ts = {

.name = "s3c2410-ts",

.id = -1,

.dev = {

.platform_data = &s3c2410ts_info,

}

};定义一个平台设备

EXPORT_SYMBOL(s3c_device_ts);

(9)添加drivers/input/touchscreen/s3c2410_ts.c 文件

该文件是开源的,可以直接从网上下载(需做适当修改),本实验提供已修改过的s3c2410_ts.c。

(10)编译内核,并将重新编译生成的 zImage文件复制到 tftp 根目录下

[root@BC linux-2.6.24.4]# make

(11)启动 Super-ARM,加载内核和文件系统。

在内核启动信息中可以看到

“input: s3c2410 Touchscreen as /class/input/input0 ” 。

2.9 移植网卡驱动

2.9.1 移植CS8900网卡驱动

CS8900 芯片是 Cirrus Logic 公司生产的一种局域网处理芯片,在嵌入式领域中使

用非常常见。它的封装是 100-pin TQFP,内部集成了在片 RAM、10BASE-T 收发滤波器,并且提供 8 位和 16 位两种接口。在本实验介绍的开发板中采用的就是 CS8900芯片。下面介绍移植网卡驱动的实验过程。(以下操作在/gdut2410/kernel/linux-2.6.24 目录下进行)

(1)修改Makefile

[root@BC linux-2.6.24.4]# vi drivers/net/arm/Makefile

在文件末尾添加一行:

obj-$(CONFIG_ARM_CS8900) += cs8900.o

(2)修改Kconfig文件

[root@BC linux-2.6.24.4]# vi drivers/net/arm/Kconfig

在文件末尾添加下面这一段:

config ARM_CS8900

tristate "CS8900 support"

depends on NET_ETHERNET && ARM && ARCH_SMDK2410

help

support for cs8900 chipset based Ethernet cards , if you have a network card of this type

(3)修改mach-smdk2410.c文件

[root@BC linux-2.6.24.4]# vi arch/arm/mach-s3c2410/mach-smdk2410.c

在60行处static struct map_desc smdk2410_iodesc[] __initdata里面添加如下内容(如图所示):

vSMDK2410_ETH_IO,

pSMDK2410_ETH_IO,

SZ_1M,

MT_DEVICE

15

图2-9-1 添加s3c_device_ts

并将下一步骤中创建的头文件添加进来,在54行后添加:

#include

(4)创建smdk2410.h文件

[root@BC linux-2.6.24.4]# vi include/asm-arm/arch-s3c2410/smdk2410.h

在文件中添加如下内容:

#ifndef __ASM_ARCH_SMDK2410_H

#define __ASM_ARCH_SMDK2410_H

#define pSMDK2410_ETH_IO __phys_to_pfn(0x19000000)

#define vSMDK2410_ETH_IO 0xE0000000

#define SMDK2410_ETH_IRQ IRQ_EINT9

#define __IRQT_FALEDGE IRQ_TYPE_EDGE_FALLING

#define __IRQT_RISEDGE IRQ_TYPE_EDGE_RISING

#define __IRQT_LOWLVL IRQ_TYPE_LEVEL_LOW

#define __IRQT_HIGHLVL IRQ_TYPE_LEVEL_HIGH

#define IRQT_NOEDGE (0)

#define IRQT_RISING (__IRQT_RISEDGE)

#define IRQT_FALLING (__IRQT_FALEDGE)

#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE)

#define IRQT_LOW (__IRQT_LOWLVL)

#define IRQT_HIGH (__IRQT_HIGHLVL)

#define IRQT_PROBE IRQ_TYPE_PROBE

#endif

(5)复制 cs8900.h 和 cs8900.c 两个文件到/drivers/net/arm 目录下,网上可以下载这两个文件,但是需要做些修改才能为 Super-ARM 所用。

(6)配置内核

[root@BC linux-2.6.24.4]# make menuconfig

增加对cs8900 的支持: Device drivers ----> Network device support ---> Ethernet (10 or 100 Mbit)----->

<*> CS8900 Support 。配置界面如下图所示:

16

图2-9-2 配置网卡(1)

图2-9-3 配置网卡(2)

2.9.2 添加对 NFS 文件系统的支持

第一项:Networking--->Networking options --->

该选项配置网络环境,选中 IP: kernel level autoconfiguration、TCP/IP networking IP:RARP support 三项界面如图 2-9-4 所示:

17

图2-9-4 配置支持NFS文件系统(1)

第二项:File system ---> Network File System --->

该选项配置内核的文件系统,选中 NFS file system support、Provide NFSv3 client support和 Root file

system on NFS三项,使其支持网络文件系统,界面如下图所示:

图2-9-5 配置支持NFS文件系统(2)

2.10 配置USB 键盘、扫描器和鼠标

(1) 在内核源代码目录的终端输入:make menuconfig,依次选择如下子菜单项:

18 Device Drivers --->

[*] HID Devices --->

出现如图内核配置菜单:

图2-10-1 配置支持USB键盘和鼠标

按空格键选中“USB Human Interface Device (full HID) support” ,这样就配置好了USB键盘和鼠标项。

提示:这里的配置选项对应的内核源代码目录是:linux-2.6.24.4/drivers/hid/usbhid,其中USB键盘和条码扫描器的原理是一样的,因此它们的代码是相同的。

(2) 修改ohci-s3c2410.c

[root@BC linux-2.6.24.4]# vi drivers/usb/host/ohci-s3c2410.c

在28行后添加如下代码

#include

#include

unsigned long upllvalue = (0x78<<12)|(0x02<<4)|(0x03); //add

然后修改约48行处的s3c2410_start_hc函数,在函数里面(66行后面)添加

while (upllvalue != __raw_readl(S3C2410_UPLLCON))

{

__raw_writel(upllvalue, S3C2410_UPLLCON);

mdelay(1);

}

19

图2-10-2 修改后的s3c2410_start_hc函数

附录 制作uImage格式镜像

(1) 进入uboot-1.3.2/tools,找到mkimage可执行文件,将其拷贝到linux2.6.24.4目录下。

(2) 制作脚本make_uImage

[root@BC linux-2.6.24.4]# vi make_uImage

[root@BC linux-2.6.24.4]#chmod +x make_uImage

内容如下所示

#! /bin/bash

#make uImage

./mkimage -A arm -T kernel -C none -O linux -a 0x30008000 -e 0x30008040 -d arch/arm/boot/zImage -n

'Linux-2.6.24.4' uImage

cp -arf uImage /mnt/hgfs/linux_lucky/

最后一行表示把uImage拷贝到共享目录linux_lucky(根据自己实际路径设置)供TFTP下载。

//更改权限为可执行

20