2.6.32.2 linux
2012-10-04 18:07:07 saylerboxer 阅读数 1543
最近一直在做U-boot-2009.08和Linux-2.6.32.2的内核的移植,今天终于可以使用自己移植的U-Boot-2009.08引导自 己修改的Linux-2.6.33.2内核了,还有移植的Yaffs2文件系统,真是太高兴的,现在在把这近两个月内,断断续续的移植做个最后的终结吧! 在这个过程中也有想放弃的时候,不过现在都过来了,哈哈!遇到困难不要放弃,也许当时解决不了,不过可以先放一放,很可能过几天,从新分析时,会发现问题 的所在。这也是我经常不是解决问题的办法的办法!下面开始这篇文章了:
1、机器码的确认:
   U-Boot和Linux中都有一个机器码,只有当这两个机器码一致的时候,才能够正确的引导Linux内核。在这个版本中的U-boot和Linux 中,对MINI2440的板子支持的都很好了,也有了官方的机器码,只要添加上就可以了。在U-Boot中我们可以看到,在u-boot- 2009.08/include/asm-arm/mach-types.h文件中的1985行附近的位置

#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

而在内核中的kernel/linux-2.6.32.2/arch/arm/tools/mach-typs.h文件中的1989行附近的位置

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 //Linux中的MINI2440的机器码
colibri300        MACH_COLIBRI300        COLIBRI300        2000
jades            MACH_JADES        JADES            2001

   从这里我们可以知道MINI2440的机器码就是1999,那么我们就需要修改U-Boot中的机器码,以便和Linux中的机器码一致。在文件u- boot-2009.08/board/frankzfz/mini2440/mini2440.c目录可能会不一样,这是我自己建立的一个目录,大约在 127行附近的位置。在board_init()函数中。

    gpio->GPHUP = 0x000007FF;
    /* arch number of SMDK2410-Board */
    #if defined(CONFIG_S3C2440)
    gd->bd->bi_arch_number = MACH_TYPE_MINI2440; //为u-boot添加机器码
    //gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
#endif

     还有一个地方也已经在另一篇文章《移植Linux内核》中做了说明,也就是在kernel/linux-2.6.32.2/arch/arm/mach-s3c2440/mach-mini2440.c文件中的230行附近中的MACHINE_START,修改成如下:

MACHINE_START(MINI2440, "FriendlyARM MINI2440 development board")

2、用u-boot引导Linux的镜象文件uImage
   通常,kernel的启动需要u-boot提供一些参数信息,比如ramdisk在RAM中的地址。经过编译后的u-boot在根目录下的tools目录 中,会有个叫做mkimage的工具,他可以给zImage添加一个header,也就是说使得通常我们编译的内核zImage添加一个数据头信息部分, 我们把添加头后的image通常叫uImage,uImage是可以被u-boot直接引导的内核镜像。我们如何使用这个工具生成我们需要的uImage格式的镜像文件呢?
1) 编译u-boot成功后会在u-boot-2009.08/tools下生成mkimage的可执行的文件,为了我们在任何地方都可以使用这个命令,首先 我们可以把这个可执行文件复制到/usr/local/bin.这样就可以在任意的目录下执行这个命令了。复制完以后我们在终端下输入 “mkimage”,并按下回车。可以看到下面的输出的信息,说明我们已经可以使用改命令了。

Usage: mkimage -l image
          -==> list image header information
       mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
          -==> set architecture to 'arch' 
//用于指定CPU类型,比如ARM
          -==> set operating system to 'os'
 //用于指定操作系统,比如Linux
          -==> set image type to 'type'
//用于指定image类型,比如Kernelramdisk
          -==> set compression type 'comp'
//指定压缩类型
          -==> set load address to 'addr' (hex)
//指定image的载入地址
          -==> set entry point to 'ep' (hex)
//内核的入口地址,一般是:image的载入地址+0x40(信息头的大小)
          -==> set image name to 'name'
//image在头结构中的命名
          -==> use image data from 'datafile'
//无头信息的image文件名
          -==> set XIP (execute in place)
//设置执行位置即不进行文件的拷贝,在当前位置执行
       mkimage [-D dtc_options] -f fit-image.its fit-image
 

对于ARM Linux我们可以这样使用各个参数:

对于ARM linux内核映象用法:
-A arm -------- 架构是arm
-O linux -------- 操作系统是linux
-T kernel -------- 类型是kernel
-none/bzip/gzip -------- 压缩类型
-a 20008000 ---- image的载入地址(hex),通常为0xX00008000
-e 200080XX---- 内核的入口地址(hex),XX为0x40或者0x00
-n linux-XXX --- image的名字,任意
-d nameXXX ---- 无头信息的image文件名,你的源内核文件
uImageXXX ---- 加了头信息之后的image文件名,任意取

   现在我们可以进入kernel/linux-2.6.32.2/arch/arm/boot目录了,然后执行下面的命令,就会在改目录下面生成uImage.img格式的,u-boot可以引导的内核镜象。

mkimage -'linux-2.6.32.2' -A arm -O linux -T kernel -none -a 0x30008000 -e 0x30008000 -d zImage uImage.img

   现在我们可以把生成的uImage.img格式的镜像文件复制到tftp目录下,使用tftp进行下载了:不过现在下载到以后复制到Nand Flash中u-boot还是无法引导内核,还是需要在u-boot中一些配置。
在u-boot-2009.08/include/configs/mini2440.h文件中

#define CONFIG_BOOTDELAY    3 //自动启动前延时3秒,不过这个要和下面的另一个配置一 

                              //起定义后才会其作用

配置命令行的参数

#define CONFIG_BOOTARGS    "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200 mem=64M"

