Chinaunix首页 | 论坛 | 博客
  • 博客访问: 82546
  • 博文数量: 15
  • 博客积分: 15
  • 博客等级: 民兵
  • 技术积分: 204
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-30 11:18
个人简介

一个奋斗在北京的东北人,一直在打杂,从未被超越!

文章存档

2021年(1)

2013年(11)

2012年(3)

我的朋友

分类: LINUX

2013-04-10 13:41:23

1. 移植准备
1.1 获取Linux内核源代码(linux-2.6.32.tar.gz)
 $ wget
1.2 解压内核源代码
 $ tar xvzf linux-2.6.32.tar.gz
 得linux-2.6.32源代码目录
1.3 指定交叉编译变量
修改总目录下的 Makefile

  1. export KBUILD_BUILDHOST := $(SUBARCH)
  2. ARCH   ?= $(SUBARCH)
  3. CROSS_COMPILE ?=
改为
  1. export KBUILD_BUILDHOST := $(SUBARCH)
  2. ARCH   ?= arm
  3. CROSS_COMPILE ?= /usr/local/arm/4.3.2/bin/arm-linux-
其中,ARCH 是指定目标平台为 arm,CROSS_COMPILE 是指定交叉编译器
接下来,要测试一下 linux 的编译是否能正常通过。
执行:
  1. $ make s3c2410_defconfig
使用缺省内核配置文件,s3c2410_defconfig 是 SMDK2440 的
缺省配置文件
  1. $ make
编译时间较长
编译通过,在此我们先不必烧写到开发板验证它的正确性。

2. 开始移植
2.1 克隆建立自己的目标平台
   删除 arch/arm/mach-s3c2440/mach-mini2440.c
   重新复制 arch/arm/mach-s3c2440/mach-smdk2440.c 为arch/arm/mach-s3c2440/mach-mini2440.c
  修改:
  1. MACHINE_START(S3C2440, "SMDK2440")
 为:
  1. MACHINE_START(MINI2440, "FriendlyARM Mini2440 development board")
2.2 修改时钟源频率

  static void __init smdk2440_map_io(void)
        16934400  ---> 12000000
2.3 从 SMDK2440 到 MINI2440
 在mach-mini2440.c中替换所有的smdk2440为mini2440 (%s/smdk2440/mini2440/g)
并注释掉mini2440_machine_init(void)函数中的 smdk_machine_init()

2.4 编译测试
  1. $ make mini2440_defconfig
  2. $ make zImage
  使用linux dnw下载zImage至开发板,命令:
  板子 ——> 选【k】 download linux kernel
  PC  ——> $ dnw arch/arm/boot/zImage
  然后板子端选 [b] Boot the system
可以看到,kernel已经可以引导,单还不能完全跑起来。

3. 移植 Nand 驱动并更改分区信息
Linux2.6.32 已 经 自 带 了 大 部 分 Nand Flash 驱 动 , 在linux-2.6.32/drivers/mtd/nand/nand_ids.c 文件中,定义了所支持的各种 Nand Flash 类型。
在 mach-mini2440.c 中加入以下代码:
  1. static struct mtd_partition mini2440_default_nand_part[] = {
  2.     [0] = {
  3.         .name = "supervivi",
  4.         .size = 0x00040000, //256K
  5.         .offset = 0,
  6.     },
  7.     [1] = {
  8.         .name = "param",
  9.         .size = 0x00020000, //128K
  10.         .offset = 0x00040000,
  11.     },
  12.     [2] = {
  13.         .name = "Kernel",
  14.         .size = 0x00500000, //5M
  15.         .offset = 0x00060000, //0x00040000 + 0x00020000
  16.     },
  17.     [3] = {
  18.         .name = "root",
  19.         .size = 0x40000000,
  20.         .offset = 0x00560000,
  21.     },
  22.     [4] = {
  23.         .name = "nand",
  24.         .size = 1024 * 1024 * 1024,
  25.         .offset = 0x00000000,
  26.     }
  27. };
  28. static struct s3c2410_nand_set mini2440_nand_sets[] = {
  29.     [0] = {
  30.         .name = "NAND",
  31.         .nr_chips = 1,
  32.         .nr_partitions = ARRAY_SIZE(mini2440_default_nand_part),
  33.         .partitions = mini2440_default_nand_part,
  34.     },
  35. };
  36. static struct s3c2410_platform_nand mini2440_nand_info = {
  37.     .tacls = 20,
  38.     .twrph0 = 60,
  39.     .twrph1 = 20,
  40.     .nr_sets = ARRAY_SIZE(mini2440_nand_sets),
  41.     .sets = mini2440_nand_sets,
  42.     .ignore_unset_ecc = 1,
  43. };
