Chinaunix首页 | 论坛 | 博客
  • 博客访问: 252978
  • 博文数量: 56
  • 博客积分: 1264
  • 博客等级: 中尉
  • 技术积分: 491
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-19 15:16
文章分类

全部博文(56)

文章存档

2012年(10)

2011年(46)

分类: LINUX

2011-07-21 18:09:24

一.内核结构
/arch 所有硬件结构特定的kernel代码。多平台设计所用,如i386,alpha,arm(与体系结构相关的代码都存放在arch//和include/asm-/目录下。如arm体系则是arch/arm和include/asm-arm.);
/drivers 内核中所有的设备驱动程序,如usb和sound;
/fs 所有的文件系统的代码,如ntfs,ext3,jffs2等;
/include 建立内核代码时所需要的大部分库文件,这个模块利用其他模块重建内核。该目录也包括了不同平台需要的库文件,如asm-arm是arm平台需要的库文件;
/init 内核的初始化代码,内核从此处开始工作;
/ipc 进程间通信代码;
/kernel 主内核代码;
/mm 所有内存管理代码;
/net 和网络相关的代码,如atm,ipv6等;

一般在每个目录下都有一个.depend文件和一个Makefile文件。这两个文件都是编译时使用的辅助文件。

1./arch
linux系统能支持如此多平台的部分原因是因为内核把sourcecode清晰地划分为与体系结构无关部分和体系结构相关部分。/arch包含与体系结构相关的代码.其中每一个目录代表一种硬件平台,such as arm,i386.对任何平台,都必须包括以下几个目录:
/boot:启动内核所使用的部分或全部平台特有代码;
/kernel:存放支持体系结构特有的(如信号处理和SMP)特征的实现;
/lib:存放告诉的体系结构特有的(如strlen和memcpy)通用的函数的实现;
/mm:存放体系结构特有的内存管理程序的实现;
/math-emu:模拟FPU的代码。对于arm处理器来说,此目录用mach-xxx代替。
So,移植工作的重点就是 /arch目录下的文件。

2./dirvers
所有的设备驱动程序。它占整个内核发行版本代码的一半以上,非常庞大。有些驱动程序是与硬件平台无关的而有些是相关的。

3./fs
所有的文件系统的代码。如ntfs,ext3,jffs2等。一般来说,文件系统也与硬件平台无关。

4./include
建立编译内核代码时所需要的大部分头文件,例如与平台无关的头文件在/include/linux下。不同的平台需要的头文件会有所不同,因此该目录和/arch一样,按平台划分了多个sub-dir,such as asm-arm.

5./init
内核的初始化代码(不是系统的引导代码),有main.c和version.c两个文件。这是研究核心如何工作的好起点。

6./ipc
进程间通信代码.

7./kernel
内核管理的核心代码。与处理器相关的代码都放在archmm下。

10./net
和网络相关的代码,如atm,ipv6等.其每一个子目录对应网络的一个方面。

11./其他
还有两个dir.:/documentation including many docs和/scripts主要在配置内核时用到,存放了配置内核的一些脚本文件,如make menuconfig.
-----------------------------------------

二、下载核心以及相应补丁:

Linux核心:linux-2.4.18.tar.bz2

下载地址:

下载补丁:
   patch-2.4.18-rmk7.gz 
   patch-2.4.18-rmk7-swl8.gz
   patch-2.4.18-rmk7-swl8-cy2.gz
   patch-2.4.18-rmk7-swl8-cy2-lc3.gz

(补丁下载地址一:

下载地址二:)


   然后解压缩:
   # tar xzvf linux-2.4.18.tar.gz
   # gunzip patch-2.4.18-rmk7.gz
   # gunzip patch-2.4.18-rmk7-swl8.gz
   # gunzip patch-2.4.18-rmk7-swl8-cy2.gz
   # gunzip patch-2.4.18-rmk7-swl8-cy2-lc3.gz
   打补丁:
   # cd linux-2.4.18
   # patch -p1 < ../patch-2.4.18-rmk7
   # patch -p1 < ../patch-2.4.18-rmk7-swl8
   # patch -p1 < ../patch-2.4.18-rmk7-swl8-cy2
   # patch -p1 < ../patch-2.4.18-rmk7-swl8-cy2-lc3

    在移植之前,先说下自己在移植时发生的错误,像我这种菜鸟级的初学者,也难免会发生。我最开始的内核是linux-2.4.20,因为随便下的一个内核, 就照着步骤移植,结果配置好后,发现不能用make menuconfig,其它的像make xconfig也不能用,都进不去界面,总是说有段错误。在网上也没查出什么原因来,当时以为配置错了,重搞了好几遍都不行,又用排除法,发现在改了 ARCH := arm后,就不能用。找到原因有了关键字百度就方便了,在网上找了半天,才搞明白需要一个ARM的补丁,目前最高的是2.4.19-rmk7,所以大家别 和我一样用2.4.20编译ARM内核。所有的补丁打上后,几乎不需要再做下面的工作了,就可以直接移植到开发板上了。这几个补丁实在是太好了,之前只用 了第一个补丁,搞了半个月也没能移植成功,后来找到后面的几个补丁,几分钟就搞定了。


三、 Linux操作系统的移植

假定内核代码存放在/usr/src/linux-2.4.18下,并设置环境变量$KERNELCODE=/usr/src/linux-2.4.18

1.根目录
只需要修改Makefile文件。这里Makefile的任务是:产生vmlinux文件和产生内核模块.
它将递归进入到内核的各个子目录中,分别调用位于这些子目录中的Makefile.起到组织内核的各模块,记录各模块的相互联系和以来关系。(建议一定读懂Makefile文件。)
对最上层的Makefile的修改:
a:指定目标平台
移植前: ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
移植后: ARCH := arm

b:指定交叉编译器
移植前: CROSS_COMPILE =
移植后: CROSS_COMPILE = arm-linux-      //反正是指定交叉编译程序的目录.

2.arch目录
这里存放着和体系结构相关部分的内核代码。
2.1 修改arch/arm目录下的Makefile
手动添加:
ifeq ($(CONFIG_ARCH_S3C2410),y)
TEXTADDR = 0xC0008000
MACHINE = s3c2410
endif

TEXTADDR决定内核起始运行地址,即image.ram应下载的地址。
要点:根据自己的电路设置TEXTADDR变量。
这里我们的电路地址是0xC0008000:从地址0xC0000000开始,总共32MB的空间。

2.2  修改arch/arm目录下的config.in
配置文件,运行make menuconfig命令时出现的菜单就是config配置的。
a.在System Type菜单中添加S3C2410-based选项。

mainmenu_option next_comment
comment 'System Type'
                                                                              
choice 'ARM system type' \
       "Anakin                 CONFIG_ARCH_ANAKIN \
        Archimedes/A5000       CONFIG_ARCH_ARCA5K \
        Cirrus-CL-PS7500FE     CONFIG_ARCH_CLPS7500 \
        CLPS711x/EP721x-based  CONFIG_ARCH_CLPS711X \
        Co-EBSA285             CONFIG_ARCH_CO285 \
        EBSA-110               CONFIG_ARCH_EBSA110 \
        Epxa10db               CONFIG_ARCH_CAMELOT \
        FootBridge             CONFIG_ARCH_FOOTBRIDGE \
        Integrator             CONFIG_ARCH_INTEGRATOR \
        LinkUp-L7200           CONFIG_ARCH_L7200 \
        RiscPC                 CONFIG_ARCH_RPC \
        SA1100-based           CONFIG_ARCH_SA1100 \
        S3C2410-based          CONFIG_ARCH_S3C2410 \

         Shark                  CONFIG_ARCH_SHARK" RiscPC \

 

b.添加CONFIG_ARCH_S3C2410子选项
if [ "$CONFIG_ARCH_S3C2410" = "y" ]; then
comment 'S3C2410 Implementation'
dep_bool ' SMDK (MERI TECH BOARD)' CONFIG_S3C2410_SMDK $CONFIG_ARCH_S3C2410
fi

c. 其他选项:

添加"$CONFIG_ARCH_S3C2410" = "y" -o \

if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
"$CONFIG_ARCH_SHARK" = "y" -o \
"$CONFIG_ARCH_CLPS7500" = "y" -o \
"$CONFIG_ARCH_EBSA110" = "y" -o \
"$CONFIG_ARCH_CDB89712" = "y" -o \
"$CONFIG_ARCH_EDB7211" = "y" -o \
"$CONFIG_ARCH_S3C2410" = "y" -o \
"$CONFIG_ARCH_SA1100" = "y" ]; then
define_bool CONFIG_ISA y
else
define_bool CONFIG_ISA n
fi
类似的添加项不只一处,读者可以根据需要在需要的地方加入。

 