// 只有这个宏定义了以后 上面的哪个宏的定义才会生效,否则还是会直接的出现命令行的提示符,不会引导内核的。 root=/dev/mtdblock3 这是有我们Linux中的nand Flash分区所决定的,我的NandFlash的第四个分区为根文件系统所以是mtdblock3,如果不是的话请修改

我的NandFlash的情况是这样的

"U-boot",0x00000000 -- 0x00040000,
"param", 0x00040000--
0x00060000,
 "Kernel", 0x00060000---0x00560000,     
"root",
 0x00560000---结束

还要在该文件中增加下面两个宏的定义:

#define CONFIG_SETUP_MEMORY_TAGS 1 //向内核传递内存分布信息
#define CONFIG_INITRD_TAG 
#define CONFIG_CMDLINE_TAG 1   //向内核传递命令行参数

在该文件中添加下面的定义

#define CONFIG_MTD_NAND_YAFFS2 1
#define MTDIDS_DEFAULT "nand0=nandflash0"
#define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k(bootloader),"\
            "128k(params),"\
            "5m(kernel),"\
            "-(root)"  //这里要和Linux内核中的分区信息相一致

下面的这两个定义也要和分区相一致

#define CONFIG_ENV_OFFSET 0x40000 //将环境变量保存在Nand中的0x30000位置
#define CONFIG_ENV_SIZE 0x20000 //Total Size of Environment Sector

为了使u-boot可以自行引导Linux内核,我们还需要添加下面的这句话。

#define CONFIG_BOOTCOMMAND    "nand read 0x32000000 0x60000 0x560000;bootm 0x32000000"  

//这个宏定义的意思是将nand中0x60000-0x560000(和kernel分区一致)的内容读到内存0x32000000中,然后用bootm命令来执行

3、下载系统到内存
  我们先把内核下载到内存中,然后我们执行bootm命令(同一个地址)看能不能启动系统。在U-Boot下执行:
tftp 0x31000000 uImage.img (或uImage)
    在提示下载完成后再执行:
bootm 0x31000000
    如果成功则证明我们的设置没有问题。
4、下载固化
   在前面我们看到了NandFlash的分区信息。下面我们使用命令,把我们的Linux内核和制作的根文件系统下载到NandFlash中,以便以开始启动就可以引导Linux内核。
                             起始地址             结束地址
   uboot            :       0x00000000      0x00040000      0
   param            :       0x00040000      0x00060000      0
   kernel           :       0x00060000      0x00560000      0
   root             :       0x00560000      0x07FFFFFF     0
这是NandFlash的分区情况;
    在u-boot下输入
tftp 0x30000000 uImage.img(或uImage),稍等即可下载uImage到内存中。
    接着执行 nand erase 0x60000 0x500000 删除掉kernel空间原有的数据。
    执行 nand write 0x30000000 0x50000 0x500000,将内存中的kernel烧入nand flash。
    接下来,输入tftp 30000000 rootfs.img,将根文件系统镜象下载到内存中。
    再输入nand erase 0x560000 0x07FFFFFF 将root空间内原有数据删除。
    再输入nand write.yaffs2 0x30000000 0x560000 0x6ffcc0,其中0x6ffcc0是文件系统镜象的size,一定不能写错,它可以tftp下载完毕后看到。
nand erase[clean][off size] 擦除NANDFlash。加上“clean”时,表示在每个块的第一个扇区的OOB区加写入清除的标记:off size表示要擦除的开始偏移地址和长度,如果省略off size 擦除整个NandFlash。现在可以从新启动开发板,从NandFlash启动可以看到启动的信息了。
下载Linux 镜像

[U-Boot@mini2440]#tftp 0x30000000 uImage.img 
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.27.10.48; our IP address is 10.27.10.23 
Filename 'uImage.img'. 
Load address: 0x30000000 
Loading: ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################### 
done 
Bytes transferred = 2092996 (1fefc4 hex) 
[U-Boot@mini2440]#nand erase 0x60000 0x500000 
                                                                                
NAND erase: device 0 offset 0x60000, size 0x500000 
Erasing at 0x54000002800000 -- 0% complete. 
OK 
[U-Boot@mini2440]#nand write 0x30000000 0x60000 0x500000 
                                                                                
NAND write: device 0 offset 0x60000, size 0x500000 
 5242880 bytes written: OK

下载根文件系统

[U-Boot@mini2440]#tftp 30000000 rootfs.img 
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.27.10.48; our IP address is 10.27.10.23 
Filename 'rootfs.img'. 
Load address: 0x30000000 
Loading: ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         ################################################################# 
         #### 
done 
Bytes transferred = 7339200 (6ffcc0 hex) 
[U-Boot@mini2440]#nand erase 0x560000 
                                                                                
NAND erase: device 0 offset 0x560000, size 0x7aa0000 
Erasing at 0x7fe000007aa0000 -- 0% complete. 
OK 
[U-Boot@mini2440]#nand write.yaffs2 0x30000000 0x560000 0x6ffcc0 
                                                                                
NAND write: device 0 offset 0x560000, size 0x6ffcc0 
skip first good block 56000000020000 
 Writing at 0xc4000000020000 --100% is complete 7116800 bytes written: OK

引导Linux内核启动

U-Boot 2009.08 ( 4??月 24 2010 - 17:34:23) 
                                                                                
DRAM: 64 MB 
Flash: 2 MB 
NAND Device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-b)
NAND: 128 MiB 
*** Warning - bad CRC or NAND, using default environment 
                                                                                
In: serial 
Out: serial 
Err: serial 
Net: dm9000 
Hit any key to stop autoboot: 0 
                                                                                
NAND read: device 0 offset 0x60000, size 0x500000 
 5242880 bytes read: OK 
