文档库 最新最全的文档下载
当前位置:文档库 › Ubuntu下arm交叉编译环境的创建及基于s3c2410的linux2.6.22移植

Ubuntu下arm交叉编译环境的创建及基于s3c2410的linux2.6.22移植

经历近2周的时间,查阅大量的参考资料和贴子,终于成功将linux2.6.22移植到ARM2410上。中间走了不少弯路,不过走弯路也是一种收获,因为可以碰到和解决许多问题,增长知识。因为linux版本问题以及开发平台的不同,网上的很多文章并不完全适合自己的板子,需要自己摸索和修改。写这点东西算是对前一阶段工作的总结,以免将来忘记。

移植大体的步骤主要有:

(1) 交叉编译环境的建立(我的主机系统是ubuntu7.04);

(2) 开发板(我用的是博创的2410)NAND flash 分区管理;

(3) LCD、网卡驱动的移植;

(4) linux内核配置和编译;

(5) rootfs的制作;

(6) 完成linux的启动和文件系统的挂载。

下面我会按照步骤逐一介绍。

一、 交叉编译环境的建立

建立交叉编译环境就是在宿主机(也就是pc机)的系统上建立一个模拟ARM的工作环境,使得在这个环境下编译产生的程序能够顺利的在ARM上的系统内运行。主要工作包括binutils、gcc以及glibc的编译生成,还有一些环境变量的设置。

(1) 准备工作:

下载源代码包: binutils-2.18.tar.bz2,gcc-4.2.1.tar.bz2,glibc-2.6.1.tar.bz2,glibc-ports-2.6.1.tar.gz,linux-2.6.22.tar.bz2

补丁包: binutils-2.18-genscripts_multilib-1.patch

binutils-2.18-posix-1.patch

gcc-4.2.1-cross_search_paths-1.patch

gcc-4.2.1-posix-1.patch

gcc-4.2.1-specs-1.patch

glibc-2.6.1-cross_hacks-1.patch

glibc-2.6.1-hppa_nptl-1.patch

glibc-2.6.1-libgcc_eh-1.patch

glibc-2.6.1-RTLD_SINGLE_THREAD_P-1.patch

glibc-2.6.1-sysdep_cancel-1.patch

glibc-csu.patch

注:Binutils 是一组开发工具,包括连接器,汇编器和其他用于目标文件和档案的工具;

GCC是C编译器,用来将C代码编译成汇编代码;

Glibc就是gcc编译时需要的库了,glibc-ports是提供glibc对ARM的支持;

Linux-2.6.22.tar.bz2是内核源代码包。

需要注意的是gcc和glibc以及linux内核版本需要保持对应。如果用比较老的编译器去编译新的内核,或者用新的编译器编译老版本的内核,会出现一些莫名其妙的错误。另外补丁包也是必备的,否则编译过程中也会出错。刚开始我就深受其害。

(2) 工作目录的建立:

目录的结构可以参考《Building.Embedded.Linux.Systems》。推荐整个目录放到/usr/local下,这样所有的用户都有访问权限。我当初没经验,直接放到home下了,后来会有些用户权限的小麻烦。这里给出我的目录结构:

$root@host:/home# ls

arm host

其中host是我的普通登陆

用户帐号目录,arm就是工作目录了。为了方便,我平时用root登陆。

$root@host:/home# cd arm

$root@host:/home/arm# mkdir build-tools kernel rootfs tmp tools

其中编译交叉工具时的主要工作都在build-tools目录下完成,kernel目录用来存放内核源代码,rootfs目录是用来建立启动根文件系统的(后面会详细介绍),tmp是临时文件存放目录,tools目录就是最终生成的编译器gcc和glibc存放的地方。

(3) 设置环境变量:

$root@host:/home/arm# export PRJROOT=/home/arm

$root@host:/home/arm# TARGET=arm-linux

$root@host:/home/arm# PREFIX=${PRJROOT}/tools

$root@host:/home/arm# TARGET_PREFIX=${PREFIX}/${TARGET}

$root@host:/home/arm# PATH=${PREFIX}/bin:${PATH}

其中TARGET定义了交叉工具的工作平台类型,PREFIX指定交叉工具的最终安装目录,PATH指定系统寻找交叉工具可执行文件所在的路径。

(4) 编译前的准备:

