将uClinux(linux-2.6.14核)移植到Samsung S3C44B0X

声明:因本人刚接触embedded不足一个月,乃embedded菜鸟。本文旨在帮助和我一样的菜鸟们少走些弯路,文中若有不对的地方还望各路英豪不吝赐教。

Hily Jiang
Email&Gtalk: hilyjiang at Gmail
Blog: http://hily.me/blog/

经过几天的浴血奋战,总算有点成果了,废话不多说,赶紧把过程记下来。

准备工作花了我不少时间,光是下载uClinux-dist就用了两天,其间还看了些移植相关的文章,不过多数是使用2.4.x核的linux。
准备工作:

开发板:Samsung S3C44B0X
uClinux大礼包:uClinux-dist-20051110.tar.gz(点击下载)
开发工具链:arm-elf-tools-20040427.sh(点击下载)
2.6.14内核:linux-2.6.14.tar.bz2(点击下载)
2.6.14内核的uClinux补丁:linux-2.6.14-uc0.patch.gz(点击下载)
韩国人Hyok S. Choi做的ARM补丁 linux-2.6.14-hsc0.patch.gz(点击下载)

开始前请准备好足够大的空间,我下载了好几个版本的dist和内核源码,差不多用了2.9G。当然,实际上用不到这么大。
我的工作目录结构如下:

linux:/home/work/uclinux # ll
总用量 322030
drwxr-xr-x  2 root root       280 2006-09-05 13:39 .
drwxr-xr-x  7 root root       632 2006-09-05 13:39 ..
-rwxr--r--  1 root root  17589174 2006-09-03 18:49 arm-elf-tools-20040427.sh
-rw-r--r--  1 root root    203995 2006-09-04 14:03 linux-2.6.14-hsc0.patch.gz
-rw-r--r--  1 root root  39172170 2006-09-04 13:44 linux-2.6.14.tar.bz2
-rw-r--r--  1 root root     29942 2006-09-04 14:29 linux-2.6.14-uc0.patch.gz
-r-xr-xr-x  1 root root 272430004 2006-08-30 16:30 uClinux-dist-20051110.tar.gz

工具链的建立:
这一部比较简单,直接运行下载的arm-elf-tools-20040427.sh即可:

linux:/home/work/uclinux # chmod u+x arm-elf-tools-20040427.sh
linux:/home/work/uclinux # ./arm-elf-tools-20040427.sh

准备代码树:
解压uClinux-dist-20051110.tar.gz:

linux:/home/work/uclinux # tar -zxf uClinux-dist-20051110.tar.gz
linux:/home/work/uclinux # ll uClinux-dist
总用量 60
drwxr-xr-x   17 root root    536 2005-11-10 12:20 .
drwxr-xr-x    3 root root    312 2006-09-05 13:45 ..
drwxrwxr-x    2  500   500   608 2005-11-10 12:21 bin
drwxrwxr-x    3  500   500   248 2005-11-10 12:21 config
-rw-rw-r--    1  500   500 18007 1999-11-22 11:46 COPYING
drwxrwxr-x    3  500   500  1600 2005-11-10 12:10 Documentation
drwxrwxr-x   11  500   500   704 2005-11-10 12:21 freeswan
drwxr-xr-x   68  500 users  3128 2005-11-10 12:16 glibc
drwxrwxr-x    2  500   500    72 2005-11-10 12:19 include
drwxrwxr-x   29  500   500   736 2005-11-10 12:21 lib
drwxrwxr-x   15  500   500   528 2005-11-10 12:10 linux-2.0.x
drwxrwxr-x   16  500   500   584 2005-11-10 12:12 linux-2.4.x
drwxr-xr-x   18  500 users   600 2005-11-10 12:21 linux-2.6.x
-rw-r--r--    1  500 users 10303 2005-08-25 11:37 Makefile
drwxrwxr-x   13  500   500   680 2005-11-10 12:14 openswan
-rw-rw-r--    1  500   500  4931 2004-11-11 12:19 README
-rw-rw-r--    1  500   500  1743 2004-01-21 07:49 SOURCE
drwxrwxr-x    5  500   500   312 2005-11-10 12:20 tools
drwxr-xr-x   18  500 users   704 2005-11-10 12:21 uClibc
drwxrwxr-x  212  500   500  5600 2005-11-10 12:21 user
drwxrwxr-x   59  500   500  1504 2005-11-10 12:21 vendors