## Booting kernel from Legacy Image at 32000000 ... 
   Image Name: linux-2.6.32.
   Created: 2010-04-24 3:25:34 UTC 
   Image Type: ARM Linux Kernel Image (uncompressed) 
   Data Size: 2092932 Bytes = 2 MB 
   Load Address: 30008000 
   Entry Point: 30008000 
   Verifying Checksum ... OK 
   Loading Kernel Image ... OK 
OK 
                                                                                
Starting kernel ... 
                                                                                
Uncompressing Linux.............................................................
Linux version 2.6.32.(zfz@zfz) (gcc version 4.3.(Sourcery G++ Lite 2008q3-70
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177 
CPU: VIVT data cache, VIVT instruction cache 
Machine: FriendlyARM MINI2440 development 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 
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 root=/dev/mtdblock3 init=/linuxrc console=ttySAC0M
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: 60500KB available (3672K code, 418K data, 132K init, 0K highmem) 
SLUB: Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=
Hierarchical RCU implementation. 
NR_IRQS:85 
irq: clearing subpending status 00000002 
Console: colour dummy device 80x30 
console [ttySAC0] enabled 
Calibrating delay loop... 201.93 BogoMIPS (lpj=504832) 
Mount-cache hash table entries: 512 
CPU: Testing write buffer 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 
usbcore: registered new interface driver usbfs 
usbcore: registered new interface driver hub 
usbcore: registered new device driver usb 
s3c-i2c s3c2440-i2c: slave address 0x10 
s3c-i2c s3c2440-i2c: bus frequency 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 udp transport module. 
RPC: Registered tcp transport module. 
RPC: Registered tcp NFSv4.1 backchannel transport module. 
JFFS2 version 2.2. (NAND) ?&#169; 2001-2006 Red Hat, Inc. 
ROMFS MTD (C) 2007 Red Hat, Inc. 
yaffs Apr 20 2010 11:10:26 Installing. 
msgmni has been set to 118 
alg: No test for stdrng (krng) 
io scheduler noop registered 
io scheduler anticipatory registered (default) 
io scheduler deadline registered 
io scheduler cfq registered 
s3c2410-lcd s3c2410-lcd: no platform data for lcd, cannot attach 
s3c2410-lcd: probe of s3c2410-lcd failed with error -22 
s3c2440-uart.0: s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2440 
s3c2440-uart.1: s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2440 
s3c2440-uart.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: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-b)
Scanning device for bad blocks 
Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit": 
0x000000000000-0x000000040000 : "U-boot" 
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"0
ftl_cs: FTL header not found. 
0x000000000000-0x000040000000 : "nand" 
mtd: partition "nand" extends beyond the end of device "NAND 128MiB 3,3V 8-bit"0
dm9000 Ethernet Driver, V1.31 
ohci_hcd: USB 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 
usbcore: registered new interface driver libusual 
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 UDA134X 
No device for DAI s3c24xx-i2s 
ALSA device list: 
  No soundcards found. 
TCP cubic registered 
NET: Registered protocol family 17 
drivers/rtc/hctosys.c: unable to open rtc device (rtc0) 
yaffs: dev is 32505859 name is "mtdblock3" 
yaffs: passed flags "" 
yaffs: Attempting MTD mount on 31.3, "mtdblock3" 
yaffs: auto selecting yaffs2 
yaffs_read_super: isCheckpointed 0 
VFS: Mounted root (yaffs filesystem) on device 31:3. 
Freeing init memory: 132K 
/etc/init.d/rcS: line 7: echo--------- munt all--------: not found 
************************* 
**********************Frankzfz ARM************** 
Kernel version:linux-2.32.
Student:zfz 
Data:2010,4,19 
*********************** 
                                                                                
Please press Enter to activate this console. 
[root@"Frankzfz"=W]#ls 
bin etc linuxrc proc sys var 
boot home lost+found root tmp 
dev lib mnt sbin usr

   到此整个的嵌入式的基本的移植告一段落了,不过中间还是有很多需要改进的地方,下一不还有驱动的移植。呵呵,就先到这里吧!在这个移植的期间参考了很多的网上资料,也谢谢他们的无私奉献了
2010-01-05 23:40:00 liu_chunhai 阅读数 1855

1. Linux系统编译内核的通用方法


  1. 下载源代码2.6.32.2 version linux kernel


  http://www.kernel.org/


  2.  解压,并把它放到/usr/src/目录下

 

note: 如果出现不能解压的情况,可以使用如下命令改变文件夹得属性

 

#sudo chmod 777 /usr/src


 

  3.    cd linux-2.6.32.2

 

 


  4. 清理源代码(如果是之前已生成一些中间文件可运行此命令,否则不必了)

   make mrproper

  5. 生成config文件

  cp /boot/config-`uname -r` ./.config

  make menuconfig

  在make menuconfig的配置界面中,先选择Load config file, 把该才拷贝的文件加载进来再进行修改,修改完成后,直接选Exit,然后在提示中选择保当前配置文件。

   6. 编译

 make

  7.安装模块

  make modules_install

 该命令会把模块及相关文件放到目录/lib/modules/2.6.18.1/下,并不会与当前内核产生冲突,除非内核版本是一样的。

  8.安装内核

  make install

 该命令会把内核相关文件(bzImage, initrd.img,System.map .config)放到/boot/目录下,文件名均带有内核版本名,与其它版本相关区别。

 

 如果系统安装了LILO,它会自己把该内核的启动加进来。如果是grub程序,那要看情况而定。我在Fodera系统中,它会自动添加该启动项到/boot/grup/menu.lst文件中,而在Ubuntu中则不会,需要手动添加。添加完也,即可重启进行新内核。

 

    9.Ubuntu 中手动添加启动新内核的选项

 

     打开文件/boot/grup/menu.lst

 

 

添加

title  Ubuntu 9.04, kernel 2.6.32.2
uuid  ba85f405-a168-4669-b838-95f631d580a2
kernel  /vmlinuz-2.6.32.2 root=UUID=25aa1e16-b459-444c-a86e-78d9547ae687 ro quiet splash
initrd  /initrd.img-2.6.32.2
quiet

title  Ubuntu 9.04, kernel 2.6.32.2 (recovery mode)
uuid  ba85f405-a168-4669-b838-95f631d580a2
kernel  /vmlinuz-2.6.32.2 root=UUID=25aa1e16-b459-444c-a86e-78d9547ae687 ro  single
initrd  /initrd.img-2.6.32.2

 

 

10.Ubuntu 检查一下以上的你添加的

 vmlinuz-2.6.32.2
initrd.img-2.6.32.2

在boot目录下是不是都存在。

我的就不存在initrd.img-2.6.32.2,所以起机的时候就会有/lib/modules/2.6.32.2/modules.dep not open.的问题

并进initramfs>的提示符下。

 

解决办法是

 

在终端里

#sudo /usr/sbin/mkinitramfs -o /boot/initrd.img-2.6.32.2 2.6.32.2

 

的命令之后就可以了。

 

11.重启电脑。你的kernel可以用了。

12 用命令 #umame -a

 

恭喜你你成功的运行在自己编译的kernel上了。

 

 

 

 

 


reference:http://blog.csdn.net/linyt/archive/2009/03/16/3995435.aspx

 

                http://www.linuxsir.org/bbs/thread356920.html

2012-11-16 08:49:08 yuesichiu 阅读数 1373

linux 2.6.32.2 各驱动代码位置

 

说明:解压内核源代码(linux-2.6.32.2 开头的tgz 压缩文件)可以找到如下驱动,mini2440
提供基于linux-2.6.32.2 内核100%完全可以使用的驱动源代码,绝无库文件,敬请放心使用。
(1)DM9000 网卡驱动
Linux-2.6.32.2/drivers/net/dm9000.c
(2)串口(包括三个串口驱动0,1,2,对应设备名/dev/ttySAC0,1,2)
Linux-2.6.32.2/drivers/serial/s3c2440.c
(3)实时时钟RTC 驱动
Linux-2.6.32.2/drivers/rtc/rtc-s3c.c
(4)LED 驱动
Linux-2.6.32.2/drivers/char/mini2440_leds.c
(5)按键驱动
Linux-2.6.32.2/drivers/char/mini2440_buttons.c
(6)触摸屏驱动
Linux-2.6.32.2/drivers/input/touchscreen/s3c2410_ts.c
(7)yaffs2 文件系统源代码目录
Linux-2.6.32.2/fs/yaffs2
(8)USB 鼠标、键盘源代码
Linux-2.6.32.2/drivers/usb/hid
(9)SD/MMC 卡驱动源代码目录(支持高速最大容量32G SD 卡)
Linux-2.6.32.2/drivers/mmc
(10)Nand Flash 驱动
Linux-2.6.32.2/drivers/mtd/nand
(11)UDA1341 音频驱动目录
Linux-2.6.32.2/sound/soc/s3c24xx
(12)LCD 驱动
Linux-2.6.32.2/drivers/video/s3c2410fb.c
(13)优盘支持驱动
Linux-2.6.32.2/drivers/usb/storage
(14)万能USB 摄像头驱动
Linux-2.6.32.2/drivers/media/video/gspca
(15)I2C-EEPROM 驱动
inux-2.6.32.2/drivers/i2c
(16)背光驱动
Linux-2.6.32.2/drivers/video/mini2440_backlight.c
(17)PWM 控制蜂鸣器驱动
Linux-2.6.32.2/drivers/char/mini2440_pwm.c
(18)看门狗驱动
Linux-2.6.32.2/drivers/watchdog/s3c2410_wdt.c
(19)AD 转换驱动
Linux-2.6.32.2/drivers/char/mini2440_ad.c
(20)CMOS 摄像头驱动
Linux-2.6.32.2/drivers/media/video/s3c2440camif.c
(21)USB 无线网卡驱动(型号:TL-WN321G+)
Linux-2.6.32.2/drivers/net/wireless/rt2x00
(22)USB 转串口驱动
Linux-2.6.32.2/drivers/usb/serial/pl2302.c

2013-05-16 21:14:36 mrjy1475726263 阅读数 935

http://blog.csdn.net/hanxuefan/article/details/7370028

1.3.1  在内核中添加触摸屏驱动程序

以下介绍为网上摘取的一部分内容:

1)、Linux输入子系统(Input Subsystem):