$root@host:/home/arm# cd ${PRJROOT}/build-tools

$root@host:/home/arm/build-tools# mkdir build-binutils build-boot-gcc build-glibc build-gcc build-glibc-headers patch

将源码包放到这个目录下

$root@host:/home/arm/build-tools# ls

build-boot-gcc build-glibc build-binutils build-gcc build-glibc-headers patch

binutils-2.18.tar.bz2 gcc-4.2.1.tar.bz2 glibc-2.6.1.tar.bz2 glibc-ports-2.6.1.tar.gz

将补丁放到patch目录下:

$root@host:/home/arm/build-tools# cd patch

$root@host:/home/arm/build-tools/patch# ls

binutils-2.18-genscripts_multilib-1.patch binutils-2.18-posix-1.patch

gcc-4.2.1-cross_search_paths-1.patch gcc-4.2.1-posix-1.patch

glibc-2.6.1-cross_hacks-1.patch

glibc-2.6.1-hppa_nptl-1.patch glibc-2.6.1-libgcc_eh-1.patch

glibc-2.6.1-RTLD_SINGLE_THREAD_P-1.patch

glibc-2.6.1-sysdep_cancel-1.patch glibc-csu.patch

将内核源码包放到${PRJROOT}/kernel目录下

$root@host:/home/arm# cd kernel

$root@host:/home/arm/kernel# ls

linux-2.6.22.tar.bz2

(5) 开始编译

编译的过程主要有6个步骤;

a. 内核头文件的生成

b. Binary utilties的生成

c. Glibc头文件的生成

d. 第一阶段gcc的生成

e. glibc库文件的生成

f. 完整编译工具的生成

注:生成第一阶段gcc主要是用来生成glibc库文件。

1、 生成内核头文件

$root@host:/home/arm/kernel# tar xvjf linux-2.6.22.tar.bz2

$root@host:/home/arm/kernel# cd linux-2.6.22

$root@host:/home/arm/kernel/linux-2.6.22#

make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig

其中menuconfig指定了配置界面,可用的还有config(全字符界面) xconfig(xwindow下的图形界面)。Ubuntu需要安装tk8.4以支持xconfig。另外需要将mawk卸载,安装gawk。(mawk有bug)

linux2.6的内核提供了对s3c2410的支持

。在system中选上s3c2410系列就可以了。配置完毕退出保存。

$root@host:/home/arm/kernel/linux-2.6.22# cd include

$root@host:/home/arm/kernel/linux-2.6.22/include# cd linux

$root@host:/home/arm/kernel/linux-2.6.22/include/linux# ls version.h autoconf.h

version.h autoconf.h

这2个文件在后面的编译中会用到。如果没有,退到内目录下make version.h就可以了。

下面建立链接:

$root@host:/home/arm/kernel/linux-2.6.22/include# ln –s asm-arm asm

$root@host:/home/arm/kernel/linux-2.6.22/include# ln -s asm/arch-s3c2410 asm/arch

将内核头文件拷贝到最终安装目录下:

$root@host:/home/arm/kernel/linux-2.6.22/include# mkdir –p ${TARGET_PREFIX}/include

$root@host:/home/arm/kernel/linux-2.6.22/include# cp –rd asm-arm ${TARGET_PREFIX}/include
$root@host:/home/arm/kernel/linux-2.6.22/include#

cp –r asm- ${TARGET_PREFIX}/include

$root@host:/home/arm/kernel/linux-2.6.22/include# cp –r linux ${TARGET_PREFIX}/include

$root@host:/home/arm/kernel/linux-2.6.22/include# cp –d asm ${TARGET_PREFIX}/include


至此内核头文件建立完毕。

2、 建立Binary utilities:

binutils是一些二进制工具的集合,其中常用的是as ,ar和ld。

$root@host:/home/arm/kernel/include# cd ${PRJROOT}/build-tools

$root@host:/home/arm/build-tools# tar xvjf binutils-2.18.tar.bz2

$root@host:/home/arm/build-tools# cd build-binutils

$root@host:/home/arm/build-tools/build-binutils#

patch –Np1 –i /home/arm/build-tools/patch/binutils-2.18*

$root@host:/home/arm/build-tools/build-binutils#

../binutils-2.18/configure --target=${TARGET} –prefix=${PREFIX}