除此之外,还需要把 nand flash 设备注册到系统中,同时加入RTC
  1. static struct platform_device *mini2440_devices[] __initdata = {
  2.     &s3c_device_usb,
  3.     &s3c_device_lcd,
  4.     &s3c_device_wdt,
  5.     &s3c_device_i2c0,
  6.     &s3c_device_iis,
  7.     &s3c_device_nand, // new added
  8.     &s3c_device_rtc, //new added
  9. };
此时执行 make zImage 会报错如下:
  1. CHK include/linux/version.h
  2. make[1]: `include/asm-arm/mach-types.h' is up to date.
  3.   CHK include/linux/utsrelease.h
  4.   SYMLINK include/asm -> include/asm-arm
  5.   CALL scripts/checksyscalls.sh
  6.   CHK include/linux/compile.h
  7.   CC arch/arm/mach-s3c2440/mach-mini2440.o
  8. arch/arm/mach-s3c2440/mach-mini2440.c:49: error: array type has incomplete element type
  9. arch/arm/mach-s3c2440/mach-mini2440.c:50: error: array index in non-array initializer
  10. arch/arm/mach-s3c2440/mach-mini2440.c:50: error: (near initialization for 'mini2440_default_nand_part')
  11. arch/arm/mach-s3c2440/mach-mini2440.c:51: error: field name not in record or union initializer
  12. arch/arm/mach-s3c2440/mach-mini2440.c:51: error: (near initialization for 'mini2440_default_nand_part')
  13. arch/arm/mach-s3c2440/mach-mini2440.c:52: error: field name not in record or union initializer
这是因为缺少以下头文件:
  1. #include <linux/mtd/mtd.h>
  2. #include <linux/mtd/nand.h>
  3. #include <linux/mtd/nand_ecc.h>
  4. #include <linux/mtd/partitions.h>
  5. #include <plat/nand.h>
加入重新编译,生成arch/arm/boot/zImage,下载至板子,重新启动,结果产生kernel panic如下:
  1. S3C24XX NAND Driver, (c) 2004 Simtec Electronics
  2. s3c24xx-nand s3c2440-nand: Tacls=4, 39ns Twrph0=8 79ns, Twrph1=8 79ns
  3. Unable to handle kernel NULL pointer dereference at virtual address 00000018
  4. pgd = c0004000
  5. [00000018] *pgd=00000000
  6. Internal error: Oops: 5 [#1]
  7. last sysfs file:
  8. Modules linked in:
  9. CPU: 0 Not tainted (2.6.32 #2)
  10. PC is at s3c24xx_nand_probe+0x2d8/0x514
  11. LR is at s3c24xx_nand_probe+0x1a4/0x514
  12. pc : [<c01d9d44>] lr : [<c01d9c10>] psr: 60000013
  13. sp : c3823f08 ip : 00000000 fp : 00000001
  14. r10: 00000000 r9 : 00000000 r8 : 00000000
  15. r7 : c03cf388 r6 : 00000000 r5 : c39b68c0 r4 : c3895800
  16. r3 : 00000001 r2 : c3895988 r1 : c4c00000 r0 : 00000002
  17. Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
  18. Control: c000717f Table: 30004000 DAC: 00000017
  19. Process swapper (pid: 1, stack limit = 0xc3822270)
  20. Stack: (0xc3823f08 to 0xc3824000)
红色的内容说明我们更改的nand驱动参数根本就没有生效,分析Linux内核中的nand flash驱动drivers/mtd/nand/s3c2410.c文件中的相应函数,
其中的static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)函数发现:
  1. struct s3c2410_platform_nand *plat = info->platform;
  2.         int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
  3.          …………
  4.     info->clk_rate = clkrate;
  5.         clkrate /= 1000; /* turn clock into kHz for ease of use */

  6.         if (plat != NULL) {
  7.                 tacls = s3c_nand_calc_rate(plat->tacls, clkrate, tacls_max);
  8.                 twrph0 = s3c_nand_calc_rate(plat->twrph0, clkrate, 8);
  9.                 twrph1 = s3c_nand_calc_rate(plat->twrph1, clkrate, 8);
  10.         } else {
  11.           /* default timings */
  12.                 tacls = tacls_max;
  13.                 twrph0 = 8;
  14.                 twrph1 = 8;
  15.             }

  16.         if (tacls < 0 || twrph0 < 0 || twrph1 < 0) {
  17.                 dev_err(info->device, "cannot get suitable timings\n");
  18.                 return -EINVAL;
  19.         }

  20.         dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
  21.                tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));
由以上内容可以看出,你的内核并没有使用你的mini2440_nand_info结构体中的配置,而是使用了它的默认配给,即
} else {      
          /* default timings */
                tacls = tacls_max;
                twrph0 = 8;
                twrph1 = 8;
      
            }
中的配置信息。这点和你的内核输出s3c24xx-nand s3c2440-nand: Tacls=4, 39ns Twrph0=8 79ns, Twrph1=8 79ns完全符合。

解决方法:
只需在mach-mini2440.c的初始化函数mini2440_machine_init(void)里加入
  1. s3c_device_nand.dev.platform_data=&mini2440_nand_info;
即可。
重新编译、下载运行,可以看到nand分区信息:
  1. S3C24XX NAND Driver, (c) 2004 Simtec Electronics
  2. s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns
  3. s3c24xx-nand s3c2440-nand: NAND soft ECC
  4. NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit)
  5. Scanning device for bad blocks
  6. Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit":
  7. 0x000000000000-0x000000040000 : "supervivi"
  8. uncorrectable error :
  9. 0x000000040000-0x000000060000 : "param"
  10. uncorrectable error :
  11. 0x000000060000-0x000000560000 : "Kernel"
  12. uncorrectable error :
  13. 0x000000560000-0x000008000000 : "root"
  14. ftl_cs: FTL header not found.
  15. 0x000000000000-0x000008000000 : "nand"
至此,就完成了 nand flash 驱动的移植

4.  移植 yaffs2
4.1 下载yaffs2源代码
网上有人说使用下述方法下载yaffs2源码
  1. $ git clone git://www.aleph1.co.uk/yaffs2
但是,我用该命令未能下载下来,连接被重置。
我是直接进入下载()
选择最新版本,点击snapshot下载。
 进入解压后源代码目录yaffs2-d43e901:
  1. $ cd yaffs2-d43e901
4.2为内核打上 yaffs2 补丁
  1. ./patch-ker.sh c m ../../kernel/linux-2.6.32
Updating ../../kernel/linux-2.6.32/fs/Kconfig
Updating ../../kernel/linux-2.6.32/fs/Makefile
此时,inux-2.6.32/fs 目录,可以看到已经多了一个 yaffs2 目录

4.3配置和编译带 YAFFS2 支持的内核
在 Linux 内核源代码根目录运行:make menuconfig
选中
  1. Kernel Features --->
  2.     [*] Use the ARM EABI to compile the kernel
  3.     [*] Allow old ABI binaries to run with this kernel (EXPERIMENTAL) (NEW)
  1. File systems --->
  2.      [*] Miscellaneous filesystems --->
  3.                 <*> yaffs2 file system support
  4.                 -*- 512 byte / page devices
保存并退出。
然后重新编译内核:
  1. make zImage
并把zImage烧写至板子,同时也把FriendlyARM随机带的root_qtopia-128M.img烧写至root分区,然后测试,串口log如下:
  1. FAT: unable to read boot sector
  2. VFS: Cannot open root device "mtdblock2" or unknown-block(31,2)
  3. Please append a correct "root=" boot option; here are the available partitions:
  4. 1f00 256 mtdblock0 (driver?)
  5. 1f01 128 mtdblock1 (driver?)
  6. 1f02 5120 mtdblock2 (driver?)
  7. 1f03 125568 mtdblock3 (driver?)
  8. 1f04 131072 mtdblock4 (driver?)
  9. Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,2)
  10. [<c00319f8>] (unwind_backtrace+0x0/0xdc) from [<c02d9044>] (panic+0x40/0x118)
  11. [<c02d9044>] (panic+0x40/0x118) from [<c0009000>] (mount_block_root+0x1d0/0x210)
  12. [<c0009000>] (mount_block_root+0x1d0/0x210) from [<c0009298>] (prepare_namespace+0x164/0x1bc)
  13. [<c0009298>] (prepare_namespace+0x164/0x1bc) from [<c00085bc>] (kernel_init+0xd8/0x10c)
  14. [<c00085bc>] (kernel_init+0xd8/0x10c) from [<c002ce14>] (kernel_thread_exit+0x0/0x8)
这个说明根据bootloader传过来的linux_cmd_line,不能找到真正的root分区。由于上文对nand flash分区如下:
  1. 0x000000000000-0x000000040000 : "supervivi"
  2. 0x000000040000-0x000000060000 : "param"
  3. 0x000000060000-0x000000560000 : "Kernel"
  4. 0x000000560000-0x000040560000 : "root"
  5. 0x000000000000-0x000040000000 : "nand"
说明root内容存放在/dev/mtdblock3上,因此,先检查bootloader设置。
按q进入vivi command line
  1. Supervivi> param show
  2. Number of parameters: 9
  3. name                                 :                                  hex                                           integer
  4. -------------------------------------------------------------------------------------------------------------
  5. mach_type                        :                             000007cf                                       1999
  6. media_type                       :                             00000003                                          3
  7. boot_mem_base               :                             30000000                                805306368
  8. baudrate                            :                             0001c200                                    115200
  9. xmodem                            :                             00000001                                           1
  10. xmodem_one_nak            :                             00000000                                           0
  11. xmodem_initial_timeout :                             000493e0                                       300000
  12. xmodem_timeout            :                              000f4240                                      1000000
  13. boot_delay                        :                              01000000                                     16777216
  14. Linux command line: noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0
linux_cmd_line设置不对,修改之
  1. Supervivi> param set linux_cmd_line "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0"
  2. Change linux command line to "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0"
  3. Supervivi> param save
  4. Found block size = 0x00020000
  5. Erasing... ... done
  6. Writing... ... done
  7. Written 49152 bytes
  8. Saved vivi private data
  9. Supervivi> menu
重新启动,输出log如下:
  1. S3C24XX RTC, (c) 2004,2006 Simtec Electronics
  2. s3c2410-rtc s3c2410-rtc: rtc disabled, re-enabling
  3. s3c2410-rtc s3c2410-rtc: rtc core: registered s3c as rtc0
  4. S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics
  5. s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled
  6. Advanced Linux Sound Architecture Driver Version 1.0.21.
  7. No device for DAI UDA134X
  8. No device for DAI s3c24xx-i2s
  9. ALSA device list:
  10.   No soundcards found.
  11. TCP cubic registered
  12. NET: Registered protocol family 17
  13. s3c2410-rtc s3c2410-rtc: hctosys: invalid date/time
  14. yaffs: dev is 32505859 name is "mtdblock3" rw
  15. yaffs: passed flags ""
  16. VFS: Mounted root (yaffs filesystem) on device 31:3.
  17. Freeing init memory: 140K
  18. hwclock: settimeofday() failed: Invalid argument
  19. [01/Jan/1970:00:00:12 +0000] boa: server version Boa/0.94.13
  20. [01/Jan/1970:00:00:12 +0000] boa: server built Mar 26 2009 at 15:28:42.
  21. [01/Jan/1970:00:00:12 +0000] boa: starting server pid=933, port 80
  22.                                                                                                                            
  23. open device leds: No such file or directory
  24. Try to bring eth0 interface up......ifconfig: SIOCGIFFLAGS: No such device
  25. ifconfig: SIOCSIFHWADDR: No such device
  26. ifconfig: SIOCSIFADDR: No such device
  27. route: SIOCADDRT: Network is unreachable
  28. Done
  29.                                                                                                                            
  30. Please press Enter to activate this console.
至此说明kernel已经可以成功mount rootfs,linux kernel移植成功!

阅读(1284) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~