在Linux中,输入子系统是由输入子系统设备驱动层、输入子系统核心层(Input Core)和输入子系统事件处理层(Event Handler)组成。其中设备驱动层提供对硬件各寄存器的读写访问和将底层硬件对用户输入访问的响应转换为标准的输入事件,再通过核心层提交给事件处理层;而核心层对下提供了设备驱动层的编程接口,对上又提供了事件处理层的编程接口;而事件处理层就为我们用户空间的应用程序提供了统一访问设备的接口和驱动层提交来的事件处理。所以这使得我们输入设备的驱动部分不在用关心对设备文件的操作,而是要关心对各硬件寄存器的操作和提交的输入事件。下面用图形来描述一下这三者的关系吧!

另外,又找了另一幅图来说明Linux输入子系统的结构,可能更加形象容易理解。如下:


2)、输入子系统设备驱动层实现原理:

在Linux中,Input设备用input_dev结构体描述,定义在input.h中。设备的驱动只需按照如下步骤就可实现了。
①、在驱动模块加载函数中设置Input设备支持input子系统的哪些事件;
②、将Input设备注册到input子系统中;
③、在Input设备发生输入操作时(如:键盘被按下/抬起、触摸屏被触摸/抬起/移动、鼠标被移动/单击/抬起时等),提交所发生的事件及对应的键值/坐标等状态。

