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

mini2440驱动移植


Linux-2.6.32.2 内核在 mini2440 上的移植(一)---构建自主开发环境
2011-05-26 20:18:34| 分类: Linux 内核移植 | 标签: |字号大中小 订阅 移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 1,主机环境:VMare 下 CentOS 5.5 ,1G 内存。 2,集成开发环境:Elipse IDE 3

,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。 4,开发板:mini2440,2M nor flash,128M nand flash。 5,u-boot 版本:u-boot-2009.08 6,linux 版本:linux-2.6.32.2 7,参考文章: 【1】嵌入式 linux 应用开发完全手册,韦东山,编著。 【2】http://blogold.chinaunix.net/u3/101649/showart_2276906.html 【3】Mini2440 之 Linux 移植开发实战指南 1.1,构建自主开发环境 我们在进行 u-boot 移植时,在 u-boot-2009.08 在 mini2440 上的移植(六)---增加引导内核功能提到过机 器码(MACH_TYPE),在引导测试时,为了便于测试,使用的是友善官方移植好的 linux 内核。现在我们将 从这里着手,逐步开始 linux 内核的移植。 【1】下载并解压内核源码 在命令行终端中可以通过下列方式下载,当然用其它下载工具下载 [root@localhost ~]# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.2.tar.gz 然后解压: [root@localhost ~]# cd ./linux-test/ [root@localhost linux-test]# tar -zxf ../linux-2.6.32.2.tar.gz [root@localhost linux-test]# ls linux-2.6.32.2 linux-2.6.39 yaffs2 yaffs2.tar.gz [root@localhost linux-test]# cd linux-2.6.32.2 [root@localhost linux-2.6.32.2]# 【2】指定交叉编译变量 我们移植目的是让 Linux-2.6.32.2 可以在 mini2440 上运行。首先,我们要使得 Linux-2.6.32.2 的缺省目 标平台成为 ARM 的平台,修改总目录下的 Makefile。 用 gedit 打开/Makefile,定位到 183 行,修改如下:

1

# Alternatively CROSS_COMPILE can be set in the environment. # Default value for CROSS_COMPILE is not to prefix executables # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile export KBUILD_BUILDHOST := $(SUBARCH) ARCH ?= arm CROSS_COMPILE ?= arm-linux# Architecture as present in compile.h 其中,ARCH 是指定目标平台为 arm,CROSS_COMPILE 是指定交叉编译器,这里指定的是系统默认的 交叉编译器,如要使用其它的,则要把编译器的全路径在这里写出。注意,在 arm 和 arm-linux-后不要留 空格,否则在编译时会出现错误。 接下来,要测试一下 linux 的编译是否能正常通过。执行: [root@localhost linux-2.6.32.2]# make s3c2410_defconfig 使用缺省内核配置文件,s3c2410_defconfig 是 SMDK2440 的缺省配置文件 [root@localhost linux-2.6.32.2]# make 编译时间较长... ... 。编译通过,在此我们先不必烧写到开发板验证它的正确性。 【3】建立自己的目标平台 (1)关于机器码 以上编译是用的 Linux 内核本身支持的目标平台配置 它对应于 SMDK2440 现在我们要参考 SMDK2440 , 。 加入自已的开发板平台,我们使用的是 mini2440,因此取名为 MINI2440。需要说明的是,Linux-2.6.32.2 本身已经包含了 mini2440 的支持,这样就出现了重名。那怎么办呢?在此我们依然使用 MINI2440 这个 名称,只不过在后面的移植步骤中,把原始内核自带的 mini2440 代码部分直接删除就可以了,以免和我 们自己移植的混淆。 首先,很关键的一点,内核在启动时,是通过 bootloader 传入的机器码(MACH_TYPE)确定应启动哪种目 标 平 台 的 , 友 善 之 臂 已 经 为 mini2440 申 请 了 自 己 的 机 器 码 为 1999 , 它 位 于 linux-2.6.32.2/arch/arm/tools/mach_types 文件中,如下面所示: 打开/arch/arm/tools/mach-types,定位到 1989 行,可以看到文件中有相应的机器码的定义定义如下(黑体 部分): exeda MACH_EXEDA EXEDA 1994 mx31sf005 MACH_MX31SF005 MX31SF005 1995 f5d8231_4_v2 MACH_F5D8231_4_V2 F5D8231_4_V2 1996 q2440 MACH_Q2440 Q2440 1997 qq2440 MACH_QQ2440 QQ2440 1998 mini2440 MACH_MINI2440 MINI2440 1999 colibri300 MACH_COLIBRI300 COLIBRI300 2000 jades MACH_JADES JADES 2001 spark MACH_SPARK SPARK 2002 benzina MACH_BENZINA BENZINA 2003 在 U-boot/include/asm-arm/mach-types.h 文件的 1985 行附近(u-boot-2009.08),可以看到 mini2440 的 机器码定义如下面所示:

2

#define MACH_TYPE_Q2440 1997 #define MACH_TYPE_QQ2440 1998 #define MACH_TYPE_MINI2440 1999 //mini2440 的机器码 #define MACH_TYPE_COLIBRI300 2000 #define MACH_TYPE_JADES 2001 这需要两者相匹配,如果内核的机器码和 bootloader 传入的不匹配,就会经常出现下面的错误: Uncompressing Linux................................................................................................................................. done, booting the kernel. 运行到这不就停住了。 接下来, 我们注意到 linux-2.6.32.2/arch/arm/mach-s3c2440 目录下有个 mach-mini2440.c 文件,它其 实 就 是 国 外 爱 好 者 为 mini2440 移 植 添 加 的 主 要 内 容 了 , 但 我 们 不 用 它 , 把 它 直 接 删 除 。 将 linux-2.6.32.2/arch/arm/mach-s3c2440/ 目 录 下 的 mach-mini2440.c ,并打开文件定位到末尾处,找到 MACHINE_START(S3C2440, "SMDK2440") , 将其修改为 MACHINE_START(MINI2440, "Mini2440 development board") 提示:开发板运行后,在命令行终端输入:cat /proc/cpuinfo 可以看到我们添加的开发板信息,当然这个 信息可以定制成我们需要的信息。 (2)修改时钟源频率 在上面我们刚刚复制并修改过的 mach-mini2440.c 文件中,定位到 163 行附近,把其中的 16934400(代表 原 SMDK2440 目标板的晶振是 16.9344MHz) 改为 mini2440 开发板上实际使用的 12000000(代表 mini2440 开发板上的晶振 12MHz,元器件标号为 X2),如下所示: static void __init smdk2440_map_io(void) { s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc)); s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs)); } (3)从 SMDK2440 到 MINI2440 因为我们要制作自己的 mini2440 平台体系,因此把 mach-mini2440.c 中所有的 smdk2440 字样改为 mini2440,可以使用批处理命令修改,在 vim 的命令模式下输入: %s/smdk2440/mini2440/g 上面这句的意思是:把所有和―smdk2440‖匹配的字符串全部替换为―mini2440‖,前面的―%s―代表字符串匹 配,最后的―g‖代表 global,是全局的意思,不过这里采用另一种办法,在 gedit 里用查找替换,比较方便, 操作如下: gedit->搜索->替换,在打开的对话框中,在搜索一栏输入―smdk2440‖,在替换为一栏输入―mini2440‖然后 点击全部替换按钮,即可完成。 mach-smdk2440.c 复 制 一 份 。 命 名 为

3

除此之外,还有一个地方需要改动,在 mini2440_machine_init(void)函数中,把 smdk_machine_init()函数 调用注释掉,因为我们后面会编写自己的初始化函数,不需要调用 smdk2440 原来的,定位到 173 行,修 改如下: static void __init mini2440_machine_init(void) { s3c24xx_fb_set_platdata(&mini2440_fb_info); s3c_i2c0_set_platdata(NULL); platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices)); //smdk_machine_init(); } (4)编译测试 在 Linux 源代码根目录下执行 [root@localhost linux-2.6.32.2]# make mini2440_defconfig # # configuration written to .config # [root@localhost linux-2.6.32.2]# make mini2440_defconfig 使用 Linux 官方自带的 mini2440 配置。 [root@localhost linux-2.6.32.2]# make uImage 编译内核,时间较长,最后会生成 uImage。把生成的内核文件 uImage(位于 arch/arm/boot 目录)下载到 板子的内存中运行,可以看到内核已经可以正常启动了,如下所示,但此时大部分硬件驱动还没加,并且 也没有文件系统,因此还无法登陆。 [u-boot@MINI2440]# usbslave USB host is connected. Waiting a download. Now, Downloading [ADDRESS:31000000h,TOTAL:2067310] RECEIVED FILE SIZE: 2067310 (672KB/S, 3S) [u-boot@MINI2440]# go 0x31000000 ## Starting application at 0x31000000 ... Uncompressing Linux............................................................. ................................................................... done, bootin g the kernel. Linux version 2.6.32.2 (root@localhost.localdomain) (gcc version 4.4.3 (ctng-1.6 .1) ) #4 Thu May 26 18:51:55 CST 2011 CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=00007177 CPU: VIVT data cache, VIVT instruction cache Machine: mini2440 devolopment board Memory policy: ECC disabled, Data cache writeback CPU S3C2440A (id 0x32440001) S3C24XX Clocks, (c) 2004 Simtec Electronics S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz

4

CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256 Kernel command line: noinitrd console=ttySAC0,115200 init=/linuxrc mem=64M root =/dev/nfs rw nfsroot=10.1.0.128:/nfsboot ip=10.1.0.129:10.1.128:10.1.0.1:255.25 5.255.0::eth0:off ... ... 【4】内核配置菜单中的 mini2440 选项和实际代码是如何关联的 在开始移植其他驱动之前,我们再了解一些看起来比较―神秘‖的常识,那就是运行 make menuconfig 时, 内核配置菜单中的 mini2440 选项是如何出现的。需要确保前面已经执行了 make mini2440_defconfig 加 载了缺省配置,因为在 x86 平台下下执行此操作,系统默认的是 x86 平台,而且还要在顶层 Makefile 里作 了如下修改: export KBUILD_BUILDHOST := $(SUBARCH) ARCH ?= arm CROSS_COMPILE ?= arm-linux现在在终端中进入到 linux-2.6.32.2 根目录下执行: [root@localhost linux-2.6.32.2]# make menuconfig 出现下图所示内核配置根菜单

按上下箭头键移动到 System Type,按回车进入该子菜单,如图

再找到 S3C2440 Machines,按回车进入该子菜单,如图

5

在此就可以看到 Linux 天生内核对 mini2440 开发板的支持选项了,那么它们是从哪里来的呢? 打开 Linux-2.6.32.2/arch/arm/mach-s3c2440/Kconfig 文件定位到 99 行附近,可以找到如下信息(黑体部 分): config MACH_AT2440EVB bool "Avantech AT2440EVB development board" select CPU_S3C2440 select S3C_DEV_USB_HOST select S3C_DEV_NAND help Say Y here if you are using the AT2440EVB development board config MACH_MINI2440 bool "MINI2440 development board" select CPU_S3C2440 select EEPROM_AT24 select LEDS_TRIGGER_BACKLIGHT select SND_S3C24XX_SOC_S3C24XX_UDA134X select S3C_DEV_NAND select S3C_DEV_USB_HOST help Say Y here to select support for the MINI2440. Is a 10cm x 10cm board available via various sources. It can come with a 3.5" or 7" touch LCD. endmenu 现在明白了吧,―MINI2440 development board‖正是在这个 Kconfig 文件中定义说明的,当然你可以根据 自己的喜好改为其他显示信息。这里的显示信息只是在内核配置菜单中出现的,要让选择的配置实际起效, 还需要根据此配置在 Makefile 中添加相应的代码文件,请看该目录下的 Makefile,定位到 25 行,如下所 示: # Machine support obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o

6

obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o 这样,配置文件就跟实际的代码文件通过配置定义联系在一起了,这里的配置定义是 ―CONFIG_MACH_MINI2440‖,内核中还有很多类似的配置定义,并且有的配置定义还存在依赖关系,我 们在此就不对它们详细说明了,随着对内核代码结构的不断熟悉,你就会逐渐学会分析和查找你所需要的 各种配置和定义等。 【5】移植 Nand 驱动并更改分区信息 (1)Linux-2.6.32.2 内核所支持的 Nand Flash 类型 Linux2.6.32.2 已经自带了大部分 Nand Flash 驱动,在 linux-2.6.32.2/drivers/mtd/nand/nand_ids.c 文件 中,定义了所支持的各种 Nand Flash 类型,定位到 84 行附近,如下所示 #define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY |

NAND_NO_AUTOINCR) #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16) /*512 Megabit */ {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16}, {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16}, /* 1 Gigabit */ {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS}, {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, LP_OPTIONS}, {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16}, {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16}, /* 2 Gigabit */ {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, LP_OPTIONS}, {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, LP_OPTIONS}, {"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, LP_OPTIONS16}, {"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, LP_OPTIONS16}, /* 4 Gigabit */ {"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, LP_OPTIONS}, {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, LP_OPTIONS}, {"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, LP_OPTIONS16}, {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, LP_OPTIONS16}, /* 8 Gigabit */ {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, LP_OPTIONS}, {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, LP_OPTIONS},

7

{"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, LP_OPTIONS16}, {"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, LP_OPTIONS16}, /* 16 Gigabit */ {"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, LP_OPTIONS}, {"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, LP_OPTIONS}, {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16}, {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, /* * Renesas AND 1 Gigabit. Those chips do not support extended id and * have a strange page/block layout ! The chosen minimum erasesize is * 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page * planes 1 block = 2 pages, but due to plane arrangement the blocks * 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 Anyway JFFS2 would * increase the eraseblock size so we chose a combined one which can be * erased in one go There are more speed improvements for reads and * writes possible, but not implemented now */ {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH }, {NULL,} }; /* * Manufacturer ID list */ struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_TOSHIBA, "Toshiba"}, {NAND_MFR_SAMSUNG, "Samsung"}, {NAND_MFR_FUJITSU, "Fujitsu"}, {NAND_MFR_NATIONAL, "National"}, {NAND_MFR_RENESAS, "Renesas"}, {NAND_MFR_STMICRO, "ST Micro"}, {NAND_MFR_HYNIX, "Hynix"}, {NAND_MFR_MICRON, "Micron"}, {NAND_MFR_AMD, "AMD"}, {0x0, "Unknown"} }; (2)修改 Nand Flash 分区表 系统默认的分区不一定是我们所需的,所以要自已修改,除此之外,还有 Nand Flash 的结构信息需要增 加填写,以便能够适合系统自带的 Nand Flash 驱动接口,这可以参考 SMDK2440 中关于 Nand Flash 设

8

备注册的一些信息。 打开/arch/arm/plat-s3c24xx/common-smdk.c,定位到 110 行附近,可以看到这样一个结构体: static struct mtd_partition smdk_default_nand_part[] = { [0] = { .name = "Boot Agent", .size = SZ_16K, .offset = 0, }, [1] = { .name = "S3C2410 flash partition 1", .offset = 0, .size = SZ_2M, }, [2] = { .name = "S3C2410 flash partition 2", .offset = SZ_4M, .size = SZ_4M, }, [3] = { .name = "S3C2410 flash partition 3", .offset = SZ_8M, .size = SZ_2M, }, [4] = { .name = "S3C2410 flash partition 4", .offset = SZ_1M * 10, .size = SZ_4M, }, [5] = { .name = "S3C2410 flash partition 5", .offset = SZ_1M * 14, .size = SZ_1M * 10, }, [6] = { .name = "S3C2410 flash partition 6", .offset = SZ_1M * 24, .size = SZ_1M * 24, }, [7] = { .name = "S3C2410 flash partition 7", .offset = SZ_1M * 48, .size = SZ_16M, } }; 9

这其实就是 Nand Flash 的分区表,在 Linux-2.6.32.2 中,nand 驱动是被注册为平台设备的,这同样可 在这个文件的 166 行看到如下信息: static struct s3c2410_platform_nand smdk_nand_info = { .tacls = 20, .twrph0 = 60, .twrph1 = 20, .nr_sets = ARRAY_SIZE(smdk_nand_sets), .sets = smdk_nand_sets, }; 参考以上结构信息,我们也在自己的 mach-mini2440.c 中照此添加实现,同时需要参考友善之臂原厂内核 中的 Nand 分区表,操作如: 打开/arch/arm/mach-s3c2440/mach-mini2440.c,定位到 151 行处,将下面更改后的分区表定义结构加入 其中:

.lpcsel = ((0xCE6) & ~7) | 1<<4, }; /* NAND parititon from 2.4.18-swl5 */ static struct mtd_partition mini2440_default_nand_part[] = { [0] = { .name = "boot", //; 这 里 是 bootloader 所 在 的 分 区 , 可 以 放 置 u-boot, supervivi 等 内 容 , 对 应 /dev/mtdblock0 .offset = 0, .size = 0x00040000, //256K }, [1] = { .name = "param", //;这里是 supervivi 的参数区,其实也属于 bootloader 的一部分,如果 u-boot 比较 大,可以把此区域覆盖掉,不会影响系统启动,对应/dev/mtdblock1 .offset = 0x00040000, .size = 0x00020000, }, [2] = { .name = "kernel", //;内核所在的分区,大小为 5M,足够放下大部分自己定制的巨型内核了,比如内核使 用了更大的 Linux Logo 图片等,对应/dev/mtdblock2 .offset = 0x00060000, .size = 0x00500000, }, [3] = { .name = "rootfs", //;文件系统分区,友善之臂主要用来存放 yaffs2 文件系统内容,对应/dev/mtdblock3 .offset = 0x00560000, .size = 1024 * 1024 * 1024, }, [4] = { 10

.name = "nand", //;此区域代表了整片的 nand flash,主要是预留使用,比如以后可以通过应用程序访问 读取/dev/mtdblock4 就能实现备份整片 nand flash 了。 .offset = 0x00000000, .size = 1024 * 1024 * 1024, } }; //;这里是开发板的 nand flash 设置表,因为板子上只有一片,因此也就只有一个表 static struct s3c2410_nand_set mini2440_nand_sets[] = { [0] = { .name = "NAND", .nr_chips = 1, .nr_partitions = ARRAY_SIZE(mini2440_default_nand_part), .partitions = mini2440_default_nand_part, }, }; /* choose a set of timings which should suit most 512Mbit * chips and beyond. */ //;这里是 nand flash 本身的一些特性,一般需要对照 datasheet 填写,大部分情况下按照以下参数填写即 可 static struct s3c2410_platform_nand mini2440_nand_info = { .tacls = 20, .twrph0 = 60, .twrph1 = 20, .nr_sets = ARRAY_SIZE(mini2440_nand_sets), .sets = mini2440_nand_sets, .ignore_unset_ecc = 1, }; 除此之外,还需要把 nand flash 设备注册到系统中 static struct platform_device *mini2440_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, &s3c_device_i2c0, &s3c_device_iis, &s3c_device_nand, //;把 nand flash 设备添加到开发板的设备列表结构 }; (3)加入编译头文件 在上面的文件中定位到 50 行附近,加入一下头文件: #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/nand_ecc.h> 11

#include <linux/mtd/partitions.h> #include <plat/nand.h> (4)传入 mini2440_nand_info 结构体初始化参数 定位到 223 行附近,修改如下: static void __init mini2440_machine_init(void) { s3c_i2c0_set_platdata(NULL); s3c_device_nand.dev.platform_data = &mini2440_nand_info; platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices)); //smdk_machine_init(); } 然后保存。 1.2,编译测试 至此,就完成了 nand flash 驱动的移植,修改完成之后,最好在每次进行 make menuconfig 后都有执行 [root@localhost linux-2.6.32.2]# make clean 因为内核中已经可能已经增减了要编译的模块,所以要在编译之前清除下已编译的目标模块,不然可能编 译出错,然后进行编译: [root@localhost linux-2.6.32.2]# make uImage 编译完成后,生成 zImage 文件,然后给开发板上电,启动 u-boot,操作如下: [u-boot@MINI2440]# tftp 31000000 uImage ... ... S3C24XX NAND Driver, (c) 2004 Simtec Electronics s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns s3c24xx-nand s3c2440-nand: NAND soft ECC NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit) Scanning device for bad blocks Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit": 0x000000000000-0x000000040000 : "boot" uncorrectable error : 0x000000040000-0x000000060000 : "param" ftl_cs: FTL header not found. 0x000000060000-0x000000560000 : "kernel" ftl_cs: FTL header not found. 0x000000560000-0x000040560000 : "root" mtd: partition "root" extends beyond the end of device "NAND 128MiB 3,3V 8-bit" -- size truncated to 0x7aa0000 ftl_cs: FTL header not found. 0x000000000000-0x000040000000 : "nand"

12

mtd: partition "nand" extends beyond the end of device "NAND 128MiB 3,3V 8-bit" -- size truncated to 0x8000000 uncorrectable error : dm9000 Ethernet Driver, V1.31 ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver s3c2410-ohci s3c2410-ohci: S3C24XX OHCI s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1 s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000 usb usb1: configuration #1 chosen from 1 choice hub 1-0:1.0: USB hub found hub 1-0:1.0: 2 ports detected 可以在启动时看到如图蓝色信息,它们正是我们刚刚添加的 nand flash 分区信息,以及开发板本身 nand flash 的一些信息,这里可以看到是 128M 的 nand flash。 .. .... rpcbind: server 10.1.0.128 not responding, timed out Root-NFS: Unable to get nfsd port number from server, using default Looking up port of RPC 100005/1 on 10.1.0.128 rpcbind: server 10.1.0.128 not responding, timed out Root-NFS: Unable to get mountd port number from server, using default Root-NFS: Server returned error -5 while mounting /nfsboot VFS: Unable to mount root fs via NFS, trying floppy. VFS: Cannot open root device "nfs" or unknown-block(2,0) Please append a correct "root=" boot option; here are the available partitions: 1f00 1f01 1f02 1f03 1f04 256 mtdblock0 (driver?) 128 mtdblock1 (driver?) 5120 mtdblock2 (driver?) 125568 mtdblock3 (driver?) 131072 mtdblock4 (driver?)

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0) [<c002e9c0>] (unwind_backtrace+0x0/0xd8) from [<c02d4798>] (panic+0x40/0x118) [<c02d4798>] (panic+0x40/0x118) from [<c0008e68>] (mount_block_root+0x1c8/0x208) [<c0008e68>] (mount_block_root+0x1c8/0x208) from [<c00090fc>] (prepare_namespace +0x160/0x1b8) [<c00090fc>] (prepare_namespace+0x160/0x1b8) from [<c0008434>] (kernel_init+0xd8 /0x10c) [<c0008434>] (kernel_init+0xd8/0x10c) from [<c002a868>] (kernel_thread_exit+0x0/ 0x8) 这里提示的挂在分区时出现了问题。 接下来,将为 linux-2.6.32.2 添加 yaffs 文件系统

13

Linux-2.6.32.2 内核在 mini2440 上的移植(二)---yaffs2 文件系统移植
2011-05-31 10:01:25| 分类: Linux 内核移植 | 标签: |字号大中小 订阅 移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 1,主机环境:VMare 下 CentOS 5.5 ,1G 内存。 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。 4,开发板:mini2440,2M nor flash,128M nand flash。 5,u-boot 版本:u-boot-2009.08 6,linux 版本:linux-2.6.32.2 7,参考文章: 【1】嵌入式 linux 应用开发完全手册,韦东山,编著。 【2】http://blogold.chinaunix.net/u3/101649/showart_2276906.html 【3】Mini2440 之 Linux 移植开发实战指南 2.1, yaffs2 文件系统移植 【1】获取 yaffs2 源代码 现在大部分开发板都可以支持 yaffs2 文件系统,它是专门针对嵌入式设备,特别是使用 nand flash 作为 存储器的嵌入式设备而创建的一种文件系统,早先的 yaffs 仅支持小页(512byte/page)的 nand flash,现在 的开发板大都配备了更大容量的 nand flash,它们一般是大页模式的(2K/page),使用 yaffs2 就可以支持 大页的 nand flash,下面是 yaffs2 的移植详细步骤。 在 http://www.yaffs.net/node/346 可以下载到最新的 yaffs2 源代码,需要使用 git 工具( 安装方法见 Git 版本控制软件安装与使用),在命令行输入: [root@localhost ~]# cd ./linux-test [root@localhost linux-test]# git clone git://www.aleph1.co.uk/yaffs2 Cloning into yaffs2... remote: Counting objects: 6592, done. remote: Compressing objects: 100% (3881/3881), done. remote: Total 6592 (delta 5237), reused 3396 (delta 2642) Receiving objects: 100% (6592/6592), 3.34 MiB | 166 KiB/s, done. Resolving deltas: 100% (5237/5237), done. [root@localhost linux-test]# ls linux-2.6.32.2 linux-2.6.39 yaffs2 [root@localhost linux-test]# 片刻时间之后,可以看到下载的最新的 yaffs2 的源代码目录。 【2】为内核打上 yaffs2 补丁 (1)将 yaffs2 代码加入内核 14

这可以通过 yaffs2 目录下的脚本文件 patch-ker.sh 来给内核打补丁,用法如下: usage: ./patch-ker.sh c/l kernelpath if c/l is c, then copy. if l then link. 这表明,如果 c/l 是 c,则 yaffs2 的代码会被复制到内核目录下,如果是 l,则在内核的目录下创建一些链 接文件。这里 yaff2 所在的目录/root/linux-test/,和 linux-2.6.32.2 在同一个目录下,执行如下命令打补丁: [root@localhost yaffs2]# ./patch-ker.sh c /root/linux-test/linux-2.6.32.2 usage: ./patch-ker.sh c/l m/s kernelpath if c/l is c, then copy. If l then link if m/s is m, then use multi version code. If s then use single version code [root@localhost yaffs2]# ./patch-ker.sh c s /root/linux-test/linux-2.6.32.2 *** Warning *** You have chosen to use the single kernel variant of the yaffs VFS glue code that only works with the latest Linux kernel tree. If you are using an older version of Linux then you probably wanted to use the multi-version variant by re-running the patch-ker.sh script using m as a the second argument. ie ./patch-ker.sh c m /root/linux-test/linux-2.6.32.2 Updating /root/linux-test/linux-2.6.32.2/fs/Kconfig Updating /root/linux-test/linux-2.6.32.2/fs/Makefile [root@localhost yaffs2]# 注意第二个参数 m/s,如果不指定,有时会执行失败。 上述命令完成下面三件事: <1>修改内核文件/fs/Kconfig,增加下面两行(在 177 行附近): if MISC_FILESYSTEMS source "fs/adfs/Kconfig" source "fs/affs/Kconfig" source "fs/ecryptfs/Kconfig" source "fs/hfs/Kconfig" source "fs/hfsplus/Kconfig" source "fs/befs/Kconfig" source "fs/bfs/Kconfig" source "fs/efs/Kconfig" source "fs/yaffs2/Kconfig" source "fs/jffs2/Kconfig" # UBIFS File system configuration <2>修改内核文件/fs/Makefile,增加下面两行(在 129 行附近): obj-$(CONFIG_GFS2_FS) obj-$(CONFIG_EXOFS_FS) += gfs2/ += exofs/

obj-$(CONFIG_YAFFS_FS) += yaffs2/

15

<3>在内核文件的 fs 目录下创建 yaffs2 子目录,然后复制如下文件: 将 yaffs2 源码目录下的 Makefile.kernel 文件复制为内核 fs/yaffs2/Makefile 文件。 将 yaffs2 源码目录下的 Kconfig 文件复制为内核 fs/yaffs2/目录下。 将 yaffs2 源码目录下的*.c、*.h 文件(不包括子目录下的文件)复制为内核 fs/yaffs2/目录下。 (2)配置内核选项 阅读内核 fs/Kconfig 文件可以了解各配置选项的作用。 以下是用到的几个选项: <1>CONFIG_YAFFS_FS:支持 yaffs 文件系统。 <2>CONFIG_YAFFS_YAFFS2:支持 yaffs2 文件系统,对于每页大小为 2k 字节 nand flash,需要选中这个 选项。 <3>CONFIG_YAFFS_AUTO_YAFFS2:自动选择 yaffs2 文件格式,如果不配置这个选项,必须使用 yaffs2 字样来表示 yaffs2 文件系统格式,如果配置这个选项,则可以使用 yaffs 字样来统一表示 yaffs1 和 yaffs2 文件系统格式,驱动程序会根据 nand flash 的页大小自动分辨是 yaffs1 还是 yaffs2。 【3】配置和编译带 YAFFS2 支持的内核 在 Linux 内核源代码根目录运行: [root@localhost linux-test]# cd linux-2.6.32.2 [root@localhost linux-2.6.32.2]# make menuconfig 移动上下按键找到 File Systems,如图

按回车进入该子菜单,再找到―Miscellaneous filesystems‖菜单项,如图

16

按回车进入该子菜单,找到―YAFFS2 file system support‖,如图

按空格选中它 这样我们就在内核中添加了 yaffs2 文件系统的支持 按―Exit‖退出内核配置 最好选中―Yes‖ , , 。 保存。 2.2,编译测试 修改完成之后,因为内核中已经增加要编译的模块,所以要先执行: [root@localhost linux-2.6.32.2]# make clean 不然可能编译出错,然后进行编译: [root@localhost linux-2.6.32.2]# make uImage 编译完成后,生成 zImage 文件,然后给开发板上电,启动 u-boot,操作如下: [u-boot@MINI2440]# tftp 31000000 uImage dm9000 i/o: 0x20000300, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:00:3e:26:0a:5b operating at 100M full duplex mode Using dm9000 device TFTP from server 10.1.0.128; our IP address is 10.1.0.129 Filename 'uImage'. Load address: 0x31000000

17

Loading: ################################################################# ################################################################# ############## done Bytes transferred = 2110688 (2034e0 hex) [u-boot@MINI2440]# bootm ## Booting kernel from Legacy Image at 31000000 ... Image Name: Created: Image Type: Data Size: Linux-2.6.32.2 4:56:08 UTC

2011-05-27

ARM Linux Kernel Image (uncompressed) 2110624 Bytes = 2 MB

Load Address: 30008000 Entry Point: 30008000 Verifying Checksum ... OK Loading Kernel Image ... OK OK Starting kernel ... Uncompressing Linux............................................................. ...................................................................... done, boo ting the kernel. Linux version 2.6.32.2 (root@localhost.localdomain) (gcc version 4.4.3 (ctng-1.6 .1) ) #8 Fri May 27 12:55:46 CST 2011 ... ... S3C24XX NAND Driver, (c) 2004 Simtec Electronics s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns s3c24xx-nand s3c2440-nand: NAND soft ECC NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit) Scanning device for bad blocks Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit": 0x000000000000-0x000000040000 : "boot" uncorrectable error : 0x000000040000-0x000000060000 : "param" ftl_cs: FTL header not found. 0x000000060000-0x000000560000 : "kernel" ftl_cs: FTL header not found. 0x000000560000-0x000040560000 : "root" mtd: partition "root" extends beyond the end of device "NAND 128MiB 3,3V 8-bit" -- size truncated to 0x7aa0000 ftl_cs: FTL header not found. 0x000000000000-0x000040000000 : "nand" mtd: partition "nand" extends beyond the end of device "NAND 128MiB 3,3V 8-bit" -- size truncated to 0x8000000

18

uncorrectable error : dm9000 Ethernet Driver, V1.31 上 面 出 现 还 出 现 ―ftl_cs: FTL header not found.‖ 原 来 应 在 配 置 菜 单 ->Device Drivers ->Memory Technology Devices (MTD),如图

按空格键取消选择,然后选―Exit‖退出,最后出现保存提示时选择―Yes‖保存。然后在终端中执行: [root@localhost linux-2.6.32.2]# make clean 然后执行 [root@localhost linux-2.6.32.2]# make uImage 编译完成后在 u-boot 中下载、运行: [u-boot@MINI2440]# tftp 31000000 uImage dm9000 i/o: 0x20000300, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:00:3e:26:0a:5b operating at 100M full duplex mode Using dm9000 device TFTP from server 10.1.0.128; our IP address is 10.1.0.129 Filename 'uImage'. Load address: 0x31000000 Loading: ################################################################# ################################################################# ############## done Bytes transferred = 2110688 (2034e0 hex) [u-boot@MINI2440]# bootm ... ... S3C24XX NAND Driver, (c) 2004 Simtec Electronics s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns s3c24xx-nand s3c2440-nand: NAND soft ECC

19

NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit) Scanning device for bad blocks Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit": 0x000000000000-0x000000040000 : "boot" 0x000000040000-0x000000060000 : "param" 0x000000060000-0x000000560000 : "kernel" 0x000000560000-0x000008000000 : "rootfs" 0x000000000000-0x000008000000 : "nand" dm9000 Ethernet Driver, V1.31 可以看到,前面的出现―ftl_cs: FTL header not found.‖信息没有了。但还是看到下面信息: VFS: Unable to mount root fs via NFS, trying floppy. VFS: Cannot open root device "nfs" or unknown-block(2,0) Please append a correct "root=" boot option; here are the available partitions: 1f00 1f01 1f02 1f03 1f04 256 mtdblock0 (driver?) 128 mtdblock1 (driver?) 5120 mtdblock2 (driver?) 125568 mtdblock3 (driver?) 131072 mtdblock4 (driver?)

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0) 这是因为内核引导参数设置问题,在 u-boot 命令行执行 [u-boot@MINI2440]# printenv bootargs=noinitrd console=ttySAC0,115200 init=/linuxrc root=/dev/mtdblock3 rw r ootfstype=yaffs ip=10.1.0.129:10.1.0.128:10.1.0.1:255.255.255.0::eth0:off bootcmd=nand read 0x30008000 0x80000 0x300000;bootm 0x30008000 bootdelay=3 baudrate=115200 ethaddr=08:00:3e:26:0a:5b ipaddr=10.1.0.129 serverip=10.1.0.128 gatewayip=10.1.0.1 netmask=255.255.255.0 stdin=serial stdout=serial stderr=serial ethact=dm9000 Environment size: 405/131068 bytes [u-boot@MINI2440]# 确认上面蓝色粗体字部分设置正确,再次执行 [u-boot@MINI2440]# tftp 31000000 uImage [u-boot@MINI2440]# bootm ... ...

