飞凌OK6410开发板之u-boot-2011.06-rc2移植之愚见
??????? 看到网上基于SAMSUNG-SOC-S3C6410的UBOOT移植文章很多,基本上都是基于6410开发板的讲解,但是基于飞凌OK6410开发板的很少,而且基于u-boot较新版本的移植的就更少,而且绝大多数都是在讲如何如何去操作,例如该CD哪个文件夹该MKDIR哪个文件夹,该RM哪些不要的东西,该CP哪些文件代码等等,没有一个很系统的讲解,总让人操作完后还是没有个啥概念,为此特地花了几天时间用自己手头上的OK6410开发板去移植了一下UBOOT,亲自实践后才整理出的这篇文章,当然我也只是个菜鸟,希望这篇文章对那些想学UBOOT移植的人有点帮助,网上看到也有些人对OK6410的UBOOT移植有困惑的,希望对你们有用。 ???? 对于开发环境的搭建,在这我就不用多说了啊,毕竟网上多的去了,在这先贴出我的开发环境供参考。 ??? 我的开发环境: ???????? 1,笔记本主机系统WINDOWS XP SP3系统??? ?????????2,虚拟机采用的是?VMware Workstation ACE版本 ???????? 3,虚拟机内采用的LINUX系统是UBUNTU10.10版本 ???????? 4,交叉编译工具是CROSS_COMPILE4.2.2版本 ? ???? 要移植UBOOT,首先得下载一个版本,这里是uboot_DNEX团队的官方地址下载? ftp://ftp.denx.de/pub/u-boot/ ???? 对于技术我是比较喜欢最新的,所以前几天就下载了最新的UBOOT版本u-boot-2011.06-rc2版本对其开工,当然在我写这篇文章的时候,前后就短短几天时间又更新到了UBOOT版本u-boot-2011.06-rc3,哎,看来这个更新真的是很快啊 ???? 下载下来后就是u-boot-2011.06-rc2.tar.bz2,大约8.09M,但是解压后差不多80多M的样子。将这个下载下来的bz2文件放进linux系统的目录下,至于这个目录随便,我的是在UBUNTU下的/SHARE下,然后tar jxvf u-boot-2011.06-rc2.tar.bz2,对其解压缩,之后便得到了我们能够操作的的u-boot-2011.06-rc2,cd 进入u-boot-2011.06-rc2,然后就可以看到整个文件架构安排了,好了,移植工作也正式开始了。?对于UBOOT移植,首先,脑袋里得有个总体概念,第一步该干嘛,然后几步又该如何去做,经过本人昨天晚上的OK6410运行情况,发现还是可行的,特地总结出来,以供大家参考。对于UBOOT移植,严格上来说,应该范围比较广,有CPU核架构级别的移植例如OK6410属于ARM1176架构的,CPU芯片级别的移植例如OK6410属于S3C6410SOC,还有基于板级移植的例如OK6410单板,而我们日常生活中大家说的移植,一般也都是这种板级移植,这种移植也是最简单的,所以大家搞UBOOT移植的时候就由板级——》CPU芯片级——》CPU核架构级去看,如果有相近的板级资源做参考,这样会事半功倍,由于本人能力有限,这里讲的也是基于板级移植的,希望大家勿喷,呵呵,所以当你拿到一个UBOOT源代码的时候,最好第一件事就是先进BOARD目录里面看看,看是否已经有你那款板子的或是相近板子的代码在里面,这样可以做到心里先有个数,如果有,那么你已经成功了一小半,呵呵。 ??? 对于UBOOT的移植学习,我建议大家还是好好看看README这个文件,这里面写的好多东西都很用的,对于你移植代码很有帮助的,当然这个不在今天的重点里面。对于上图中的那些文件和文件夹以及递归的文件等等可能会使人觉得头晕,我已开始也是这种感觉,但是当你真正自己亲自独立移植成功之后,就会感觉一目了然了,好了,这里就以我的OK6410单板来说吧。 ?? 第一步,我CD 进入u-boot-2011.06-rc2源代码根目录,然后进入BOARD/SAMSUNG ???发现了该版本自带SMDK6400,恩OK,基本成功了一小半了,这里我要给大家说明一点三星公司自家生产的开发板一般都是SMDK开头,例如SMDK2410,SMDK6400等等,既然板级资源已经找到,那么后面的CPU芯片级和核架构级得资源就肯定对路了,由于SMDK6400单板采用的是S3C6400SOC,与S3C6410SOC大部分资源差不多,就是在多媒体,省电方面,主频方面还有少数寄存器地址方面等等有点区别,绝大部分还是通用的,而且SMDK6400也是与OK6410最相近的一块板子了,毕竟采用的都是ARM1176的核,况且两款CPU也相近,那就拿SMDK6400开刀了。而且通过我看两2款芯片的DATASHEET比较,2者很相近,然后通过对比UBOOT1.16里面的CPU级别的初始化代码,发现绝大部分代码是通用的,所以,我有个大胆的猜测,直接将SMDK6400的u-boot-2011.06编译产生的U-BOOT.BIN通过DNW加载到OK6410的内存中,应该能够跑起来,呵呵,但是经过后来的实践验证,跑不起来,这个是DNW的加载UBOOT的截图,校验和OK之后就没反应了,看来我的猜测还是有BUG啊,呵呵,但是我的猜测大部分应该是对的,只不过可能离成功还差那么一点,那么看来是相关代码需要更改了,既然需要改代码,所以建议大家还是另起炉灶,切忌不要在SMDK6400代码里面乱改一通,然后放到自己的开发板上,咦,可以跑起来了,移植OK,这样是个很不好的习惯,因为这样你就破坏了别个的代码,我们既然借鉴了别人的劳动成果,就不应该再去破坏别人的代码,况且,这样你的代码估计也会很乱。 ? 第二步,刚才看到了既然有SMDK6400,那么我们可以先将这个编译一遍,看是否可以编译成功,为以后的移植做好准备。在根目下使用命令 make smdk6400_config,然后使用make,如果不出意外,7到8分钟就可以编译成功,然后在根目下就会产生u-boot.bin,当然对于编译SMDK6400来说,几乎都是编译不通过的,总是出现._end未定义,但是SMDK2410很顺利,呵呵,这是为什么呢?其实这个应该是UBOOT的一个BUG吧,不用担心,你只用在/u-boot-2011.06-rc2/board/samsung/smdk6400/u-boot-nand.lds文件里.bss __rel_dyn_start (OVERLAY) : {前面加上_end = .;就行了,这个是必须的哦,呵呵,参考/u-boot-2011.06-rc2/nand_spl/board/samsung/smdk6400/u-boot.lds,加完后保存,然后再编译一遍,这次OK。 ? 第三步,刚刚第一步已经说了,这样编译的代码是无法加载到OK6410的板载内存里面运行的,因此需要修改相应的代码,为了避免破坏他人的劳动成果,还是另起炉灶,那就开始吧,在这之前,先介绍下几个移植需要重点关注的文件夹,一个是/u-boot-2011.06-rc2/board/文件夹,它代表板级相关代码资源,一个是/u-boot-2011.06-rc2/arch/文件夹,它代表CPU架构级资源,还有一个就是/u-boot-2011.06-rc2/nand_spl/文件夹,那就以我的OK6410为例来说明吧: ?? 1,在/u-boot-2011.06-rc2/board/下新建文件夹:mkdir feilin/ok6410(飞凌) ?? 2,将/u-boot-2011.06-rc2/board/samsung/smdk6400/所有文件复制到/u-boot-2011.06-rc2/board/feilin/ok6410下,cp? ../../samsung/smdk6400/* ./ ?? 3,将smdk6400.c改名为ok6410.c ,mv smdk6400.c ok6410.c 将smdk6400_nand_spl.c改名为ok6410_nand_spl.c? mv smdk6400_nand_spl.c?? ok6410_nand_spl.c? 将Makefile 打开,用vi 或是gedit都行,更改COBJS-y?:= ok6410.o, ??4,在/u-boot-2011.06-rc2/nand_spl/board/下新建文件夹:mkdir feilin/ok6410 ??5,将/u-boot-2011.06-rc2/nand_spl/board/samsung/smdk6400/所有文件复制到/u-boot-2011.06-rc2/nand_spl/board/feilin/ok6410/,cp ../../samsung/smdk6400/* ./,并更改Makefile内与板级有关的部分, ?6,将u-boot-2011.06-rc2/include/configs/smdk6400.h 复制一份并更名为ok6410.h,mv smdk6400.h ok6410.h这个是必需的哦,要不然无法完成编译,这上面全是板级配置资源,现在不必修改 7,将u-boot-2011.06-rc2/arch/arm/include/asm/arch-s3c64xx/s3c6400.h复制一份,并更名为s3c6410.h?? mv s3c6400.h? s3c6410.h,可能有人会问干嘛复制这个文件呢,其实这个文件代表的就是CPU_S3C6410的资源代码,必定会与CPU_S3C6400有所不同,方便以后修改,不破坏SMDK6400的,所以在这里就需要将3条里面的ok6410.c里面用用到的头文件换成s3c6410.h,凡事遇到s3c6400.h的地方都换成s3c6410.h 8,也是这一步中的最后一个环节了,就是修改u-boot-2011.06-rc2/根目录下的Makefile文件,这个是主导make文件,资源配置都是靠它的,在其后添加 CROSS_COMPILE = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux- 将 smdk6400_noUSB_config?/ 修改为 ok6410_noUSB_config?/ ??? 以上第三步看起来步骤很多,其实则不然,归根到底就是COPY,将SMDK6400的板载资源代码复制一份到自己建的OK6410中,看是OK6410,其实用的还是SMDK6400的代码,呵呵,只不过现在改动就不要紧了,相当于是在一份副本上修改了,对吧,所以到目前为止,我们做的工作还是停留在COPY阶段,当然,这个时候最好先make ok6410_config 然后在make,如果编译无问题,那恭喜你,已经离成功很近了,当然了,其实这个时候你编译的代码U-BOOT.BIN其实还是SMDK6400的,所以和你第二步编译的是一个代码,仍无法在OK6410上跑起来。好了,既然我们已经有了SMDK6400的副本了,就该为它做点啥子修改了,要不然可就对不住自己前面的那一番折腾啊,对吧。 ???? 第四步:先来说说我到这一步当时的想法吧,由于手头没有啥子SDRAM内程序调试工具,就只有个串口,也只能借助串口来调试了,关键是现在串口根本就没有输出,不知道是UBOOT没跑起来,还是OK6410板子上的串口没有初始化,网上找了好久也没找出个问题所在,关键还是要靠自己啊 ,没办法,只好去参考哈UBOOT1.16内的代码了,但是那么多的东西,该看啥呢,呵呵,对了,这个也是需要好好琢磨的,所以多看哈子源代码会很有用的,通过代码大致翻阅最终被我锁定在了/u-boot-2011.06-rc2/board/feilin/ok6410/lowlevel_init.S这个文件上,其实这个文件就是板载资源底层初始化,发现其内缺少UBOOT内存搬运代码以及串口初始化部分的代码有点问题,毕竟这个是SMDK6400的板载代码,现在是OK6410,所以需要修改,于是参考UBOOT1.16内的部分代码:第一处 第二处 ? 在其后加上 //<-add by hwq ?ldr?r0,=ELFIN_UART_CONSOLE_BASE??@0x7F005000 ?mov?r1,#0x3??????????????? ?@was 0. #if defined(CONFIG_CLKSRC_CLKUART) ?str?r1,#UCON_OFFSET] #if defined(CONFIG_UART_50) #if defined(CONFIG_UART_50) ?ldr?r1,=0x4f4f4f4f ,通过修改后,再次编译,成功,然后将其u-boot.bin再一次通过DNW加载进OK6410的SDRAM内运行,奇迹出现了,呵呵,截图如下: 截图显示FLASH 失败,其实是由于还没有移植FLASH驱动的缘故,基本这个移植版本还是雏形,啥子也做不了,因为驱动都还没搞定,但是说明UBOOT可以跑了毕竟看上面的时间还是我昨晚1点43分才测试好的,呵呵,哎写这篇文章又花了不少时间,觉得既然有心得体会,还是写出来供大家交流,后面有时间会逐步去完善的,当然了后期的工作量估计会更大啊,呵呵 在最后面启动的时候,串口输出UBOOT启动画面会定格在FLASH:......FAILED.....这个位置,然后要求RESTART BOARD,所以UBOOT虽然是启动了,但是还没启动完全,卡在FLASH这一块了,所以昨天又花了半天时间整这个问题,通过不断地代码追踪,最终找到了问题的所在。 ???? 对于UBOOT的移植这一块,我的方法就是尽量自己去寻求问题的解决方案,不要一出问题就去BAIDU,GOOLE,运气好,可能搜到与你问题相近或是一样的答案,运气不好的话,可能搜了半天,也找不到,这个都是有可能的,即使搜到问题的解决方案了,你也只是明白该怎么做,但是却不明白为什么要去这么做,这样自己的印象也不深刻。所以我在这也主要是谈谈我移植?u-boot-2011.06-rc2到OK6410开发板上的一个大体思路与方法,希望对你们有帮助,不会去直接将如何修改如何做直接就贴出来,感觉这样意义也不大。下面就来说说今天的重点吧——how to solve the problem about failure of flash ??? 如果手头有RAM程序调试工具的话,估计就更好办,但一般的UBOOT调试基本都是用串口输出打印信息辅助调试,CPU信息,DRAM信息全都打印出来了,到达FLASH这一块,就打印FAILED,然后UBOOT便挂起,一开始我也是不得其解,以为是?u-boot-2011.06-rc2内自带的CFI_FLASH(commom flash interface)driver对OK6410不起作用,后来便直接丢弃之,然后将UB00T1.16内的SMDK6410内的flash驱动移植了过来,这个花了一点时间,毕竟驱动代码是现成的,只是需要做些稍微的修改就可以加入u-boot-2011.06-rc2,但是通过单板实践验证,一到DRAM信息输出后开发板就立刻重启,连FLASH信息也没输出,但是在UBOOT1.16上却顺利通过,我想肯定还是有哪些位置需要修改,毕竟uboot1.16与u-boot-2011.06-rc2在代码结构以及文件结构上安排还是很不同的,可我没有一点头绪,所以舍弃了这个思路,后来仔细想想,原来采用自带的CFI_FLASH DRIVER时可以看到FLASH信息输出,只不过是FAILED,要不先从这块入手,于是开始跟踪代码的运行,呵呵,说是跟踪其实也是费了一番心血的,毕竟,你都不知道如何去下手,从哪去跟踪,其实,跟踪代码还是要有一定的技巧的,如果对UBOOT内部代码结构熟悉的话,应该会很容易,既然是FLASH这一块自检失败,就需要找到相关的位置,而FLASH是属于板载资源的,所以代码应该与BOARD文件相关,于是我锁定了OK6410.C,LOWLEVEL_INIT.S以及ARCH/ARM/LIB/BOARD.C这3个文件,毕竟这几个文件与板载资源初始化关系很密切,最后通过代码分析,在ARCH/ARM/LIB/BOARD.C这个文件里发现了问题。 ???? 仔细的看了一遍这个文件,发现原来串口打印信息以及打印的顺序全都是由这个文件来决定的,通过一步一步的代码分析,我找到了这么一段代码: #if !defined(CONFIG_SYS_NO_FLASH) ? ???看到标红色的没,那就是串口输出信息?FLASH:.....FAILED.... 而这个failed 只是一个指针变量,在这段代码的前面有一小段代码说明: #if !defined(CONFIG_SYS_NO_FLASH) 看到那个puts (failed);函数下一条的函数没,hang ();其实就是一个系统挂起函数,来粗略分析一下这段代码吧。 ???if ((flash_size = flash_init ()) > 0), flash_init ();这个函数是在/driver/mtd/cfi_flash.c中定义的一个flash初始化函数,而它会返回一个值,也就是flash_size ,而OK6410单板上没有带flash芯片,只有2个64M(共128M)的DRAM内存芯片,还有一个FLC的1G NAND FLASH芯片,所以导致flash_size = flash_init ()) <=0,进而去执行ELSE后面的puts (failed);hang ();两个函数,所以导致最终UBOOT启动卡在FLASH:FAILED 然后挂起。 ?? 由于OK6410没有自带flash,因此在这里最简单的一个解决办法就是将hang ();函数屏蔽掉,不让系统挂起,代码继续往下执行就可以了,也就是://hang ();。 ?? 如果,你觉得flash:.....failed.....这个输出信息看起来很别扭的话,可以直接屏蔽掉,或是将failed这个指针变量换一下,这里我换的的NULL。好了。最后再保存编译,下载到OK6410的DRAM内运行: CPU:???? S3C6400@533MHz ???????? Fclk = 533MHz,Hclk = 133MHz,Pclk = 66MHz (ASYNC Mode) Board:?? OK6410 DRAM:? 128 MiB Flash: *** NULL *** NAND:? raise: Signal # 8 caught raise: Signal # 8 caught raise: Signal # 8 caught raise: Signal # 8 caught raise: Signal # 8 caught raise: Signal # 8 caught 1024 MiB *** Warning - bad CRC,using default environment
Out:?? serial Err:?? serial Net:?? CS8900-0 Hit any key to stop autoboot:? 0 OK6410 # ?这个就是最后的输出结果,看到没,OK6410自带的NAND也识别出来了,只不过可能是自带的驱动不完善的缘故,导致对NAND的一切操作都无效,这个工作后面再进行,还有NET网卡驱动上面现实的是SMDK6400默认的CS8900,也是需要更改的,后面会继续移植相关驱动部分的。 ?? 其实本来是想等驱动移植的差不多再贴出来的,但是感觉还是一步实践,一步记录下来最好,免得到时一起写的话,工作量太大了,到这里,可以说OK6410的u-boot-2011.06-rc2移植才算真正启动启动起来了,后面的工作主要就是相关驱动的移植,以及可能需要增加的功能的实现代码的ADD了。 现在当你输入NAND READ 或是NAND WRITE命令的时候,#命令符号后会不断地打印 一串信号: raise: Signal # 8 caught raise: Signal # 8 caught而且是循环打印,无法停止,但是NAND ERASE命令是可行的 没有这种信号输出,起初我开始怀疑是不是NAND驱动有问题,导致NAND的读写函数功能没有实现完全,但是事实上这种可能很小,因为既然SMDK6400已经实现了,我想OK6410应该不会出现这个问题啊,况且1GB的NAND芯片已经被识别了,带着这种疑问,我想了好久,还是想不通,核查代码一遍又一遍,搞的我还去翻了一遍单板上的NAND芯片英文资料还有SOC_S3C6410的DATASHEET,哎,看的头都大了,但是一切都是都那么的美好,看不出个问题,没办法,还是去GOOLE一下吧,带着渺茫的希望,翻了好几页,终于让我在国外的一个网站论坛上看到了希望,原来 对于S3C6410来说,较新版的UBOOT版本都有一个BUG,那就是再u-boot-2011.06-rc2/arch/arm/cpu/arm1176/s3c64xx/timer.c这个文件上,其实这个问题早几个月以前就有人提出来了,因为我看他们的聊天记录视乎是1月份左右的,本人英语虽很稀烂,但是看这些还是不成问题的了,可能会有人问,既然问题出了,为啥子DENX TEAM不加进新版本的UBOOT呢?其实我也很疑惑,但是正如DENX TEAM的UBOOT软件工程师WOLF GANG所气愤的,他不希望因为某一个芯片而去把UBOOT里面的代码的可读性以及可理解性破坏掉,改了timer.c里面的几个变量名的确可以让S3C6410 WORK WELL,但是这样,代码的可读性将会变得很差,因此,他的建议是需要的人直接去修改TIMER.C的代码,即使是以后更新的版本,也不会因为S3C6410这个芯片而去改动,其实,他说的很对,毕竟代码如果可读性降低了,那维护起来也很不方便,更让人很难理解啊,在这点上我还是很认同的,呵呵。好了,废话,说了一大堆,在这,贴出这个 PATCH吧: diff --git a/arch/arm/cpu/arm1176/s3c64xx/timer.c b/arch/arm/cpu/arm1176/s3c64xx/timer.c ,可能会有人会觉得照着去手动改写的地方有40处,太多了,好麻烦,好了,这里教大家一个办法,其实就是打补丁了,呵呵,大家将这段代码粘贴下来,在LINUX环境下任意一个目录下,新建一个文件,文件名name.patch,也就是gedit name.patch,或是vi name.patch,看你习惯了,这里的name 你随便命名,然后粘贴代码,保存,然后进到UBOOT的根目录下, 输入命令:patch -Np1 -i /.../directory/name.patch,这里的directory也就是你保存那个PATCH补丁的位置,这样,timer.c文件的补丁就打好了,不需要再去修改了,如果你不相信,也可以进到相应的目录查看,呵呵,好了,然后 你再次编译,下载到DRAM里面运行, U-Boot 2011.06-rc2 (Jul 01 2011 - 17:06:03) for OK6410 ? CPU:???? S3C6410@533MHz ???????? Fclk = 533MHz,Pclk = 66MHz (ASYNC Mode) Board:?? OK6410 DRAM:? 128 MiB Flash: *** NULL *** NAND:? 1024 MiB *** Warning - bad CRC,using default environment
Out:?? serial Err:?? serial Net:?? CS8900-0 Hit any key to stop autoboot:? 0 OK6410 # nand erase 0 100000
OK,看到没,NAND后面的那几个 raise: Signal # 8 caught也没了,的确,这个补丁对于S3C6410来说是VERY GOOD的,经过自己实践验证,NAND读写完全没问题,看来新版本的UBOOT对与6410的NAND的MTD驱动真的是支持的很好了啊。 对了,最后我在这有必要说明一下啊,我这个u-boot-2011.06-rc2虽然是对飞凌OK6410移植的,但是对只要是采用S3C6410芯片的板子理论上基本都是可行的,还有一点,就是现在虽然已近实现了NAND驱动了,但是还并没有实现NAND启动,这点也不难,有时间我会去完善的,对了,还有后续的一些其他功能我会逐步去加进去的,比如现在的U-Boot 2011.06-rc2的USB-OTG下载功能已经实现了,具体运行截图请点击我下方的QQ空间的链接,没办法,现在我还无法上传图片啊,所以这里贴不出来,移植方法我会稍后放出的,等有时间一定会写上详细的方法的,以后会陆续添加更多的功能的,至于那个DM9000网卡驱动后面也会移植的,我的目标就是将这个新版的OK6410的UBOOT版本功能变得强大起来 呵呵 纯属个人爱好了,不知道有没有啥实用价值。 ? WARNING: 目前这个版本只能在DRAM里面运行加载LINUX镜像,因为我还没加入代码实现NAND搬运UBOOT前4K代码入DRAM最终实现NAND启动UBOOT,当然这个会在以后加进去的,还有一点需要提醒大家的是,这个版本编译默认好像是没有开启MMU的,所以对于对于高地址的范围是无法访问的,如需要,可以在OK6410.H里面定义启用。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |