Chinaunix首页 | 论坛 | 博客
  • 博客访问: 333691
  • 博文数量: 81
  • 博客积分: 4016
  • 博客等级: 上校
  • 技术积分: 800
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-17 18:38
文章分类

全部博文(81)

文章存档

2016年(5)

2015年(2)

2010年(1)

2008年(1)

2007年(4)

2006年(68)

我的朋友

分类: LINUX

2006-03-17 19:24:40

一.内核结构 

/arch       所有硬件结构特定的kernel代码。多平台设计所用,如i386,alpha,arm(与体系结构相关的代码都存放在arch//include/asm-/目录下。如arm体系则是arch/arminclude/asm-arm.);

/drivers   内核中所有的设备驱动程序,如usbsound;

/fs   所有的文件系统的代码,如ntfs,ext3,jffs2;

/include   建立内核代码时所需要的大部分库文件,这个模块利用其他模块重建内核。该目录也包括了不同平台需要的库文件,如asm-armarm平台需要的库文件;

/init  内核的初始化代码,内核从此处开始工作;

/ipc  进程间通信代码;

/kernel       主内核代码;

/mm 所有内存管理代码;

/net  和网络相关的代码,如atm,ipv6等;

 

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

 

1./arch

  linux系统能支持如此多平台的部分原因是因为内核把sourcecode清晰地划分为与体系结构无关部分和体系结构相关部分。/arch包含与体系结构相关的代码.其中每一个目录代表一种硬件平台,such as arm,i386.对任何平台,都必须包括以下几个目录:

/boot:启动内核所使用的部分或全部平台特有代码;

/kernel:存放支持体系结构特有的(如信号处理和SMP)特征的实现;

/lib:存放告诉的体系结构特有的(strlenmemcpy)通用的函数的实现;

/mm:存放体系结构特有的内存管理程序的实现;

/math-emu:模拟FPU的代码。对于arm处理器来说,此目录用mach-xxx代替。

So,移植工作的重点就是 /arch目录下的文件。

 

2./dirvers

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

 

3./fs

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

 

4./include

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

 

5./init

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

 

6./ipc

  进程间通信代码.

 

7./kernel

  内核管理的核心代码。与处理器相关的代码都放在arch/*/kernel目录下。

 

8./lib

  与平台无关的如strlenmemcpy等通用函数.

 

9./mm

  所有的内存管理代码。与具体硬件体系结构相关的内存管理代码位于/arch/*/mm下。

 

10./net

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

 

11./其他

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

-----------------------------------------

 

二、    Linux操作系统的移植

 

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

 

1.根目录

  只需要修改Makefile文件。这里Makefile的任务是:产生vmlinux文件和产生内核模块.

它将递归进入到内核的各个子目录中,分别调用位于这些子目录中的Makefile.起到组织内核的各模块,记录各模块的相互联系和以来关系。(建议一定读懂Makefile文件。)

  对最上层的Makefile的修改:

 a:指定目标平台

 before: ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)

 after:  ARCH := arm

 

 b:指定交叉编译器

 before: CROSS_COMPILE        =

 after:  CROSS_COMPILE        = /opt/host/armv4l/bin/armv4l-unknown-linux-

 //反正是指定交叉编译程序的目录.

 Note that if you reset the CROSS_COMPILE,

      CC          = $(CROSS_COMPILE)gcc

 if not reset,

       CC          = $(shell if [ -n "$(CROSS_COMPILE)" ]; then echo $(CROSS_COMPILE)gcc; else \

                $(CONFIG_SHELL) scripts/kwhich gcc296 2>/dev/null || echo cc; fi)

 

 另外,你可能需要设置:

----------------

TMPDIR        = /dev/shm

而不需要

AWK              = awk

TMPPREFIX  =

-------------

export中好象不要FINDHPATH,其他基本都加上。

-----------------

# INSTALL_PATH specifies where to place the updated kernel and system map

# images.  Uncomment if you want to place them anywhere other than root.

这个应该不要。

#export   INSTALL_PATH=/boot

----------------------

# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory

# relocations required by build roots.  This is not defined in the

# makefile but the arguement can be passed to make if needed.

需要加入

export INSTALL_MOD_PATH=/tmp

 

------------------

2.arch目录

  这里存放着和体系结构相关部分的内核代码。

2.1 Makefile

  手动add:

ifeq ($(CONFIG_ARCH_S3C2410),y)

TEXTADDR   = 0xC0008000

MACHINE             = s3c2410

endif

 

TEXTADDR决定内核起始运行地址,即image.ram应下载的地址。