Linux中输入设备的事件类型有(这里只列出了常用的一些,更多请看linux/input.h中):

 

1.           EV_SYN     0x00     同步事件 

2.               

3.           EV_KEY     0x01     按键事件 

4.               

5.           EV_REL     0x02     相对坐标(如:鼠标移动,报告的是相对最后一次位置的偏移) 

6.               

7.           EV_ABS     0x03     绝对坐标(如:触摸屏和操作杆,报告的是绝对的坐标位置) 

8.               

9.           EV_MSC     0x04     其它 

10.           

11.       EV_LED     0x11     LED 

12.           

13.       EV_SND     0x12     声音 

14.           

15.       EV_REP     0x14     Repeat 

16.           

17.       EV_FF      0x15     力反馈 

18.        

 

用于提交较常用的事件类型给输入子系统的函数有:

1.           void input_report_key(struct input_dev *dev, unsigned int code, int value); 

2.               

3.           //提交按键事件的函数 

4.               

5.           void input_report_rel(struct input_dev *dev, unsigned int code, int value); 

6.               

7.           //提交相对坐标事件的函数 

8.               

9.           void input_report_abs(struct input_dev *dev, unsigned int code, int value); 

10.           

11.       //提交绝对坐标事件的函数 

12.        

注意,在提交输入设备的事件后必须用下列方法使事件同步,让它告知input系统,设备驱动已经发出了一个完整的报告:

1.           void input_sync(struct input_dev *dev) 

 

3)、触摸屏驱动的实现步骤

S3c2440芯片内部触摸屏接口与ADC接口是集成在一起的,硬件结构原理图请看:S3C2440上ADC驱动实例开发讲解中的图,其中通道7(XP或AIN7)作为触摸屏接口的X坐标输入,通道5(YP或AIN5)作为触摸屏接口的Y坐标输入。在"S3C2440上ADC驱动实例开发讲解"中,AD转换的模拟信号是由开发板上的一个电位器产生并通过通道1(AIN0)输入的,而这里的模拟信号则是由点触触摸屏所产生的X坐标和Y坐标两个模拟信号,并分别通过通道7和通道5输入。S3c2440提供的触摸屏接口有4种处理模式,分别是:正常转换模式、单独的X/Y位置转换模式、自动X/Y位置转换模式和等待中断模式,对于在每种模式下工作的要求,请详细查看数据手册的描述。本驱动实例将采用自动X/Y位置转换模式和等待中断模式。

 

4)Linux-2.6.32.2 内核也没有包含支持 S3C2440 的触摸屏驱动,因此我们需要加入一个mini2440_touchscreen.c

将它放于linux-src/drivers/input/touchscreen目录下

    #include <linux/module.h>    

    #include <linux/kernel.h>    

    #include <linux/clk.h>    

    #include <linux/init.h>    

    #include <linux/input.h>     

    #include <linux/serio.h>        

    #include <plat/regs-adc.h>   

    #include <asm/irq.h>        

    #include <asm/io.h>

            

    /*用于保存从平台时钟列表中获取的ADC时钟*/

    static struct clk *adc_clk;         

    /*定义了一个用来保存经过虚拟映射后的内存地址*/

    static void __iomem *adc_base;     

    /*定义一个输入设备来表示我们的触摸屏设备*/

    static struct input_dev *ts_dev;        

    /*设备名称*/         

    #define DEVICE_NAME    "my2440_TouchScreen"

       

    /*定义一个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))

       

 

    /*定义一个外部的信号量ADC_LOCK,因为ADC_LOCK在ADC驱动程序中已申明 

    这样就能保证ADC资源在ADC驱动和触摸屏驱动中进行互斥访问*/   

    extern struct semaphore ADC_LOCK;

   

 

   

    /*做为一个标签,只有对触摸屏操作后才对X和Y坐标进行转换*/    

    static int OwnADC = 0; //在ADC驱动里面也有 ADC资源的控制权

       

     

       

    /*用于记录转换后的X坐标值和Y坐标值*/    

    static long xp;    

    static long yp;

   

 

    /*用于计数对触摸屏压下或抬起时模拟输入转换的次数*/    

    static int count;

   

   

    /*定义一个AUTOPST宏,将ADC触摸屏控制寄存器设置成自动转换模式*/    

    #define AUTOPST    (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | \

        S3C2410_ADCTSC_XP_SEN |S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))

   

       static void touch_timer_fire(unsigned long data) ;

       /*定义并初始化了一个定时器touch_timer,定时器服务程序为touch_timer_fire*/

       static struct timer_list touch_timer = TIMER_INITIALIZER(touch_timer_fire, 0, 0);

   

static void touch_timer_fire(unsigned long data)   