$root@host:/home/arm/build-tools/build-binutils# make

$root@host:/home/arm/build-tools/build-binutils# make install

${PREFIX}/bin下应该生成一些以arm-linux开头的文件

$root@host:/home/arm/build-tools/build-binutils# ls ${PREFIX}/bin

3、 生成glibc头文件:

$root@host:/home/arm/build-tools/build-binutils# cd ..

$root@host:/home/arm/build-tools/# tar xvjf glibc-2.6.1.tar.bz2

$root@host:/home/arm/build-tools/#

tar xvzf glibc-ports-2.6.1.tar.gz --directory ./glibc-2.6.1/

$root@host:/home/arm/build-tools/# cd glibc-2.6.1

$root@host:/home/arm/build-tools/glibc-2.6.1# mv glibc-ports-2.6.1 ports –v

打上补丁:

$root@host:/home/arm/build-tools/glibc-2.6.1#

patch –Np1 –i /home/arm/build-tools/patch/glibc-2.6.1-*patch

$root@host:/home/arm/build-tools/glibc-2.6.1# cd ..

$root@host:/home/arm/build-tools/# cd build-glibc-headers

这里需要添加对NPTL线程库的支持:

$root@host:/home/arm/build-tools/build-glibc-headers#

echo “libc_cv_forced_unwind=yes”>>config.cache

echo “libc_cv_c_cleanup=yes”>>config.cache

echo “libc_cv_arm_tls=yes”>>config.cache

注:如果编译中出现”cannot compute long double size”,添加:

echo “ac_cv_sizeof_long_double=12”>>config.cache

$root@host:/

home/arm/build-tools/build-glibc-headers#

../glibc-2.6.1/configure --host=${TARGET} --prefix=”/usr” --enable-add-ons

--with-headers=${TARGET_PREFIX}/include --cache-file=config.cache

$root@host:/home/arm/build-tools/build-glibc-headers#

make cross-compiling=yes install_root=${TARGET_PREFIX} prefix=””

install-headers

$root@host:/home/arm/build-tools/build-glibc-headers#

mkdir –p ${TARGET_PREFIX}/include/gnu

$root@host:/home/arm/build-tools/build-glibc-headers#

touch ${TARGET_PREFIX}/include/gnu/stubs.h

注:如果编译过程中出现找不到头文件的错误,可以根据错误提示的文件名用touch命令在相应目录下建立一个空文件,一般就可以编译通过了。

4、 生成第一阶段gcc:

$root@host:/home/arm/build-tools/# tar xvjf gcc-4.2.1.tar.bz2

打补丁:

$root@host:/home/arm/build-tools/# cd gcc-4.2.1

$root@host:/home/arm/build-tools/gcc-4.2.1#

patch –Np1 –i /home/arm/build-tools/patch/gcc-4.2.1-*

$root@host:/home/arm/build-tools/ gcc-4.2.1# cd ..

$root@host:/home/arm/build-tools/# cd build-boot-gcc

$root@host:/home/arm/build-tools/build-boot-gcc#

../gcc-4.2.1/configure --target=${TARGET} --prefix=${PREFIX} --with-headers=${TARGET_PREFIX}/include

--with-newlib --enable-languages=c --disable-threads --disable-shared

$root@host:/home/arm/build-tools/build-boot-gcc # make all-gcc

$root@host:/home/arm/build-tools/build-boot-gcc # make install-gcc

在${PREFIX}/bin下会生成 arm-linux-开头的文件:

$root@host:/home/arm/build-tools/build-boot-gcc # ls ${PREFIX}/bin

5、 生成glibc库文件:

$root@host:/home/arm/build-tools/build-boot-gcc # cd ..

$root@host:/home/arm/build-tools# cd build-glibc

$root@host:/home/arm/build-tools/build-glibc# CC=arm-linux-gcc ../glibc-2.6.1/configure --host=$TARGET --prefix=”/usr”

--enable-add-ons --with-headers=${TARGET_PREFIX}/include

--cache-file=config.cache

这里的config.cache与前面编译glibc头文件时的config.cache完全相同。

$root@host:/home/arm/build-tools/build-glibc# make

$root@host:/home/arm/build-tools/build-glibc#

make install_root=${TARGET_PREFIX} prefix=”” install

