ARM linux内核移植

继续分享一篇2013年上学时期的帖子

linux操作系统的内核代码主要是由具有跨平台特性的C语言编写的。并采用GNU软件体系,这使得它具有良好的可移植性。同时它也是一个开源操作系统,用户可以免费下载,并根据实际需要修改内核配置,提高系统的运行效能。

linux内核移植概述

嵌入式操作系统与计算机的硬件体系机构,特别是与处理器及外部设备密切相关。在一种处理器的开发板上运行的嵌入式操作系统往往不能在另一种处理器的开发板上运行。即使两个开发板处理器相同,如果外部设备不同,两个开发板也可能不能运行同一个嵌入式系统,这时就需要对操作系统进行跨平台移植。由于Linux操作系统的内核代码主要是由具有跨平台特性的C语言编写的,并支持多种处理器平台,所以是操作系统移植的首选。

linux系统移植包括3个部分:引导程序(BootLoader)移植、内核移植和文件系统制作。其中,内核移植是Linux系统移植的关键,它包括修改内核代码和配置内核选项两个部分。

修改内核代码主要是选定Linux内核代码对处理器的支持和修改与外部设备相关的内核代码。

linux支持多种处理器,这主要体现在linux将与处理器相关的代码集中在arch目录中和include目录下文件名以asm开头的子目录中。

arch目录中每个目录代表一个与处理器相关的代码。内核移植只要选定相应的处理器类型就可以。

Include目录下文件名以asm开头的子目录主要作用是为操作系统提供类型就可以了,它的选择会根据处理器的不同而不同。修改与外部设备相关的内核代码主要是针对Linux已经支持的外部设备。

配置内核选项主要是将linux系统中多余的设备驱动程序和一些不必要的操作性功能删除掉,并根据实际开发板配置对一些外部设备进行设置。

从linux官方网站获取的内核源代码包括种类繁多的外部设备,不适合嵌入式系统体积小、功耗低、结构精简的特点。

这要求用户在实际设计中,根据嵌入式系统的硬件配置情况,裁掉linux内核多余的设备驱动程序,以及一些不必要的操作系统功能。另一方面,在实际开发中,一些开发平台的外部设备需要设置才能使用,如需要设置linux下串口设备对DMA传输的支持才能进行DMA传输等。这些都是通过配置内核选项完成的。

修改内核代码

由于linux2.6.10以后的内核版本支持的处理器和外部设备逐渐增多,内核代码的修改也变得相对简单。最小化的嵌入式系统必须具备处理器、SDRAM、Flash等基本设备。

选定处理器支持

三星公司的S3C2440处理器已经成为linux的一个标准支持平台,arch/arm/目录下的mach-s3c2440目录就是对S3C2440平台的支持,在linux内核向S3C2440处理器移植时无需修改相关代码。实际要做的是指定交叉编译器和选定处理器类型。

首先修改linux 2.6.24根目录下的Makefile文件,更改目标代码的类型并为编译内核指定一个编译器。

删除一下内容:

#ARCH ?=$(SUBARCH)

#CROSS_COMPILE ?=

由于目标处理器是ARM,编译器是arm-linux-gcc-3.4.1编译器,因此需在刚才删除位置增加如下代码:

#ARCH :=arm

#CROSS_COMPILE :=/usr/local/arm/3.4.1/arm-linux-

经过这样的修改后,即指定了处理器类型为ARM,编译器为arm-linux-gcc-3.4.1,内核编译生成的镜像文件就可以在ARM平台上运行了。

修改与Flash存储器相关的内核代码

linux 2.6内核已有Flash的程序代码,但不同的开发 往往需要Flash存储器的分区信息不同,开发人员在实际移植时再linux 2.6内核中要加入对Flash存储器分区的支持。

devs.c是linux 2.6以后版本内核才出现的非常重要的文件,位置为arch/arm/mach-s3c2440/devs.c,该文件主要是对开发平台设备的定义,包括USB、LCD、I2C、SPI、I2S和看门狗等设备。

devs.c文件中定义一个设备主要用到的数据结构是resource和platform_device。其中,platform_device的定义在include/linux/platform_device.h文件中,具体如下:

struct platform_device{

const char *name;

u32 id;

struct device dev;

u32 num_resources;

struct resource *resource;

};

假定Nand Flash总共64MB,并且假设Nand Flash分区信息如下表所示。

文件

地址空间

注释

Bootloader

0x00000000

0x00038000

224KB

param

0x00038000

0x00040000

32KB

kernel

0x00040000

0x00200000

1.75MB

rootfs

0x00200000

0x01000000

30MB

ext-fs1

0x01000000

0x02000000

16MB

ext-fs2

0x02000000

0x03000000

16MB

Nand Flash地址空间分配

在devs.c中添加头文件

#include 

#include 

#include 

增加Nand Flash分区信息

根据Nand Flash地址空间分配表,在devs.c程序文件后半部分增加Nand Flash分区信息。

static struct mtd_partition partition_info[]=

{
    {
        name:”bootloader”,

        size:0x00038000,

        offset:0,

    },

    {

        name:”parameter”,

        size:0x00008000,

        offset:0x00038000,

    },

    {

        name:”kernel”,

        size:0x001C0000,

        offset:0x00040000,

    },

    {

        name:”rootfs”,

        size:0x01E00000,

        offset:0x00200000,

        mask_flags:MTD_WRITEABLE,

    },