{  

    /*用于记录这一次AD转换后的值*/

      unsigned long data0;

      unsigned long data1;

   

   

    /*用于记录触摸屏操作状态是按下还是抬起*/

    int updown;

   

    /*读取这一次AD转换后的值,注意这次主要读的是状态*/

      data0 = readl(adc_base + S3C2410_ADCDAT0);

      data1 = readl(adc_base + S3C2410_ADCDAT1);

   

    /*记录这一次对触摸屏是压下还是抬起,该状态保存在数据寄存器的第15位,

    所以与上 S3C2410_ADCDAT0_UPDOWN*/    

    updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));

        

    /*判断触摸屏的操作状态*/

     if (updown)

    {

   

        /*如果状态是按下,并且ADC已经转换了就报告事件和数据*/

         if (count != 0)

        {

            long tmp;                                                                                         

            tmp = xp;

            xp = yp;

            yp = tmp;                                                                                      

            xp >>= 2;

            yp >>= 2;

   

#ifdef CONFIG_TOUCHSCREEN_MY2440_DEBUG    

        /*触摸屏调试信息,编译内核时选上此项后,点击触摸屏会在终端上打印出坐标信息*/  

        struct timeval tv;

        do_gettimeofday(&tv);

        printk(KERN_DEBUG "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, xp, yp);

           

#endif

        /*报告X、Y的绝对坐标值*/

        input_report_abs(ts_dev, ABS_X, xp);

        input_report_abs(ts_dev, ABS_Y, yp);

   

        /*报告触摸屏的状态,1表明触摸屏被按下*/

           

        input_report_abs(ts_dev, ABS_PRESSURE, 1);

   

        /*报告按键事件,键值为1(代表触摸屏对应的按键被按下)*/

        input_report_key(ts_dev, BTN_TOUCH, 1);

   

           

        /*等待接收方受到数据后回复确认,用于同步*/

        input_sync(ts_dev);

   

    }

    

    /*如果状态是按下,并且ADC还没有开始转换就启动ADC进行转换*/     

    xp = 0;    

    yp = 0;   

    count = 0;

       

    /*设置触摸屏的模式为自动转换模式*/

       

    writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, adc_base + S3C2410_ADCTSC);

   

    /*启动ADC转换*/     

    writel(readl(adc_base + S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START,

         adc_base + S3C2410_ADCCON);

           

    }

    else

    {

   

    /*否则是抬起状态*/   

    count = 0;  

    /*报告按键事件,键值为0(代表触摸屏对应的按键被释放)*/    

    input_report_key(ts_dev, BTN_TOUCH, 0);   

    /*报告触摸屏的状态,0表明触摸屏没被按下*/     

    input_report_abs(ts_dev, ABS_PRESSURE, 0);     

    /*等待接收方受到数据后回复确认,用于同步*/         

    input_sync(ts_dev);

    /*将触摸屏重新设置为等待中断状态*/    

    writel(WAIT4INT(0), adc_base + S3C2410_ADCTSC);    

    /*如果触摸屏抬起,就意味着这一次的操作结束,所以就释放ADC资源的占有*/     

    if (OwnADC)     

    {

       

        OwnADC = 0;         

        up(&ADC_LOCK);

       

    }

   

   }

   

}

 

/*触摸屏中断服务程序,对触摸屏按下或提笔时触发执行*/

   

static irqreturn_t tc_irq(int irq, void *dev_id)        

    {

       

        /*用于记录这一次AD转换后的值*/        

        unsigned long data0;         

        unsigned long data1;

            

        /*用于记录触摸屏操作状态是按下还是抬起*/

       

        int updown;

       

        /*ADC资源可以获取,即上锁*/

        if (down_trylock(&ADC_LOCK) == 0)        

        {  

            /*标识对触摸屏进行了操作*/  

            OwnADC = 1;

           

            /*读取这一次AD转换后的值,注意这次主要读的是状态*/

       

            data0 = readl(adc_base + S3C2410_ADCDAT0);

            data1 = readl(adc_base + S3C2410_ADCDAT1);

       

     

       

        /*记录这一次对触摸屏是压下还是抬起,该状态保存在数据寄存器的第15位,

           

        所以与上 S3C2410_ADCDAT0_UPDOWN*/

           

        updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));

           

            /*判断触摸屏的操作状态*/

       

            if (updown)

            {

        /*如果是按下状态,则调用touch_timer_fire函数来启动ADC转换,该函数定义后面再讲*/

                touch_timer_fire(0);

       

            }

            else

            {

       

        /*如果是抬起状态,就结束了这一次的操作,所以就释放ADC资源的占有*/

                OwnADC = 0;

                up(&ADC_LOCK);

       

            }

       

        }

    return IRQ_HANDLED;

   

}

 

    /*ADC中断服务程序,AD转换完成后触发执行*/     

    static irqreturn_t adc_irq(int irq, void *dev_id)     

    {

    /*用于记录这一次AD转换后的值*/

    unsigned long data0;     

    unsigned long data1;

   

    if(OwnADC) //OwnADC初始值为0,只有对触摸屏操作后才对X和Y坐标进行转换

       

    {

   

    /*读取这一次AD转换后的值,注意这次主要读的是坐标*/

       

    data0 = readl(adc_base + S3C2410_ADCDAT0);

       

    data1 = readl(adc_base + S3C2410_ADCDAT1);

   

    /*记录这一次通过AD转换后的X坐标值和Y坐标值,根据数据手册可知,X和Y坐标转换数值

       

    分别保存在数据寄存器0和1的第0-9位,所以这里与上S3C2410_ADCDAT0_XPDATA_MASK就是取0-9位的值*/

       

    xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;

       

    yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;

   

    /*计数这一次AD转换的次数*/

       

    count++;

       

    if (count < (1<<2))

       

    {

       

    /*如果转换的次数小于4,则重新启动ADC转换*/

       

    writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, adc_base + S3C2410_ADCTSC);

       

    writel(readl(adc_base + S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START,

       

     adc_base + S3C2410_ADCCON);

   

    }

       

    else

       

    {

   

    /*否则,启动1个时间滴答的定时器,这是就会去执行定时器服务程序上报事件和数据*/

     /*touch_timer = TIMER_INITIALIZER(touch_timer_fire, 0, 0); */  

    mod_timer(&touch_timer, jiffies + 1);

       

    writel(WAIT4INT(1), adc_base + S3C2410_ADCTSC);

   

    }

   

    }

   

    return IRQ_HANDLED;

       

}