移除linux-2.6.x,准备用新核替换:

linux:/home/work/uclinux # cd uClinux-dist/
linux:/home/work/uclinux/uClinux-dist # rm -rf linux-2.6.x/

解压linux-2.6.14内核包:

linux:/home/work/uclinux # cd ..
linux:/home/work/uclinux # tar -jxf linux-2.6.14.tar.bz2

为新内核打上补丁:

linux:/home/work/uclinux # cd linux-2.6.14/
linux:/home/work/uclinux/linux-2.6.14 # gzip -dc ../linux-2.6.14-uc0.patch.gz | patch -p1
......
linux:/home/work/uclinux/linux-2.6.14 # gzip -dc ../linux-2.6.14-hsc0.patch.gz | patch -p1
......

将新核移到uClinux代码树中:

linux:/home/work/uclinux/linux-2.6.14 # cd ..
linux:/home/work/uclinux # mv linux-2.6.14 uClinux-dist/linux-2.6.x
linux:/home/work/uclinux # cd uClinux-dist/
linux:/home/work/uclinux/uClinux-dist # ll
总用量 60
drwxr-xr-x   17 root root    536 2006-09-05 13:56 .
drwxr-xr-x    3 root root    312 2006-09-05 13:56 ..
drwxrwxr-x    2  500   500   608 2005-11-10 12:21 bin
drwxrwxr-x    3  500   500   248 2005-11-10 12:21 config
-rw-rw-r--    1  500   500 18007 1999-11-22 11:46 COPYING
drwxrwxr-x    3  500   500  1600 2005-11-10 12:10 Documentation
drwxrwxr-x   11  500   500   704 2005-11-10 12:21 freeswan
drwxr-xr-x   68  500 users  3128 2005-11-10 12:16 glibc
drwxrwxr-x    2  500   500    72 2005-11-10 12:19 include
drwxrwxr-x   29  500   500   736 2005-11-10 12:21 lib
drwxrwxr-x   15  500   500   528 2005-11-10 12:10 linux-2.0.x
drwxrwxr-x   16  500   500   584 2005-11-10 12:12 linux-2.4.x
drwxr-xr-x   18 root root    656 2006-09-05 13:54 linux-2.6.x
-rw-r--r--    1  500 users 10303 2005-08-25 11:37 Makefile
drwxrwxr-x   13  500   500   680 2005-11-10 12:14 openswan
-rw-rw-r--    1  500   500  4931 2004-11-11 12:19 README
-rw-rw-r--    1  500   500  1743 2004-01-21 07:49 SOURCE
drwxrwxr-x    5  500   500   312 2005-11-10 12:20 tools
drwxr-xr-x   18  500 users   704 2005-11-10 12:21 uClibc
drwxrwxr-x  212  500   500  5600 2005-11-10 12:21 user
drwxrwxr-x   59  500   500  1504 2005-11-10 12:21 vendors

在vendors目录下建立Samsung S3C44B0X相关的目录,并准备好相关文件。否则在后面的make menuconfig的vendors中将不会出现44b0的选项。

linux:/home/work/uclinux/uClinux-dist # mkdir vendors/Samsung/44B0X
linux:/home/work/uclinux/uClinux-dist # cp vendors/Samsung/4510B/* vendors/Samsung/44B0X/
linux:/home/work/uclinux/uClinux-dist # cp linux-2.6.x/arch/arm/configs/s3c44b0x_defconfig vendors/Samsung/44B0X/config.linux-2.6.x

内核的配置:
好了,现在可以运行make menuconfig进行内核的配置了:

linux:/home/work/uclinux/uClinux-dist # make menuconfig

如果你的系统中装了ncurse,则会出现以下菜单:

Vendor/Product Selection  --->
Kernel/Library/Defaults Selection  --->
---
Load an Alternate Configuration File
Save Configuration to an Alternate File