对libc.so作出修改:

$root@host:/home/arm/build-tools/build-glibc# cd ${TARGET_PREFIX}/lib

$root@host:/home/arm/tools/arm-linux/lib# cat libc.so

/* GNU ld script

Use the shared library, but some functions are only in

the static library, so try that secondarily. */

OUTPUT_FORMAT(elf32-littlearm)

GROUP ( /lib/libc.so.6 /lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) )

将GROUP这一行的内容改为:

GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux.so.2 ) )

$root@host:/home/arm/tools/arm-linux/lib# cat libpthread.so

/* GNU ld script

Use the shared library, but some functions are only in

the static library, so try that secondarily. */


OUTPUT_FORMAT(elf32-littlearm)

GROUP ( /lib/libpthread.so.0 /lib/libpthread_nonshared.a )

将GROUP这一行的内容改为:

GROUP (libpthread.so.0 libpthread_nonshared.a )

6、 生成完整的编译工具:

$root@host:/home/arm/tools/arm-linux/lib# cd ${PRJROOT}/build-tools/build-gcc

$root@host:/home/arm/build-tools/build-gcc#

../gcc-4.2.1/configure --target=$TARGET --prefix=${PREFIX} --enable-shared

--enable-languages=c,c++ --with-threads=posix

$root@host:/home/arm/build-tools/build-glibc# make all

$root@host:/home/arm/build-tools/build-glibc# make install


二、 NAND flash 分区管理

这块2410板自带了vivi,启动之后可以进到vivi的提示符下:

vivi>

查看分区情况:

vivi> part show

mtdpart info. (6 partitions)



name offset size flag

vivi :0x00000000 0x00020000 0 128k

param :0x00020000 0x00010000 0 64k

kernel :0x00030000 0x00200000 0 2M

root :0x00230000 0x00300000 4 3M

yaffs :0x00530000 0x03a00000 8 58M

使用part命令可以添加、删除各个mtd分区。

另外还有一种分区格式:BON,具体用法参照bon命令帮助即可。2.6内核对mtd分区格式支持的很好,所以这里采用了mtd分区方式。

其中vivi是bootloader区,param是存放启动参数设置区,kernel是内核镜像文件区,root是启动文件系统区,yaffs是文件系统区,可以视情况修改这些区域的大小。

三、 网卡和LCD驱动的移植

1. 网卡驱动移植:

这块板使用的是DM9000的网卡芯片,驱动的源代码在内核源代码的目录中可以找到:

$root@host:/home/arm/# cd kernel/linux-2.6.22

$root@host:/home/arm/kernel/linux-2.6.22# cd drivers/net

$root@host:/home/arm/kernel/linux-2.6.22/drivers/net# ls dm*

dm9000.c dm9000.h

修改dm9000.c:

$root@host:/home/arm/kernel/linux-2.6.22# vi dm9000.c

找到函数:

static int dm9000_probe(struct platform_device *pdev)