/*初始化ADC控制寄存器和ADC触摸屏控制寄存器*/

   

static void adc_initialize(void)

   

{

   

    /*计算结果为(二进制):111111111000000,再根据数据手册得知

       

    此处是将AD转换预定标器值设为255、AD转换预定标器使能有效*/

   

    writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF), adc_base + S3C2410_ADCCON);

   

    /*对ADC开始延时寄存器进行设置,延时值为0xffff*/

   

    writel(0xffff, adc_base + S3C2410_ADCDLY);

  

    /*WAIT4INT宏计算结果为(二进制):11010011,再根据数据手册得知

   

    此处是将ADC触摸屏控制寄存器设置成等待中断模式*/

   

    writel(WAIT4INT(0), adc_base + S3C2410_ADCTSC);

   

}

   

static int __init ts_init(void)     

    {

       

        int ret;    

     

        //touch_timer = TIMER_INITIALIZER(touch_timer_fire, 0, 0);   

        /*从平台时钟队列中获取ADC的时钟,这里为什么要取得这个时钟,因为ADC的转换频率跟时钟有关。

           

        系统的一些时钟定义在arch/arm/plat-s3c24xx/s3c2410-clock.c中*/

        adc_clk = clk_get(NULL, "adc");

        if(!adc_clk)    

        {

        /*错误处理*/

            printk(KERN_ERR "falied to find adc clock source\n");

            return -ENOENT;     

        }

       

        /*时钟获取后要使能后才可以使用,clk_enable定义在arch/arm/plat-s3c/clock.c中*/     

        clk_enable(adc_clk);

            

        /*将ADC的IO端口占用的这段IO空间映射到内存的虚拟地址,ioremap定义在io.h中。

           

        注意:IO空间要映射后才能使用,以后对虚拟地址的操作就是对IO空间的操作,

           

        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;

       

        }

   

    /*初始化ADC控制寄存器和ADC 触摸屏控制寄存器*/

    adc_initialize();

 

        /*申请ADC中断,AD转换完成后触发。这里使用共享中断IRQF_SHARED 是因为该中断号在ADC驱动

               

        中也使用了,最后一个参数1是随便给的一个值,因为如果不给值设为NULL的话,中断就申请不成功*/

               

        //因为是共享中断必须最后一个此参数不为NULL

        ret = request_irq(IRQ_ADC, adc_irq, IRQF_SHARED | \

       

                IRQF_SAMPLE_RANDOM, DEVICE_NAME, 1);

       

        if(ret)

        {

       

            printk(KERN_ERR "IRQ%d error %d\n", IRQ_ADC, ret);

            ret = -EINVAL;    

            goto err_nomap;

        }

       

    /*申请触摸屏中断,对触摸屏按下或提笔时触发*/

        ret = request_irq(IRQ_TC, tc_irq, IRQF_SAMPLE_RANDOM, DEVICE_NAME, 1);    

        if(ret)    

        {   

            printk(KERN_ERR "IRQ%d error %d\n", IRQ_TC, ret);

            ret = -EINVAL;

            goto err_noirq;   

        }

 

    /*给输入设备申请空间,input_allocate_device定义在input.h中*/

        ts_dev = input_allocate_device();

       

 

    /*下面初始化输入设备,即给输入设备结构体input_dev的成员设置值。

       

    evbit字段用于描述支持的事件,这里支持同步事件、按键事件、绝对坐标事件,

       

    BIT宏实际就是对1进行位操作,定义在linux/bitops.h中*/

       

    ts_dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);

   

    /*keybit字段用于描述按键的类型,在input.h中定义了很多,

       

    这里用BTN_TOUCH类型来表示触摸屏的点击*/

   

      ts_dev->keybit[BITS_TO_LONGS(BTN_TOUCH)] = BIT(BTN_TOUCH);

   

    /*对于触摸屏来说,使用的是绝对坐标系统。这里设置该坐标系统中X和Y坐标的最小值和最大值

       

    (0-1023范围)ABS_X和ABS_Y就表示X坐标和Y坐标,ABS_PRESSURE就表示触摸屏是按下还是抬起状态*/

       

        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);

   

    /*以下是设置触摸屏输入设备的身份信息,直接在这里写死。

       

        这些信息可以在驱动挂载后在/proc/bus/input/devices中查看到*/

       

        ts_dev->name          = DEVICE_NAME;   /*设备名称*/

       

        ts_dev->id.bustype    = BUS_RS232;     /*总线类型*/    

       

        ts_dev->id.vendor     = 0xDEAD;        /*经销商ID号*/

       

        ts_dev->id.product    = 0xBEEF;        /*产品ID号*/

       

        ts_dev->id.version    = 0x0101;        /*版本ID号*/

 

    /*好了,一些都准备就绪,现在就把 ts_dev触摸屏设备注册到输入子系统中*/

       

        input_register_device(ts_dev);

        return 0;

    /*下面是错误跳转处理*/

   

    err_noclk:

        clk_disable(adc_clk);

        clk_put(adc_clk);

       

    err_nomap:

        iounmap(adc_base);

       

    err_noirq:

        free_irq(IRQ_ADC, 1);

        return ret;

}

static void __exit ts_exit(void)   

