热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于FS2410(s3c2410)开发板的U-boot和Linux内核移植

经过差不多一周时间的折腾(当然是业余时间)终于在我的FS2410开发板上将自己亲手编译的U-boot1.1.6和Linux内核2.6.24跑起来了,在此以图为证,呵呵,这其中的曲折岂能用一两句能

经过差不多一周时间的折腾(当然是业余时间)终于在我的FS2410开发板上将自己亲手编译的U-boot 1.1.6和Linux内核2.6.24跑起来了,在此以图为证,呵呵,

这其中的曲折岂能用一两句能表达清楚呀,可以说是酸甜苦辣咸五味俱全了。

首先说明一下我的操作环境:

OS:Deepin 11.06

GCC:4.5.2

ARM-Linux-GCC:gcc version 4.6.1 (Sourcery CodeBench Lite 2011.09-70) 

为了能正常编译busybox 1.19.4,还专门下载了友善之臂提供的arm-linux 4.4.3

 

网上有关此类技术的文件可以说是一抓一大把,但按其说明操作下来,成功的不算多,也许是因为文件年头太老,用现在的新编译器可能不支持了,(当然是不同的Linux内核版本都有对应的
GCC版本的)。这里特别感谢一下http://bbs.ednchina.com/BLOG_ARTICLE_179329.HTM这系列的三篇文章,按这里的操作,慢慢走出迷茫,找到其中的门道。

 具体步骤不再详述,可直接参考上述文章内容,这里只记录一下大概步骤及我所碰到的一个个‘拦路虎’

一、根据FS2410配置,修改u-boot 1.1.6的代码,并添加一些代码让它具有读写NandFlash功能及常用的基本命令,如tftp,printenv,nand erase , nand write等关键功能。

编译生成U-boot产物通过DWN软件写入Nandflash的开头位置(即从0x00000000位置开始),将开发板切换到Nor Flash启动方式,通过自带bootloader来将自己的u-boot写入Nand中。

然后再切换为Nand Flash启动模式,可以通过printenv命令来查看当前的设置,如下图所示:

 

二、Linux内核2.6.24移植

此类文件网上也很丰富,这里我主要参考了http://hi.chinaunix.net/?uid-20754091-action-viewspace-itemid-36292的步骤,特别的是我这为Nand Flash重新划分为四个区如下:

arch/arm/plat-s3c24xx/common-smdk.c

/* NAND parititon from 2.4.18-swl5 */
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "BootLoader",
.size = 0x00040000, /* 256KB */
.offset = 0,
},
[1] = {
.name = "Kernel",
.size = 0x00200000, /* 2MB */
.offset = 0x00040000,
},
[2] = {
.name = "Rootfs",
.size = 0x01000000, /* 16MB */
.offset = 0x00240000,
},
[3] = {
.name = "Appfs",
.size = 0x02DC0000, /* 44MB + 792KB */
.offset = 0x01240000,
}
};

Linux内核编译成功后,又将产物做成u-boot支持的镜像形式,即在原镜像头部添加一段数据,(这也是为什么内核镜像文件从Nand 上读到0x30007fc0位置,而不是0x30008000)

这部分操作主要参考了http://blog.chinaunix.net/uid-20662820-id-3073461.html,生成uImage的命令是:

mkimage -n "linux-2.6.29.6-maguicai-arm" -A arm -O linux -T kernel -C none -a 0x30007fc0 -e 30008000 -d zImage uImage

注:

-A == set architecture to 'arch'
-O == set operating system to 'os'
-T == set image type to 'type'
-C == set compression type 'comp'
-a == set load address to 'addr' (hex)
-e == set entry point to 'ep' (hex)
-n == set image name to 'name'
-d == use image data from 'datafile'
-x == set XIP (execute in place)

1)有所不同的地方就是写内核文件到Nand Flash时,命令是:

nand erase 0x00040000 0x200000;tftp 0x30008000 uImage;nand write 0x30008000 0x00040000 0x200000

注:这里nand earse和nand write对应的nand flash上的地址范围是与上面的第二分区(name为kernel)的范围对应的,

另注:要理解tftp和nand write第一个参数是指RAM上的地址,通过tftp下载镜像,是先下载到RAM中,然后再写入到nand flash里去的。

2)设置bootcmd

这个U-boot变量是用来启动内核用的,在U-boot运行状态下,执行如下命令,

set bootcmd nand read 0x30007fc0 0x00040000 0x200000\;bootm 0x30007fc0;saveenv

3)设置启动参数bootargs

这个参数是U-Boot传给Linux内核的,在Linux内核编译时可以设置,但没在U-boot里设置灵活,

设置后,通过printenv命令,查看如下图所示:

这其中设置了根文件系统在mtdblock2即Nand Flash的第三分区,根文件系统类型为jffs2,加载内核文件后,执行linuxrc文件来启动相关程序。

三、根文件系统的制作 

根文件系统和Linux内核是两个独立的部分,但又是不可分割的。具体操作可参考网上其它资源,

这里只记录一下主要注意的地方,

(1)生成根文件系统:
mkfs.jffs2 -r my_rootfs -o jffs2.img -e 0x4000 --pad=0x01000000 -n

注:1)my_rootfs是我本地搭建的根文件系统的目录,用来生成镜像的,

  2) -o jffs2.img是指生成为jffs2.img镜像文件

  3) -e 0x4000 ,是指块大小,这与不同的Nand Flash相关,这里是三星的K9F1208U0B.固定为0x4000

  4) --pad=0x01000000 用16進制來表示所要輸出檔案的大小,即jffs2.img的大小,为了不浪费Nand Flash空间,这里设成与当前第三分区大小一致。

(2)烧写根文件系统:

tftp 0x30008000 jffs2.img;nand erase 0x00240000 0x01000000;nand write 0x30008000 0x00240000 0x01000000

注:1)nand erase时一定要是当前分区 的全部,nand write时,大小为当前文件的实际大小,这里与当前分区一致了即 0x01000000

 

常见问题:(我所遇到的几个问题)

1)错误信息:

到内核启动时,报:Error: unrecognized/unsupported machine ID

原因及解决办法:

原因大致是u-boot 传递给
内核的machine ID错误,可以手动在内核源代码中添加machine ID.
解决方法:
在u-boot 命令行中输入bdinfo
查看板卡信息,我的输出如下:
FS2410# bdinfo
arch_number = 0x000000C1
env_t = 0x00000000
boot_params = 0x30000100
DRAM bank = 0x00000000
-> start = 0x30000000
-> size = 0x04000000
ethaddr = 08:00:3E:26:0A:5B
ip_addr = 10.1.8.245
baudrate = 115200 bps
修改内核的arch/arm/kernel/head.S,直接将s3c2410的参数赋给内核
# cd linux-2.6.19
# vi arch/arm/kernel/head.S +72
----------------------------------------------
70 __INIT
71 .type stext, %function
72 ENTRY(stext)
/********* add here *********/
mov r0, #0
mov r1, #0xc1
ldr r2, =0x30000100
/********* end add *********/
73 msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode

 

2)错误信息:在加载Linux内核时报:Verifying Checksum ... Bad Data CRC

一般原因是由于内核所点区域被其它所侵占,导致检测异常,我这里是nand erase和nand write时,没有与该分区大小对应上。

3)错误信息:

在启动内核加载根文件系统过程中,报

Further such events for this erase block will not be printed
Node at 0x00147fbc with length 0x0000004b would run over the end of the erase block
Perhaps the file system was created with the wrong erase size?

原因及解决办法:

根文件系统写入到Nand Flash时,要指定文件的实际大小,即nand write 0x30008000 0x00240000 0x01000000 中,最后一个数目是文件的实际大小。

4)错误信息:

加载内核根文件系统时,报错:

jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0050e154: 0xfbeb instead 

一般原因是

是制作文件系统时使用 mkfs.jffs2 命令有误,FS2410板的nand flash是三星的K9F1208U0B。使用的命令是:
mkfs.jffs2 -r /source/rootfs -o rootfs.jffs2 -e 0x4000 --pad=0x800000 -n
各参数的意义:
(1)-r : 指定要做成image的源資料夾.
(2)-o : 指定輸出image檔案的文件名.
(3)-e : 每一塊要抹除的block size,預設是64KB.要注意,不同的flash, 其block size會不一樣.我的是三星的K9F1208U0B.
(4)--pad (-p): 用16進制來表示所要輸出檔案的大小,也就是root.jffs2的size。很重要的是, 為了不浪費flash空間, 這個值最好符合flash driver所規劃的區塊大小.这里使用的是8MB.
(5)如果挂载后会出现类似:CLEANMARKER node found at 0x0042c000 has totlen 0xc != normal 0x0 的警告,则加上 -n 就会消失。
(6) 还有的选项,自己看帮助!-h

 

我这里是-e参数值错误所导致。

5)启动最后报:

Warning: unable to open an initial console.

这个一般是因为在创建根文件系统时,并没有创建 console设备。

 


推荐阅读
  • C#设计模式之八装饰模式(Decorator Pattern)【结构型】
    一、引言今天我们要讲【结构型】设计模式的第三个模式,该模式是【装饰模式】,英文名称:DecoratorPattern。我第一次看到这个名称想到的是另外一个词语“装修”,我就说说我对“装修”的理 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文讨论了编写可保护的代码的重要性,包括提高代码的可读性、可调试性和直观性。同时介绍了优化代码的方法,如代码格式化、解释函数和提炼函数等。还提到了一些常见的坏代码味道,如不规范的命名、重复代码、过长的函数和参数列表等。最后,介绍了如何处理数据泥团和进行函数重构,以提高代码质量和可维护性。 ... [详细]
  • Java SE从入门到放弃(三)的逻辑运算符详解
    本文详细介绍了Java SE中的逻辑运算符,包括逻辑运算符的操作和运算结果,以及与运算符的不同之处。通过代码演示,展示了逻辑运算符的使用方法和注意事项。文章以Java SE从入门到放弃(三)为背景,对逻辑运算符进行了深入的解析。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • PHP中的单例模式与静态变量的区别及使用方法
    本文介绍了PHP中的单例模式与静态变量的区别及使用方法。在PHP中,静态变量的存活周期仅仅是每次PHP的会话周期,与Java、C++不同。静态变量在PHP中的作用域仅限于当前文件内,在函数或类中可以传递变量。本文还通过示例代码解释了静态变量在函数和类中的使用方法,并说明了静态变量的生命周期与结构体的生命周期相关联。同时,本文还介绍了静态变量在类中的使用方法,并通过示例代码展示了如何在类中使用静态变量。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文详细介绍了cisco路由器IOS损坏时的恢复方法,包括进入ROMMON模式、设置IP地址、子网掩码、默认网关以及使用TFTP服务器传输IOS文件的步骤。 ... [详细]
  • 本文记录了作者对x265开源代码的实现与框架进行学习与探索的过程,包括x265的下载地址与参考资料,以及在Win7 32 bit PC、VS2010平台上的安装与配置步骤。 ... [详细]
  •    实现了uboot对非linuxkernel的引导。虽然有一个IH_TYPE_STANDALONE,但是没有实现。nnd.只能自己想办法。实现详细见 ... [详细]
author-avatar
飞天猪的世界公寓
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有