在“Vendor/Product Selection”中选择Vendor为Samsung,Product为44B0X

--- Select the Vendor you wish to target
(Samsung) Vendor
--- Select the Product you wish to target
(44B0X) Samsung Products

在Kernel/Library/Defaults Selection中选择内核版本为linux-2.6.x,Libc选择uClibc,其余选项不动:

(linux-2.6.x) Kernel Version
(uClibc) Libc Version
[ ] Default all settings (lose changes) (NEW)
[ ] Customize Kernel Settings (NEW)
[ ] Customize Vendor/User Settings (NEW)
[ ] Update Default Vendor Settings (NEW)

[EXIT]后保存内核配置,将会出现如下信息:

Saving your kernel configuration...

*** End of Linux kernel configuration.
*** Check the top-level Makefile for additional configuration.
*** Next, you must run 'make dep'.

make[1]: Entering directory `/home/work/uclinux/uClinux-dist'
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x oldconfig
make[2]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/split-include
  HOSTCC  scripts/basic/docproc
  SHIPPED scripts/kconfig/zconf.tab.h
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/kxgettext.o
  HOSTCC  scripts/kconfig/mconf.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/lex.zconf.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf -o arch/arm/Kconfig
#
# using defaults found in .config
#
.config:13: trying to assign nonexistent symbol GENERIC_IOMAP
.config:265: trying to assign nonexistent symbol IP_TCPDIAG
.config:266: trying to assign nonexistent symbol IP_TCPDIAG_IPV6
.config:297: trying to assign nonexistent symbol KGDBOE
.config:478: trying to assign nonexistent symbol REISER4_FS
.config:497: trying to assign nonexistent symbol FSCACHE
.config:518: trying to assign nonexistent symbol DEVFS_FS
*
* Linux Kernel Configuration
*
Memory Management Support
  1. MMU (MMU)
  2. MPU (MPU)
> 3. NONE (NO_MU)
choice[1-3?]: 3
*
* Code maturity level options
*
Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [Y/n/?] y
  Select only drivers expected to compile cleanly (CLEAN_COMPILE) [N/y/?] n
*
* General setup
*
Local version - append to kernel release (LOCALVERSION) []
Automatically append version information to the version string (LOCALVERSION_AUTO) [Y/n/?] (NEW)

有一些选项已经在config.linux-2.6.x中设定了,但还有一些选项需要手动进行设置。
这步请根据自己的需要进行设置,注意不要将太多的选项设置为y,否则会增加后面的编译时间。
配置完成会回到一个ncurse的界面,在这里可以对您刚才选错的应用程序部分重新进行配置:

Core Applications  --->
Library Configuration  --->
Flash Tools  --->
Filesystem Applications  --->
Network Applications  --->
Miscellaneous Applications  --->
BusyBox  --->
Tinylogin  --->
MicroWindows  --->
Games  --->
Miscellaneous Configuration  --->
Debug Builds  --->
---
Load an Alternate Configuration File
Save Configuration to an Alternate File

然后退出保存,这样内核的配置就完成了。

内核的编译

完成内核的配置后直接运行make进行编译。
这一步是最让人郁闷的,不仅要等待漫长的编译过程,还有好多意想不到的bug会发生。
准备接受挑战吧:

linux:/home/work/uclinux/uClinux-dist # make
make -C tools/ucfront
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
cc -g -Werror -Wall -DHAVE_MKSTEMP -o ucfront ucfront.c args.c util.c execute.c vasprintf.c
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-gcc
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-g++
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x  || exit 1
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  CHK     include/linux/version.h
  UPD     include/linux/version.h
  SPLIT   include/linux/autoconf.h -> include/config/*
  SYMLINK include/asm-arm/arch -> include/asm-arm/arch-s3c44b0x
  Generating include/asm-arm/mach-types.h
  SYMLINK include/asm -> include/asm-arm
  CC      arch/arm/kernel/asm-offsets.s
arch/arm/kernel/asm-offsets.c:37: warning: `__GNUC_PATCHLEVEL__' is not defined
  GEN     include/asm-arm/asm-offsets.h
  CC      init/main.o
  CHK     include/linux/compile.h
  UPD     include/linux/compile.h
  CC      init/version.o
  CC      init/do_mounts.o
  CC      init/do_mounts_rd.o
  CC      init/do_mounts_initrd.o
  LD      init/mounts.o
  CC      init/initramfs.o
  CC      init/calibrate.o
  LD      init/built-in.o
  HOSTCC  usr/gen_init_cpio
  CHK     usr/initramfs_list
  UPD     usr/initramfs_list
  CPIO    usr/initramfs_data.cpio
  GZIP    usr/initramfs_data.cpio.gz
  AS      usr/initramfs_data.o
  LD      usr/built-in.o
  CC      arch/arm/kernel/compat.o
  CC      arch/arm/kernel/dma.o
  AS      arch/arm/kernel/entry-armv.o
  AS      arch/arm/kernel/entry-common.o
  CC      arch/arm/kernel/irq.o
  CC      arch/arm/kernel/process.o
  CC      arch/arm/kernel/ptrace.o
  CC      arch/arm/kernel/semaphore.o
  CC      arch/arm/kernel/setup.o