d.还有一处需添加,不然后面的make zImage会错误
# we use the PC-type keyboard map?
  if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
       "$CONFIG_ARCH_SHARK" = "y" -o      \
       "$CONFIG_ARCH_SA1100" = "y" -o     \
       "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
       "$CONFIG_ARCH_TBOX" = "y" -o       \
       "$CONFIG_ARCH_CLPS7500" = "y" -o   \
       "$CONFIG_ARCH_P720T" = "y" -o      \
       "$CONFIG_S3C2410_SMDK" = "y" -o \
       "$CONFIG_ARCH_ANAKIN" = "y" ]; then
     define_bool CONFIG_PC_KEYMAP y
  fi

移植要点:config文件决定了menuconfig菜单的内容。把使用的平台加在需要的地方,这样在配置linux内核时就能够选择是否支持你的平台了。

3 arch/arm/boot目录
编译出来的内核是存放在这个目录中。这里将指定内核解压到目标板的地址,所以如果内核无法正常启动,很有可能是这里的地址指定错误。
3.1 Makefile

ifeq ($(CONFIG_ARCH_S3C2410),y)
ZTEXTADDR = 0x30008000
ZRELADDR = 0x30008000
endif
------
ZRELADDR决定内核解压后数据输出的地址。
ZTEXTADDR为bootloader的压缩内核文件烧入flash的起始地址,即从哪个位置开始执行bootloader,若启动时直接运行,则将其设为0;若自带bios可以跳到想要的地址,则可改为所要的位置。
移植要点:要根据自己的电路设置ZTEXTADDR和ZRELADDR变量。