20

ALSA device list: No soundcards found. TCP cubic registered NET: Registered protocol family 17 drivers/rtc/hctosys.c: unable to open rtc device (rtc0) IP-Config: Device `eth0' not found. yaffs: dev is 32505859 name is "mtdblock3" rw yaffs: passed flags "" VFS: Mounted root (yaffs filesystem) on device 31:3. Freeing init memory: 132K Warning: unable to open an initial console. Failed to execute /linuxrc. Attempting defaults... 可以看到 yaffs 文件系统加载成功。但是又遇到―Warning: unable to open an initial console.‖这个主要 是因为现在还没有建立根问系统,内核找不到字符设备的挂载点。不过为了减少对 nand flash 的写操作次 数,需要在 nfs 文件系统上测试内核。 接下来,将为内核移植 dm9000 网卡驱动。

21

Linux-2.6.32.2 内核在 mini2440 上的移植(三)---DM9000 网卡驱动移 植
2011-06-01 19:46:50| 分类: Linux 内核移植 | 标签: |字号大中小 订阅 移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 1,主机环境:VMare 下 CentOS 5.5 ,1G 内存。 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。 4,开发板:mini2440,2M nor flash,128M nand flash。 5,u-boot 版本:u-boot-2009.08 6,linux 版本:linux-2.6.32.2 7,参考文章: 【1】嵌入式 linux 应用开发完全手册,韦东山,编著。 【2】Mini2440 之 Linux 移植开发实战指南 【3】http://linux.chinaunix.net/techdoc/system/2009/08/24/1131864.shtml 3.1,移植 DM9000 网卡驱动 【1】设备资源初始化 Linux-2..6.32.2 已 经 自 带 了 完 善 的 DM9000 网 卡 驱 动 驱 动 ( 源 代 码 位 置 :

linux-2.6.32.2/drivers/net/dm9000.c),它也是一个平台设备,因此在目标平台初始化代码中,只要填写好 相应的结构表即可,具体步骤如下: (1)确认已经添加了驱动所需的头文件 dm9000.h: 用 gedit 打开 linux-2.6.32.2/arch/arm/mach-mini2440.c,定位到 55 行附近,加入 dm9000.h,如下所示: #include <plat/common-smdk.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/nand_ecc.h> #include <linux/mtd/partitions.h> #include <plat/nand.h> #include <linux/dm9000.h> (2)填充该平台设备的资源设置 定位到 210 行附近,如入下面代码: tatic struct s3c2410_platform_nand mini2440_nand_info = { .tacls = 20, 22

.twrph0 = 60, .twrph1 = 20, .nr_sets = ARRAY_SIZE(mini2440_nand_sets), .sets = mini2440_nand_sets, .ignore_unset_ecc = 1, }; /* DM9000AEP 10/100 ethernet controller */ //定义 DM9000 网卡设备的物理基地址,以便后面用到 #define MACH_MINI2440_DM9K_BASE (S3C2410_CS4 + 0x300) //再填充该平台设备的资源设置,以便和 DM9000 网卡驱动接口配合起来 static struct resource mini2440_dm9k_resource[] = { [0] = { .start = MACH_MINI2440_DM9K_BASE, .end = MACH_MINI2440_DM9K_BASE + 3,

.flags = IORESOURCE_MEM }, [1] = { .start = MACH_MINI2440_DM9K_BASE + 4, .end = MACH_MINI2440_DM9K_BASE + 7,

.flags = IORESOURCE_MEM }, [2] = { .start = IRQ_EINT7, .end = IRQ_EINT7,

.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; /* * * The DM9000 has no eeprom, and it's MAC address is set by * * * the bootloader before starting the kernel. */

static struct dm9000_plat_data mini2440_dm9k_pdata = { .flags }; static struct platform_device mini2440_device_eth = { .name .id = "dm9000", = -1, = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),

.num_resources = ARRAY_SIZE(mini2440_dm9k_resource), .resource .dev = mini2440_dm9k_resource, ={ .platform_data = &mini2440_dm9k_pdata, }, }; static struct platform_device *mini2440_devices[] __initdata = { 23

&s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, &s3c_device_i2c0, &s3c_device_iis, &s3c_device_nand, //;把 nand flash 设备添加到开发板的设备列表结构 &mini2440_device_eth, //;把网卡平台设备添加到开发板的设备列表结构 }; static void __init mini2440_map_io(void) 【2】调整 DM9000 所用的位宽寄存器 因为 Linux-2.6.32.2 的 DM9000 网卡驱动并不是专门为 mini2440 准备的,所以还要在其源代码中做一 些移植工作,如下步骤。 (1)打开 linux-2.6.32.2/drivers/net/dm9000.c,定位到 41 行附近,添加 2410 相关的配置定义,如下红色 部分: #include <asm/delay.h> #include <asm/irq.h> #include <asm/io.h> #include "dm9000.h" #if defined(CONFIG_ARCH_S3C2410) #include <mach/regs-mem.h> #endif (2) 在 dm9000 设备的初始化函数中添加如下红色部分,这里是配置 DM9000 所用片选总线的时序,因为 mini2440 目前只有一个通过总线外扩的设备 在此设备驱动中直接修改相关的寄存器配置会更加容易理解 , 一些,当然这部分也可以放到 mach-mini2440.c 中。 打开 linux-2.6.32.2/drivers/net/dm9000.c,定位到 1555 行附近,加入下面代码: static int __init dm9000_init(void) { #if defined(CONFIG_ARCH_S3C2410) unsigned int oldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON; unsigned int oldval_bankcon4 = *(volatile unsigned int *)S3C2410_BANKCON4; *((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<16)) | S3C2410_BWSCON_DW4_16 | S3C2410_BWSCON_WS4 | S3C2410_BWSCON_ST4; *((volatile unsigned int *)S3C2410_BANKCON4) = 0x1f7c; #endif printk(KERN_INFO "%s Ethernet Driver, V%s\n", CARDNAME, DRV_VERSION); return platform_driver_register(&dm9000_driver); }

24

【3】需要注意的是,本开发板所用的 DM9000 网卡并没有外接 EEPROM 用以存储 MAC 地址,因此系 统中的 MAC 地址是一个―软‖地址,也就是可以通过软件进行修改,可以随意改为其他值。 打开 linux-2.6.32.2/drivers/net/dm9000.c,定位到 1461 行附近,加入下面一行代码: static int __devinit dm9000_probe(struct platform_device *pdev) { ... ... /* try reading the node address from the attached EEPROM */ //;尝试从 EEPROM 读取 MAC 地址 for (i = 0; i < 6; i += 2) dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i); if (!is_valid_ether_addr(ndev->dev_addr) && pdata != NULL) { mac_src = "platform data"; memcpy(ndev->dev_addr, pdata->dev_addr, 6); } if (!is_valid_ether_addr(ndev->dev_addr)) { /* try reading from mac */

mac_src = "chip"; for (i = 0; i < 6; i++) ndev->dev_addr[i] = ior(db, i+DM9000_PAR); } //;使用―软‖MAC 地址: 08:90:90:90:90:90 memcpy(ndev->dev_addr, "\x08\x90\x90\x90\x90\x90", 6); if (!is_valid_ether_addr(ndev->dev_addr)) dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please " "set using ifconfig\n", ndev->name); platform_set_drvdata(pdev, ndev); ret = register_netdev(ndev); if (ret == 0) printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)\n", ndev->name, dm9000_type_to_char(db->type), db->io_addr, db->io_data, ndev->irq, ndev->dev_addr, mac_src); return 0; out: dev_err(db->dev, "not found (%d).\n", ret);

25

dm9000_release_board(pdev, db); free_netdev(ndev); return ret; } 实际上到此为止 DM9000 就已经移植结束了。 3.2,编译测试 【1】在编译之前,需要确认在内核中已经配置了网卡驱动 在内核目录下执行: [root@localhost linux-2.6.32.2]# make menuconfig 在打开的配置菜单 Device Drivers --->Network device support ---> Ethernet (10 or 100Mbit) --->,可以看 到如下图

DM9000 已经被选中,这是因为 Linux-2.6.32.2 默认的内核配置已经加入了 DM9000 的支持。

【2】编译 [root@localhost linux-2.6.32.2]# make clean [root@localhost linux-2.6.32.2]# make uImage 编译完成后生成 zImage 和 uImage 【3】进行网卡驱动测试 (1)采用友善官方已经移植好的根文件系统,可以从其提供的光盘映像/linux 目录下直接复制过来。 [root@localhost ~]# cd linux-test [root@localhost linux-test]# ls busybox-1.13.3 mkyaffs2image.tgz

busybox-1.13.3-mini2440.tgz myrootfs busybox-1.18.4 busybox-1.18.4.tar.bz2 linux-2.6.32.2 linux-2.6.39 usr yaffs2 rootfs_qtopia_qt4 rootfs_qtopia_qt4-20110304.tar.gz

[root@localhost linux-test 26

(2)将其复制到宿主机/nfsboot 目录下并命名为 roorfs [root@localhost linux-test]# cp -rf rootfs_qtopia_qt4 /nfsboot/rootfs [root@localhost linux-test]# 并确保 rootfs 目录可读写 [root@localhost linux-test]# cd /nfsboot [root@localhost nfsboot]# ls -l 总计 65280 drwxr-xr-x 18 root root 4096 06-01 19:06 rootfs

-rwxrw-rw- 1 root root 58487616 2009-07-18 root_qtopia-128M.img -rw-r--r-- 1 root root 2110720 06-01 13:31 uImage -rwxr-xr-x 1 root root 2022412 05-12 11:37 uImage_T35 -rwxr-xr-x 1 root root 2110656 06-01 13:31 zImage -rwxrw-rw- 1 root root 2022348 2009-07-08 zImage_T35 [root@localhost nfsboot]# (3)修改/etc/exports 配置文件将 rootfs 默认的共享目录 [root@localhost ~]# vim /etc/exports 打开的配置文件将共享目录修改成如下所示: /nfsboot/rootfs 10.1.0.*(rw,sync,no_root_squash) /nfsboot/kernel 10.1.0.*(rw,sync,no_root_squash) /nfsboot/nfs 10.1.0.*(rw,sync,no_root_squash) # /nfsboot/rootfs 是共享目录,存放跟文件系统(使用绝对路径) # /nfsboot/kernel 是共享目录,存放跟文件系统(使用绝对路径) # /nfsboot/nfs 是共享目录,存放应用程序(使用绝对路径) # 10.1.0.*表示客户端所在网段 10.1.0.0/24 # 10.1.0.0/24 表示 10.1.0.1~10.1.0.254 网段,子网掩码是 255.255.255.0。 # 子网掩码是怎么来的呢?其实关键就在―24‖上。我们知道 IP 地址是四个十进制数 # 组成的,相当于 32 位二进制。用 CIDR 表示形式,后一个数字将这 32 位进行了间隔 #(以 24 为例):前 24 位用"1"表示,后面 8 位用 0 表示,得到一个二进制数: # 11111111 11111111 11111111 00000000 # 将其转化为十进制,就是:255.255.255.0 了。 # rw:可读写 # sync:同步写入磁盘。 # no_root_squash:允许非 root 用户操作改文件夹 然后保存退出,重新启动 nfs 服务: [root@localhost ~]# service nfs restart 关闭 NFS mountd: 关闭 NFS 守护进程: 关闭 NFS quotas: 关闭 NFS 服务: 启动 NFS 服务: [确定] [确定] [确定] [确定] [确定] 27

关掉 NFS 配额: 启动 NFS 守护进程: 启动 NFS mountd: [root@localhost ~]# (4)修改 u-boot 内核引导参数 在 u-boot 启动并进入命令行状态下

[确定] [确定] [确定]

A,确保 bootargs ="noinitrd console=ttySAC0,115200 init=/linuxrc mem=64M \ root=/dev/nfs rw nfsroot=10.1.0.128:/nfsboot \ ip=10.1.0.129:10.1.128:10.1.0.1:255.255.255.0::eth0:off" B,确保 bootcmd="nfs 0x30008000 10.1.0.128:/nfsboot/uImage;bootm" 先查看 u-boot 的环境变量 [u-boot@MINI2440]# printenv bootargs=noinitrd console=ttySAC0,115200 init=/linuxrc root=/dev/mtdblock3 rw r ootfstype=yaffs ip=10.1.0.129:10.1.0.128:10.1.0.1:255.255.255.0::eth0:off bootcmd=nand read 0x30008000 0x80000 0x300000;bootm 0x30008000 bootdelay=3 baudrate=115200 ethaddr=08:00:3e:26:0a:5b ipaddr=10.1.0.129 serverip=10.1.0.128 gatewayip=10.1.0.1 netmask=255.255.255.0 stdin=serial stdout=serial stderr=serial ethact=dm9000 Environment size: 405/131068 bytes [u-boot@MINI2440]# 这里的 u-boot 内核引导参数 bootargs 和 bootcmd 显然与我们要求的不一致,要重新设置此参数: [u-boot@MINI2440]# setenv bootargs 'noinitrd console=ttySAC0,115200 init=/linux' rc mem=64M root=/dev/nfs rw nfsroot=10.1.0.128:/nfsboot/rootfs ip=10.1.0.129:10' .1.0.128:10.1.0.1:255.255.255.0::eht0:off' [u-boot@MINI2440]# setenv bootcmd 'nfs 0x31000000 10.1.0.128:/uImage;bootm 0x31000000' 然后保存此变量到 nand flash [u-boot@MINI2440]# saveenv Saving Environment to NAND... Erasing Nand... Erasing at 0x4000000000002 -Writing to Nand... done 0% complete.

28

有关内核引导参数的含义请参照 u-boot-2009.08 在 mini2440 上的移植(六)---增加引导内核功能。 (5)确认内核的命令行参数 如果编译内核生成的是 zImage 映像文件,那么 CONFIG_CMDLINE 需要 CONFIG_CMDLINE="root=/dev/nfs console=ttySAC0 mem=64M" 如果编译内核生成的是 uImage 映像文件,那么 CONFIG_CMDLINE 可以为空,因为 uImage 的文件头中 的参数会被传进这个地方来。 (6)将编译生成 zImage 和 uImage 文件复制到宿主机/nfsboot/目录下 [root@localhost nfsboot]# ls rootfs root_qtopia-128M.img uImage uImage_T35 zImage zImage_T35 [root@localhost nfsboot]# (7)给开发板上电,启动 u-boot I2C: ready rw nfsroot=10.1.0.128:/nfsboot/rootfs ip=10.1.0.129

DRAM: 64 MB Flash: 2 MB NAND: 128 MiB Video: 240x320x16 20kHz 62Hz In: Out: Err: Net: serial serial serial dm9000

U-Boot 2009.08 modified by singleboy(singleboy@163.com) Love Linux forever!!! Hit any key to stop autoboot: 0 dm9000 i/o: 0x20000300, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:00:3e:26:0a:5b operating at 100M full duplex mode Using dm9000 device File transfer via NFS from server 10.1.0.128; our IP address is 10.1.0.129 Filename '/nfsboot/uImage'. Load address: 0x31000000 Loading: ################################################################# ################################################################# ################################################################# ################################################################# ################################################################# ################################################################# ####################### done

29

Bytes transferred = 2110772 (203534 hex) ## Booting kernel from Legacy Image at 31000000 ... Image Name: Created: Image Type: Data Size: Linux-2.6.32.2

2011-06-01 11:10:24 UTC ARM Linux Kernel Image (uncompressed) 2110708 Bytes = 2 MB

Load Address: 30008000 Entry Point: 30008000 Verifying Checksum ... OK Loading Kernel Image ... OK OK Starting kernel ... Uncompressing Linux............................................................. ...................................................................... done, boo ting the kernel. Linux version 2.6.32.2 (root@localhost.localdomain) (gcc version 4.4.3 (ctng-1.6 .1) ) #11 Wed Jun 1 19:10:07 CST 2011 CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=00007177 CPU: VIVT data cache, VIVT instruction cache Machine: my mini2440 devolopment board singleboy@163.com ... ... S3C24XX NAND Driver, (c) 2004 Simtec Electronics s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns s3c24xx-nand s3c2440-nand: NAND soft ECC NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bi t) Scanning device for bad blocks Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit": 0x000000000000-0x000000040000 : "boot" 0x000000040000-0x000000060000 : "param" 0x000000060000-0x000000560000 : "kernel" 0x000000560000-0x000008000000 : "rootfs" 0x000000000000-0x000008000000 : "nand" dm9000 Ethernet Driver, V1.31 eth0: dm9000e at c486e300,c4872304 IRQ 51 MAC: 08:90:90:90:90:90 (chip) ... ... eth0: link up, 100Mbps, full-duplex, lpa 0x45E1 IP-Config: Complete: device=eth0, addr=10.1.0.129, mask=255.255.255.0, gw=10.1.0.1, host=10.1.0.129, domain=, nis-domain=(none), bootserver=10.1.0.128, rootserver=10.1.0.128, rootpath= Looking up port of RPC 100003/2 on 10.1.0.128 30

Looking up port of RPC 100005/1 on 10.1.0.128 VFS: Mounted root (nfs filesystem) on device 0:14. Freeing init memory: 132K ----------munt all---------------*********************************************** ************booting to mini2440 ***************** Kernel version:linux-2.6.32.2 the fans:singelboy Date:2011.5.30 *********************************************** Please press Enter to activate this console. 根据内核启动信息,可以看到 dm9000 网卡驱动移植成功。 接下来,将为内核建立根文件系统。

31

Linux-2.6.32.2 内核在 mini2440 上的移植(四)---根文件系统制作(1)
2011-06-16 18:18:56| 分类: Linux 内核移植 | 标签: |字号大中小 订阅 移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 1,主机环境:VMare 下 CentOS 5.5 ,1G 内存。 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gn?i-gcc v4.5.1。 4,开发板:mini2440,2M nor flash,128M nand flash。 5,u-boot 版本:u-boot-2009.08 6,linux 版本:linux-2.6.32.2 7,参考文章: 【1】嵌入式 linux 应用开发完全手册,韦东山,编著。 【2】Mini2440 之 Linux 移植开发实战指南 【3】http://linux.chinaunix.net/techdoc/system/2009/08/24/1131864.shtml 4.1,根文件系统制作 在构建文件系统时,建议遵循 FHS(Filesystem Hierarchy Standard,文件系统层次标准),它定义了文件系 统中目录、文件的分类存放原则,定义了系统运行需要的最小文件目录的集合, FHS 文档可以到 www.pathname.com/fhs/下载。 【1】下载 busybox 源代码 可以从 http://www.busybox.net/downloads/,这里下载的是 busybox-1.13.3.tar.bz2,友善官方也有提供直 接复制过来即可: [root@localhost linux-test]# ls busybox-1.13.3-mini2440.tgz [root@localhost linux-test]# 【2】根文件系统目录说明 嵌入式 Linux 中都需要构建根文件系统,构建根文件系统的规则在 FHS(FilesystemHierarchy Standard) 文档中,下面是根文件系统顶层目录。 目录 内容 bin sbin usr 存放所有用户都可以使用的、基本的命令。 存放的是基本的系统命令,它们用于启动系统、修复系统等。 里面存放的是共享、只读的程序和数据。 该目录存放设备文件和其它特殊文件。 存放系统配置文件,包括启动文件。 存放共享库和可加载块(即驱动程序),共享库用于启动系统、运行根文件系统中的可执行程序 32 linux-2.6.32.2 linux-2.6.39 yaffs2

proc 这是个空目录,常作为 proc 文件系统的挂载点。 dev etc lib

boot 引导加载程序使用的静态文件。 home 用户主目录,包括供服务账号锁使用的主目录,如 FTP。 mnt opt root tmp var 用于临时挂接某个文件系统的挂接点,通常是空目录。也可以在里面创建空的子目录。 给主机额外安装软件所摆放的目录。 root 用户的主目录 存放临时文件,通常是空目录。 存放可变的数据,如日志等。

【3】创建系统目录。操作如下: 在与 linux 内核相同的目录下创建一个目录,此目录名字可以自己指定,这里创建的目录名为 myrootfs。 [root@localhost linux-test]# mkdir myrootfs [root@localhost linux-test]# ls busybox-1.18.4.tar.bz2 linux-2.6.32.2 linux-2.6.39 myrootfs yaffs2 进入到/root/linux-test/myrootfs/rootfs 目录,新建一个建立根文件系统目录的脚本文件 mkrootfs: [root@localhost linux-test]# cd myrootfs [root@localhost myrootfs]# vim mkrootfs 将下列内容复制其中: #!/bin/sh echo "------Create rootfs directons start...--------" mkdir rootfs cd rootfs echo "--------Create root,dev....----------" mkdir bin boot dev etc home lib mnt proc root sbin sys tmp usr var www mkdir etc/init.d etc/rc.d etc/sysconfig mkdir usr/sbin usr/bin usr/lib usr/modules echo "make node in dev/console dev/null" mknod -m 666 dev/console c 5 1 mknod -m 666 dev/null c 1 3 mkdir mnt/etc mnt/jffs2 mnt/yaffs mnt/data mnt/temp mkdir var/lib var/lock var/run var/tmp chmod 1777 tmp chmod 1777 var/tmp echo "-------make direction done---------" 然后执行:wq 保存退出。 使用命令 chmod a+x mkrootfs 改变文件的可执行权限: [root@localhost myrootfs]# chmod a+x mkrootfs 运行./mkrootfs 脚本: [root@localhost myrootfs]# ./mkrootfs ------Create rootfs directons start...---------------Create root,dev....---------33

make node in dev/console dev/null -------make direction done--------[root@localhost myrootfs]# 这样就完成了根文件系统目录的创建。在上面脚本执行过程创建的两个设备文件 console 和 null 非常重 要,这两文件和控制台设备有关,在前面提到过的在内核挂载文件系统时出现的告警―Warning: unable to open an initial console‖与之有关。 其中,mknod 命令格式如下: mknod [OPTION]... NAME TYPE [MAJOR MINOR] 参数-m, --mode=MODE,表示指定用户操作权限,console 和 null 表示文件名,c 表示是字符设备,后面 的两个数字分别表示主设备号和次设备号。 改变了 tmp 目录的使用权,让它开启 sticky 位,为 tmp 目录的使用权开启此位,可确保 tmp 目录底下建 立的文件,只有建立它的用户有权删除。尽管嵌入式系统多半是单用户,不过有些嵌入式应用不一定用 root 的权限来执行,因此需要遵照根文件系统权限位的基本规定来设计。 【4】编译并安装内核模块 首 先 就 进 入 到 内 核 顶 级 目 录 下 , 并 确 认 内 核 顶 层 目 录 下 的 Makefile 中 的 ARCH=arm , CROSS_COMPILE=arm-linux- ,然后执行编译: [root@localhost linux-test]# cd linux-2.6.32.2 [root@localhost linux-2.6.32.2]# make modules 等到编译完成后,安装编译好的模块: [root@localhost linux-2.6.32.2]# make modules_install ARCH=arm

INSTALL_MOD_PATH=/root/linux-test/myrootfs/rootfs 等到模块安装完成后可以看到 [root@localhost linux-2.6.32.2]# cd ../myrootfs/rootfs [root@localhost rootfs]# ls ./lib/modules 2.6.32.2 2.6.32.2-FriendlyARM [root@localhost rootfs]# ls ./lib/modules/2.6.32.2 build kernel modules.dep modules.ofmap modules.symbols modules.usbmap source

modules.ieee1394map modules.order modules.inputmap modules.pcimap

modules.alias

modules.ccwmap modules.isapnpmap

modules.seriomap

[root@localhost rootfs]# ls ./lib/modules/2.6.32.2/kernel crypto drivers fs lib net sound [root@localhost rootfs]# 上面的目录中有 make modules_install 安装的模块。 【5】建立动态链接库 这 里 的 动 态 链 接 库 直 接 用 友 善 之 臂 的 , 可 以 从 其 官 方 光 盘 映 像 /linux 目 录 下 rootfs_qtopia_qt4-20110304.tar.gz,先解压友善之臂的根文件包:

34

[root@localhost myrootfs]# cd ../ [root@localhost linux-test]# ls busybox-1.13.3-mini2440.tgz linux-2.6.39 rootfs_qtopia_qt4-20110304.tar.gz linux-2.6.32.2 myrootfs yaffs2

[root@localhost linux-test]# tar -zxf rootfs_qtopia_qt4-20110304.tar.gz -C ./ [root@localhost linux-test]# ls busybox-1.13.3-mini2440.tgz linux-2.6.39 rootfs_qtopia_qt4 linux-2.6.32.2 myrootfs rootfs_qtopia_qt4-20110304.tar.gz yaffs2

[root@localhost linux-test]# 拷贝其 lib 的内容到新建的根文件目录 lib 内: [root@localhost linux-test]# cp -rfd ./rootfs_qtopia_qt4/lib/* ./myrootfs/rootfs/lib/ [root@localhost linux-test]# 还有一种做法: 对于"lib"目录:这个里面放的都是库文件,直接从交叉编译器的库文件目录中拷贝过来: #cp -f /usr/local/arm/4.4.3/arm-none-linux-gneabi/libc/armv4t/lib/*so* lib/ -a 【5】交叉编译 Bosybox Bosybox 是一个遵循 GPL v2 协议的开源项目,它在编写过程总对文件大小进行优化,并考虑了系统资源 有限(比如内存等)的情况,使用 Busybox 可以自动生成根文件系统所需的 bin、sbin、usr 目录和 linuxrc 文 件。 (1)解压 busybox [root@localhost linux-test]# ls busybox-1.13.3-mini2440.tgz linux-2.6.39 rootfs_qtopia_qt4 linux-2.6.32.2 myrootfs rootfs_qtopia_qt4-20110304.tar.gz yaffs2

[root@localhost linux-test]# tar -zxf busybox-1.13.3-mini2440.tgz [root@localhost linux-test]# ls busybox-1.13.3 linux-2.6.39 rootfs_qtopia_qt4-20110304.tar.gz yaffs2

busybox-1.13.3-mini2440.tgz linux-2.6.32.2

myrootfs

rootfs_qtopia_qt4

[root@localhost linux-test]# (2)进入 busybox 的顶层目录,修改 Makefile [root@localhost linux-test]# cd busybox-1.13.3 [root@localhost busybox-1.13.3]# gedit Makefile 在 gedit 打开的 Makefile 中,定位到 164 行附近,修改如下: # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile CROSS_COMPILE ?= arm-linux# bbox: we may have CONFIG_CROSS_COMPILER_PREFIX in .config, # and it has not been incl? yet... thus using an awkward syntax. ... ...

35

定位到 189 行附近,修改如下: ARCH ?= arm # Architecture as present in compile.h UTS_MACHINE := $(ARCH) 然后保存。 (3)配置 busybox 在 busybox 顶层目录下执行 make menconfig 进行配置 [root@localhost busybox-1.13.3]# make menconfig 出现如下图配置菜单

下面只列出了要注意的地方,没有列出的默认即可。 <1>、Busybox Settings---> Build Options---> [*] Build BusyBox as a static binary (no shared libs) [ ] Force NOMMU build [*] Build with Large File Support (for accessing files > 2 GB) (arm-linux-) Cross Compiler prefix //指定编译前缀,按回车就可进行修改 Installation Options ---> [*] Don't use /usr //选中该项可以避免 buysbox 被安装到宿主机系统的/usr 目录下,破坏宿主机系统。 //这里需要指定 busybox 的安装路

Applets links (as soft-links) ---> (/root/linux-test/myrootfs/rootfs) BusyBox installation prefix 径,按回车即可输入。 Busybox Library Tuning ---> [*] Support for /etc/networks [*] Command line editing

36

(1024) Maximum length of input [*] vi-style line editing commands (15) History size [*] [*] [*] [*] History saving Tab completion Username completion Fancy shell prompts

<2>Linux Module Utilities---> (/lib/modules)Default directory containing modules (modules.dep)Default name of modules.dep 下面是在 busybox 中配置对 dev 下设备类型的支持,dev 的创建有手动创建、使用 devfs 文件系统创建 和?v 创建三种方法,而?v 的一个简化版是 busybox 自带的 mdev ,适合于嵌入式的应用埸合。其具有使 用简单的特点。它的作用,就是在系统启动和热插拔或动态加载驱动程序时,自动产生驱动程序所需的节 点文件。在以 busybox 为基础构建嵌入式 linux 的根文件系统时,使用它是最优的选择。 <3>Linux System Utilities ---> [*]Support /etc/mdev.conf [*]Support command execution at device addition/removal <4>Init Utilities ---> ―Support reading an inittab file‖应该选中,这样可以根据自己编写的 inittab 文件初始化;―Support running commands with a controlling-tty‖应该选中,否则会提示非常困扰的―/bin/sh: can't access tty; job control turned off‖的提示,尽管可以进入控制台命令行。 (4)编译 busybox 编译 busybox 到指定目录,在 busybox-1.13.3 的根目录下执行 make CONFIG_PREFIX=/root/linux-test/myrootfs/rootfs install 在 rootfs 目录下会生成目录 bin、sbin、usr 和文件 linuxrc 的内容。 [root@localhost busybox-1.13.3]# make CONFIG_PREFIX=/root/linux-test/myrootfs/rootfs install ... ... -------------------------------------------------You will probably need to make your busybox binary setuid root to ensure all configured applets will work properly. -------------------------------------------------[root@localhost busybox-1.13.3]#

[root@localhost busybox-1.13.3]# ls ../myrootfs/rootfs bin dev home linuxrc proc sbin tmp var mnt root sys usr www

boot etc lib

[root@localhost busybox-1.13.3]# 【6】建立 etc 目录下的配置文件 37

(1) 建立/etc/group 系统用户组配置文件,内容如下: root:*:0: daemon:*:1: bin:*:2: sys:*:3: adm:*:4: tty:*:5: disk:*:6: lp:*:7:lp mail:*:8: news:*:9: u p:*:10: proxy:*:13: kmem:*:15: dialout:*:20: fax:*:21: voice:*:22: cdrom:*:24: floppy:*:25: tape:*:26: s o:*:27: a io:*:29: ppp:x:99: 500:x:500:plg 501:x:501:fa (2)建立 passwd 系统密码文件,内容如下: root::0:0:root:/:/bin/sh ftp::14:50:FTP User:/var/ftp: bin:*:1:1:bin:/bin: daemon:*:2:2:daemon:/sbin: nobody:*:99:99:Nobody:/: sky::502:502:Linux User,,,:/home/sky:/bin/sh [root@localhost rootfs]# ls ./etc group init.d passwd rc.d [root@localhost rootfs]# (3) 在 etc/sysconfig 目录下新建主机文件名 HOSTNAME,内容为"mini2440"。 [root@localhost rootfs]# cat >>./etc/sysconfig/HOSTNAME mini2440 [root@localhost rootfs]# 当录入完文件内容―mini2440‖并回车后需要按下 Ctrl+C 组合键结束录入状态。此时该文件内容为: ―mini2440",这句话就是我们在文件系统里面看到那个―[root@ mini2440 /]‖。 sysconfig

38

(4)新建 etc/inittab 系统 init 进程配置文件,将下面内容复制并粘贴其中: #etc/inittab ::sysinit:/etc/init.d/rcS console::askfirst:-/bin/sh ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a –r 要记住赋予其可执行属性 [root@localhost rootfs]# chmod a+x ./etc/inittab (5)新建 etc/init.d/rcS 系统启动加载项文件,将下面内容复制并粘贴其中: #!/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin runlevel=S //运行的级别 prevlevel=N umask 022 //文件夹的掩码 export PATH runlevel prevlevel echo "----------munt all----------------" mount -a //挂载/etc/fstab/文件指定的所有的文件系统 echo /sbin/mdev>/proc/sys/kernel/hotplug mdev -s echo "***********************************************" echo "************booting to mini2440 *****************" echo "Kernel version:linux-2.6.32.2" echo "the fans:singleboy" echo "Date:2011.5.30" echo "***********************************************" /bin/hostname -F /etc/sysconfig/HOSTNAME 然后使用以下命令改变 rcS 的执行权限: Chmod +x rcS [root@localhost rootfs]# chmod +x ./etc/init.d/rcS [root@localhost rootfs]# (6)新建 etc/fstab 系统挂载文件系统列表文件,将下面内容复制并粘贴其中: #device mount-point type proc none sysfs mdev /proc /tmp /sys /dev proc ramfs sysfs ramfs option defaults defaults defaults defaults dump fsck order 0 0 0 0 0 0 0 0

(7)新建 etc/profile 用户环境配置文件,将下面内容复制并粘贴其中: #Ash profile #vim:syntax=sh

39

#No core file by defaults #ulimit -S -c 0>/dev/null 2>&1 USER="id -un" LOGNAME=$USER PS1='[\u@\h \W]\$' PATH=$PATH HOSTNAME='/bin/hostname' export USER LOGNAME PS1 PATH 修改环境变量 PS1(命令行提示符),可以使用 vi 编辑/etc/profile 文件,在最后加上: export PS1='[\u@\h \W]\$ ' 即可,其中\u 显示当前用户账号,\h 显示当前主机名,\W 显示当前路径,\$显示'$'符号 \W 代替 \w 就可以实现绝对路径到相对路径的转换 下面简单说说环境下默认的特殊符号所代表的意义: \d :代表日期,格式为 weekday month date,例如:"Mon Aug 1" \H :完整的主机名称。例如:我的机器名称为:fc4.linux,则这个名称就是 fc4.linux \h :仅取主机的第一个名字,如上例,则为 fc4,.linux 则被省略 \t :显示时间为 24 小时格式,如:HH:MM:SS \T :显示时间为 12 小时格式 \A :显示时间为 24 小时格式:HH:MM \u :当前用户的账号名称 \v :BASH 的版本信息 \w :完整的工作目录名称。家目录会以 ~代替 \W :利用 basename 取得工作目录名称,所以只会列出最后一个目录 \# :下达的第几个命令 \$ :提示字符,如果是 root 时,提示符为:# ,普通用户则为:$ (8) 建 立 etc/mdev.conf (mdev 设 备 配 置 文 件 ) 、 net.conf ( 网 络 配 置 文 件 件 ) , mime.types: MIME(Multipurpose Internet Mail Extensions) 内容均为空。 [root@localhost rootfs]# to h ./etc/mdev.conf [root@localhost rootfs]# to h ./etc/net.conf [root@localhost rootfs]# to h ./etc/mine.types (9)建立 boa WEB 服务器文件配置文件 在 etc/boa 目录,并在 boa 目录中建立 boa.conf 文件,内容为空。 [root@localhost rootfs]# mkdir ./etc/boa [root@localhost rootfs]# to h ./etc/boa/boa.conf [root@localhost rootfs]# (10)先建立 etc/rc.d/init.d 目录 [root@localhost rootfs]# mkdir ./etc/rc.d/init.d 然后建立 etc/rc.d/init.d/httpd 文件 [root@localhost rootfs]# gedit ./etc/rc.d/init.d/httpd [root@localhost rootfs]# 40

将下面内容复制并粘贴: #!/bin/sh base=boa # See how we were called. case "$1" in start) /usr/sbin/$base ;; stop) pid=`/bin/pidof $base` if [ -n "$pid" ]; then kill -9 $pid fi ;; esac exit 0 (11)新建 etc/resolv.conf,DNS 配置文件,存放访问外网时需要 DNS 的信息,内容如下: nameserver 61.144.56.100 (12)在/home/sky 目录,与 etc 目录 passwd 文件中的 sky 相对应 [root@localhost rootfs]# mkdir ./home/sky [root@localhost rootfs]# 3.2,根文件系统测试 将制作的文件系统通过下面三种方法测试 【1】将 nfs 文件系统作为根文件系统进行测试 (1) 将制作好的根文件系统 rootfs 复制到/nfsboot 目录下作为 mini2440 的根文件系统 [root@localhost myrootfs]# cp -drf ./rootfs /nfsboot/ [root@localhost myrootfs]# cd /nfsboot [root@localhost nfsboot]# 复制时需要加上 drf 参数,d 表示文件的链接关系不变。r 表示递归复制此目录下所有的子目录和文件。 (2)确保 rootfs 目录可读写 [root@localhost nfsboot]# ls -l 总计 63216 drwxr-xr-x 17 root root 4096 06-01 07:14 rootfs

-rwxrw-rw- 1 root root 58487616 2009-07-18 root_qtopia-128M.img -rw-r--r-- 1 root root 2114212 05-27 11:45 uImage [root@localhost nfsboot]#

41

进入到内核目录下,执行: [root@localhost myrootfs]# cd ../linux-2.6.32.2 [root@localhost linux-2.6.32.2]# vim .config 在打开的配置文件中在命令模式下:/CMD,会自动定位到 340 行,对照上面 CONFIG_CMDLINE 参数修改 成如下: # # Boot options # CONFIG_ZBOOT_ROM_TEXT=0 CONFIG_ZBOOT_ROM_BSS=0 CONFIG_CMDLINE="root=/dev/nfs console=ttySAC0 mem=64M" # CONFIG_XIP_KERNEL is not set CONFIG_KEXEC=y CONFIG_ATAGS_PROC=y 在内核目录下命令终端中执行 [root@localhost linux-2.6.32.2]# make men onfig 在打开的配置菜单-> Boot options --->回车可以看到刚才的修改结果,如下图: rw nfsroot=10.1.0.128:/nfsboot/rootfs ip=10.1.0.129

当然上图高亮的菜单选项上按回车也可以进行修改,但没有在 vim 编辑器中修改方便。 (5)确保内核提供 nfs boot 支持 在刚才的配置菜单中定位到 Device Drivers ---> <*> Memory Technology Device (MTD) support ---> <*> Caching block device access to MTD devices

[*] Network device support --->

42

[*] <*>

Ethernet (10 or 100Mbit) ---> DM9000 support

File systems ---> [*] Network 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 (EXPERIMENTAL) NFS client support for NFSv4.1 (DEVELOPER ONLY) Root file system on NFS NFS server support

要确保上面蓝色高亮部分的选项被选上。 (6)重新编译内核,将生成的 uImage 和 zImage 文件复制到/nfsboot/目录下 [root@localhost nfsboot]# ls rootfs root_qtopia-128M.img uImage uImage_T35 zImage zImage_T35 [root@localhost nfsboot]# (7)给开发板上电,启动 u-boot I2C: ready

DRAM: 64 MB Flash: 2 MB NAND: 128 MiB Video: 240x320x16 20kHz 62Hz In: Out: Err: Net: serial serial serial dm9000

U-Boot 2009.08 modified by singleboy(singleboy@163.com) Love Linux forever!!! Hit any key to stop autoboot: 0 dm9000 i/o: 0x20000300, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:00:3e:26:0a:5b operating at 100M full duplex mode Using dm9000 device File transfer via NFS from server 10.1.0.128; our IP address is 10.1.0.129 Filename '/nfsboot/uImage'. Load address: 0x31000000 Loading: ################################################################# ################################################################# 43

################################################################# ################################################################# ################################################################# ################################################################# ####################### done Bytes transferred = 2110772 (203534 hex) ## Booting kernel from Legacy Image at 31000000 ... Image Name: Created: Image Type: Data Size: Linux-2.6.32.2

2011-06-01 11:10:24 UTC ARM Linux Kernel Image (uncompressed) 2110708 Bytes = 2 MB

Load Address: 30008000 Entry Point: 30008000 Verifying Checksum ... OK Loading Kernel Image ... OK OK Starting kernel ... Uncompressing Linux............................................................. ...................................................................... done, boo ting the kernel. Linux version 2.6.32.2 (root@localhost.localdomain) (gcc version 4.4.3 (ctng-1.6 .1) ) #11 Wed Jun 1 19:10:07 CST 2011 CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=00007177 CPU: VIVT data cache, VIVT instr tion cache Machine: my mini2440 devolopment board singleboy@163.com ... ... Kernel command line: noinitrd console=ttySAC0,115200 init=/linuxrc mem=64M root= /dev/nfs rw nfsroot=10.1.0.128:/nfsboot/rootfs ip=10.1.0.129:10.1.0.128:10.1.0.1 :255.255.255.0::eth0:off PID hash table entries: 256 (order: -2, 1024 bytes) Dentry cache hash table entries: 8192 (order: 3, 32768 bytes) Inode-cache hash table entries: 4096 (order: 2, 16384 bytes) Memory: 64MB = 64MB total ... ... S3C24XX NAND Driver, (c) 2004 Simtec Electronics s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns s3c24xx-nand s3c2440-nand: NAND soft ECC NAND device: Man?turer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit) Scanning device for bad blocks Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit": 0x000000000000-0x000000040000 : "boot"

44

0x000000040000-0x000000060000 : "param" 0x000000060000-0x000000560000 : "kernel" 0x000000560000-0x000008000000 : "rootfs" 0x000000000000-0x000008000000 : "nand" dm9000 Ethernet Driver, V1.31 eth0: dm9000e at c486e300,c4872304 IRQ 51 MAC: 08:90:90:90:90:90 (chip) ... ... eth0: link up, 100Mbps, full-duplex, lpa 0x45E1 IP-Config: Complete: device=eth0, addr=10.1.0.129, mask=255.255.255.0, gw=10.1.0.1, host=10.1.0.129, domain=, nis-domain=(none), bootserver=10.1.0.128, rootserver=10.1.0.128, rootpath= Looking up port of RPC 100003/2 on 10.1.0.128 Looking up port of RPC 100005/1 on 10.1.0.128 VFS: Mounted root (nfs filesystem) on device 0:14. Freeing init memory: 132K ----------munt all---------------*********************************************** ************booting to mini2440 ***************** Kernel version:linux-2.6.32.2 the fans:singelboy Date:2011.5.30 *********************************************** Please press Enter to activate this console. [root@mini2440 /]#ls bin boot dev etc home lib linuxrc proc mnt root sys sbin usr tmp var

www

[root@mini2440 /]# 可以看到制作的根文件系统内核成功地引导起来了。

【2】将制作根文件系统编译进内核,并制作成 initramfs 文件系统 现在基于 Linux 的发行版通常采用 initramfs 代替 initrd,架构更简单,应用也更灵活一些,不需要创建内 存设备块,能根据文件的大小自动申请或释放内存。 (1) 配置 linux 内核,支持 initramfs 在命令终端的 linux-2.6.32.2 内核目录下 [root@localhost ~]# cd linux-test/linux-2.6.32.2 然后执行 [root@localhost linux-2.6.32.2]# make menconfig General setup --->

45

[*] Initial RAM filesystem and RAM disk (initramfs/initrd) suppor (/root/linux-test/myrootfs/rootfs) Initramfs source file(s) //填写你要制作成 initramfs 格式的根文件系统目 录。 原因很简单,我们使用的是 initramfs,而不是 ramdisk,所以不用配置 ramdisk 的驱动支持项 Device Drivers-->Block devices-->RAM block device support 项。相应的之后的(4096)Default RAM disk size kbytes 等相关默认配置选项就不会再出现了。 另外 initramfs 技术和 ramdisk 技术的另一个重要的区别就是 initramfs 并不是在内存中模拟出一个磁盘 所 , 以也就不在需要 ramdisk 中所需的 ext2 驱动支持。所以,File systems 菜单下的 ext2 文件系统支持< > Second extended fs support 选项就可以取消了。 (2) 进入制作好的根文件系统 rootfs [root@localhost linux-2.6.32.2]# cd ../myrootfs/rootfs [root@localhost rootfs]# 因为 initramfs 根文件系统启动时执行的第一个程序是 init,而不是 linuxrc,所以在此,我们制作的根文件 系统需要添加一个 init 文件,相应的 linuxrc 文件就不再需要了。于是执行 [root@localhost rootfs]# ln -s ./bin/busybox init 这样就为 busybox 创建了一个软链接 init,这个文件就是我们要创建的 init 文件。 (3)修改内核的命令行参数 [root@localhost rootfs]# cd ../../linux-2.6.32.2 [root@localhost linux-2.6.32.2]# vim .config 用/CMD 定位到 CONFIG_CMDLINE 处,修改如下: CONFIG_CMDLINE="console=ttySAC0 mem=64M" (4)重新编译内核 [root@localhost linux-2.6.32.2]# make uImage 按照上面的配置,经过重新编译的内核后将 initramfs 根文件系统直接合并到内核镜像里边了。这样,合二 为一的镜像就不再需要单独烧写根文件系统镜像了,相应的,启动内核时的参数就不需要添加 initrd=…… 来指定 initramfs 的位置了。 (4)启动 u-boot 下载测试 Hit any key to stop autoboot: 0 [u-boot@MINI2440]# usbslave USB host is connected. Waiting a download. Now, Downloading [ADDRESS:31000000h,TOTAL:24052958] RECEIVED FILE SIZE:24052958 (618KB/S, 38S) [u-boot@MINI2440]# bootm 31000000 ... ... NET: Registered protocol family 1 RPC: Registered p transport module. RPC: Registered tcp transport module. 46

RPC: Registered tcp NFSv4.1 backchannel transport module. Kernel panic - not syncing: Out of memory and no killable processes... ... ... 发现确实是小内存的问题,参照文章 http://www.dbanotes.net/database/linux_outofmemory_oom_killer.html 这里需要将 rootfs/lib/modules 目录下的模块文件移除,然后重新编译 [root@localhost ~]# cd linux-test/myrootfs [root@localhost myrootfs]# ls mkrootfs rootfs [root@localhost myrootfs]# mv ./rootfs/lib/modules/* ./ [root@localhost myrootfs]# cd ../linux-2.6.32.2 [root@localhost linux-2.6.32.2]# make uImage 编译完成后生成 uImage 文件,启动 u-boot 下载 [u-boot@MINI2440]# tftp 31000000 uImage dm9000 i/o: 0x20000300, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:00:3e:26:0a:5b operating at 100M full duplex mode Using dm9000 device TFTP from server 10.1.0.128; our IP address is 10.1.0.129 Filename 'uImage'. Load address: 0x31000000 Loading: ################################################################# ################################################################# ################################################################# ################################################################# ################################################################# ############### done Bytes transferred = 6895692 (69384c hex) [u-boot@MINI2440]# bootm 31000000 ## Booting kernel from Legacy Image at 31000000 ... Image Name: Created: Image Type: Data Size: Linux-2.6.32.2 7:00:10 UTC

2011-06-07

ARM Linux Kernel Image (uncompressed) 6895628 Bytes = 6.6 MB

Load Address: 30008000 Entry Point: 30008000 Verifying Checksum ... OK Loading Kernel Image ... OK OK

47

Starting kernel ... Uncompressing Linux............................................................. ................................................................................ ................................................................................ ........................................................ done, booting the kernel. Linux version 2.6.32.2 (root@localhost.localdomain) (gcc version 4.4.3 (ctng-1.6 .1) ) #16 T Jun 7 14:59:55 CST 2011 CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=00007177 CPU: VIVT data cache, VIVT instr tion cache Machine: my mini2440 devolopment board singleboy@163.com Memory policy: ECC disabled, Data cache writeback CPU S3C2440A (id 0x32440001) S3C24XX Clocks, (c) 2004 Simtec Electronics S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256 Kernel command line: noinitrd console=ttySAC0,115200 init=/linuxrc mem=64M root= /dev/nfs rw nfsroot=10.1.0.128:/nfsboot/rootfs ip=10.1.0.129:10.1.0.128:10.1.0.1 :255.255.255.0::eth0:off PID hash table entries: 256 (order: -2, 1024 bytes) Dentry cache hash table entries: 8192 (order: 3, 32768 bytes) Inode-cache hash table entries: 4096 (order: 2, 16384 bytes) Memory: 64MB = 64MB total Memory: 55836KB available (3680K code, 418K data, 4828K init, 0K highmem) SL : Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 Hierarchical RCU implementation. NR_IRQS:85 irq: clearing s pending status 00000003 irq: clearing s pending status 00000002 Console: colour dummy device 80x30 console [ttySAC0] enabled Calibrating delay loop... 50.38 BogoMIPS (lpj=125952) Mount-cache hash table entries: 512 CPU: Testing write b?r coherency: ok NET: Registered protocol family 16 S3C2440: Initialising architecture S3C2440: IRQ Support S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics DMA channel 0 at c4808000, irq 33 DMA channel 1 at c4808040, irq 34 DMA channel 2 at c4808080, irq 35 DMA channel 3 at c48080c0, irq 36 S3C244X: Clock Support, DVS off bio: create slab <bio-0> at 0 48

usbcore: registered new interface driver usbfs usbcore: registered new interface driver h usbcore: registered new device driver usb s3c-i2c s3c2440-i2c: slave address 0x10 s3c-i2c s3c2440-i2c: bus freqncy set to 98 KHz s3c-i2c s3c2440-i2c: i2c-0: S3C I2C adapter NET: Registered protocol family 2 IP route cache hash table entries: 1024 (order: 0, 4096 bytes) TCP established hash table entries: 2048 (order: 2, 16384 bytes) TCP bind hash table entries: 2048 (order: 1, 8192 bytes) TCP: Hash tables configured (established 2048 bind 2048) TCP reno registered NET: Registered protocol family 1 RPC: Registered p transport module. RPC: Registered tcp transport module. RPC: Registered tcp NFSv4.1 backchannel transport module. JFFS2 version 2.2. (NAND) 漏 2001-2006 Red Hat, Inc. ROMFS MTD (C) 2007 Red Hat, Inc. msgmni has been set to 109 alg: No test for stdrng (krng) io scheduler noop registered io scheduler anticipatory registered (default) io scheduler deadline registered io scheduler cfq registered Console: switching to colour frame b?r device 60x53 fb0: s3c2410fb frame b?r device s3c2440- rt.0: s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2440 s3c2440- rt.1: s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2440 s3c2440- rt.2: s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2440 brd: module loaded S3C24XX NAND Driver, (c) 2004 Simtec Electronics s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns s3c24xx-nand s3c2440-nand: NAND soft ECC NAND device: Man?turer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit) Scanning device for bad blocks Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit": 0x000000000000-0x000000040000 : "boot" 0x000000040000-0x000000060000 : "param" 0x000000060000-0x000000560000 : "kernel" 0x000000560000-0x000008000000 : "rootfs" 0x000000000000-0x000008000000 : "nand" dm9000 Ethernet Driver, V1.31 eth0: dm9000e at c486e300,c4872304 IRQ 51 MAC: 08:90:90:90:90:90 (chip) ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver

49

s3c2410-ohci s3c2410-ohci: S3C24XX OHCI s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1 s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000 usb usb1: configuration #1 chosen from 1 choice h 1-0:1.0: USB h found h 1-0:1.0: 2 ports detected usbcore: registered new interface driver libus l mice: PS/2 mouse device common for all mice S3C24XX RTC, (c) 2004,2006 Simtec Electronics i2c /dev entries driver S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled cpuidle: using governor ladder sdhci: Secure Digital Host Controller Interface driver sdhci: Copyright(c) Pierre Ossman usbcore: registered new interface driver hiddev usbcore: registered new interface driver usbhid usbhid: v2.6:USB HID core driver Advanced Linux Sound Architecture Driver Version 1.0.21. No device for DAI A134X No device for DAI s3c24xx-i2s ALSA device list: No soundcards found. TCP c ic registered NET: Registered protocol family 17 drivers/rtc/hctosys.c: unable to open rtc device (rtc0) eth0: link up, 100Mbps, full-duplex, lpa 0x45E1 IP-Config: Complete: device=eth0, addr=10.1.0.129, mask=255.255.255.0, gw=10.1.0.1, host=10.1.0.129, domain=, nis-domain=(none), bootserver=10.1.0.128, rootserver=10.1.0.128, rootpath= Freeing init memory: 4828K ----------munt all---------------*********************************************** ************booting to mini2440 ***************** Kernel version:linux-2.6.32.2 the fans:singleboy Date:2011.5.30 *********************************************** Please press Enter to activate this console. 为了与后续生成的 uImage 文件区别,将这次生成的 uImage 文件备份到 myrootfs 目录下,重命名为 uImag_initramfs

50

[root@localhost linux-2.6.32.2]# cp ./arch/arm/boot/uImage ../myrootfs/uImage_initramfs [root@localhost linux-2.6.32.2]# ls ../myrootfs 2.6.32.2 2.6.32.2-FriendlyARM mkrootfs rootfs uImage_initramfs 为了方便后面的操作,现将之前移除的 rootfs/lib/modules 目录下的文件还原 [root@localhost myrootfs]# ls 2.6.32.2 2.6.32.2-FriendlyARM mkrootfs rootfs uImage_initramfs [root@localhost myrootfs]# mv 2.6.32.2 ./rootfs/lib/modules/2.6.32.2 [root@localhost myrootfs]# mv 2.6.32.2-FriendlyARM ./rootfs/lib/modules/2.6.32.2-FriendlyARM [root@localhost myrootfs]# 然后需要执行 [root@localhost linux-2.6.32.2]# make menconfig General setup ---> [*] Initial RAM filesystem and RAM disk (initramfs/initrd) suppor 按空格键将―[*] Initial RAM filesystem and RAM disk (initramfs/initrd) suppor‖选项关闭。 [ ] Initial RAM filesystem and RAM disk (initramfs/initrd) suppor 然后重新编译。 【3】将制作根文件系统通过 mkyaffs2image 工具制作成 yaffs 文件系统映像文件,然后烧录到 nand flash 中。 (1) 将友善提供的 mkyaffs2image.tgz 包进行解压,即可使用: [root@localhost linux-test]# ls busybox-1.13.3 linux-2.6.39 rootfs_qtopia_qt4

busybox-1.18.4.tar.bz2 mkyaffs2image.tgz rootfs_qtopia_qt4-20110304.tar.gz linux-2.6.32.2 myrootfs yaffs2 然后在 myrootfs 目录下,使用命令 mkyaffs2image rootfs rootfs.img 生成根文件系统映像文件。 [root@localhost linux-test]# tar -vxzf mkyaffs2image.tgz -C / usr/sbin/mkyaffs2image usr/sbin/mkyaffs2image-128M [root@localhost linux-test]# [root@localhost myrootfs]# cd myrootfs [root@localhost myrootfs]# mkyaffs2image-128M rootfs rootfs-128M [root@localhost myrootfs]# ls mkrootfs rootfs rootfs-128M uImage_initramfs [root@localhost myrootfs]# 其中 mkyaffs2image-128M 是用于 128M 及以上的 nand flash。 (2)确认其是否有执行权限 [root@localhost myrootfs]# ll 总计 62760 -rwxr-xr-x 1 root root drwxr-xr-x 17 root root 554 05-30 14:40 mkrootfs 4096 06-02 10:41 rootfs 51

-rw------- 1 root root 57285888 06-07 16:32 rootfs-128M -rw-r--r-- 1 root root 6895692 06-07 16:07 uImage_initramfs 赋予其执行权限 [root@localhost myrootfs]# chmod a+rwx rootfs-128M [root@localhost myrootfs]# ll 总计 62760 -rwxr-xr-x 1 root root drwxr-xr-x 17 root root 554 05-30 14:40 mkrootfs 4096 06-02 10:41 rootfs

-rwxrwxrwx 1 root root 57285888 06-07 16:32 rootfs-128M -rw-r--r-- 1 root root 6895692 06-07 16:07 uImage_initramfs [root@localhost myrootfs]# 否则会产生'Permission denied' (0) 错误。 (2) 下载测试 将生成的 rootfs.img 文件复制到主机的/tftpboot 目录下 [root@localhost myrootfs]# cp -drf rootfs-128M /tftpboot/ [root@localhost myrootfs]# 参数 d 表示保持与库文件的链接关系 (3) 给开发板上电,启动 u-boot 后用 tftp 下载 rootfs 根文件系统 U-Boot 2009.08 modified by singleboy (singleboy@163.com) Love Linux forever!! I2C: ready

DRAM: 64 MB Flash: 2 MB NAND: 128 MiB Video: 240x320x16 20kHz 62Hz In: Out: Err: Net: serial serial serial dm9000

U-Boot 2009.08 modified by singleboy(singleboy@163.com) Love Linux forever!!! Hit any key to stop autoboot: 0 [u-boot@MINI2440]# tftp 30008000 rootfs-128M dm9000 i/o: 0x20000300, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:00:3e:26:0a:5b operating at 100M full duplex mode Using dm9000 device 52

TFTP from server 10.1.0.128; our IP address is 10.1.0.129 Filename 'rootfs-128M'. Load address: 0x30008000 Loading: ################################################################# ################################################################# ...... ################################################################# ####################################################### done Bytes transferred = 55678656 (35196c0 hex) [u-boot@MINI2440]# OK!下载成功。将其烧录到 nand flash,注意,nand flash 分区表 Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit": 0x000000000000-0x000000040000 : "boot" 0x000000040000-0x000000060000 : "param" 0x000000060000-0x000000560000 : "kernel" 0x000000560000-0x000008000000 : "rootfs" 0x000000000000-0x000008000000 : "nand" rootfs 起始地址是 560000。 [u-boot@MINI2440]# nand erase 0x560000 0x3600000 NAND erase: device 0 offset 0x560000, size 0x3600000 Erasing at 0x3b4000000000000 -OK [u-boot@MINI2440]# nand write 0x30008000 0x560000 0x3600000 NAND write: device 0 offset 0x560000, size 0x3600000 Writing at 0x3b4000000020000 -- 100% is complete. 56623104 bytes written: OK 重启开发板 ... ... VFS: Mounted root (yaffs filesystem) on device 31:3. Freeing init memory: 132K Warning: unable to open an initial console. Failed to execute /linuxrc. Attempting defaults... Kernel panic - not syncing: No init found. 问题分析:rootfs 能够在 nfs 根文件系统中启动,nfs 只能验证文件系统本身,而不能验证 yaffs2 格式的支 持,重新设定引导参数从 nfs 启动,然后进入控制台将分别挂载/dev/mtdbolck0~3 分区。 接下来,要解决 nand flash 的 mtd 分区的操作工具问题 0% complete.

53

Linux-2.6.32.2 内核在 mini2440 上的移植(四)---根文件系统制作(2)
2011-06-16 18:22:38| 分类: Linux 内核移植 | 标签: |字号大中小 订阅 移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 接上篇,问题的解决 解题思路:用 tar 压缩我自己做的 rootfs 根文件系统打包, 这个系统是可以启动到 NFS 的,所以东西是全 的。然后用 nand flash 工具将 nand flash 的 mtdblock3 分区格式化后挂载,再将打包的 rootfs 下所有子目 录和文件解压到此分区。 【4】挂载分区测试 按照之前内核引导参数的设定方式,将 u-boot 的 bootgars 参数设为 nfs 启动 [root@mini2440 /]#mount -t yaffs /dev/mtdblock1 /mnt/yaffs yaffs: dev is 32505857 name is "mtdblock1" rw yaffs: passed flags "" mount: mounting /dev/mtdblock1 on /mnt/yaffs failed: Invalid argument [root@mini2440 /]#mount -t yaffs /dev/mtdblock0 /mnt/yaffs yaffs: dev is 32505856 name is "mtdblock0" rw yaffs: passed flags "" mount: mounting /dev/mtdblock0 on /mnt/yaffs failed: Invalid argument [root@mini2440 /]#umount /mnt/yaffs [root@mini2440 /]#mount -t yaffs /dev/mtdblock2 /mnt/yaffs yaffs: dev is 32505858 name is "mtdblock2" rw yaffs: passed flags "" [root@mini2440 /]#ls -a /mnt/yaffs . .. lost+found

[root@mini2440 /]#umount /mnt/yaffs [root@mini2440 /]#mount -t yaffs /dev/mtdblock3 /mnt/yaffs yaffs: dev is 32505859 name is "mtdblock3" rw yaffs: passed flags "" [root@mini2440 /]#ls -a /mnt/yaffs . .. lost+found

[root@mini2440 /]#cat proc/mtd dev: size erasesize name

mtd0: 00040000 00020000 "boot" mtd1: 00020000 00020000 "param" mtd2: 00500000 00020000 "kernel" mtd3: 07aa0000 00020000 "rootfs" mtd4: 08000000 00020000 "nand" [root@mini2440 /]# 根据挂载的反馈信息,可以确定 mtdblock0 和 mtdblock1 分别是 u-boot 和其参数的分区而不能够被挂载, mtdblock2 和 mtdblock3 分别是内核 kernel 和根文件系统 rootfs 分区能够被挂载。虽然成功挂载了 yaffs 文件系统,但不能从中读取因存在的文件信息。 54

【5】制作在 nand flash 操作工具 mtd-utils 工具 参考文章 mtd-utils 工具的编译和使用 mtd-utils 及 i-utils 交叉编译 mtd-utils 交叉编译 UBI 文件系统简介 在 ubuntu 10.04 上交叉编译编译 mtd-utils 交叉编译 libz, lzo, mtd-utils 的脚本 对于 mtd-utils 工具的编译,可谓是费了不少周折,着重参考了上面几篇文章,可以用以下两种办法来解决 其 libz,lzo,uuid 库的依赖问题 <1>手动安装 mtd-utils 所需要的库 A ,下载源代码: zlib 和 lzo 是编译 mtd-utils 所需库文件,需提前交叉编译完成,以供 mtd-utils 编译时调用 zlib: http://www.zlib.net/zlib-1.2.5.tar.gz http://www.dnaphp.com/downloads/server/linux/30-zlib-1-2-5-tar lzo: http://www.oberhumer.com/opensource/lzo/download/,这里下载是 lzo-2.05.tar.gz E2fsprogs: http://e2fsprogs.sourceforge.net/,这里下载的是 e2fsprogs-1.41.14.tar.gz mtd-utils: ftp://ftp.infradead.org/p /mtd-utils/ 下载后 [root@localhost linux-test]# cd mtdtools [root@localhost mtdtools]# ls e2fsprogs-1.41.14.tar.gz mtd-utils-1.4.4.tar.bz2 lzo-2.05.tar.gz zlib-1.2.5.tar.gz

可以在打开的页面中下载最新版本,分别对其进行解压 [root@localhost mtdtools]# tar -zxf zlib-1.2.5.tar.gz [root@localhost mtdtools]# tar -zxf lzo-2.05.tar.gz [root@localhost mtdtools]# tar -jxf mtd-utils-1.4.4.tar.bz2 -C ./

55

B,编译安装 zlib [root@localhost linux-test]# cd zlib-1.2.5 [root@localhost zlib-1.2.5]#CC=arm-linux-gcc ./configure --enable-static --disable-shared

--prefix=/usr/local/arm/4.4.3/arm-none-linux-gnueabi [root@localhost zlib-1.2.5]# make [root@localhost zlib-1.2.5]# make install 检查: zconf.h 和 libz.a 都安装到了工具链目录. 其中-prefix 指定 zlib 的安装路径,需要指定到交叉编译器所在路径,而且是与命令执行的 bin 文件夹同一 级别的目录下而非软连接的 bin 目录! C,编译安装 lzo [root@localhost zlib-1.2.5]# cd ../lzo-2.05 [root@localhost lzo-2.05]#CC=arm-linux-gcc ./configure --host=arm-linux --enable-static

--disable-shared --prefix=/usr/local/arm/4.4.3/arm-none-linux-gnueabi [root@localhost lzo-2.05]# make [root@localhost lzo-2.05]# make install 检查:liblzo2.a 已经拷贝到工具链的 lib 目录. 解决错误现象:error: lzo/lzo1x.h: No s h file or director D,编译安装 e2fsprogs 配置 e2fsprogs [root@localhost e2fsprogs-1.41.14]#CC=arm-linux-gcc ./configure --host=arm-linux

--prefix=/usr/local/arm/4.4.3/arm-none-linux-gnueabi 编译 [root@localhost e2fsprogs-1.41.14]# make 安装,因为我们只需要 uuid 库, 所以不需要完全安装, 查看 Makefile 文件, 所以只执行 make install-libs [root@localhost e2fsprogs-1.41.14]# make install-libs 检查,可以在工具链目录看到, uuid/uuid.h 文件已经安装. libuuid.a 已经安装. 解决错误现象:uuid/uuid.h: No s h file or directory E,编译安装 mtd-uitls 进入到 mtd-uitls 目录所在的目录,在 make 时需要指定交叉编译工具 [root@localhost lzo-2.05]# cd ../mtd-utils-1.4.4 [root@localhost mtd-utils-1.4.4]# mkdir mtd_install [root@localhost mtd-utils-1.4.4]# export CROSS=arm-linux[root@localhost mtd-utils-1.4.4]# export WITHOUT_XATTR=1 [root@localhost mtd-utils-1.4.4]# export DESTDIR=./mtd_install 需要指定 WITHOUT_XATTR=1 是由于在编译 mkfs.jffs2 使其不调用 acl.h 而是用 zlib 的库,否则出现

56

sys/acl.h:mkfs.jffs2.c:69:21: error: sys/acl.h: No s h file or directory

直接编译: make make install 检查 1:mtdtools/mtd-utils-1.4.4/arm-linux(即所指定的 CROSS)目录已经拷贝了所有 mtd-utils 的工具. 检查 2:file flash_erase flash_erase: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped 上面信息有两点要注意, 第一是使用静态/动态库,第二是没有 striped/not triped。 这里 strip 是用来去除编译出来的命令中的 debug 信息的。 如果 file 出的信息是 dynamically linked 和 stripped ,那么要在目标板上执行此程序,需要将编译器的 lib 目录下所有库文件复制到目标板的 lib 目录下,如果不想使用库文件,就要编译成静态链接方式: 查看 mtd-utils-1.4.4 的 common.mk 文件,发现有 CFLAGS ?= -O2 -g 编译选项。 所以再加上一个选项: export CFLAGS="-static -O2 -g" 重新运行 make 和 make install 后发现 file flash_erase flash_erase: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped 遗留问题 1 显然采用-static 方式编译后,仍然是动态链接方式,这个问题目前也是悬而未决。 目前也只能采用复制库的方式。 F,去掉调试信息: 在当前目录的 mtd_intall/usr/sbin 下运行 arm-linux-strip * //注意*前面有一空格 再次检查:file flash_erase flash_erase: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped 完成, 编译出来的工具如: flash_eraseall, ubimkvol, ubiattach 等都可以独立运行而不需要链接库文件。 下面是有关 trip 一些用法: strip 经常用来去除目标文件中的一些符号表、调试符号表信息,以减小程序的大小,在 rpmbuild 包的最后 就用到。 其支持的选项如下:

57

>strip -h 用法:strip <选项> 输入文件 从文件中删除符号和节 选项为: -I --input-target=<bfdname> -O --output-target=<bfdname> -F --target=<bfdname> -p --preserve-dates Assume input file is in format <bfdname> Create an output file in format <bfdname> Set both input and output format to <bfdname> Copy modified/access timestamps to the output Remove section <name> from the output

-R --remove-section=<name> -s --strip-all -g -S -d --strip-debug --strip-unneeded --only-keep-debug -N --strip-symbol=<name> -K --keep-symbol=<name> --keep-file-symbols -w --wildcard -x --discard-all -X --discard-locals -v --verbose -V --version -h --help --info -o <file> strip : 支 持 的 目 标 : ecoff-littlealpha elf64-little

Remove all symbol and relocation information Remove all debugging symbols & sections Remove all symbols not needed by relocations Strip everything but the debug information Do not copy symbol <name> Do not strip symbol <name> Do not strip file symbol(s) Permit wildcard in symbol comparison Remove all non-global symbols Remove any compiler-generated symbols List all object files modified Display this program's version number Display this output List object formats & architectures supported Place stripped output into <file> elf32-i386 a.out-i386-linux efi-app-ia32 elf32-little elf32-big elf64-alpha elf64-big elf32-littlearm elf32-bigarm elf32-hppa-linux elf32-hppa

elf64-ia64-little elf64-ia64-big efi-app-ia64 elf32-m68k a.out-m68k-linux elf32-powerpc aixcoff-rs6000 elf32-powerpcle ppcboot elf64-powerpc elf64-powerpcle aixcoff64-rs6000 elf32-s390 elf64-s390 elf32-sparc a.out-sparc-linux elf64-sparc a.out-sunos-big elf64-x86-64 pe-i386 pei-i386 srec symbolsrec tekhex binary ihex trad-core 目标文件分为:可重定位文件、可执行文件、共享文件 strip 的默认选项会去除.symbol 节的内容以及.debug 节的内容 因此尽量只对可执行文件执行 strip 而不要 , 对静态库或动态库等目标文件 strip。

可见无论是静态库(libxxx.a)还是动态库(libxxx.so)还是可执行文件(如 test),去掉一些符号信息后都减小了 很多,但如果这时再链接这两个库的话是编不过的,因此,如果不是指定特殊的 strip 选项的话,还是尽量 不要对库文件 strip,只对链接后的可执行文件 strip 就可以了(如果也不调试)。

<2>制作脚本文件,使其自动生成 mtd-utils 工具。 A,在 mtdtools 目录下新建一个文件 mtdtools_build.sh,将下面内容复制其中,此文件我在 GuoWenxue 博主的基础上做了一些改动经过调试运行完成。

58

#!/bin/sh #+----------------------------------------------------------------------------+ #|decription: This shell script is used to download lzo,zlib,e2fsporgs, #| mtd-utils source code and cross compile it for ARM Linux, #| all is static cross compile. #| Author: GuoWenxue <guowenxue@gmail.com>

#| Modified: singleboy <singleboy@163.com> #| ChangeLog: #| 1, Initialize 1.0.1 on 2011.06.16

#+----------------------------------------------------------------------------+ PRJ_PATH=`pwd` #CROSS=arm-linuxCROSS=arm-none-linux-gnueabi#COMPILER_PATH=/usr/local/arm/4.4.3/arm-none-linux-gnueabi #COMPILER_PATH=/usr/local/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi CC=${CROSS}gcc AR=${CROSS}ar LD=${CROSS}ld STRIP=${CROSS}strip NM=${CROSS}nm RANLIB=${CROSS}ranlib OBJDUMP=${CROSS}objdump export CC=${CC} export AR=${AR} export LD=${LD} export STRIP=${STRIP} export NM=${NM} export RANLIB=${RANLIB} export OBJDUMP=${OBJDUMP} LZO="lzo-2.05" ZLIB="zlib-1.2.5" E2FSPROGS="e2fsprogs" function decompress_packet() ( echo "+----------------------------------------+" echo "| Decompress $1 now" echo "+----------------------------------------+" if [ `ls $1 | grep "tar.bz2"` ] ; then set -x tar -xjf $1 set +x fi 59

if [ `ls $1 | grep "tar.gz"` ] ; then set -x tar -xzf $1 set +x fi )

echo "+----------------------------------------+" echo "| Cross compile $ZLIB now " echo "+----------------------------------------+" # Download zlib source code packet if [ ! -s $ZLIB.tar* ] ; then #wget http://www.zlib.net/$ZLIB.tar.gz wget http://www.imagemagick.org/download/delegates/$ZLIB.tar.bz2 fi # Decompress zlib source code packet if [ ! -d $ZLIB ] ; then decompress_packet $ZLIB.tar.* fi #Cross compile zlib cd $ZLIB echo "first clean the middle object files befor compiling in case of incompatible compiled error" make clean if [ ! -s libz.a ] ; then unset LDFLAGS ./configure --static make fi cd -

echo "+----------------------------------------+" echo "| Cross compile $LZO now " echo "+----------------------------------------+" # Download lzo source code packet if [ ! -s $LZO.tar.gz ] ; then wget http://www.oberhumer.com/opensource/lzo/download/$LZO.tar.gz fi # Decompress lzo source code packet if [ ! -d $LZO ] ; then decompress_packet $LZO.tar.* fi

60

# Cross compile lzo cd $LZO echo "first clean the middle object files befor compiling in case of incompatible compiled error" make clean if [ ! -s src/.libs/liblzo*.a ] ; then unset LDFLAGS ./configure --host=arm-linux --enable-static --disable-shared \ CC=${CROSS}gcc AR=${AR} LD=${LD} \ NM=${NM} RANLIB=${RANLIB} STRIP="${STRIP}" OBJDUMP=${OBJDUMP} make fi cd -

echo "+----------------------------------------+" echo "| Cross compile $E2FSPROGS now " echo "+----------------------------------------+" # Download e2fsprogs source code packet if [ ! -s $E2FSPROGS.tar* ] ; then #wget http://cdnetworks-kr-1.dl.sourceforge.net/project/e2fsprogs/e2fsprogs/1.41.14/e2fsprogs-1.41.14. tar.gz git clone git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git fi # Decompress e2fsprogs source code packet if [ ! -d $E2FSPROGS ] ; then decompress_packet $E2FSPROGS.tar.* fi #Cross compile e2fsprogs cd $E2FSPROGS # echo "first make clean the middle object files" echo "first clean the middle object files befor compiling in case of incompatible compiled error" # make clean

if [ ! -s libuuid.a ] ; then unset LDFLAGS ./configure --host=arm-linux --enable-static --disable-shared \ CC=${CROSS}gcc AR=${AR} LD=${LD} \ NM=${NM} RANLIB=${RANLIB} STRIP="${STRIP}" OBJDUMP=${OBJDUMP} make fi cd -

echo "+----------------------------------------+"

61

echo "| Cross compile mtd-utils now " echo "+----------------------------------------+" if [ -s mtd-utils.tar.* ] ; then decompress_packet mtd-utils.tar.* fi # download mtd-utils source code if [ ! -d mtd-utils ] ; then git clone git://git.infradead.org/mtd-utils.git fi #Add the CROSS tool in file mtd-utils/common.mk #head -1 mtd-utils/common.mk | grep "CROSS=${CROSS}" #if [ 0 != $? ] ; then # # #fi cd mtd-utils echo "first clean the middle object files befor compiling in case of incompatible compiled error" make clean unset LDFLAGS export CFLAGS="-DWITHOUT_XATTR -I$PRJ_PATH/$ZLIB -I$PRJ_PATH/$LZO/include echo "Modify file mtd-utils/common.mk" sed -i -e 1i"CROSS=${CROSS}" mtd-utils/common.mk

-I$PRJ_PATH/$E2FSPROGS/lib/" export ZLIBLDFLAGS=-L$PRJ_PATH/$ZLIB export LZOLDFLAGS=-L$PRJ_PATH/$LZO/src/.libs export E2FSPROGSLDFLAGS=-L$PRJ_PATH/$E2FSPROGS/lib export LDFLAGS=-static make CROSS=${CROSS} echo "now build the mtd-utils tools directory to install" if [ ! -d usrdir ] ; then mkdir usrdir echo "the directory to install is usrdir" fi make CROSS=${CROSS} DESTDIR=./usrdir install # remove the debug infomation with trip command # BUILDDIR=${CROSS%-} # echo "now entering ${BUILDDIR} ..." # cd ${BUILDDIR} echo "now entering the directory usrdir/usr/sbin" cd usrdir/usr/sbin echo "now remove the debug infomation with trip command" ${CROSS}strip * file * echo "now the mtd-utils has been made completely and you can copy the tools in ./usrdir/usr/sbin/ to your target directory/usr/sbin/" 62

cd cd 遗留问题 2 说 明 , 这 个 脚 本 arm-none-linux-gnueabi-gcc v 4.5.1 版 本 中 执 行 成 功 , 但 是 在 arm-linux-gcc(arm-none-linux-gnueabi-gcc v4.4.3) 没 有 执 行 成 功 , 出 现 ―Unknown mandatory EABI object attribute 44‖错误,目前还未查清原因。 以下是脚本在 v4.5.1 版本运行的部分信息: [root@localhost mtdtools]#./mtdtools_build.sh ... ... now entering the directory usrdir/usr/sbin now remove the debug infomation with trip command arm-none-linux-gnueabi-strip:flash_eraseall: File format not recognized docfdisk: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped doc_loadbios: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped flashcp: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically linked,

for GNU/Linux 2.6.16, stripped flash_erase: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped flash_eraseall: Bourne shell script text executable flash_info: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped flash_lock: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped flash_otp_dump: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically linked, for GNU/Linux 2.6.16, stripped flash_otp_info: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically linked, for GNU/Linux 2.6.16, stripped flash_unlock: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped ftl_check: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped ftl_format: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped jffs2dump: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped mkfs.jffs2: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped mtd_debug: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped nanddump: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically 63

linked, for GNU/Linux 2.6.16, stripped nandtest: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped nandwrite: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped nftldump: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped nftl_format: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped recv_image: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped rfddump: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped rfdformat: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped serve_image: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped sumtool: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, statically

linked, for GNU/Linux 2.6.16, stripped now the mtd-utils has been made completely and you can copy the tools in ./usrdir/usr/sbin/ to your target directory/usr/sbin/ /root/linux-test/mtdtools/mtd-utils /root/linux-test/mtdtools/mtd-utils/usrdir/usr/sbin [root@localhost mtdtools]# ls mtd-utils/arm-none-linux-gnueabi/ compr_lzo.o compr.o flash_erase flash_info ftl_format jffs2dump lib nanddump nandtest nandwrite rfddump

rfdformat serve_image sumtool

compr_rtime.o flash_lock compr_zlib.o docfdisk

flash_otp_dump mkfs.jffs2

nftldump

flash_otp_info mkfs.jffs2.o nftl_format ubi-utils flash_unlock mkfs.ubifs rbtree.o

doc_loadbios flashcp

ftl_check

mtd_debug

recv_image

[root@localhost mtdtools]# 其中 mkfs.ubifs 目录中存放的是制作 ubifs 文件系统映像的工具,ubi-utils 目录中存放的是 ubifs 文件系统 的操作工具。 接下来,将回到前面遗留问题即 mtdblock 分区加载和挂载根目录问题

64

Linux-2.6.32.2 内核在 mini2440 上的移植(四)---根文件系统制作(3)
2011-06-20 15:15:00| 分类: Linux 内核移植 | 标签: |字号大中小 订阅 移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 接上篇,回到 nand flash 分区的挂载问题 【6】 将上篇文章中制作好的 mtd-uitls 工具位于/root/linux-test/mtdtools/mtd-utils/usrdir/sbin 目录下工具复 制到已经制作的根文件系统的 usr/sbin 目录下 [root@localhost mtdtools]# cp -a mtd-utils/usrdir/usr/sbin/* /nfsboot/rootfs/usr/sbin/ [root@localhost mtdtools]# 【7】测试 mtd 工具的正确性,有关 mtd 工具的使用请参考 mtd-utils 工具的使用 在 min2440 启动后,在终端中运行 [root@mini2440 /]#flash_info Illegal instruction [root@mini2440 /]# 网上搜索发现,illegal instruction 是非法指令,出现 illegal instruction 的原因是程序收到了 SIGILL 信 号,而这个信号是 cpu 在发现非法指令之后发出一个异常,然后由负责处理该异常的内核的 ISR 对含有这 个非法指令的进程发出的。程序收到这个信号,一般就是报告 illegal instruction 错误信息。 可执行程序含有非法指令的原因,一般也就是 cpu 架构不对,编译时指定的 march 和实际执行的机器 的 march 不同 这种情况 因为工具链一样 连接脚本一样 所以可执行程序可以执行 不会发生 exec format 。 , , , , error。但是会包含一些不兼容的指令。还有另外一种可能,就是程序的执行权限不够,比如在目态下运行 的程序只能执行非特权指令,一旦 CPU 遇到特权指令,将产生 illegal instruction 错误。 在系统运行过程中,处理机状态是动态变化的。从目态转换为管态只能通过中断来实现。从管态到目 态的转换可通过修改程序状态字 PSW 来实现 很有可能是你编译和运行的 CPU 架构或者内核不一样导致 。 。 另外,linux 是 sysV 风格的 UNIX 系统,freeBSD 是 BSD 风格的 UNIX 系统。 编译器支持新的嵌入式应用程序二进制接口标准 EABI,而 kernel 默认并未打开对 eabi 的支持,编绎使用 的是非 EABI 的编译器。这时需要 Kernel Features ---> [*] Use the ARM EABI to compile the kernel (CONFIG_AEABI=y) [*] Allow old ABI binaries to run with this kernel (EXPERIMENTA) (CONFIG_OABI_COMPAT=y)

尝试方式一 配置内核打开 eabi 和 old eabi 支持选项,然后复制编译器下 lib 库文件到目标板 lib 库中(arm-linux-gcc v4.4.3) [root@localhost ~]# cp -a /usr/local/arm/4.4.3/lib/ /nfsboot/rootfs/lib [root@localhost ~]# 然后用 arm-linux 重新编译生成的工具位于 mtdtools/mtd-utils/mtd_install/usr/sbin 复制到根目录 usr/sbin 65

[root@localhost ~]# cp -a ./linux-test/mtd-utils-1.4.4/mtd_install/usr/sbin/ /nfsboot/rootfs/usr/sbin 再次启动 min2440 后,在终端中运行 [root@mini2440 /]#flash_info Illegal instruction [root@mini2440 /]# 经过仔细检查,上面的操作有点问题,就是 cp 的的结果是 lib 下又建了一个 lib 目录,sbin 下又建了一个 sbin 目录,现在分别将 lib 下的 lib 子目录和 sbin 下的 sbin 子目录的文件移动到上一级的目录中,替换掉 之前已经存在相应文件,正确的操作 [root@localhost ~]# cp -av /usr/local/arm/4.4.3/lib/* /nfsboot/rootfs/lib [root@localhost ~]# cp -av ./linux-test/mtd-utils-1.4.4/mtd_install/usr/sbin/* /nfsboot/rootfs/usr/sbin [root@mini2440 /]#flash_info Usage: flash_info device OK,总算得到了可以在目标板上执行的 mtd 操作工具! 尝试方式二 参 考 Illegal instruction 的 解 决 方 法 这 篇 文 章 , 把

/usr/local/arm/compiler/arm-none-linux-gnueabi/libc/armv4t/lib 目录(也就是你的编译器的库目录)下的所有 文件拷贝到根目录的 lib 目录下,然后修改内核 Makefile 使 CROSS=arm-none-linux-gnueabi- (即 v4.5.1 版本,arm-linux-是友善官方提供的 4.4.3 版本)。 (1)修改 linux-2.6.32.2 根目录下 Makefile 的 CROSS_COMPILE [root@localhost linux-2.6.32.2]# vim Makefile 打开编辑器后在命令模式下执行 /CROSS 然后定位到 export KBUILD_BUILDHOST := $(SUBARCH) ARCH ?= arm ?= arm-none-linux-gnueabi-

CROSS_COMPILE

# Architecture as present in compile.h 然后保存退出,执行 [root@localhost linux-2.6.32.2]# make clean [root@localhost linux-2.6.32.2]# make uImage 重新生成 uImage 映像 (2)将编译内核的编译器用 lib 库复制到目标板根文件系统的 lib 目录下 [root@localhost linux-2.6.32.2]# cp -a /usr/local/arm/compiler/arm-none-linux-gnueabi/libc/armv4t/lib/* /nfsboot/rootfs/lib 这里将方式二作为备用处理手段放到这里。

66

【8】首先了解下/dev/mtd 和/dev/mtdblock 的区别 (1)/dev/mtdn 是 linux 中的 MTD 架构中,系统自己实现的 mtd 分区所对应的字符设备,其里面添加了一些 ioctl,支持很多命令,如 MEMGETINFO,MEMERASE 等。而 mtd-util 中的 flash_eraseall 等工具,就是 以这些 ioctl 为基础而实现的工具,实现一些关于 flash 的操作,比如,mtd 工具中的 flash_erase 等。 if(ioctl(fd,MEMGETINFO,&meminfo) != 0) { perror("MEMGETINFO"); close(fd); exit(1); } 其中,MEMGETINFO,就是 linux mtd 中的\drivers\mtd\nand\mtdchar.c 中的: case MEMGETINFO: info.type = mtd->type; info.flags = mtd->flags; info.size = mtd->size; info.erasesize = mtd->erasesize; info.writesize = mtd->writesize; info.oobsize = mtd->oobsize; /* The below fields are obsolete */ info.ecctype = -1; info.eccsize = 0; if (copy_to_user(argp, &info, sizeof(struct mtd_info_user))) return -EFAULT; break; 而/dev/mtdblockn,是 NandFlash 驱动中,驱动在用 add_mtd_partitions()添加 MTD 设备分区而生成的对 应的块设备。根据以上内容也更加明白,为什么不能用 nandwrite,flash_eraseall,flash_erase 等工具去 对/dev/mtdblockn 去操作了,因为/dev/mtdblock 中不包含对应的 ioctl,不支持你这么操作。 (2)mtd char 设备的主设备号是 90;而 mtdblock 设备的主设备号是 31; 此设备号定义在\include\linux\mtd\mtd.h 中 (3)mtd 块设备的大小可以通过查看分区信息来得到: [root@mini2440 /]#cat proc/partitions major minor #blocks name 31 31 31 31 31 0 1 2 3 4 256 mtdblock0 128 mtdblock1 5120 mtdblock2 125568 mtdblock3 131072 mtdblock4

[root@mini2440 /]#

67

上面显示的块设备的大小,是 block 的数目,每个 block 是 1KB;而每个字符设备,其实就是对应着上面 的饿每个设备,即/dev/mtd0 对应/dev/mtdblock0,以此类推,换句话说,mtdblockn 的一些属性,也就是 mtdn 的属性,比如大小。 (4)对每个 mtd 字符设备的操作 比如利用 nandwrite 去对/dev/mtd0 写数据 实际就是操作/dev/mtdblock0 , , 。 而这些操作里面涉及到得 offset 都指的是 mtd 分区内的偏移。比如向/dev/mtd1 的 offset 为 0 的位置写入 数据,实际操作的物理偏移是 offset=/dev/mtd0 的大小=128KB。 【9】向 mtdblock3 分区中写入根文件系统 (1)查看分区信息 [root@mini2440 /]#mtd_debug info /dev/mtd3 mtd.type = MTD_NANDFLASH mtd.flags = MTD_CAP_NANDFLASH mtd.size = 128581632 (122M) mtd.erasesize = 131072 (128K) mtd.writesize = 2048 (2K) mtd.oobsize = 64 regions = 0 (2)擦除 nand 的 mtd3 分区 [root@mini2440 /]#flash_erase dev/mtd3 0x560000 0x1e0 Erasing 128 Kibyte @ 4140000 -- 100 % complete [root@mini2440 /]#mount -t yaffs dev/mtd3 mnt/yaffs mount: mounting dev/mtd3 on mnt/yaffs failed: Block device required [root@mini2440 /]#mount -t yaffs dev/mtdblock3 mnt/yaffs yaffs: dev is 32505859 name is "mtdblock3" rw (3)挂载/dev/mtdblock3 到/mnt/yaffs [root@mini2440 /mnt]#ls yaffs [root@mini2440 /mnt]#mount -t yaffs /dev/mtdblock3 yaffs yaffs: dev is 32505859 name is "mtdblock3" rw yaffs: passed flags "" (4)将打包好的 rootfs.tar.gz 文件系统解压到刚刚挂载的 yaffs 目录下,注意要去掉其结对路径,解压后显示 的是根文件系统内容 [root@mini2440 /mnt]#ls yaffs bin boot dev etc home init lib mnt linuxrc proc sbin sys tmp usr var www

lost+found root

【10】修改 u-boot 启动参数,从 mtdblock3 引导 [u-boot@MINI2440]# setenv bootargs 'noinitrd console=ttySAC0,115200 init=/linuxr c mem=64M root=/dev/mtdblock3 rw rootfstype=yaffs ip=10.1.0.129:10.1.0.128:10.1. 0.1:255.255.255.0::eth0:off' [u-boot@MINI2440]# saveenv

68

Saving Environment to NAND... Erasing Nand... Erasing at 0x4000000000002 -Writing to Nand... done [u-boot@MINI2440]# 【11】重启开发板后,检查启动信息 ... ... IP-Config: Complete: device=eth0, addr=10.1.0.129, mask=255.255.255.0, gw=10.1.0.1, host=10.1.0.129, domain=, nis-domain=(none), bootserver=10.1.0.128, rootserver=10.1.0.128, rootpath= yaffs: dev is 32505859 name is "mtdblock3" rwyaffs: passed flags "" VFS: Mounted root (yaffs filesystem) on device 31:3. Freeing init memory: 112K ----------munt all---------------*********************************************** ************booting to mini2440 ***************** Kernel version:linux-2.6.32.2 the fans:singleboy Date:2011.5.30 *********************************************** Please press Enter to activate this console. 可以看根系统成功地引导起来了。 这也说明之前用来制作 yaffs 映像的工具存在问题。 【12】总结 为了能够从 nand flash 引导根文件系统,整个过程可谓比较曲折,不过通过学习和研究,获得了其它途径 来解决此问题也有简便办法。 (1)挂载 nfs 文件系统,确保整个系统能够从 nfs 正确引导。 (2)确保能够在启动信息中看到有关 yaffs 信息,否则说明 yaffs 文件系统本身存在问题 (3)尝试从 nfs 启动的系统中挂载 mtdblockx 分区,由于系统本身并未带 mtd 工具,注意 mtd 工具的制作。 (4)在挂载 mtdblockx 成功后,可以 nfs 服务器端直接将根文件系统打包到 nfs 根文件系统的 root 或 home 目录下 然后再到开发板的控制终端中将根文件系统解压到 mtdblock 分区中 注意一定要去掉其绝对路径 , , 。 (5)修改 u-boot 启动参数从 mtdblockx 引导。 遗留问题,UBI 文件系统在 u-boot 和 linux 系统上的移植 接下来,将进行内核的 RTC 驱动移植 0% complete.

69

Linux-2.6.32.2 内核在 mini2440 上的移植(五)---激活 RTC 驱动
2011-06-20 21:31:02| 分类: Linux 内核移植 | 标签: |字号大中小 订阅 移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 1,主机环境:VMare 下 CentOS 5.5 ,1G 内存。 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。 4,开发板:mini2440,2M nor flash,128M nand flash。 5,u-boot 版本:u-boot-2009.08 6,linux 版本:linux-2.6.32.2 7,参考文章: 嵌入式 linux 应用开发完全手册,韦东山,编著。 Mini2440 之 Linux 移植开发实战指南 【1】在初始化文件中加入 RTC 设备结构 Linux-2.6.32.2 内核对 2440 的 RTC 驱动已经十分完善了,但并未在 mach-mini2440.c 中的设备集中加 入它,因此并没有被激活,加入 RTC 结构体如下红色字体: 打开/arch/arm/mach-s3c2440/mach-mini2440.c,定位到 249 行附近,修改如下 static struct platform_device *mini2440_devices[] __initdata = { &s3c_device_usb, &s3c_device_rtc, &s3c_device_lcd, &s3c_device_wdt, &s3c_device_i2c0, &s3c_device_iis, &s3c_device_nand, //;把 nand flash 设备添加到开发板的设备列表结构 &mini2440_device_eth,//;把网卡平台设备添加到开发板的设备列表结构 }; 【2】在内核中配置 RTC 接下来重新配置内核,以加入 RTC 的驱动支持,依次选择如下菜单项: Device Drivers ---> <*> Real Time Clock ---> <*> Samsung S3C series SoC RTC //这里才是内核中真正的 2440 之 RTC 驱动配置项。

确认完毕后,退出。 【3】测试 RTC 70

[root@localhost linux-2.6.32.2]# make uImage 编译生成 uImage 之后,将其复制到/nfsboot 目录下,因为现在内核还是被放在此位置启动。然后重启开发 板。 [root@mini2440 /]#ls -l dev/rtc* crw-rw---1 root root 254, 0 Jan 1 00:00 dev/rtc0

[root@mini2440 /]# 在 Linux 中有硬件时钟与系统时钟两种时钟。硬件时钟是指主机板上的时钟设备,也就是通常可在 BIOS 画面设定的时钟。系统时钟则是指 kernel 中的 时钟。当 Linux 启动时,系统时钟会去读取硬件时钟的设定, 之後系统时钟即独立运作。所有 Linux 相关指令与函数都是读取系统时钟的设定。 hwclock 实现了 BIOS 和 linux 的时间同步 既然 Linux 有两个时钟系统,那么大家所使用的 Linux 默认使用哪种时钟系统呢?会不回出现两种系统时 钟冲突的情况呢?这些疑问和担心不无道理。首先,Linux 并没有默认哪个时钟系统。当 Linux 启动时,硬 件时钟会去读取系统时钟的设置,然后系统时钟就会独立于硬件运作。 从 Linux 启动过程来看,系统时钟和硬件时钟不会发生冲突,但 Linux 中的所有命令(包括函数) 都是采用 的系统时钟设置。不仅如此,系统时钟和硬件时钟还可以采用异步方式,即系统时间和硬件时间可以不同。 这样做的好处对于普通用户意义不大,但对于 Linux 网络管理员却有很大的用处。例如,要将一个很大的 网络中(跨越若干时区)的服务器同步,假如位于美国纽约的 Linux 服务器和北京的 Linux 服务器,其中一 台服务器无须改变硬件时钟而只需临时设置一个系统时间,如要将北京服务器上的时间设置为纽约时间, 两台服务器完成文件的同步后,再与原来的时钟同步一下即可。这样系统和硬件时钟就提供了更为灵活的 操作。 Linux 中更改时间的方法一般使用 date 命令,为了把 S3C2440 内部带的时钟与 linux 系统时钟同步,一 般使用 hwclock 命令,下面是它们的使用方法: (1) date -s 062016192011 #设置时间为 2011-06-20 16:19 [root@mini2440 /]#date -s 062016202011 Mon Jun 20 16:20:00 UTC 2011 [root@mini2440 /]# (2) hwclock -w #把刚刚设置的时间存入 S3C2440 内部的 RTC [root@mini2440 /]#hwclock -w [root@mini2440 /]# (3).开机时使用 hwclock -s 命令可以恢复 linux 系统时钟为 RTC, 一般把该语句放入/etc/init.d/rcS 文件自 动执行。 [root@mini2440 /]#vi etc/init.d/rcS 在打开的编辑界面中加入下面内容 #!/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin runlevel=S prevlevel=N umask 022 export PATH runlevel prevlevel

71

echo "----------munt all----------------" mount -a echo /sbin/mdev>/proc/sys/kernel/hotplug mdev -s echo "*************************************************" echo "************booting to mini2440 *****************" echo "Kernel version:linux-2.6.32.2" echo "the fans:singleboy" echo "Date:2011.5.30" echo "*************************************************" /bin/hostname -F /etc/sysconfig/HOSTNAME echo "update the time from RTC" hwclock -s #show the current system time date ~ ~ ~ I etc/init.d/rcS [Modified] 18/19 94% 然后保存退出。 下面是启动信息 ----------munt all---------------************************************************* ************booting to mini2440 ***************** Kernel version:linux-2.6.32.2 the fans:singleboy Date:2011.5.30 ************************************************* update the time from RTC Mon Jun 20 21:19:49 UTC 2011 Please press Enter to activate this console. 然而,在有时启动时发现: ... ... mice: PS/2 mouse device common for all mice S3C24XX RTC, (c) 2004,2006 Simtec Electronics s3c2410-rtc s3c2410-rtc: rtc disabled, re-enabling s3c2410-rtc s3c2410-rtc: rtc core: registered s3c as rtc0 i2c /dev entries driver ... ...

72

NET: Registered protocol family 17 s3c2410-rtc s3c2410-rtc: hctosys: invalid date/time eth0: link up, 100Mbps, full-duplex, lpa 0x45E1 ... ... ----------munt all---------------************************************************* ************booting to mini2440 ***************** Kernel version:linux-2.6.32.2 the fans:singleboy Date:2011.5.30 ************************************************* update the time from RTC hwclock: settimeofday() failed: Invalid argument Thu Jan 1 00:00:08 UTC 1970 Please press Enter to activate this console. 网上给出的答案:这个是正常的,原因是你没有同步硬件时钟。第一次启动,没有正确设置 RTC 日期。 启动文件系统后执行 Data 命令设置系统时间后,再使用 hwclock -w 将系统时间同步到 RTC 即可避免这个 错误提示。 现在明白了,上面的错误信息是重新编译内核后才出现的。现在可以按照开始时的办法重新设置。 [root@mini2440 /]#date -s 062110092011.00 Tue Jun 21 10:09:00 UTC 2011 [root@mini2440 /]#hwclock -w [root@mini2440 /]#date Tue Jun 21 10:09:36 UTC 2011 [root@mini2440 /]# 接下来,将进行 LCD 相关移植

73

Linux-2.6.32.2 内核在 mini2440 上的移植(六)---添加 LCD 背光驱动
2011-06-21 22:40:18| 分类: Linux 内核移植 | 标签: |字号大中小 订阅 移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 1,主机环境:VMare 下 CentOS 5.5 ,1G 内存。 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。 4,开发板:mini2440,2M nor flash,128M nand flash。 5,u-boot 版本:u-boot-2009.08 6,linux 版本:linux-2.6.32.2 7,参考文章: 嵌入式 linux 应用开发完全手册,韦东山,编著。 Mini2440 之 Linux 移植开发实战指南 到目前为止,我们一直都在命令行下移植,查看结果,LCD 屏幕上似乎总是如伸手不见五指的黑夜,神秘 而又无可奈何,从这里开始,我们就要打开这道神秘之门了。 【1】LCD 背光控制原理 在 mini2440/micro2440 开发板中,LCD 背光是通过 CPU 的 LCD_PWR 引脚来控制的,从原理图中可 以看出,它对应于 GPG4,如图

当 LCD_PWR 输出为高电平―1‖时,将打开背光;当输出为低电平―0‖时,将关闭背光(注意:这里只是打开 和关闭背光,而并没有背光亮度的调节作用)。 【2】 在内核中添加背光驱动程序 现在,我们需要增加一个简单的背光驱动,以便能够通过软件便可简单的控制背光的开关。我们要达到的 目的是:在命令终端通过向背光设备发送偶数比如―0‖便可关闭背光,发送奇数比如―1‖便可打开背光,这样 使用起来就方便多了,而不需要专门的应用程序控制它,正如在用户手册中所描述的方法(2.5.10 控制 LCD 的背光): 提示:LCD 背光设备文件:/dev/backlight 在命令行种输入:echo 0 > /dev/backlight 可以关闭 LCD 背光。 在命令行种输入:echo 1 > /dev/backlight 可以打开 LCD 背光。

74

为了实现这点,我们在 linux-2.6.32.2/drivers/video/backlight 目录增加一个 mini2440_backlight.c 文件,内 容如下: #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/init.h> #include <linux/serio.h> #include <linux/delay.h> #include <linux/clk.h> #include <linux/miscdevice.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <mach/regs-clock.h> #include <plat/regs-timer.h> #include <mach/regs-gpio.h> #include <linux/cdev.h> #define DEVICE_NAME "backlight" //设备名称 #define DEVICE_MINOR 5 //次设备号,这里我们将设备注册为 misc 设备,这种设备的主设备号都为 10 extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to); extern void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function); static int mini2440_backlight_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { switch(cmd) { case 0: //当接收的命令为 0 时,就将 GPG4 引脚设为低电平,关闭背光 s3c2410_gpio_setpin(S3C2410_GPG(4), 0); printk(DEVICE_NAME " turn off!\n"); return 0; case 1: //当接收的命令为 1 时,就将 GPG4 引脚设为高电平,开启背光 s3c2410_gpio_setpin(S3C2410_GPG(4), 1); printk(DEVICE_NAME " turn on!\n"); return 0; default:

75

return -EINVAL; } } static struct file_operations dev_fops = { .owner = THIS_MODULE, .ioctl = mini2440_backlight_ioctl, //这里只使用控制 IO 口的方式来控制背光 }; static struct miscdevice misc = { .minor = DEVICE_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; static int __init dev_init(void) { int ret; ret = misc_register(&misc); //注册成 misc 设备 if(ret < 0) { printk("Register misc device fiald!"); return ret; } //将 GPG4 口配置成输出口 s3c2410_gpio_cfgpin(S3C2410_GPG(4), S3C2410_GPIO_OUTPUT); return ret; } static void __exit dev_exit(void) { misc_deregister(&misc); //注销该 misc 设备 } module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("singleboy"); MODULE_DESCRIPTION("Backlight control for mini2440"); 【3】把背光配置选项加入内核配置菜单 打开 linux-2.6.32.2/drivers/video/backlight/Kconfig,定位到 1929 行附近,加入如下代码:

76

# # Backlight & LCD drivers configuration # menuconfig BACKLIGHT_LCD_SUPPORT bool "Backlight & LCD device support" help Enable this to be able to choose the drivers for controlling the backlight and the LCD panel on some platforms, for example on PDAs. #在里加入 MINI2440 的背光驱动配置 config BACKLIGHT_MINI2440 tristate "Backlight support for mini2440 from FriendlyARM" depends on BACKLIGHT_LCD_SUPPORT help backlight driver for MINI2440 from FriendlyARM # # LCD # config LCD_CLASS_DEVICE 再打开 linux-2.6.32.2/drivers/video/backlight/Makefile,定位到文件末尾,根据配置定义加入驱动目标文 件,如下: obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o obj-$(CONFIG_BACKLIGHT_MINI2440) += mini2440_backlight.o 这样,我们就在内核中移植好了 mini2440 的背光驱动。 【4】在内核配置菜单中确认 "Backlight support for mini2440 from FriendlyARM",被选中。 在内核源代码根目录执行: make menuconfig,依次选择如下子菜单: Device Drivers ---> Graphics support ---> [*] Backlight & LCD device support ---> 就可以找到该配置选项,如图

77

在这里,如果没有被选中,按空格选中我们刚刚加入的 mini2440 配置项,然后退出时保存内核配置菜单, 在命令行执行:make uImage 将生成的 arch/arm/boot/uImage 复制到/nfsboot 目录下,然后启动开发板,可以在启动时看到 LCD 屏显示 的企鹅图像,这说明我们已经点亮了背光。 【5】编写测试程序 linux-test/codetest/backlight_test.c,代码如下: #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/ioctl.h> int main(int argc, char **argv) { int turn; int fd;

//检测命令后面带的参数 if(argc == 1 || argc > 2) { printf("Usage: backlight_test on|off!\n"); exit(1); }

//打开背光设备 fd = open("/dev/backlight", O_RDWR);

if(fd < 0) { printf("Open Backlight Device Faild!\n"); exit(1); }

//判断输入的参数 if(strcmp(argv[1], "on") == 0) { turn = 1; } else if(strcmp(argv[1], "off") == 0) { turn = 0; } else { printf("Usage: backlight_test on|off!\n");

78

exit(1); } //进行 IO 控制 ioctl(fd, turn); //关闭背光设备 close(fd); return 0; } 然后保存退出,之后在主机终端交叉编译 [root@localhost codetest]# arm-linux-gcc -o backlight_test backlight_test.c 将其复制到 nfsboot 目录下以便在开发板挂载该目录后能够执行 [root@localhost codetest]# cp backlight_test /nfsboot/nfs 【6】挂载 nfs 文件系统 在目标板的串口终端中执行 [root@mini2440 /mnt]#mkdir nfs [root@mini2440 /mnt]#ls data etc jffs2 nfs temp yaffs

[root@mini2440 /]#mount -o nolock -t nfs 10.1.0.128:/nfsboot/nfs /mnt/nfs //注意要加 -o nolock 参数,否 则挂载不上。 [root@mini2440 /]#cd mnt/nfs [root@mini2440 nfs]#ls backlight_test 【7】运行测试程序 [root@mini2440 nfs]#./backlight_test [root@mini2440 nfs]#./backlight_test --help Usage: backlight_test on|off! [root@mini2440 nfs]# [root@mini2440 nfs]#./backlight_test off backlight turn off! //观察 LCD 屏,看到背光灯灭了 [root@mini2440 nfs]#./backlight_test on backlight turn on! //观察 LCD 屏,看到背光灯亮了 [root@mini2440 nfs]#./backlight_test off backlight turn off! //观察 LCD 屏,看到背光灯又灭了 [root@mini2440 nfs]#./backlight_test on backlight turn on! //观察 LCD 屏,看到背光灯亮了 只不过 LCD 驱动还有些问题,下一节我们将会详细的介绍如何移植 LCD 驱动。 79

Linux-2.6.32.2 内核在 mini2440 上的移植(七)---LCD 驱动移植
2011-06-21 23:31:23| 分类: Linux 内核移植 | 标签: |字号大中小 订阅 移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 【1】LCD 驱动基础知识 Linux-2.6.32.2 内核已经支持 S3C2440 的 LCD 控制器驱动,但在此我们先介绍一下关于 2440 LCD 控 制器以及驱动相关的 LCD 的一些基础知识。 注意:在此我们只讨论 TFT LCD,也就是真彩屏。 LCD 驱动中最关键的就是时钟频率(Clock frequency)的设置,时钟频率设置不对,LCD 的显示就会闪,或 者根本没有显示。一般 LCD 的 Datasheet 上会写有一个推荐的频率,比如 mini2440 所用的统宝 3.5‖LCD,在它的数据手册第 13 页,有这样一个表格:

可以看到,这里推荐的时钟频率是 6.39MHz,近似于 6.4MHz,范围,是 5M-6.85MHz。S3C2440 之 LCD 控制器与此相关的设置为 CLKVAL,通过设置它,就可以在 LCD 接口的 VCLK 引脚上产生 LCD 所需要 的时钟频率,那么 CLKVAL 和 VCLK 有何种关系呢?在 2440 手册(411 页)中,有这样一段描述: The rate of VCLK signal depends on the CLKVAL field in the LCDCON1 register. Table 15-3 defines the relationship of VCLK and CLKVAL. The minimum value of CLKVAL is 0 接下来,手册中提供了它们的数学关系公式: VCLK(Hz) = HCLK/[(CLKVAL+1)x2] 因此可以得出: VCLK = HCLK / ((CLKVAL+1)*2) 那么 HCLK 是多少呢?我们的开发板运行于 400Mhz,这个可以在 u-boot/cpu/arm920t/start.s 的 172 行 附近可以看到如下代码: # if defined(CONFIG_S3C2440) #define MPLLCON 0x4C000004 //the s3c2440'clock //the address of register base to the main frequency

80

ldr r0, =CLKDIVN mov r1, #5 str r1, [r0]

//FCLK:HCLK:PCLK = 1:4:8

ldr r0, =MPLLCON //the main frequency is 405MHz ldr r1, =0x7f021 //refer to the manual PLL VALUE SELECTION TABLE of the s3c2440 chip str r1, [r0] 可见,FCLK:HCLK:PCLK = 1:4:8,因此得出 HCLK=100Mhz,再根据上述公式得出 CLKVAL 应为: CLKVAL=HCLK/(VCLK*2) -1 CLKVAL = 100000000 / (6400000 * 2) - 1 = 6.8 选择最接近的整数值 7,并把它写入 LCDCON1:17-8(注意:我们实际使用的数值是 8),由此产生的 VCLK 频率实测为 5.63Mhz 左右,它也是在 5-6.85Mhz 之间的数值,如图:

【2】 新内核中的 pixclock 参数 在以前较老的 Linux 内核中,对于 LCD 寄存器的设置都是这样直接填写 CLKVAL 的,但 Linux-2.6.32.2 内核却不再使用这样简单直观的方式,而是通过一个称为―pixclock‖的参数进行调节,它的计算变的复杂和 难以理解 我们不清楚 Linux 内核中关于 2440 部分的移植为何改变成这样的方式 这有可能是为了和 X86 , , 体系中的设置保持一致的风格,下面我们根据实际的代码进行一些推导和说明,但推导结果和我们的实际 设置是并不一致的,会有一些误差。 提示:我们实际提供的 pixclock 参数并不是按照以下的方式推导计算出的,而是先确定好 CLKVAL 的数 值,再反复尝试、猜测得到的。 在 Framebuffer 驱动(linux-2.6.32.2/ drivers/video/s3c2410fb.c)中有这样一个函数: clkdiv = DIV_ROUND_UP(s3c2410fb_calc_pixclk(fbi, var->pixclock), 2); 这 里 的 clkdiv 就 是 我 们 上 面 提 到 的 CLKVAL , 而 DIV_ROUND_UP 是 一 个 宏 定 义 , 它 位 于 include/linux/kernel.h 文件中: #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) 这其实是一个数学概念:向上取整。下面是关于―向上取整‖的一段说明: 以下信息来自:http://www.vckbase.com/document/viewdoc/?id=743 1>. 问题 A,B 都是整数并且 A>1, B>1

81

求┌ A/B ┐ 即 A/B 的上取整。 当 A/B 整除,往上取整返回值为 A/B。 当 不整除,返回值是 int(A/B) + 1 这个算法的一个应用:如果你有一个动态增长的缓冲区,增长的步长是 B, 某一次缓冲区申请的大小是 A,这个时候,就可以用这个算法,计算出缓冲区的一个合 适大小了,正好可以容纳 A,并且不会过于得多,多余部分不会比 B 多。 2>. 方法 int( (A+B-1)/B ) 3>. HUNTON 的证明 上取整用 UP 表示 由于 A>1、B>1,且 A、B 都是整数,所以可以设 A=NB+M 其中 N 为非负整数,M 为 0 到 B-1 的数,则 A/B = N + M/B (A+B-1)/B = N + 1 + (M - 1)/B; 当 M 为 0 时, UP(A/B) = N, int((A+B-1)/B) = N + int(1 - 1/B) = N 当 M 为 1 到 B-1 的数时,0 <= M-1 <= B-2 UP(A/B) = N + 1, int((A+B-1)/B) = N + 1 + int((M-1)/B) = N + 1 所以对 A>1、B>1 的整数 A、B 都有: UP(A/B) = int((A+B-1)/B) 对于除数为―2‖的本算法而言,我们可以简单的理解为―(n/2)+0.5‖所对应的整数值,因此这里不可能避免的 就 出 现 了 误 差 , 也 就 是 说 n 的 数 值 是 有 一 定 范 围 的 , 这 里 的 n 就 是 ―s3c2410fb_calc_pixclk(fbi, var->pixclock)‖,因此上面的公式可以改写为: clkdiv= s3c2410fb_calc_pixclk(fbi, var->pixclock)/2 + 0.5 而 s3c2410fb_calc_pixclk(fbi, var->pixclock) 这个函数在 linux-2.6.32.2/drivers/video/s3c2410fb.c 中是 这样定义的: /* s3c2410fb_calc_pixclk() * * calculate divisor for clk->pixclk */ static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi, unsigned long pixclk) { unsigned long clk = fbi->clk_rate; unsigned long long div; /* pixclk is in picoseconds, our clock is in Hz * * Hz -> picoseconds is / 10^-12 */ //;这里计算出本函数的结果 div = (unsigned long long)clk * pixclk;

82

div >>= 12; /* div / 2^12 */ do_div(div, 625 * 625UL * 625); /* div / 5^12 */ dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div); return div; } 因此得出: clkdiv=clk*pixclk/(10^12)/2 + 0.5 根据实际打印结果验证,此处的 clk 其实就是 HCLK。 而根据 static void s3c2410fb_activate_var(struct fb_info *info)函数中的描述,会得出这样一个关系: CLKVAL=clkdiv-1 再结合从 2440 芯片手册得到的公式 CLKVAL=HCLK/(VCLK*2) -1,因此可以得出大致这样的结果(―大致‖ 可以理解为一定的误差范围): Pixclk=(HCLK-VLCK)x10^12/HCLK*VCLK 以我们所用的统宝屏为例: HCLK=100Mhz=100,000,000Hz VLCK=6.4Mhz=6400,000Hz 因此计算出:pixclk =146250,单位是 ps(picoseconds),这和我们实际设置的数值 170000 是有一定误差 的。 另 外 , 在 Linux 内 核 文 档 中 , 还 有 另 外 一 种 计 算 pixclock 的 方 式 , 见

linux/Documentation/fb/framebuffer.txt,在此我们就不再详细介绍了,感兴趣的可以自己看下,或者到网 上查下相关资料。 如果你对这些参数比较―晕‖,建议你按照友善官方已经移植验证好的参数进行设置,下面是具体的参考步 骤。 【3】在内核中添加各种 LCD 类型的支持 打开 arch/arm/mach-s3c2440/mach-mini2440.c,定位到 114 行到 157 行之间,先删除之前的 LCD 设备 平台代码,如下: /* LCD driver info */ static struct s3c2410fb_display mini2440_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 = 166667, /* HCLK 60 MHz, divisor 10 */ .xres = 240, .yres = 320, .bpp = 16,

83

.left_margin = 20, .right_margin = 8, .hsync_len = 4, .upper_margin = 8, .lower_margin = 7, .vsync_len = 4, }; static struct s3c2410fb_mach_info mini2440_fb_info __initdata = { .displays = &mini2440_lcd_cfg, .num_displays = 1, .default_display = 0, #if 0 /* currently setup by downloader */ .gpccon = 0xaa940659, .gpccon_mask = 0xffffffff, .gpcup = 0x0000ffff, .gpcup_mask = 0xffffffff, .gpdcon = 0xaa84aaa0, .gpdcon_mask = 0xffffffff, .gpdup = 0x0000faff, .gpdup_mask = 0xffffffff, #endif .lpcsel = ((0xCE6) & ~7) | 1<<4, }; 再把友善之臂已经移植好的代码加入,如下: //;NEC 3.5‖LCD 的配置和参数设置 #if defined(CONFIG_FB_S3C2410_N240320) #define LCD_WIDTH 240 #define LCD_HEIGHT 320 #define LCD_PIXCLOCK 100000 #define LCD_RIGHT_MARGIN 36 #define LCD_LEFT_MARGIN 19 #define LCD_HSYNC_LEN 5 #define LCD_UPPER_MARGIN 1 #define LCD_LOWER_MARGIN 5 #define LCD_VSYNC_LEN 1 //;夏普 8‖LCD 的配置和参数设置 #elif defined(CONFIG_FB_S3C2410_TFT640480) #define LCD_WIDTH 640 #define LCD_HEIGHT 480 #define LCD_PIXCLOCK 80000 #define LCD_RIGHT_MARGIN 67

84

#define LCD_LEFT_MARGIN 40 #define LCD_HSYNC_LEN 31 #define LCD_UPPER_MARGIN 25 #define LCD_LOWER_MARGIN 5 #define LCD_VSYNC_LEN 1 //;统宝 3.5‖LCD 的配置和参数设置 #elif defined(CONFIG_FB_S3C2410_T240320) #define LCD_WIDTH 240 #define LCD_HEIGHT 320 #define LCD_PIXCLOCK 146250//170000 #define LCD_RIGHT_MARGIN 25 #define LCD_LEFT_MARGIN 0 #define LCD_HSYNC_LEN 4 #define LCD_UPPER_MARGIN 1 #define LCD_LOWER_MARGIN 4 #define LCD_VSYNC_LEN 1 //;群创 7‖LCD 的配置和参数设置 #elif defined(CONFIG_FB_S3C2410_TFT800480) #define LCD_WIDTH 800 #define LCD_HEIGHT 480 #define LCD_PIXCLOCK 11463//40000 #define LCD_RIGHT_MARGIN 67 #define LCD_LEFT_MARGIN 40 #define LCD_HSYNC_LEN 31 #define LCD_UPPER_MARGIN 25 #define LCD_LOWER_MARGIN 5 #define LCD_VSYNC_LEN 1 //;LCD2VGA(分辨率为 1024x768)模块的配置和参数设置 #elif defined(CONFIG_FB_S3C2410_VGA1024768) #define LCD_WIDTH 1024 #define LCD_HEIGHT 768 #define LCD_PIXCLOCK 80000 #define LCD_RIGHT_MARGIN 15 #define LCD_LEFT_MARGIN 199 #define LCD_HSYNC_LEN 15 #define LCD_UPPER_MARGIN 1 #define LCD_LOWER_MARGIN 1 #define LCD_VSYNC_LEN 1 #define LCD_CON5 (S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_HWSWP) #endif #if defined (LCD_WIDTH) static struct s3c2410fb_display mini2440_lcd_cfg __initdata = { #if !defined (LCD_CON5) .lcdcon5 = S3C2410_LCDCON5_FRM565 |

85

S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME | S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, #else .lcdcon5 = LCD_CON5, #endif .type = S3C2410_LCDCON1_TFT, .width = LCD_WIDTH, .height = LCD_HEIGHT, .pixclock = LCD_PIXCLOCK, .xres = LCD_WIDTH, .yres = LCD_HEIGHT, .bpp = 16, .left_margin = LCD_LEFT_MARGIN + 1, .right_margin = LCD_RIGHT_MARGIN + 1, .hsync_len = LCD_HSYNC_LEN + 1, .upper_margin = LCD_UPPER_MARGIN + 1, .lower_margin = LCD_LOWER_MARGIN + 1, .vsync_len = LCD_VSYNC_LEN + 1, }; static struct s3c2410fb_mach_info mini2440_fb_info __initdata = { .displays = &mini2440_lcd_cfg, .num_displays = 1, .default_display = 0, .gpccon = 0xaa955699, .gpccon_mask = 0xffc003cc, .gpcup = 0x0000ffff, .gpcup_mask = 0xffffffff, .gpdcon = 0xaa95aaa1, .gpdcon_mask = 0xffc0fff0, .gpdup = 0x0000faff, .gpdup_mask = 0xffffffff, .lpcsel = 0xf82, }; #endif 然后打开 drivers/video/Kconfig,在大概 1930 行加入以下配置信息: config FB_S3C2410_DEBUG bool "S3C2410 lcd debug messages" depends on FB_S3C2410 help Turn on debugging messages. Note that you can set/unset at run time through sysfs

86

choice prompt "LCD select" depends on FB_S3C2410 help S3C24x0 LCD size select config FB_S3C2410_T240320 boolean "3.5 inch 240X320 Toppoly LCD" depends on FB_S3C2410 help 3.5 inch 240X320 Toppoly LCD config FB_S3C2410_N240320 boolean "3.5 inch 240X320 NEC LCD" depends on FB_S3C2410 help 3.5 inch 240x320 NEC LCD config FB_S3C2410_TFT640480 boolean "8 inch 640X480 L80 LCD" depends on FB_S3C2410 help 8 inch 640X480 LCD config FB_S3C2410_TFT800480 boolean "7 inch 800x480 TFT LCD" depends on FB_S3C2410 help 7 inch 800x480 TFT LCD config FB_S3C2410_VGA1024768 boolean "VGA 1024x768" depends on FB_S3C2410 help VGA 1024x768 endchoice config FB_SM501 tristate "Silicon Motion SM501 framebuffer support" depends on FB && MFD_SM501 select FB_CFB_FILLRECT select FB_CFB_COPYAREA 定位到 326 行附近,在初始化部分加入: static void __init mini2440_map_io(void) { s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc));

87

s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));

} static void __init mini2440_machine_init(void) { #if defined (LCD_WIDTH) s3c24xx_fb_set_platdata(&mini2440_fb_info); #endif s3c_i2c0_set_platdata(NULL); s3c_device_nand.dev.platform_data = &mini2440_nand_info; platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices)); //smdk_machine_init(); } 这样,我们就完成了 LCD 驱动的移植,如果你需要加入其他型号的 LCD 驱动,也可以参照上面的方式复 制即可,一般小尺寸的 pixclock 参数可以参考统宝 3.5‖的,超过 640x480 分辨率的参数可以参考 8‖LCD 的,特别要注意你使用的 LCD 的长宽也要修改。 【4】配置内核并下载到开发板测试 现在,我们在命令行输入:make menuconfig 进入内核配置,依次按下面的子菜单项选择: Device Drivers ---> Graphics support ---> <*> Support for frame buffer devices ---> LCD select (3.5 inch 240X320 Toppoly LCD) ---> (X) 3.5 inch 240X320 Toppoly LCD Console display driver support ---> <*> Framebuffer Console support //支持 Framebuffer 控制台 //选择统宝 3.5 寸液晶

[*] Select compiled-in fonts //选择字库,默认 VGA 8x8 , VGA 8x16 [*] [*] VGA 8x8 font VGA 8x16 font

[*] Bootup logo ---> [*] Standard 224-color Linux logo

按空格或者回车键选择我们需要的 LCD 型号,然后退出保存内核配置。 在命令行执行: #make uImage 将会生成 arch/arm/boot/uImage,把它烧写到开发板中,就可以看到一个小企鹅出现在屏幕上了,如图

88

而且 logo 左下方有一个光标提示符在闪动。 【5】修改 Linux Logo (1)使用命令行工具修改 Linux LOGO 在上一小节中我们看到 Linux 系统启动时会出现一个小企鹅图像。大部分 Linux 系统会有这个开机图片, 它对应的文件其实就是 linux-2.6.32.2/drivers/video/logo/linux_logo_clut224.ppm 该文件是一个特殊格式的图像文件,有很多方法可以把普通的图片转换为 logo 文件,最常用的就是 netpbm 工具组。 ―netpbm‖是一组命令行的工具,它可以转换很多格式的图片,在此以 png 格式为例介绍一下如何把普通的 PNG 文件转换为我们需要的 Linux LOGO 图片: 假定我们要转换的文件名为 linux_logo.png,首先将 png 图片转成 pnm # pngtopnm linux_logo.png > linux_logo.pnm 然后将 pnm 图片的颜色数限制在 224 # pnmquant 224 linux_logo.pnm > linux_logo_clut224.pnm 最后将 pnm 图片转换成我们需要的 ppm # pnmtoplainpnm linux_logo_clut224.pnm > linux_logo_clut224.ppm 然 linux_logo_clut224.ppm 替换 linux-2.6.32.2/drivers/video/logo 中对应的图像就可以了。 (2)使用图形化的 logomaker 制作 Linux LOGO 为了让用户使用的更方便些,友善之臂开发一个图形界面的制作工具 LogoMaker,它基于 Fedora 9 平台 开发,其实它的底层调用的就是上述命令行工具,如果你运行的结果出现浮点数错误,那可能你使用的平 台并非 Federa9,如果在 Fedora9 下运行出现如图错误,你可能没有正确安装 netpbm 工具(这里强烈推 荐用户按照手册介绍的步骤安装 Fedora9 平台):

友善官方光盘中 logomaker 工具包,这里复制到的 linux-test 目录

89

[root@localhost ~]# cd linux-test [root@localhost linux-test]# ls busybox-1.13.3 lzo-2.05

busybox-1.13.3-mini2440.tgz mkyaffs2image.tgz logomaker.tgz [root@localhost linux-test]# tar xzvf logomaker.tgz -C / usr/sbin/logomaker [root@localhost linux-test]# 注意:C 是大写的,C 后面有个空格,C 是改变解压安装目录的意思 执行以上命令,LogoMaker 将会被安装到/usr/sbin 目录下,它只有一个文件,安装完之后在命令行输入 logomaker 可出现如下界面

下面是 Linux LogoMaker 的使用步骤: 点 File->Open a picture file…或者使用快捷键 Ctrl+O 可以打开一个图片文件(其大小应该不大于屏幕像 素大小),在跳出的文件打开窗口中选择一个图片:

90

这时点 File->Convert the picture to a Linux Logo File,或者使用快捷键 Crtl+C 会跳出文件保存目录窗 口,不需要输入任何东西,选择要保存的目录即可,文件名将会自动保存为 linux_logo_clut224.ppm,使 用这个文件代替 linux-2.6.32.2/drivers/video/logo 目录下的同名文件即可。 【6】通过 LCD 显示内核启动信息 之前内核通过串口打印内核信息时,内核命令行参数为 console=ttySAC0,现在可以多加一项,即 ―console=ttySAC0, console=tty1 ‖。 注意,tty1 表示第一个虚拟终端,tty2 表示第二个虚拟终端,... ... tty0 表示当前虚拟终端。 不过要想通过它来登录,还需要修改 inittab 文件,增加以下 6 行: #/etc/inittab ::sysinit:/etc/init.d/rcS console::askfirst:-/bin/sh tty1::askfirst:-/bin/sh tty2::askfirst:-/bin/sh tty3::askfirst:-/bin/sh tty4::askfirst:-/bin/sh tty5::askfirst:-/bin/sh tty6::askfirst:-/bin/sh ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a –r 这样会在虚拟终端上启动 shell 程序。在 LCD 的 USB 键盘上按下 Alt+Fn(n=1~6)可以在第 1~6 个控制台之 间切换。 在串口终端中 [root@mini2440 /]#ls -l /dev/tty0 crw-rw---1 root root 4, 0 Jan 1 00:00 /dev/tty0

[root@mini2440 /]#ls -l /dev/tty1 crw-rw---1 root root 4, 1 Jan 1 00:00 /dev/tty1

[root@mini2440 /]# 可以看到虚拟终端 tty0,tty1 的主设备号位 4,此设备号分别为 0 和 1,c 表示是字符设备。 在串口终端中 [root@mini2440 /]#echo hello >/dev/tty0 [root@mini2440 /]# 可以子在当前 LCD 上显示 hello 字符。 接下来,将要为内核添加 ADC 驱动。

91

Linux-2.6.32.2 内核在 mini2440 上的移植(八)---添加 ADC 驱动
【1】关于 S3C2440 的 ADC 和触摸屏接口 在 S3C2440 芯片中,AD 输入和触摸屏接口使用共同的 A/D 转换器,见 2440 芯片手册第 16 章节,如 图,其中通道 7(XP 或 AIN7)作为触摸屏接口的 X 坐标输入,通道 5(YP 或 AIN5)作为触摸屏接口的 Y 坐标 输入。

我们从上面的结构图和数据手册可以知道,该 ADC 模块总共有 8 个通道可以进行模拟信号的输入,分别 是 AIN0、AIN1、AIN2、AIN3、YM、YP、XM、XP。那么 ADC 是怎么实现模拟信号到数字信号的转换呢? 首先模拟信号从任一通道输入,然后设定寄存器中预分频器的值来确定 AD 转换器频率,最后 ADC 将模拟 信号转换为数字信号保存到 ADC 数据寄存器 0 中(ADCDAT0),然后 ADCDAT0 中的数据可以通过中断或 查询的方式来访问。对于 ADC 的各寄存器的操作和注意事项请参阅数据手册。

上图是 mini2440 上的 ADC 应用实例,开发板通过一个 10K 的电位器(可变电阻)来产生电压模拟信号,然 后通过第一个通道(即:AIN0)将模拟信号输入 ADC。 ADC 设备在 Linux 中可以看做是简单的字符设备,也可以当做是一混杂设备(misc 设备),这里我们就看做 是 misc 设备来实现 ADC 的驱动。注意:这里我们获取 AD 转换后的数据将采用中断的方式,即当 AD 转 换完成后产生 AD 中断,在中断服务程序中来读取 ADCDAT0 的第 0-9 位的值(即 AD 转换后的值)。 92

【2】在内核中添加 ADC 驱动 Linux-2.6.32.2 内核并没有提供支持 S3C2440 的 ADC 驱动程序,由于《移植开发实战指南》中 ADC 部 分代码在实际测试中始终输出-1,而无法通过测试,于是结合博主黄刚嵌入式 Linux 之我行——S3C2440 上 ADC 驱 动 实 例 开 发 讲 解 的 ADC 驱 动 程 序 作 了 下 修 改 , 经 过 修 改 后 有 一 个 好 处是 方 便 地 通 过 s3c24xx-adc.h 文件中提供的宏修改通道获取采样数据,该头文件的代码也在 drivers/misc 目录下内容为: #ifndef _S3C2410_ADC_H_ #define _S3C2410_ADC_H_ #define ADC_WRITE(ch, prescale) ((ch)<<16|(prescale)) #define ADC_WRITE_GETCH(data) (((data)>>16)&0x7) #define ADC_WRITE_GETPRE(data) ((data)&0xff) #endif /* _S3C2410_ADC_H_ */ 驱动程序的文件名为:mini2440_adc.c 位于 drivers/misc 目录下。由上述内容可知,ADC 驱动和触摸屏 驱动若想共存,就必须解决共享―A/D 转换器‖资源这个问题,因此在 ADC 驱动程序中声明了一个全局的 ―ADC_LOCK‖信号量,ADC 驱动程序的内容和注解如下: #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/init.h> #include <linux/serio.h> #include <linux/delay.h> #include <linux/clk.h> #include <linux/wait.h> #include <linux/sched.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <mach/regs-clock.h> #include <plat/regs-timer.h> #include <plat/regs-adc.h> #include <mach/regs-gpio.h> #include <linux/cdev.h> #include <linux/miscdevice.h> //;自己定义的头文件,因原生内核并没有包含 #include "s3c24xx-adc.h" #undef DEBUG //#define DEBUG #ifdef DEBUG #define DPRINTK(x...) {printk(__FUNCTION__"(%d): ",__LINE__);printk(##x);} #else 93

#define DPRINTK(x...) (void)(0) #endif //;定义 ADC 转换设备名称,将出现在/dev/adc #define DEVICE_NAME "adc" static void __iomem *adc_base; /*定义了一个用来保存经过虚拟映射后的内存地址*/ //;定义 ADC 设备结构 typedef struct { wait_queue_head_t wait; int channel; int prescale; }ADC_DEV; static ADC_DEV adcdev; //;声明全局信号量,以便和触摸屏驱动程序共享 A/D 转换器 DECLARE_MUTEX(ADC_LOCK); //;ADC 驱动是否拥有 A/D 转换器资源的状态变量 //static volatile int OwnADC = 0; /*用于标识 AD 转换后的数据是否可以读取,0 表示不可读取*/ static volatile int ev_adc = 0; /*用于保存读取的 AD 转换后的值,该值在 ADC 中断中读取*/ static int adc_data; /*保存从平台时钟队列中获取 ADC 的时钟*/ static struct clk *adc_clk; //;定义 ADC 相关的寄存器 #define ADCCON (*(volatile unsigned long *)(adc_base + S3C2410_ADCCON)) //ADC control #define ADCTSC (*(volatile unsigned long *)(adc_base + S3C2410_ADCTSC)) //ADC touch screen control #define ADCDLY (*(volatile unsigned long *)(adc_base + S3C2410_ADCDLY)) //ADC start or IntervalDelay #define ADCDAT0 (*(volatile unsigned long *)(adc_base + S3C2410_ADCDAT0)) //ADC conversion data 0 #define ADCDAT1 (*(volatile unsigned long *)(adc_base + S3C2410_ADCDAT1)) //ADC conversion data 1 #define ADCUPDN (*(volatile unsigned long *)(adc_base + 0x14)) //Stylus Up/Down interrupt status #define PRESCALE_DIS (0 << 14) #define PRESCALE_EN (1 << 14) #define PRSCVL(x) ((x) << 6) #define ADC_INPUT(x) ((x) << 3) #define ADC_START (1 << 0) #define ADC_ENDCVT (1 << 15)

94

//;定义―开启 AD 输入‖宏,因为比较简单,故没有做成函数 //#define START_ADC_AIN(ch, prescale) #define start_adc(ch, prescale) \ do{ \ ADCCON = PRESCALE_EN | PRSCVL(prescale) | ADC_INPUT((ch)) ; \ ADCCON |= ADC_START; \ }while(0) /*设置 ADC 控制寄存器,开启 AD 转换*/ /*static void start_adc(int ch,int prescale) { unsigned int tmp; tmp = PRESCALE_EN | PRSCVL(prescale) | ADC_INPUT(ch); //(1 << 14)|(255 << 6)|(0 << 3);// 0 1 00000011 000 0 0 0 //此处 writl()的原型是 void writel(u32 b, volatile void __iomem *addr),addr 是经过地址重映射后的地址 writel(tmp, ADCCON); //AD 预分频器使能、模拟输入通道设为 AIN0 tmp = readl(ADCCON); tmp = tmp | ADC_START; //(1 << 0); writel(tmp, ADCCON); } 问题:此函数被调用时为什么地址映射错误?答案应该需要使用专用的函数 iowrite32 操作。 */ //;ADC 中断处理函数 static irqreturn_t adc_irq(int irq, void *dev_id) { //;如果 ADC 驱动拥有―A/D 转换器‖资源,则从 ADC 寄存器读取转换结果 if (!ev_adc) { /*读取 AD 转换后的值保存到全局变量 adc_data 中,S3C2410_ADCDAT0 定义在 regs-adc.h 中, 这里为什么要与上一个 0x3ff,很简单,因为 AD 转换后的数据是保存在 ADCDAT0 的第 0-9 位, 所以与上 0x3ff(即:1111111111)后就得到第 0-9 位的数据,多余的位就都为 0*/ adc_data = ADCDAT0 & 0x3ff; /*将可读标识为 1,并唤醒等待队列*/ ev_adc = 1; wake_up_interruptible(&adcdev.wait); } return IRQ_HANDLED; } //;ADC 读函数,一般对应于用户层/应用层的设备读函数(read) static ssize_t adc_read(struct file *filp, char *buffer, size_t count, loff_t *ppos) { //AD 转换开始 // 0 1 00000011 000 0 0 1

95

/*试着获取信号量(即:加锁)*/ if (down_trylock(&ADC_LOCK)) { return -EBUSY; } if(!ev_adc) /*表示还没有 AD 转换后的数据,不可读取*/ { if(filp->f_flags & O_NONBLOCK) { /*应用程序若采用非阻塞方式读取则返回错误*/ return -EAGAIN; } else /*以阻塞方式进行读取*/ { /*设置 ADC 控制寄存器,开启 AD 转换*/ start_adc(adcdev.channel, adcdev.prescale); /*使等待队列进入睡眠*/ wait_event_interruptible(adcdev.wait, ev_adc); } } /*能到这里就表示已有 AD 转换后的数据,则标识清 0,给下一次读做判断用*/ ev_adc = 0; /*将读取到的 AD 转换后的值发往到上层应用程序*/ copy_to_user(buffer, (char *)&adc_data, sizeof(adc_data)); /*释放获取的信号量(即:解锁)*/ up(&ADC_LOCK); return sizeof(adc_data);

} //;打开 ADC 设备的函数,一般对应于用户态程序的 open static int adc_open(struct inode *inode, struct file *filp) { int ret; /* normal ADC */ ADCTSC = 0; //;初始化中断队列 init_waitqueue_head(&(adcdev.wait)); adcdev.channel=0;//;缺省通道为“0” adcdev.prescale=0xff; /* 申请 ADC 中断服务,这里使用的是共享中断:IRQF_SHARED,为什么要使用共享中断,因为在触摸屏 驱动中 也使用了这个中断号。中断服务程序为:adc_irq 在下面实现,IRQ_ADC 是 ADC 的中断号,这里注意: 96

申请中断函数的最后一个参数一定不能为 NULL,否则中断申请会失败,这里传入的是 ADC_DEV 类 型的变量*/ ret = request_irq(IRQ_ADC, adc_irq, IRQF_SHARED, DEVICE_NAME, &adcdev); if (ret) { /*错误处理*/ printk(KERN_ERR "IRQ%d error %d\n", IRQ_ADC, ret); return -EINVAL; } DPRINTK( "adc opened\n"); return 0; } static int adc_release(struct inode *inode, struct file *filp) { DPRINTK( "adc closed\n"); return 0; } static struct file_operations dev_fops = { owner: THIS_MODULE, open: adc_open, read: adc_read, release: adc_release, }; static struct miscdevice adc_miscdev = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; static int __init dev_init(void) { int ret; /* 1,从平台时钟队列中获取 ADC 的时钟,这里为什么要取得这个时钟,因为 ADC 的转换频率跟时钟有 关。 系统的一些时钟定义在 arch/arm/plat-s3c24xx/s3c2410-clock.c 中*/ adc_clk = clk_get(NULL, "adc"); if (!adc_clk) { printk(KERN_ERR "failed to get adc clock source\n"); return -ENOENT; } /*时钟获取后要使能后才可以使用,clk_enable 定义在 arch/arm/plat-s3c/clock.c 中*/ clk_enable(adc_clk); /* 2,将 ADC 的 IO 端口占用的这段 IO 空间映射到内存的虚拟地址,ioremap 定义在 io.h 中。 注意:IO 空间要映射后才能使用,以后对虚拟地址的操作就是对 IO 空间的操作, 97

S3C2410_PA_ADC 是 ADC 控制器的基地址,定义在 mach-s3c2410/include/mach/map.h 中,0x20 是 虚拟地址长度大小*/ adc_base=ioremap(S3C2410_PA_ADC,0x20); if (adc_base == NULL) { printk(KERN_ERR "Failed to remap register block\n"); ret = -EINVAL; goto err_noclk; } /* 3,把看 ADC 注册成为 misc 设备,misc_register 定义在 miscdevice.h 中 adc_miscdev 结构体定义及内部接口函数在第 2 步中讲,MISC_DYNAMIC_MINOR 是次设备号,定义在 miscdevice.h 中*/ ret = misc_register(&adc_miscdev); if (ret) { /*错误处理*/ printk(KERN_ERR "Cannot register miscdev on minor=%d (%d)\n", MISC_DYNAMIC_MINOR, ret); goto err_nomap; } printk(DEVICE_NAME "\tinitialized!\n"); return 0; //以下是上面错误处理的跳转点 err_noclk: clk_disable(adc_clk); clk_put(adc_clk); err_nomap: iounmap(adc_base); return ret; } static void __exit dev_exit(void) {

free_irq(IRQ_ADC, &adcdev); //;释放中断 iounmap(adc_base); /*释放虚拟地址映射空间*/ if (adc_clk) /*屏蔽和销毁时钟*/ { clk_disable(adc_clk); clk_put(adc_clk); adc_clk = NULL; } misc_deregister(&adc_miscdev); } 98

//;导出信号量―ADC_LOCK‖,以便触摸屏驱动使用 EXPORT_SYMBOL(ADC_LOCK); module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("singleboy"); MODULE_DESCRIPTION("Mini2440 ADC Driver"); 说明:杂项设备(misc device) 杂项设备也是在嵌入式系统中用得比较多的一种设备驱动。在 Linux 内核的 include/linux 目录下有 Miscdevice.h 文件,要把自己定义的 misc device 从设备定义在这里。其实是因为这些字符设备不符合预 先确定的字符设备范畴,所有这些设备采用主编号 10,一起归于 misc device,其实 misc_register 就是用 主标号 10 调用 register_chrdev()的。也就是说,misc 设备其实也就是特殊的字符设备。 然后打开 drivers/misc/Makefile 文件,在大概 24 行加入 ADC 驱动程序目标模块 obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o obj-$(CONFIG_C2PORT) += c2port/ obj-$(CONFIG_MINI2440_ADC) += mini2440_adc.o obj-y obj-y += eeprom/ += cb710/

再打开 drivers/char/Kconfig 文件,定位到 16 行附近,加入 ADC 驱动配置选项: menuconfig MISC_DEVICES bool "Misc devices" default y ---help--Say Y here to get to see options for device drivers from various different categories. This option alone does not add any kernel code. If you say N, all options in this submenu will be skipped and disabled. if MISC_DEVICES config MINI2440_ADC bool "ADC driver for FriendlyARM Mini2440 development boards" depends on MACH_MINI2440 default y if MACH_MINI2440 help this is ADC driver for FriendlyARM Mini2440 development boards Notes: the touch-screen-driver required this option config ATMEL_PWM tristate "Atmel AT32/AT91 PWM support" depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 help This option enables device driver support for the PWM channels on certain Atmel processors. Pulse Width Modulation is used for

99

purposes including software controlled power-efficient backlights on LCD displays, motor control, and waveform generation. 这样,我们就在内核中添加了 ADC 驱动。 【3】确认配置选项 现在内核源代码目录的命令行执行:make menuconfig,依次选择如下子菜单项,找到刚刚添加的 ADC 驱 动配置选项: Device Drivers ---> [*] Misc devices ---> 如图所示,按空格键选中 ADC 配置选项

然后退出保存所选配置, 在命令行执行: make uImage , 将会生成 arch/arm/boot/uImage,然后将其 复制到/nfsboot 目录下后启动开发板。可以在看到串口终端中启动信息: ... ... brd: module loaded adc initialized!

S3C24XX NAND Driver, (c) 2004 Simtec Electronics ... ... 说明 ADC 设备加载成功。

【4】ADC 测试程序 测试程序也是采用博主黄刚测试程序,这里作一点小小修改,加了一秒钟的睡眠,这样在旋转电位器 W1 时能够清楚地看到变化。代码位于 linux-test/codetest/adc_test.c,代码如下: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/wait.h>

100

int main(int argc, char **argv) { int fd; fprintf(stderr, "press Ctrl-C to stop\n"); //以阻塞方式打开设备文件,非阻塞时 flags=O_NONBLOCK fd = open("/dev/adc", 0); if(fd < 0) { printf("Open ADC Device Faild!\n"); exit(1); } while(1) { int ret; int data;

//读设备 ret = read(fd, &data, sizeof(data)); if(ret != sizeof(data)) { if(errno != EAGAIN) { printf("Read ADC Device Faild!\n"); } continue; } else { printf("Read ADC value is: %d\n", data); } sleep(1); } close(fd); return 0; } 然后保存退出,之后在主机终端交叉编译 [root@localhost codetest]# arm-linux-gcc -o adc_test adc_test.c 将其复制到 nfsboot 目录下以便在开发板挂载该目录后能够执行 [root@localhost codetest]# cp adc_test /nfsboot/nfs 101

【5】挂载 nfs 文件系统 在目标板的串口终端中执行 [root@mini2440 /]#mount -o nolock -t nfs 10.1.0.128:/nfsboot/nfs /mnt/nfs //注意要加 -o nolock 参数,否 则挂载不上。 [root@mini2440 /]#cd mnt/nfs [root@mini2440 nfs]#ls adc_test 【7】运行测试程序 在开发板的命令行终端输入:./adc-test,然后旋转开发板上的 W1 可调电阻 [root@mini2440 nfs]#./adc_test press Ctrl-C to stop Read ADC value is: 224 Read ADC value is: 225 Read ADC value is: 213 Read ADC value is: 379 Read ADC value is: 50 Read ADC value is: 358 Read ADC value is: 34 Read ADC value is: 0 Read ADC value is: 0 Read ADC value is: 321 Read ADC value is: 549 Read ADC value is: 738 Read ADC value is: 846 Read ADC value is: 914 Read ADC value is: 997 Read ADC value is: 1023 ^C [root@mini2440 nfs]# 可以看到 ADC 转换的结果也在变动 接下来,将进行触摸屏驱动移植

102

Linux-2.6.32.2 内核在 mini2440 上的移植(九)---触摸屏驱动移植
2011-06-27 14:10:12| 分类: Linux 内核移植 | 标签: |字号大中小 订阅 移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 1,主机环境:VMare 下 CentOS 5.5 ,1G 内存。 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。 4,开发板:mini2440,2M nor flash,128M nand flash。 5,u-boot 版本:u-boot-2009.08 6,linux 版本:linux-2.6.32.2 7,参考文章: 嵌指南入式 linux 应用开发完全手册,韦东山,编著。 Mini2440 之 Linux 移植开发实战 博主黄刚嵌入式 Linux 之我行——S3C2440 上 ADC 驱动实例开发讲解 【1】在内核中添加触摸屏驱动程序 Linux-2.6.32.2 内 核 也 没 有 包 含 支 持 S3C2440 的 触 摸 屏 驱 动 , 因 此 友 善 官 方 自 行 设 计 了 一 个 s3c2410_ts.c,它位于 linux-src/drivers/input/touchscreen 目录下,你可以自己增加一个 s3c2410_ts.c 文 件,并复制如下内容: #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/init.h> #include <linux/serio.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/gpio.h> #include <asm/io.h> #include <asm/irq.h> #include <plat/regs-adc.h> #include <mach/regs-gpio.h> /* For ts.dev.id.version */ #define S3C2410TSVERSION 0x0101

103

/*定义一个 WAIT4INT 宏,该宏将对 ADC 触摸屏控制寄存器进行操作 S3C2410_ADCTSC_YM_SEN 这些宏都定义在 regs-adc.h 中*/ #define WAIT4INT(x) (((x)<<8) | \ S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \ S3C2410_ADCTSC_XY_PST(3)) #define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN |

S3C2410_ADCTSC_XP_SEN | \ S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0)) //static char *s3c2410ts_name = "s3c2410 TouchScreen"; #define DEVICE_NAME "mini2440_TouchScreen" /*设备名称*/

static struct input_dev *ts_dev; /*定义一个输入设备来表示我们的触摸屏设备*/ static long xp; static long yp; static int count; /*定义一个外部的信号量 ADC_LOCK,因为 ADC_LOCK 在 ADC 驱动程序中已申明 这样就能保证 ADC 资源在 ADC 驱动和触摸屏驱动中进行互斥访问*/ extern struct semaphore ADC_LOCK; static int OwnADC = 0; static void __iomem *base_addr; /*定义了一个用来保存经过虚拟映射后的内存地址*/ static inline void s3c2410_ts_connect(void) { s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON); s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON); s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON); s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON); } static void touch_timer_fire(unsigned long data) { /*用于记录这一次 AD 转换后的值*/ unsigned long data0; unsigned long data1; int updown; /*用于记录触摸屏操作状态是按下还是抬起*/ data0 = ioread32(base_addr+S3C2410_ADCDAT0); data1 = ioread32(base_addr+S3C2410_ADCDAT1); /*记录这一次对触摸屏是压下还是抬起,该状态保存在数据寄存器的第 15 位,所以需要逻辑与上 S3C2410_ADCDAT0_UPDOWN*/ updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 &

S3C2410_ADCDAT0_UPDOWN)); if (updown) /*判断触摸屏的操作状态*/ { 104

/*如果状态是按下,并且 ADC 已经转换了就报告事件和数据*/ if (count != 0) //转换四次后进行事件汇报 { long tmp;

tmp = xp; xp = yp; yp = tmp; //这里进行转换是因为我们的屏幕使用时采用的是 240*320,相当于把原来的屏幕的 X,Y 轴变换。 //个人理解,不知是否正确 //设备 X,Y 值 xp >>= 2; yp >>= 2; #ifdef CONFIG_TOUCHSCREEN_MINI2440_DEBUG /*触摸屏调试信息,编译内核时选上此项后,点击触摸屏会在终端上打印出坐标信息*/ struct timeval tv; do_gettimeofday(&tv); printk(KERN_DEBUG "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, xp, yp); #endif input_report_abs(ts_dev, ABS_X, xp); input_report_abs(ts_dev, ABS_Y, yp); /*报告按键事件,键值为 1(代表触摸屏对应的按键被按下)*/ input_report_key(ts_dev, BTN_TOUCH, 1); /*报告触摸屏的状态,1 表明触摸屏被按下*/ input_report_abs(ts_dev, ABS_PRESSURE, 1); /*等待接收方受到数据后回复确认,用于同步*/ input_sync(ts_dev); //这个表明我们上报了一次完整的触摸屏事件,用来间隔下一次的报告 } /*如果状态是按下,并且 ADC 还没有开始转换就启动 ADC 进行转换*/ xp = 0; yp = 0; count = 0; /*设置触摸屏的模式为自动转换模式*/ iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC); /*启动 ADC 转换*/ iowrite32(ioread32(base_addr+S3C2410_ADCCON) base_addr+S3C2410_ADCCON); //如果还没有启动 ADC 或者 ACD 转换四次完毕后则启动 ADC } else /*否则是抬起状态*/ { | S3C2410_ADCCON_ENABLE_START,

105

//如果是 up 状态,则提出报告并让触摸屏处在等待触摸的阶段 count = 0; input_report_key(ts_dev, BTN_TOUCH, 0); /*报告按键事件,键值为 0(代表触摸屏对应的按键被释 放)*/ input_report_abs(ts_dev, ABS_PRESSURE, 0); /*报告触摸屏的状态,0 表明触摸屏没被按下*/ input_sync(ts_dev); /*等待接收方受到数据后回复确认,用于同步*/ iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC); if (OwnADC) { OwnADC = 0; up(&ADC_LOCK); } } } /*定义并初始化了一个定时器 touch_timer,定时器服务程序为 touch_timer_fire*/ static struct timer_list touch_timer = TIMER_INITIALIZER(touch_timer_fire, 0, 0); /*ADC 中断服务程序,AD 转换完成后触发执行*/ static irqreturn_t stylus_updown(int irq, void *dev_id) { unsigned long data0; unsigned long data1; int updown; //注意在触摸屏驱动模块中,这个 ADC_LOCK 的作用是保证任何时候都只有一个驱动程序使用 ADC 的 //中断线,因为在 mini2440adc 模块中也会使用到 ADC,这样只有拥有了这个锁,才能进入到启动 ADC if (down_trylock(&ADC_LOCK) == 0) { OwnADC = 1; data0 = ioread32(base_addr+S3C2410_ADCDAT0); data1 = ioread32(base_addr+S3C2410_ADCDAT1); /*记录这一次对触摸屏是压下还是抬起,该状态保存在数据寄存器的第 15 位,所以需要逻辑与上 S3C2410_ADCDAT0_UPDOWN*/ updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 &

S3C2410_ADCDAT0_UPDOWN)); if (updown) { touch_timer_fire(0); //这是一个定时器函数,当然在这里是作为普通函数调用,用来启动 ADC } else { OwnADC = 0; up(&ADC_LOCK); //注意这部分是基本不会执行的,除非你触摸后以飞快的速度是否,还来 //不及启动 ADC,当然这种飞快的速度一般是达不到的,笔者调试程序时发现这里是进入不了的

106

} } return IRQ_HANDLED; }

static irqreturn_t stylus_action(int irq, void *dev_id) { unsigned long data0; unsigned long data1; if (OwnADC) { //读取数据 data0 = ioread32(base_addr+S3C2410_ADCDAT0); data1 = ioread32(base_addr+S3C2410_ADCDAT1); xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK; yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK; count++; if (count < (1<<2)) { //如果小如四次重新启动转换 iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC); iowrite32(ioread32(base_addr+S3C2410_ADCCON) base_addr+S3C2410_ADCCON); } else { //如果超过四次,则等待 1ms 后进行数据上报 mod_timer(&touch_timer, jiffies+1); iowrite32(WAIT4INT(1), base_addr+S3C2410_ADCTSC); } } return IRQ_HANDLED; } static struct clk *adc_clock; /*用于保存从平台时钟列表中获取的 ADC 时钟*/ static int __init s3c2410ts_init(void) { struct input_dev *input_dev; /*从平台时钟队列中获取 ADC 的时钟,这里为什么要取得这个时钟,因为 ADC 的转换频率跟时钟有关。 系统的一些时钟定义在 arch/arm/plat-s3c24xx/s3c2410-clock.c 中*/ adc_clock = clk_get(NULL, "adc"); if (!adc_clock) { printk(KERN_ERR "failed to get adc clock source\n"); return -ENOENT; } /*时钟获取后要使能后才可以使用,clk_enable 定义在 arch/arm/plat-s3c/clock.c 中*/ clk_enable(adc_clock); //获取时钟,挂载 APB BUS 上的外围设备,需要时钟控制,ADC 就是这样的设备。 | S3C2410_ADCCON_ENABLE_START,

107

/*I/O 内存是不能直接进行访问的,必须对其进行映射,为 I/O 内存分配虚拟地址,这些虚拟地址以 __iomem 进行说明,但不能直接对其进行访问,需要使用专用的函数,如 iowrite32 S3C2410_PA_ADC 是 ADC 控制器的基地址,定义在 mach-s3c2410/include/mach/map.h 中,0x20 是虚 拟地址长度大小*/ base_addr=ioremap(S3C2410_PA_ADC,0x20); if (base_addr == NULL) { printk(KERN_ERR "Failed to remap register block\n"); return -ENOMEM; } /* Configure GPIOs */ s3c2410_ts_connect(); /*计算结果为(二进制):111111111000000,再根据数据手册得知此处是将 AD 转换预定标器值设为 255、 AD 转换预定标器使能有效*/ iowrite32(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF),\ base_addr+S3C2410_ADCCON); //使能预分频和设置分频系数 iowrite32(0xffff, base_addr+S3C2410_ADCDLY); //设置 ADC 延时,在等待中断模式下表示产生 INT_TC 的间隔延时值为 0xffff*/ /*WAIT4INT 宏计算结果为(二进制):11010011,再根据数据手册得知此处是将 ADC 触摸屏控制寄存器设 置成等待中断模式*/ iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC); //按照等待中断的模式设置 TSC

/* Initialise input stuff */ //allocate memory for new input device,用来给输入设备分配空间,并做一些输入设备通用的初始的设置 input_dev = input_allocate_device(); if (!input_dev) { printk(KERN_ERR "Unable to allocate the input device !!\n"); return -ENOMEM; } //设置事件类型 ts_dev = input_dev; ts_dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); ts_dev->keybit[BITS_TO_LONGS(BTN_TOUCH)] = BIT(BTN_TOUCH); input_set_abs_params(ts_dev, ABS_X, 0, 0x3FF, 0, 0); input_set_abs_params(ts_dev, ABS_Y, 0, 0x3FF, 0, 0); input_set_abs_params(ts_dev, ABS_PRESSURE, 0, 1, 0, 0); /*以上四句都是设置事件类型中的 code,如何理解呢,先说明事件类型,常用的事件类型 EV_KEY、 EV_MOSSE, EV_ABS(用来接收像触摸屏这样的绝对坐标事件),而每种事件又会有不同类型的编码 code, 比方说 ABS_X,ABS_Y,这些编码又会有相应的 value*/ ts_dev->name = DEVICE_NAME; ts_dev->id.bustype = BUS_RS232; 108

ts_dev->id.vendor = 0xDEAD; ts_dev->id.product = 0xBEEF; ts_dev->id.version = S3C2410TSVERSION; //以上是输入设备的名称和 id,这些信息时输入设备的身份信息了,在用户空间如何看到呢? //可以通过 cat /proc/bus/input/devices,下面是其输出信息 /*[root@mini2440 /]#cat proc/bus/input/devices I: Bus=0013 Vendor=dead Product=beef Version=0101 N: Name="s3c2410 TouchScreen" P: Phys= S: Sysfs=/devices/virtual/input/input0 U: Uniq= H: Handlers=event0 B: EV=b B: KEY=0 B: ABS=1000003 */ /* Get irqs */ //中断处理 //stylus_action 和 stylus_updown 两个中断处理函数,当笔尖触摸时,会进入到 stylus_updown if (request_irq(IRQ_ADC, stylus_action, IRQF_SHARED|IRQF_SAMPLE_RANDOM, "s3c2410_action", ts_dev)) { printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n"); iounmap(base_addr); return -EIO; } if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM, "s3c2410_action", ts_dev)) { printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n"); iounmap(base_addr); return -EIO; } printk(KERN_INFO "%s successfully loaded\n", s3c2410ts_name); /* All went ok, so register to the input system */ //前面已经设置了设备的基本信息和所具备的能力,所有的都准备好了,现在就可以注册了 input_register_device(ts_dev); return 0; } static void __exit s3c2410ts_exit(void) { disable_irq(IRQ_ADC); disable_irq(IRQ_TC);

109

free_irq(IRQ_TC,ts_dev); free_irq(IRQ_ADC,ts_dev); if (adc_clock) { clk_disable(adc_clock); clk_put(adc_clock); adc_clock = NULL; } input_unregister_device(ts_dev); iounmap(base_addr); } module_init(s3c2410ts_init); module_exit(s3c2410ts_exit);

我们从整体上描述转换的过程: (1) 如果触摸屏感觉到触摸,则进入 updown ISR,如果能获取 ADC_LOCK 则调用 touch_timer_fire, 启动 ADC, (2) ADC 转换,如果小于四次继续转换,如果四次完毕后,启动 1 个时间滴答的定时器,停止 ADC, 也就是说在这个时间滴答内,ADC 是停止的, (3) 这样可以防止屏幕抖动。 (4) 如果 1 个时间滴答到时候,触摸屏仍然处于触摸状态则上报转换数据,并重启 ADC,重复(2) (5) 如果触摸笔释放了,则上报释放事件,并将触摸屏重新设置为等待中断状态。 然后打开 linux-2.6.32.2/drivers/input/touchscreen/Makefile ,定位到文件末尾,添加该源代码的目标模块, 如下红色部分: obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o obj-$(CONFIG_TOUCHSCREEN_MINI2440) += s3c2410_ts.o 再打开 linux-2.6.32.2/drivers/input/touchscreen/Kconfig ,定位到 14 行附近,加入如下红色部分,这样就 在内核配置中添加了 mini2440 的触摸屏驱动选项: if INPUT_TOUCHSCREEN config TOUCHSCREEN_MINI2440 tristate "Samsung S3C2440 touchscreen input driver" depends on MACH_MINI2440 && INPUT && INPUT_TOUCHSCREEN && MINI2440_ADC default y help Say Y here if you have the s3c2440 touchscreen. If unsure, say N. To compile this driver as a module, choose M here: the module will be called s3c2410_ts. config TOUCHSCREEN_MY2440_DEBUG boolean "S3C2440 touchscreens input driver debug messages"

110

depends on TOUCHSCREEN_MINI2440 help Select this if you want debug messages config TOUCHSCREEN_ADS7846 tristate "ADS7846/TSC2046 and ADS7843 based touchscreens" depends on SPI_MASTER depends on HWMON = n || HWMON help 至此,我们就已经在内核中添加完了触摸屏驱动。 【2】配置编译并启动内核 在命令行执行:make menuconfig,然后依次选择如下子菜单,找到刚刚添加的触摸屏驱动选项: Device Drivers ---> Input device support ---> [*] Touchscreens ---> 如图所示,按空格键选中―S3C2440 touchscreens input driver debug messages (NEW)‖ 触摸屏驱动配置 选项:

退出并保存以上内核配置,在命令行输入:make uImage,将生成 arch/arm/boot/uImage 文件,然后复制 到 nfsboot/kernel 目录下。启动开发板,可以在串口终端看到如下启动信息: ... ... mice: PS/2 mouse device common for all mice mini2440_TouchScreen successfully loaded input: mini2440_TouchScreen as /devices/virtual/input/input0 S3C24XX RTC, (c) 2004,2006 Simtec Electronics ... .. 说明触摸屏的驱动加载成功。 【3】创建触摸屏设备节点并测试 (1)新建一个测试文件,代码位于 linux-test/codetest/tstest.c,代码如下: 111

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <sys/poll.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <linux/input.h> struct sample{ char position[15]; int x; int y; }; struct sample sample_array[4]= { {"topleft",0,0}, {"topright",0,0}, {"bottonleft",0,0}, {"bottonright",0,0}, }; int X1,X2,Y1,Y2;

getsample(int fd,int position) { struct input_event ev[128]; int rb,sample_cnt,cntx=0,cnty=0; rb=read(fd,ev,sizeof(struct input_event)*128);

if (rb < (int) sizeof(struct input_event)) { perror("evtest: short read"); 112

exit (1); }

for (sample_cnt = 0; sample_cnt< (int) (rb / sizeof(struct input_event)); sample_cnt++) { if (EV_ABS== ev[sample_cnt].type){ if( sample_cnt%20==0){ printf("%ld.%06ld ", ev[sample_cnt].time.tv_sec, ev[sample_cnt].time.tv_usec); printf("type %d code %d value %d\n", ev[sample_cnt].type, ev[sample_cnt].code, ev[sample_cnt].value); } if(ABS_X==ev[sample_cnt].code){ sample_array[position].x+= ev[sample_cnt].value; cntx++; } if(ABS_Y==ev[sample_cnt].code){ sample_array[position].y+= ev[sample_cnt].value; cnty++; } } } sample_array[position].x/=cntx; sample_array[position].y/=cnty; }

113

int ts_coordinate(int value,int axes) { int tempX,ret; if(ABS_X==axes)ret=240-(240*(value-X2)/(X1-X2)); if(ABS_Y==axes)ret=320-(320*(value-Y2)/(Y1-Y2)); return ret; }

int main(int argc, char **argv) { struct pollfd pfd; int n,fd,i=0; if ((fd = open("/dev/input/event0",O_RDONLY) )< 0) { printf("open error! \n"); exit(1); }

for(i=0;i<4;i++){ printf("Please touch the %s for 6 second ! \n",sample_array[i].position); sleep(6); printf("Time is up Please release\n"); getsample(fd,i); sleep(1); } for(i=0;i<4;i++){ printf("%12s x=%4d,y=%4d\n",sample_array[i].position, sample_array[i].x, sample_array[i].y); } X1=(sample_array[0].x+ sample_array[2].x )/2; X2=(sample_array[1].x+ sample_array[3].x )/2; Y1=(sample_array[0].y+ sample_array[1].y )/2; Y2=(sample_array[2].y+ sample_array[3].y )/2; printf("Coordinate complete,test it now\n"); for(i=0;i<4;i++){ printf("Please touch the %s for 6 second ! \n",sample_array[i].position); sleep(6); 114

printf("Time is up Please release\n"); getsample(fd,i); sample_array[i].x=ts_coordinate(sample_array[i].x,ABS_X); sample_array[i].y=ts_coordinate(sample_array[i].y,ABS_Y); sleep(1); } printf("the data after coordinate \n"); for(i=0;i<4;i++){ printf("%12s x=%4d,y=%4d\n",sample_array[i].position, sample_array[i].x, sample_array[i].y); } close(fd); exit(0); } 然后保存退出。 (2)在主机终端交叉编译 [root@localhost codetest]# arm-linux-gcc -o tstest tstest.c 将其复制到 nfsboot 目录下以便在开发板挂载该目录后能够执行 [root@localhost codetest]# cp tstest /nfsboot/nfs (3)查看设备信息 由启动信息得知触摸屏设备为输入类设备,按如下操作: [root@mini2440 /]#cat proc/devices Character devices: 1 mem 2 pty 3 ttyp 4 /dev/vc/0 4 tty 5 /dev/tty 5 /dev/console 5 /dev/ptmx 7 vcs 10 misc 13 input 14 sound 可以得知输入类设备的主设备号为 13,又按如下操作: [root@mini2440 /]#cat proc/bus/input/devices I: Bus=0013 Vendor=dead Product=beef Version=0101 115

N: Name="mini2440_TouchScreen" P: Phys= S: Sysfs=/devices/virtual/input/input0 U: Uniq= H: Handlers=event0 B: EV=b B: KEY=0 B: ABS=1000003 [root@mini2440 /]# 可看查看总线的具体输入设备输入设备的名称和 id 等详细的身份信息信息。 根据这些信息我们建立好设备节点,设置内核调试级别为 8,至于为什么设置内核调试级别为 8,可以参考 文章 内核模块调试方法 [root@mini2440 /]#mkdir /dev/input [root@mini2440 /]#mknod /dev/input/event0 c 13 64 [root@mini2440 /]#echo 8 > /proc/sys/kernel/printk [root@mini2440 /]#cat /dev/input/event0 然后打开触摸屏设备,点击触摸屏,出现如下信息: ? N 鐉 N 此时看不到打印的坐标信息,运行测试文件,可以看到如下信息: [root@mini2440 nfs]#./tstest Please touch the topleft for 6 second ! Time is up Please release 1308931371.064677 type 3 code 0 value 910 1308931373.034652 type 3 code 0 value 916 Please touch the topright for 6 second ! Time is up Please release 1308931379.909666 type 3 code 1 value 921 1308931380.059651 type 3 code 0 value 920 Please touch the bottonleft for 6 second ! Time is up Please release 1308931387.144660 type 3 code 1 value 72 Please touch the bottonright for 6 second ! Time is up Please release topleft x= 911,y= 82 topright x= 920,y= 920 bottonleft x= 101,y= 72 bottonright x= 98,y= 945 Coordinate complete,test it now Please touch the topleft for 6 second ! Time is up Please release 116 ?? N{ ?? N3{ ? NB{ ? N{? m ? N 驳 ?? N 蔚 ? N ? w ?

1308931395.359705 type 3 code 1 value 944 Please touch the topright for 6 second ! Time is up Please release Please touch the bottonleft for 6 second ! Time is up Please release Please touch the bottonright for 6 second ! Time is up Please release 1308931421.859651 type 3 code 0 value 97 1308931421.979651 type 3 code 0 value 97 1308931422.084660 type 3 code 1 value 937 the data after coordinate topleft x=-14480,y=21165 topright x=45920,y=28480 bottonleft x=-30560,y=-17920 bottonright x=-32400,y=22034 [root@mini2440 nfs]# 有关触摸屏驱动原理详解请参见 Mini2440 触摸屏程序分析。 接下来,将进行 USB 外设配置。

117

Linux-2.6.32.2 内核在 mini2440 上的移植(十)---配置 USB 外设
2011-06-27 19:46:26| 分类: Linux 内核移植 | 标签: |字号大中小 订阅 移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 【1】在内核中配置 USB 键盘和鼠标等 hci 设备驱动程序 Linux-2.6.32.2 内核对 USB 外设的支持是相当丰富的,并且已经包含了 S3C2440 的 USBHost 驱动支 持,因此我们只要配置一下内核就可以了,下面是各种 USB 外设的内核配置。 在 linux-2.6.32.2 根目录下执行 make menuconfig,然后确认如下选项被选中 Device Drivers ---> [*] HID Devices ---> <*> USB Human Interface Device (full HID) support //支持 usb 键盘鼠标等 hci 设备

提示:这里的配置选项对应的内核源代码目录是:linux-2.6.32.2/drivers/hid/usbhid,其中 USB 键盘和条 码扫描器的原理是一样的,因此它们的代码是相同的。 [*] /dev/hiddev raw HID device support //以原始的 raw 方式访问 HID 设备。

以上信息被选中后可以在控制台看到如下启动信息 ... ... usbcore: registered new interface driver hiddev usbcore: registered new interface driver usbhid usbhid: v2.6:USB HID core driver ... ... 使用 LCD 和 USB 键盘作为终端 现在的内核已经支持 LCD 和 USB 键盘可以用它来作为控制台终端了,确保然按前篇文章 Linux-2.6.32.2 内核在 mini2440 上的移植(七)---LCD 驱动移植说过的在命令行增加―console=tty1‖和修改 inittab 文件,当 接上 USB 键盘和 LCD 后,可以在 LCD 上看到如下信息―Please press Enter to activate this console.‖。 这里有一点要注意,点选择了使用 USB 键盘和 LCD 作为独立的输入输出设备之后,串口控制终端将不再 起作用了,在开发调试阶段,还是不这样做为好。 【2】在内核中配置 U 盘驱动程序 因为优盘用到了 SCSI 命令,所以我们先增加 SCSI 支持。 Device Drivers ---> SCSI device support ---> <*> SCSI device support //要支持 USB 磁盘,此项要选中。 [*] legacy /proc/scsi/ support //在/proc/scsi 目录下提供一些信息。

118

<*> SCSI disk support //SCSI 硬盘,要支持 U 盘,此项要选中。 [*] USB support ---> <*> [*] <*> <*> Support for Host-side USB //usb 主机控制器 USB device filesystem (DEPRECATED) //在/proc 文件系统中提供一些调试信息

OHCI HCD support //OHCI 主机控制驱动程序 USB Mass Storage support //USB 存储设备

现在的 U 盘等移动存储器使用的大都是 FAT/FAT32 格式的,因此我们还需要添加 FAT32 文件系统的支 持,在内核配置主菜单下依次选择如下菜单项: File systems ---> DOS/FAT/NT Filesystems ---> <*> MSDOS fs support //加 FAT32 文件系统的支持 //以下为支持中英文的编码

-*- Native language support ---> <*> <*> <*> <*> <*>

Codepage 437 (United States, Canada) Simplified Chinese charset (CP936, GB2312) Traditional Chinese charset (Big5) NLS ISO 8859-1 (Latin 1; Western European Languages) NLS UTF-8

配置完成后,退出并保存以上配置,重新编译 make uImage。然后复制生成的 uImage 到/nfsboot/kernel, 重启开发板,看到如下信息: ... ... eth0: dm9000e at c4872300,c4876304 IRQ 51 MAC: 08:90:90:90:90:90 (chip) ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver s3c2410-ohci s3c2410-ohci: S3C24XX OHCI s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1 s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000 usb usb1: configuration #1 chosen from 1 choice hub 1-0:1.0: USB hub found hub 1-0:1.0: 2 ports detected Initializing USB Mass Storage driver... usbcore: registered new interface driver usb-storage USB Mass Storage support registered. usbcore: registered new interface driver libusual mice: PS/2 mouse device common for all mice mini2440_TouchScreen successfully loaded input: mini2440_TouchScreen as /devices/virtual/input/input0 S3C24XX RTC, (c) 2004,2006 Simtec Electronics

119

s3c2410-rtc s3c2410-rtc: rtc disabled, re-enabling s3c2410-rtc s3c2410-rtc: rtc core: registered s3c as rtc0 i2c /dev entries driver S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled cpuidle: using governor ladder ... ... 测试 U 盘 为了看到插入 U 盘时的打印信息,系统启动时先不要插入优盘,等系统启动后,进入命令行控制台,此时 插入 U 盘,可以看到如下信息: [root@mini2440 /]#usb 1-1: new full speed USB device using s3c2410-ohci and addr ess 2 usb 1-1: configuration #1 chosen from 1 choice scsi0 : SCSI emulation for USB Mass Storage devices scsi 0:0:0:0: Direct-Access USB 2.0 Flash Drive 5.00 PQ: 0 ANSI: 2

sd 0:0:0:0: [sda] 2073600 512-byte logical blocks: (1.06 GB/1012 MiB) sd 0:0:0:0: [sda] Write Protect is off sd 0:0:0:0: [sda] Assuming drive cache: write through sd 0:0:0:0: [sda] Assuming drive cache: write through sda: sda1 sd 0:0:0:0: [sda] Assuming drive cache: write through sd 0:0:0:0: [sda] Attached SCSI removable disk [root@mini2440 /]# 根据上面的提示信息,U 盘对应的是/dev/sda1,现在可以挂载它了 [root@mini2440 /]#mount -t vfat /dev/sda1 /mnt/udisk [root@mini2440 /]#cd /mnt/udisk [root@mini2440 udisk]#ls 100MLT29 18X8??????.jpg 2.4X3.5 20X24??.jpg 20x15 24X18 8X6???.jpg ???? ?????,????? ????????.pdf FileRecv20100328 Photo picall uImage_T35

24X36??.jpg 6X8??.jpg

[root@mini2440 udisk]# 可以看到上面列出的 U 盘的内容。 【4】配置并测试 USB 摄像头驱动 (待续) 【5】配置并测试 USB 无线网卡 (待续) 下一步,将进行 SD 卡驱动移植

120

Linux-2.6.32.2 内核在 mini2440 上的移植(十一)---移植 SD 卡驱

相关文章:
linux DM9000网卡驱动移植(mini2440)
linux DM9000网卡驱动移植(mini2440)_计算机软件及应用_IT/计算机_专业资料。一.Linux 网络体系架构 1.linux TCP/IP 使用四层概念模型:网络接口层,网际层,传输层...
mini2440_lcd_x35驱动的移植
mini2440_lcd_x35驱动移植_计算机软件及应用_IT/计算机_专业资料。从 linux 2.6 起引入了新一套的驱动管理和注册机制:platform_device 和 piatform_driver. (...
友善之臂 mini2440 SPI 驱动移植
友善之臂 mini2440 SPI 驱动移植_信息与通信_工程科技_专业资料。SPI驱动移植 友善之臂mini2440SPI驱动移植 mini2440 spi 2440Linux2.6.32 下 SPI 驱动的移植如...
linux-2.6.32.2内核在mini2440上移植
... 【4】内核配置菜单中的 mini2440 选项和实际代码是如何关联的 ip=10.1.0.129:10.1.128:10.1.0.1:255.25 在 开始移植其他驱动之前, 我们再了解...
mini2440驱动程序tang2440
mini2440驱动程序tang2440_计算机软件及应用_IT/计算机_专业资料。驱动开发程序迷你...mini2440 按键中断 14页 免费 移植Madplay到Mini2440 12页 免费 mini2440_200905...
Linux-2.6.32.2内核在mini2440上的移植(三)
(void) 【2】调整 DM9000 所用的位宽寄存器 因为 Linux-2.6.32.2 的 DM9000 网卡驱动并不是专门为 mini2440 准备的,所以还要在其 源代码中做一些移植工作,...
Linux-2.6.32.2内核在mini2440上的移植(八)
Linux-2.6.32.2 内核在 mini2440 上的移植(八)---添加 ADC 驱动移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 1,主机环境:VMare 下 CentOS...
mini2440底层驱动源程序
mini2440底层驱动源程序_计算机软件及应用_IT/计算机_专业资料。自己写的 已经测试...mini2440驱动移植 169页 免费 Mini2440之i2c驱动(2) 15页 免费 MINI2440 LED...
基于mini2440的按键驱动编写总结
基于mini2440的按键驱动编写总结_信息与通信_工程科技_专业资料。mini2440 按键 ...mini2440按键驱动及详细... 21页 免费 mini2440驱动移植 169页 免费 MINI2440...
mini2440按键驱动及详细解释
mini2440按键驱动及详细解释_IT/计算机_专业资料。mini2440 按键驱动及详细解释 ...mini2440驱动移植 169页 免费 MINI2440 LED驱动程序 7页 免费 Mini2440之i2c驱动...
更多相关标签:
mini2440 uboot移植 | mini2440内核移植 | mini2440移植linux | mini2440上移植opencv | qt5移植到mini2440 | mini2440 lcd驱动 | mini2440 usb下载驱动 | mini2440 led驱动 |