arch/arm/kernel/setup.c: In function `cpu_init':
arch/arm/kernel/setup.c:357: warning: implicit declaration of function `dump_cpu_info'
arch/arm/kernel/setup.c: In function `request_standard_resources':
arch/arm/kernel/setup.c:541: warning: assignment makes integer from pointer without a cast
  CC      arch/arm/kernel/signal.o
  CC      arch/arm/kernel/sys_arm.o
  CC      arch/arm/kernel/time.o
  CC      arch/arm/kernel/traps.o
  CC      arch/arm/kernel/io.o
  LD      arch/arm/kernel/built-in.o
  AS      arch/arm/kernel/../mach-s3c44b0x/head.o
  CC      arch/arm/kernel/init_task.o
  LDS     arch/arm/kernel/vmlinux.lds
  CC      arch/arm/mm/consistent-nommu.o
  CC      arch/arm/mm/extable.o
  CC      arch/arm/mm/fault.o
  CC      arch/arm/mm/init.o
arch/arm/mm/init.c: In function `bootmem_init':
arch/arm/mm/init.c:435: warning: assignment makes integer from pointer without a cast
  CC      arch/arm/mm/ioremap.o
  CC      arch/arm/mm/mm-armv.o
  CC      arch/arm/mm/alignment.o
  AS      arch/arm/mm/cache-v4.o
  AS      arch/arm/mm/proc-arm7tdmi.o
arch/arm/mm/proc-arm7tdmi.S:16: asm/constants.h: ?????????
make[2]: *** [arch/arm/mm/proc-arm7tdmi.o] 错误 1
make[1]: *** [arch/arm/mm] 错误 2
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

第一击 找不到asm/constants.h:
这个好解决,打开linux-2.6.x/arch/arm/mm/proc-arm7tdmi.S,将#include 删掉即可。
重新make,进入第二击:

linux:/home/work/uclinux/uClinux-dist # make
make -C tools/ucfront
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
make[1]: “ucfront”是最新的。
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-gcc
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-g++
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x  || exit 1
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  CHK     include/linux/version.h
make[2]: “include/asm-arm/mach-types.h”是最新的。
  CHK     include/linux/compile.h
  CHK     usr/initramfs_list
  AS      arch/arm/mm/proc-arm7tdmi.o
  LD      arch/arm/mm/built-in.o
  CC      arch/arm/common/rtctime.o
  LD      arch/arm/common/built-in.o
  CC      arch/arm/mach-s3c44b0x/arch.o