{

……….

int ret=0;

int iosize;

int i;

u32 idval

//添加下面数组,前6个数作为网卡的mac地址,注意不能和现有的网卡冲突

unsigned char ne_defethadder[]={0x08,0x08,0x08,0x08,0x12,0x27,0}

………………………….

………………………….

/* Set Node Address */

for (i = 0; i < 6; i++)

ndev->dev_addr[i] = db->srom[i];



if (!is_valid_ether_addr(ndev->dev_addr)) {


/* try reading from mac */



for (i = 0; i < 6; i++)

//修改mac地址

// ndev->dev_addr[i] = ior(db, i+DM9000_PAR);

ndev->dev_addr[i]=ne_defethaddr[i];

………………………

……………………….

}

退出保存。

修改smdk2410.c:

$root@host:/home/arm/kernel/linux-2.6.22# cd arch/arm/mach-s3c2410

$root@host:/home/arm/kernel/linux-2.6.22/arch/arm/mach-s3c2410#

vi mach-smdk2410.c

在mach-smdk2410.c中添加如下内容:

…………

#include

//添加:

#include

…………

………….

#define UCON S3C2410_UCON_DEFAULT

#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB

#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE

//添加:



static struct resource s3c_d9k_resource[]=

{

[0]={

.start =0x10000000,

.end =0x10000000,

.flags=IORESOURCE_MEM

},

[1]={

.start =0x10000000+0x2,

.end =0x10000000+0x2,

.flags=IORESOURCE_MEM

},

[2]={

.start =IRQ_EINT2,

.end =IRQ_EINT2,

.flags =IORESOURCE_IRQ

}

};

static struct dm9000_plat_data s3c_device_d9k_platdata = {

.flags= DM9000_PLATF_16BITONLY

};



struct platform_device s3c_device_d9k = {

.name= "dm9000",

.id= 0,

.num_resources= ARRAY_SIZE(s3c_d9k_resource),

.resource= s3c_d9k_resource,

.dev= {

.platform_data = &s3c_device_d9k_platdata,

}

};

………………….

………………….

static struct platform_device *smdk2410_devices[] __initdata = {

&s3c_device_usb,

//启动lcd

&s3c_device_lcd,

&s3c_device_wdt,

&s3c_device_i2c,

&s3c_device_iis,

//添加

&s3c_device_d9k

//&s3c_device_ts,

};

需要注意的是起始地址和中断号的选择。这块板上DM9000芯片的INT引脚接的是EINT2,CMD引脚接的是A1,CS引脚接的是nGCS2,所以DM9000的index端口地址是0x10000000,data端口地址是0x10000000+0x00000002,据此设置结构resource s3c_d9k_resource中的参数。最后在内核编译时加上对DM9000驱动的支持就可以了,具体见内核配置和编译。

2. LCD驱动移植:

继续在mach-smdk2410.c中添加如下内容:

………….

#include

#include

#include

………….

………….

static struct s3c2410fb_mach_info smdk2410_lcdcfg __initdata={

.type=S3C2410_LCDCON1_TFT,

.fixed_syncs= 0,

.regs={


.lcdcon1= S3C2410_LCDCON1_TFT16BPP|

S3C2410_LCDCON1_TFT |

S3C2410_LCDCON1_CLKVAL(0X01), /*HCLK/4*/

.lcdcon2= S3C2410_LCDCON2_VBPD(18)| /*19*/

S3C2410_LCDCON2_LINEVAL(479)|

S3C2410_LCDCON2_VFPD(10)| /*11*/

S3C2410_LCDCON2_VSPW(14), /*15*/

.lcdcon3= S3C2410_LCDCON3_HBPD(43)|

S3C2410_LCDCON3_HOZVAL(639)| /*640*/

S3C2410_LCDCON3_HFPD(115), /*116*/

.lcdcon4= S3C2410_LCDCON4_MVAL(0) |

S3C2410_LCDCON4_HSPW(95), /*96*/

.lcdcon5= S3C2410_LCDCON5_FRM565 |

S3C2410_LCDCON5_INVVLINE|

S3C2410_LCDCON5_INVVFRAME|

S3C2410_LCDCON5_PWREN|

S3C2410_LCDCON5_HWSWP,

},

.lpcsel= ((0XCE6)&~7)|1<<4,//0x0,

.gpccon= 0xAA8002A8,//0xaaaaaaaa,

.gpccon_mask= 0xFFC003FC,//0xffffffff,

.gpcup= 0xF81E,//0xffffffff,

.gpcup_mask= 0xF81E,//0xffffffff,

.gpdcon= 0xAA80AAA0,//0xaaaaaaaa,

.gpdcon_mask= 0xFFC0FFF0,//0x0,

.gpcup= 0xF8FC,//0xffffffff,

.gpcup_mask= 0xF8FC,//0xffffffff,



.width= 640,//240,

.height= 480,//320,

.xres= {640,640,640},//{240,240,240}, .min .max .defval

.yres= {480,480,480},//{320,320,320},

.bpp= {16,16,16}, //{16,16,16},

};

……………

……………

static void __init smdk2410_init(void)

{

s3c24xx_fb_set_platdata(&smdk2410_lcdcfg);

platform_add_devices(smdk2410_devices, ARRAY_SIZE(smdk2410_devices));

smdk_machine_init();

}

………………..

注:注释掉drivers/char/vt.c的blank_screen_t(unsigned long dummy)的函数内容,否则lcd会在10分钟左右关掉显示。“

最后在内核编译时需要选中对LCD的支持,具体见内核配置和编译。




相关文档
相关文档 最新文档