    {

        name:”ext-fs1”,

        size:0x01000000,

        offset:0x0200000,

    },

    {

        name:”ext-fs2”,

        size:0x01000000,

        offset:0x03000000,

    },

};

name:代表分区名字。

size:代码Flash分区大小,单位为字节。

offset:代表Flash分区的起始地址(相对于0x0的偏移)。

目标板计划分6个区,分别存放bootloader、parameter、kernel、rootfs,以及便于日后扩展使用的两个用户文件系统空间。

加入Nand Flash分区

在partition_info[]定义后增加如下程序:

struct .s3c2440_nand_set.nandset.={

nr_partitions:.6,

partitions:.partition_info,

};

nr_partitions:指明partition_info中定义的分区数目。

partitons:分区信息表。

s3c2440_nand_set结构体定义在nand.h文件中,并给了详细的解释:

struct d3c2440_nand_set{

int nr_chips;  //number of chips in this set

int nr_partitions;  //number of partitions to be partitions

char *name;   //name of set

int *nr_map;  //map for low_lawer logical to physical chip numbers

struct mtd_partition *partitions;   //mtd partition list

}

建立Nand Flash芯片支持

在s3c_nand_nifo定义后增加如下程序:

struct .s3c2440_platform_nand.superlpplatform={

tacls:0,

twrph0:30,

twrph1:0,

sets:.&nandset,

nr_sets:.1,

};

加入Nand Flash芯片支持

前面定义了Flash分区的信息,需要把此设备信息加进去,修改此文件中的s3c_device_nand结构体变量,添加对dev成员的赋值。

struct s3c2440_platform_nand s3c_nand_info; //新增加的代码

struct platform_device s3c_device_nand ={

.name =”s3c2440_nand”,

.id =1,

.dev={ .platform_data=& superlpplatform},//新增加的代码

.num_resources  =ARRAY_SIZE(s3c_nand_resource),

.resource =s3c_nand_resource,

};

name:设备名称。

id:有效设备编号,如果只有唯一的一个设备编号为1,有多个设备从0开始计数。

num_resource:有几个寄存器区。

resource:寄存器数组首地址。

dev:支持的Nand Flash设备。

指定启动时初始化

为了使内核启动时能够初始化Nand Flash,需要在arch/arm/mach-s3c2440/mach-smdk2440.c中的._initdata部分增加&s3c_device_nand。其中,smdk2440_devices[]指明初始化时包括前面所设置的Flash分区信息。

static .struct .platform_device.*smdk2440_devices[]._initdata={

…

&s3c_device_i2c,

&s3c_device_iis,

&s3c_device_nand,  //新增加的内容

};

配置内核选项

裁剪与外围设备相关的功能模块是根据开发板的具体硬件情况采取配置内核选项的方式完成的。

配置系统的基本结构

在linux2.6以后版本的内核中,系统采用了kbuild机制来处理整个内核的配置、编译和链接,相对于linux 2.4版本内核,该机制简化了内核配置过程。

2.6内核配置系统由以下3个部分组成:

Makefile:分布在Linux内核源代码中各个层次目录中的Makefile,定义内核的编译规则。

配置文件(Kconfig):给用户提供配置选择的功能。Kconfig分布在各层目录中。

配置工具:包括配置命令解释器(解释配置脚本中使用的配置命令)和配置用户界面(提供基于字符界面、基于Ncurses图形界面,以及基于Xwindows图形界面的用户配置界面,各自对应于Make config、Make menuconfig和make xconfig)。

Kconfig文件

Kconfig文件时kbuild的主要部分。顶层的Kconfig递归调用子目录下的Kconfig,形成Kconfig树。配置工具会根据该Kconfig树形成配置菜单界面,该配置菜单界面接收用户的内核配置选项,并将选择结果保存到内核配置文件.config中。顶层Makefile文件根据内核配置文件.config,通过递归编译内核代码在子目录建立vmlinux(内核image)和moudules(模块)两个文件。每一个子目录有一个Makefile文件,子目录Makefile根据.config产生,并执行上级目录Makefile传递过来的命令来启动编译。kbuild机制就是通过这样的递归机制来编译和链接各层目录的程序最终形成一个完整的内核vmlinux(内核image)。

内核配置选项说明

根据内核配置原理,配置工具会根据该Kconfig树形成配置菜单界面,该配置菜单界面接受用户的内核配置选项,并将选择结果保存到内核配置文件.config中。内核配置的命令有4个,分别如下。

#make config:基于文本的最为传统的配置界面,不推荐使用。

#make menuconfig:基于文本选单的配置界面,字符终端下推荐使用。

#make xconfig:基于图形窗口的配置界面,Xwindow下推荐使用。

#make oldconfig:在原来内核配置的基础上做修改。

make xconfig基于图形界面,使用起来比较直观,make menuconfig次之,make config用起来麻烦一点。

选择相应的配置是,有3中选择,它们分别代表的含义如下。

Y:将该功能编译进内核。

N:不将该功能编译进内核。

M:将该功能编译成可以在需要时动态插入到内核中的模块。

在编译内核的过程中,配置工作比较麻烦,实际配置时,大部分选项可以使用其默认值,只有小部分选项要根据用户的需要进行比较。

你可能感兴趣的:(linux内核,linux,驱动开发,arm开发)