arch/arm/mach-s3c44b0x/arch.c:50: warning: `CONFIG_DEBUG_NICKMIT' is not defined
arch/arm/mach-s3c44b0x/arch.c:95: warning: `CONFIG_NICKMIT_DEBUG' is not defined
arch/arm/mach-s3c44b0x/arch.c:93: warning: `struct param_struct' declared inside parameter list
arch/arm/mach-s3c44b0x/arch.c:93: warning: its scope is only this definition or declaration, which is probably not what you want.
arch/arm/mach-s3c44b0x/arch.c:102: warning: implicit declaration of function `MAINTAINER'
arch/arm/mach-s3c44b0x/arch.c:103: initializer element is not constant
arch/arm/mach-s3c44b0x/arch.c:103: (near initialization for `__mach_desc_S3C44B0.boot_params')
arch/arm/mach-s3c44b0x/arch.c:103: parse error before `FIXUP'
arch/arm/mach-s3c44b0x/arch.c:107: initializer element is not constant
arch/arm/mach-s3c44b0x/arch.c:107: (near initialization for `__mach_desc_S3C44B0')
make[2]: *** [arch/arm/mach-s3c44b0x/arch.o] 错误 1
make[1]: *** [arch/arm/mach-s3c44b0x] 错误 2
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

第二击 语法错误:
这一击耗了我不少时间,惨痛的过程就不再多说。
出错原因是程序中用到的一些宏没有定义,打开linux-2.6.x/arch/arm/mach-s3c44b0x/arch.c,跳到101行。

    101 MACHINE_START(S3C44B0, "S3C44B0X Development Board")
    102         MAINTAINER("nickmit ")
    103         FIXUP(s3c44b0x_fixup)
    104         INITIRQ(s3c44b0x_init_irq)
    105         INIT_MACHINE(s3c44b0x_init_machine)
    106         INITTIME(s3c44b0x_time_init)
    107 MACHINE_END

再打开linux-2.6.x/include/asm/mach/arch.h,跳到52行,发现上述代码中的MAINTAINER、FIXUP等多个宏都没有定义:

     52 /*
     53  * Set of macros to define architecture features.  This is built into
     54  * a table by the linker.
     55  */
     56 #define MACHINE_START(_type,_name)              \
     57 const struct machine_desc __mach_desc_##_type   \
     58  __attribute__((__section__(".arch.info.init"))) = {    \
     59         .nr             = MACH_TYPE_##_type,    \
     60         .name           = _name,
     61
     62 #define MACHINE_END                             \
     63 };

增加对它们的定义即可解决该问题(INITTIME不知道怎么定义:():

     52 /*
     53  * Set of macros to define architecture features.  This is built into
     54  * a table by the linker.
     55  */
     56 #define MACHINE_START(_type,_name)              \
     57 const struct machine_desc __mach_desc_##_type   \
     58  __attribute__((__section__(".arch.info.init"))) = {    \
     59         .nr             = MACH_TYPE_##_type,    \
     60         .name           = _name,
     61
     62 #define MAINTAINER(n)
     63
     64 #define BOOT_MEM(_pram,_pio,_vio)               \
     65         .phys_ram       = _pram,                \
     66         .phys_io        = _pio,                 \
     67         .io_pg_offst    = ((_vio)>>18)&0xfffc,
     68
     69 #define BOOT_PARAMS(_params)                    \
     70         .param_offset   = _params,
     71
     72 #define VIDEO(_start,_end)                      \
     73         .video_start    = _start,               \
     74         .video_end      = _end,
     75
     76 #define DISABLE_PARPORT(_n)                     \
     77         .reserve_lp##_n = 1,
     78
     79 #define SOFT_REBOOT                             \
     80         .soft_reboot    = 1,
     81
     82 #define FIXUP(_func)                            \
     83         .fixup          = _func,
     84
     85 #define MAPIO(_func)                            \
     86         .map_io         = _func,
     87
     88 #define INITIRQ(_func)                          \
     89         .init_irq       = _func,
     90
     91 #define INIT_MACHINE(_func)                     \
     92         .init_machine   = _func,
     93
     94 #define INITTIME(_func)                         \
     95         .timer	= _func,
     96
     97 #define MACHINE_END                             \
     98 };

再make:

linux:/home/work/uclinux/uClinux-dist # make
make -C tools/ucfront
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
make[1]: “ucfront”是最新的。
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/tools/ucfront'
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-gcc
ln -sf /home/work/uclinux/uClinux-dist/tools/ucfront/ucfront tools/ucfront-g++
make ARCH=arm CROSS_COMPILE=arm-elf- -C linux-2.6.x  || exit 1
make[1]: Entering directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
  CHK     include/linux/version.h
make[2]: “include/asm-arm/mach-types.h”是最新的。
  CC      arch/arm/kernel/asm-offsets.s
arch/arm/kernel/asm-offsets.c:37: warning: `__GNUC_PATCHLEVEL__' is not defined
  GEN     include/asm-arm/asm-offsets.h
  CHK     include/linux/compile.h
  CHK     usr/initramfs_list
  CC      arch/arm/kernel/compat.o
  AS      arch/arm/kernel/entry-armv.o
  AS      arch/arm/kernel/entry-common.o
  CC      arch/arm/kernel/setup.o
arch/arm/kernel/setup.c: In function `cpu_init':
arch/arm/kernel/setup.c:357: warning: implicit declaration of function `dump_cpu_info'
arch/arm/kernel/setup.c: In function `request_standard_resources':
arch/arm/kernel/setup.c:541: warning: assignment makes integer from pointer without a cast
  LD      arch/arm/kernel/built-in.o
  AS      arch/arm/kernel/../mach-s3c44b0x/head.o
  CC      arch/arm/mm/init.o
arch/arm/mm/init.c: In function `bootmem_init':
arch/arm/mm/init.c:435: warning: assignment makes integer from pointer without a cast
  AS      arch/arm/mm/cache-v4.o
  LD      arch/arm/mm/built-in.o
  CC      arch/arm/mach-s3c44b0x/arch.o
arch/arm/mach-s3c44b0x/arch.c:50: warning: `CONFIG_DEBUG_NICKMIT' is not defined
arch/arm/mach-s3c44b0x/arch.c:95: warning: `CONFIG_NICKMIT_DEBUG' is not defined
arch/arm/mach-s3c44b0x/arch.c:93: warning: `struct param_struct' declared inside parameter list
arch/arm/mach-s3c44b0x/arch.c:93: warning: its scope is only this definition or declaration, which is probably not what you want.
arch/arm/mach-s3c44b0x/arch.c:103: warning: initialization from incompatible pointer type
arch/arm/mach-s3c44b0x/arch.c:106: warning: implicit declaration of function `INITTIME'
arch/arm/mach-s3c44b0x/arch.c:107: warning: excess elements in struct initializer
arch/arm/mach-s3c44b0x/arch.c:107: warning: (near initialization for `__mach_desc_S3C44B0')
  CC      arch/arm/mach-s3c44b0x/irq.o
  CC      arch/arm/mach-s3c44b0x/mm.o
arch/arm/mach-s3c44b0x/mm.c:16: warning: `s3c44b0x_map_io' defined but not used
  CC      arch/arm/mach-s3c44b0x/dma.o
  CC      arch/arm/mach-s3c44b0x/time.o
arch/arm/mach-s3c44b0x/time.c:26: warning: `CONFIG_ARM_CLK_ADJUST' is not defined
arch/arm/mach-s3c44b0x/time.c:52: warning: `CONFIG_ARM_CLK_ADJUST' is not defined
arch/arm/mach-s3c44b0x/time.c:64: warning: `CONFIG_DEBUG_NICKMIT' is not defined
arch/arm/mach-s3c44b0x/time.c: In function `s3c44b0x_time_init':
arch/arm/mach-s3c44b0x/time.c:95: `gettimeoffset' undeclared (first use in this function)
arch/arm/mach-s3c44b0x/time.c:95: (Each undeclared identifier is reported only once
arch/arm/mach-s3c44b0x/time.c:95: for each function it appears in.)
arch/arm/mach-s3c44b0x/time.c:99: warning: implicit declaration of function `s3c44b0x_clear_pb'
arch/arm/mach-s3c44b0x/time.c:100: warning: implicit declaration of function `s3c44b0x_unmask_irq'
make[2]: *** [arch/arm/mach-s3c44b0x/time.o] 错误 1
make[1]: *** [arch/arm/mach-s3c44b0x] 错误 2
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

第三击 未声明的变量gettimeoffset:
这个也好办,打开linux-2.6.x/arch/arm/mach-s3c44b0x/time.c,将95行注释掉即可:

     95         //gettimeoffset     = s3c44b0x_gettimeoffset;

再make,这次正常地编译了比较长的时间,终于可以歇口气了。
好吧,就来说点其它的。说说我的惨痛过程吧,在编译成功之前我试过许多版本的uClinux以及linux内核,但是每次在编译的过程中都会出错,有些错误在网上可以找到答案,而大多数没有。我在碰到那些网上找不到答案的问题时,往往选择放弃,再换用其它版本。直到大多数新版本的uClinux都被试过后,我才发现没有一个版本是没有问题的。而我解决问题的方式仍然停留在如果在网上找到解决方法上,譬如上面的第二击,我曾用google搜索“arch/arm/mach-s3c44b0x/arch.c”,发现uClinux的邮件列表中有人遇到了和我一样的问题(http://mailman.uclinux.org/pipermail/uclinux-dev/2006-June/038774.html)。这个问题好几个月了都没有人回复,于是我想,他们都解决不了的问题,我应该也没有能力解决吧,弃之……
但是后来我还是自己解决了那个问题,只是个简单的语法问题。搜索引擎能够帮助我们快速地解决问题,但是也容易让人失去独立解决问题的锻炼机会。我太依赖于网络,导致本来自己能够解决的问题没能及早解决,希望各位引以为戒。也许有人(在某个论坛上看到的)说的对:“能在搜索引擎中找到答案的都不是问题。”,用另一种方式来歪解就是:“所有问题只有在搜索引擎中找不到答案时才需要自己动手解决。”。好啦,不说了,又出错了,再来看看

......(略过正常的信息)
/usr/local/bin/arm-elf-ld.real:arch/arm/kernel/vmlinux.lds:919: parse error
make[1]: *** [vmlinux] 错误 1
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

第四击 vmlinux.lds分析错误:
老方法,打开linux-2.6.x/arch/arm/kernel/vmlinux.lds,注释掉出错的两行:

    918 /* those must never be empty */
    919 /*
    920 ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
    921 ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
    922 */

担心这样的注释方法会导致其它问题,于是上网搜,发现有些人也是这么解决的:
http://www.handhelds.org/hypermail/familiar/301/30180.html

Delete the line “ASSERT ((__procXXXX …)” in the file vmlinux.lds

And then try to recompile

make zImage

安心了,进入下一个问题。

arch/arm/kernel/built-in.o(.text+0x34d0): In function `cpu_init':
/home/work/uclinux/uClinux-dist/linux-2.6.x/arch/arm/kernel/setup.c:357: undefined reference to `dump_cpu_info'
make[1]: *** [vmlinux] 错误 1
make[1]: Leaving directory `/home/work/uclinux/uClinux-dist/linux-2.6.x'
make: *** [linux] 错误 1

第五击 dump_cpu_info调用出错:
网上找到说法:
http://www.kernel.org/hg/linux-2.6/?cs=c176368cddac

date:  	Sun Nov 6 19:49:21 2005 +0000 (10 months ago)
files: 	arch/arm/kernel/setup.c
description: 	[ARM] Don't call dump_cpu_info unless we're booting

We don't want to call dump_cpu_info() from cpu_init() after boot since
it produces a lot of unnecessary noise - since cpu_init() gets called
on resume and hotplug cpu insertion events.

既然不需要,那么就直接将它删除掉。
继续make,你会发现,后面的路太平坦了……
一帆风顺绝对不是什么好事,因为祸乱往往就隐匿在平静之中,我肯定后边的配置过程还会出现更多奇怪的问题。
本篇待续……

参考文献:

— EOF —

18 thoughts on “将uClinux(linux-2.6.14核)移植到Samsung S3C44B0X”

  1. 你好,我正在做uclinux移植到44b0,你的文章写的很详细,我试着跟着做,但是我去:http://opensrc.sec.samsung.com/download/linux-2.6.14-hsc0.patch.gz
    下的补丁不能用,它现在后缀变成.tgz,网上有人说这种格式容易出现错误…
    如果你以前的资料还在能不能发我一个patch?或者有其他什么办法解决?
    我的邮箱:**** 谢谢~~~

发表评论

电子邮件地址不会被公开。 必填项已用*标注