3.2 compressed/Makefile
通过这个文件将从vmlinux创建一个压缩的vmlinuz镜像。此文件中用到的SYSTEM,ZTEXTADDR,ZBSSADDR和ZRELADDR是从arch/arm/boot/Makefile获得的。
ifeq ($(CONFIG_ARCH_S3C2410),y)
OBJS = head-s3c2410.o
endif
移植要点:加入head-s3c2410.S

3.3 arch/arm/boot/compressed/head-s3c2410.S
主要用来init处理器。好好研究下汇编代码//如何进行初始化需要仔细研究处理器的手册。
#include
#include
#include

.section ".start", #alloc, #execinstr

__S3C2410_start:

   bic r2, pc, #0x1f            @清除pc中的相关位,存放在寄存器r2中
   add r3, r2, #0x4000          @ r3
1:  ldr r0, [r2], #32            @r0
   teq r2, r3                   @compare contents of two regs
   bne 1b
   mcr p15, 0, r0, c7, c10, 4   @ drain WB
   mcr p15, 0, r0, c7, c7, 0    @ flush I & D caches
#if 0
                                @ 禁用mmu和caches
   mrc p15, 0, r0, c1, c0, 0    @ read control register
   bic r0, r0, #0x05            @ disable D cache and MMU
   bic r0, r0, #1000            @ disable I cache
   mcr p15, 0, r0, c1, c0, 0    @使前面的设置生效
#endif

   mov r0, #0x00200000
1:  subs r0, r0, #1
   bne 1b
-------------------
Note that:arm的D cache必须和MMU一起打开,而I cache可以单独打开。

3.4 arch/arm/def-configs目录
定义了一些平台的config文件,比如lart和assert等.把配置好的文件复制到这里就可以了。

3.5 arch/arm/kernel目录
与硬件平台相关的内核代码
3.5.1 Makefile
a.add the support for s3c2410x