要点:根据自己的电路设置TEXTADDR变量。

这里我们的电路地址是0xC0008000:从地址0xC0000000开始,总共32MB的空间。

 

2.2 config.in

  配置文件,运行make menuconfig命令时出现的菜单就是config配置的。

a.添加CONFIG_ARCH_S3C2410子选项

if [ "$CONFIG_ARCH_S3C2410" = "y" ]; then

comment 'S3C2410 Implementation'

dep_bool ' SMDK (MERI TECH BOARD)' CONFIG_S3C2410_SMDK $CONFIG_ARCH_S3C2410

dep_bool '   change AIJI' CONFIG_SMDK_AIJI

dep_tristate 'S3C2410 USB function support' CONFIG_S3C2410_USB $CONFIG_ARCH_S3C2100

dep_tristate '  Support for S3C2410 USB character device emulation' CONFIG_S3C2410_USB_CHAR $CONFIG_S3C2410_USB

fi     # /* CONFIG_ARCH_S3C2410 */

 

b. other options

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_S3C2400" = "y" -o \

     "$CONFIG_ARCH_S3C2410" = "y" -o \

     "$CONFIG_ARCH_SA1100" = "y" ]; then

   define_bool CONFIG_ISA y

else

   define_bool CONFIG_ISA n

fi

---------

类似的添加项不只一处,读者可以根据需要在需要的地方加入。

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

 

3 arch/arm/boot目录

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

3.1 Makefile

 

ifeq ($(CONFIG_ARCH_S3C2410),y)

ZTEXTADDR = 0x30008000

ZRELADDR   = 0x30008000

endif

------

ZRELADDR决定内核解压后数据输出的地址。

ZTEXTADDRbootloader的压缩内核文件烧入flash的起始地址,即从哪个位置开始执行bootloader,若启动时直接运行,则将其设为0;若自带bios可以跳到想要的地址,则可改为所要的位置。

移植要点:要根据自己的电路设置ZTEXTADDRZRELADDR变量。

 

3.2 compressed/Makefile

  通过这个文件将从vmlinux创建一个压缩的vmlinuz镜像。此文件中用到的SYSTEM,ZTEXTADDR,ZBSSADDRZRELADDR是从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:

 

       @ Preserve r8/r7 i.e. kernel entry values

       @ What is it?

       @ Nandy

 

       @ Data cache, Intstruction cache, MMU might be active.

       @ Be sure to flush kernel binary out of the cache,

       @ whatever state it is, before it is turned off.

       @ This is done by fetching through currently executed

       @ memory to be sure we hit the same cache

 

       bic   r2, pc, #0x1f         @清楚pc中的相关位,存放在寄存器r2

       add r3, r2, #0x4000              @ r3<-r2+0x4000(16 kb is quite enough)

1:     ldr r0, [r2], #32             @r0<-r2,r2<-r2+32

       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

       @ disabling MMU and caches禁用mmucaches

       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

 

       /*

        * Pause for a short time so that we give enough time

        * for the host to start a terminal up.

        *暂停一段时间,等待主机启动终端

        */

       mov r0, #0x00200000

1:     subs r0, r0, #1

       bne  1b

-------------------

Note that:armD cache必须和MMU一起打开,而I cache可以单独打开。

 

3.4 arch/arm/def-configs目录

 定义了一些平台的config文件,比如lartassert.把配置好的文件复制到这里就可以了。

 

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_S3C2400) $(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.capm2.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 << 2            @ 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_OFFSETMEM——SIZE都在include/asm-arm/arch-s3c2410/memory.h中定义,PAGE_OFFSET是内存的开始地址,这块板子设置该值为0x00000000UL,就是前面介绍的initdata的开始地址,结束地址自然就是内存的结束地址。后文介绍的函数就将根据meminfo进行内存结构初始化。

 

3.6 arch/arm/mm目录

  此目录下的文件是和arm平台相关的内存管理内容,只有mm-armv.c文件需要移植。

init_maps->bufferable = 0;

改为:

init_maps->bufferable = 1;

init_maps是一个map_desc性数据结构。map_desc定义在/include/asm-arm/mach/map.h

struct map_desc {

       unsigned long virtual;

       unsigned long physical;

       unsigned long length;

       int domain:4,

           prot_read:1,

           prot_write:1,

           cacheable:1,

           bufferable:1,

           last:1;

};

 

3.7 arch/arm/mach-s3c2410目录

  这里只是对处理器的基本信息提供了支持,有关开发板的外设,如usbpowermanage等都需要用户自己添加。(可参考相应开发板配套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

 

 

 

 

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