{

   

    /*屏蔽和释放中断*/   

    disable_irq(IRQ_ADC);     

    disable_irq(IRQ_TC);

    free_irq(IRQ_ADC, 1);

    free_irq(IRQ_TC, 1);

  

    /*释放虚拟地址映射空间*/

    iounmap(adc_base);

   

    /*屏蔽和销毁时钟*/

   

    if(adc_clk)

    {

        clk_disable(adc_clk);

        clk_put(adc_clk);   

        adc_clk = NULL;

    }

 

    /*将触摸屏设备从输入子系统中注销*/

    input_unregister_device(ts_dev);

}

   

module_init(ts_init);   

module_exit(ts_exit);

   

MODULE_LICENSE("GPL");   

MODULE_AUTHOR("Huang Gang");   

MODULE_DESCRIPTION("My2440 Touch Screen Driver"); 



然后在  linux-2.6.32.2/drivers/input/touchscreen/Makefile  文件中添加该源代码的目标模块,如图红色部分:

obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)  +=zylonite-wm97xx.o

obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o

obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o

obj-$(CONFIG_TOUCHSCREEN_MINI2440) += mini2440_touchscreen.o



再打开 linux-2.6.32.2/drivers/input/touchscreen/Kconfig 文件,加入如下红色部分,这样就在内核配置中添加了 mini2440 的触摸屏驱动选项:

menuconfig INPUT_TOUCHSCREEN

bool "Touchscreens"

help

Say Y here, and a list of supported touchscreens will be displayed.

This option doesn't affect the kernel.

 

If unsure, say Y.

 

if INPUT_TOUCHSCREEN

 

config TOUCHSCREEN_MINI2440

tristate "Samsung S3C2410 touchscreen input driver"

depends on MACH_MINI2440 && INPUT && INPUT_TOUCHSCREEN && MINI2440_ADC

help

Say Y here if you have the mini2440 touchscreen.

 

If unsure, say N.

 

To compile this driver as a module, choose M here: the

module will be called s3c2410_ts.

 

config TOUCHSCREEN_ADS7846

tristate "ADS7846/TSC2046 and ADS7843 based touchscreens"

depends on SPI_MASTER

depends on HWMON = n || HWMON

help

 

1.3.2  配置编译内核并测试触摸屏驱动

 

在命令行执行:make  menuconfig,然后依次选择如下子菜单,找到刚刚添加的触摸屏驱动选项:

Device Drivers    --->

Input device support    --->

[*]      Touchscreens    --->

按空格键选中触摸屏驱动配置选项,并且进入选择自己的驱动。退出并保存以上内核配置,在命令行输入:make zImage,将生成 arch/arm/boot/zImage 文件,使用supervivi "k"命令把它烧写到开发板。

 

1.3.3  触摸屏驱动原理详解

 

原文出处:

http://www.arm9home.net/read.php?tid-2406-keyword-%B4%A5%C3%FE%C6%C1%B3%CC%D0%F2.html

这里不再赘述。


2012-09-10 15:38:21 taozi343805436 阅读数 1761

1.获取内核移植源码

http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.2.tar.bz2

2.解压内核源码

(1).bzip2 -d linux-2.6.32.2.tar.bz2

(2).tar -xvf  linux-2.6.32.2.tar

3.修改总目录下的Makefile

原:

export KBUILD_BUILDHOST := $(SUBARCH)
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=


改为
export KBUILD_BUILDHOST := $(SUBARCH)
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
其中,ARCH 是指定目标平台为 arm, CROSS_COMPILE 是指定交叉编译器,这里指定的是系统默认的交叉编译器,如要使用其它的,则要把编译器的全路径在这里写出。

4.测试一下linux编译是否能通过

 #make s3c2410_defconfig ;使用缺省内核配置文件,s3c2410_defconfig 是 SMDK2440 的缺省配置文件
 #make ;编译时间较长

5.克隆建立自己的平台

5.1 linux-2.6.32.2/arch/arm/mach-s3c2440 目 录 下 有 个mach-mini2440.c 文件,它其实就是国外爱好者为 mini2440 移植添加的主要内容了,但我们不需要,直接删除。

5.2 将 linux-2.6.32.2/arch/arm/mach-s3c2440/目录下的 mach-smdk2440.c 复制一份。命名为mach-mini2440.c , 找 到 MACHINE_START(S3C2440, "SMDK2440") , 修 改 为
MACHINE_START(MINI2440, "FriendlyARM Mini2440 development board")

5.3修改时钟源频率

mach-mini2440.c( 就 是 我 们 刚 刚 通 过 复 制mach-smdk2440.c 得到的)的第 160 行 static void __init smdk2440_map_io(void)函数中,把其中的 16934400(代表SMDK2440 目标板上的晶振是 16.9344MHz)改为 mini2440 开发板上实际使用的 12000000(代表 mini2440 开发板上的晶振 12MHz,元器件标号为 X2)

因为我们要制作自己的 mini2440 平台体系,因此把 mach-mini2440.c 中所有的smdk2440 字样改为 mini2440,可以使用批处理命令修改,在 vim 的命令模式下输入:
%s/smdk2440/mini2440/g
上面这句的意思是:把所有和“smdk2440”匹配的字符串全部替换为“mini2440”,前面的“%s“代表字符串匹配,最后的“g”代表 global,是全局的意思。
除此之外,还有一个地方需要改动,在 mini2440_machine_init(void)函数中,把smdk_machine_init()函数调用注释掉,因为我们后面会编写自己的初始化函数,不需要调用smdk2440 原来的。

6.在 Linux 源代码根目录下执行
#make mini2440_defconfig ;使用 Linux 官方自带的 mini2440 配置
#make zImage ;编译内核,时间较长,最后会生成 zImage
重新编译并把生成的内核文件 zImage(位于 arch/arm/boot 目录)下到板子中,可以看到内核已经可以正常启动了。








没有更多推荐了,返回首页