no-irq-arch := $(CONFIG_ARCH_INTEGRATOR) $(CONFIG_ARCH_CLPS711X) \
              $(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \
              $(CONFIG_ARCH_SA1100) $(CONFIG_ARCH_CAMELOT) \

               $(CONFIG_ARCH_S3C2410) $(CONFIG_ARCH_MX1ADS) \

               $(CONFIG_ARCH_PXA)


b.add other function
obj-$(CONFIG_MIZI) = event.o
obj-$(CONFIG_APM) = apm2.o

移植要点:有任何新加的功能都要告知Makefile文件。上述两条语句的目的是编译event.c和apm2.c,当然需要将这两个文件拷贝到当前目录,不需要的话可省略这步.

3.5.2 debug-armv.S
在适当的地方加入如下代码,目的是关闭全部外围设备的时钟,从而保证系统正确运行.
#elif defined(CONFIG_ARCH_S3C2410)
     .macro addruart,rx
     mrc p15, 0, \rx, c1, c0
     tst \rx, #1 @ MMU enabled 查看是否运行mmu?
     moveq \rx, #0x50000000 @ physical base address
     movne \rx, #0xf0000000 @ virtual address
     .endm

     .macro senduart,rd,rx
     str \rd, [\rx, #0x20] @ UTXH
     .endm

     .macro waituart,rd,rx
     .endm

     .macro busyuart,rd,rx
1001: ldr \rd, [\rx, #0x10] @ read UTRSTAT
     tst \rd, #1 @ TX_EMPTY ?
     beq 1001b
     .endm

3.5.3 entry-armv.S
加入cpu的中断部分。
#elif defined(CONFIG_ARCH_S3C2410)
#include
     .macro disable_fiq
     .endm

     .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
     mov r4, #INTBASE @ virtual address of IRQ registers

     ldr \irqnr, [r4, #0x8] @ read INTMSK
     ldr \irqstat, [r4, #0x10] @ read INTPND

     bics \irqstat, \irqstat, \irqnr
     bics \irqstat, \irqstat, \irqnr
     beq 1002f

     mov \irqnr, #0
1001: tst \irqstat, #1
     bne 1002f @ jump if found IRQ
     add \irqnr, \irqnr, #1
     mov \irqstat, \irqstat, lsr #1
     cmp \irqnr, #32
     bcc 1001b
1002:
     .endm
     .macro irq_prio_table
     .endm
---
移植要点:了解cpu初始化时是如何处理中断的。寄存器在s3c2410.h中定义。

3.5.4 setup.c
   这个文件中有一个非常重要的函数setup_arch。这个函数用来完成和体系相关的初始化工作,比如对物理内存结构meminfo的初始化。这个结构将 在后面的内存初始化中起到很重要的作用。其中,nr_banks指定了内存块的数量,bank指定了每块内存的范围。用来指定块开始及长度的 PAGE_OFFSET和MEM——SIZE都在include/asm-arm/arch-s3c2410/memory.h中定 义,PAGE_OFFSET是内存的开始地址,这块板子设置该值为0x00000000UL,就是前面介绍的init和data的开始地址,结束地址自然 就是内存的结束地址。后文介绍的函数就将根据meminfo进行内存结构初始化。

3.6 arch/arm/mm目录
此目录下的文件是和arm平台相关的内存管理内容,只有mm-armv.c文件需要移植。
把init_maps->bufferable = 0;
改为:
init_maps->bufferable = 1;

3.7 arch/arm/mach-s3c2410目录
这里只是对处理器的基本信息提供了支持,有关开发板的外设,如usb,powermanage等都需要用户自己添加。(可参考相应开发板配套cd).


三、 编译linux内核

之前要配置内核:
make config;
make oldconfig;
make menuconfig;
make xconfig.

无论哪个命令都产生一个.config文件,并在每个.c文件中加上,使define的宏CONFIG_XXX起全局性作用。
查看内核的配置:
make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig

执行make dep
make zImage
make modules
make modules_install

安装内核需要copy 4个文件:没压缩的内核镜像zImage,压缩的内核镜像vmlinux,内核符号映射文件System.map以及配置文件.config.
zImage文件是和平台无关的,它在Makefile文件中设置。这里使用arm平台,so生成的镜像文件在/arch/arm/boot/zImage下。其他三个文件在内核代码的根目录/usr/src/linux-2.4.18下.
对创建的内核进行backup的好处是能通过配置文件知道内核的功能。比如是否lcd的驱动,是否有bluetooth等。代码如下:

cp arch/arm/boot/zImage $(YOURBAKPATH)/image/zImage-2.4.18-rmk7
cp System.map $(YOURBAKPATH)/image/System.map-2.4.18-rmk7
cp vmlinux $(YOURBAKPATH)/image/vmlinux-2.4.18-rmk7
cp .config $(YOURBAKPATH)/image/2.4.18-rmk7.config

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