u-boot2010.03 移植篇(二)-----修改start.S,支持nand启动

2024-02-26 02:58

本文主要是介绍u-boot2010.03 移植篇(二)-----修改start.S,支持nand启动,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

下面开始 移植篇(二)-----修改start.S,支持nand启动
----------------------------------------------------------
使用环境
PC:     ubuntu 11.04
kernel: 2.6.32-28-generic
corss:  arm-linux-gcc 4.3.2
arm:    s3c6410
uboot:  uboot-2010-03
----------------------------------------------------------

一切版权均有作者所有,欢迎转载,请指明出处,如何修改请与本人联系,谢谢


uboot的第一阶段,其实做的事情也是比较多的,,但是一般来说,重点就是配置各种硬件环境,来保证第二阶段能正常启动.
而该部分根据不同的硬件也是不同的..像我的,s3c6410有2片dram,和一片nand..所以我为了保证我的代码能正常执行,
我必须得把代码搬移到内存里面去.不然代码在nand中也没法执行...但是为什么代码在nand中不能执行呢?其中一个比较
重要的原因就是nand并不是挂在CPU总线上面的,而是采用专门的硬件处理单元来控制的...nand控制器.
在你不添加任何代码的情况下,是不能控制外围的nand芯片的...但是怎么办.cpu内根本没有代码,怎么才能读取nand中的
代码到内存中去呢?没错-----s3c6410在启动的时候会帮我们以nand的最基本的时序.搬移nand中的前8K代码,到stepping
这样就可以执行了.而uboot的代码远比这个大..以至于我们得紧靠这部分代码,来完成剩下的代码部分的搬移....

今天的重点就是这个了.主要是来完成nand中剩余部分的uboot搬移到ram中,以便uboot能正常启动起来....好了.直接开始..

首先,你得有smdk6410_config 编译目标,不然怎么开始.....此处省略N字...请看我的移植篇第一篇...

下面开始.打开start.S (cpu/arm1176/start.S)和smdk6410.h (include/configs/smdk6410.h)
我们得一边参看头文件中的配置,一边修改代码,来达到我们的目的..
start.S 中,最开始就是一段啥?异常向量表,此处忽略,请参考分析篇中对start.S的分析

前面一部分是MMU啥的...直接招待after_copy:这个标签
什么?之前没有任何copy的东西???怎么有after_copy一说呢?
没错..所以我们得把copy代码添加在这里..从nand中把数据搬移出来,放到这之前完成,这样才对得起这个after_copy的标签
说干就干,这里我是调用的C代码,你也可以用汇编来完成的,只要功能一样就行了

这里我们得向我们的配置头文件内添加一个宏,就是 #define CONFIG_NAND_BOOT
接着,我们要去添加我们要调用的copy_from_nand

[cpp] plain copy
  1. *   
  2.  * copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND)   
  3.  * r0: size to be compared   
  4.  * Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size   
  5.  *///   
  6. .globl copy_from_nand   
  7.     
  8. copy_from_nand:   
  9.     mov r10, lr                     /* save return address */  
  10.       
  11.     mov r9, r0   
  12.     /* get ready to call C functions */    
  13.     ldr sp, _TEXT_PHY_BASE          /* setup temp stack pointer */  
  14.     sub sp, sp, #12   
  15.     mov fp, #0                      /* no previous frame, so fp=0 */  
  16.     mov r9, #0x1000   
  17.     bl  copy_uboot_to_ram           /* 此函数需要添加,稍后说明。 */  
  18. 3:  tst r0, #0x0                      
  19.     bne copy_failed                 /* 判断返回值是否失败 */  
  20.     ldr r0, =0x0c000000             /* 判断内容是否一致 */  
  21.     ldr r1, _TEXT_PHY_BASE   
  22. 1:  ldr r3, [r0], #4   
  23.     ldr r4, [r1], #4   
  24.     teq r3, r4   
  25.     bne compare_failed              /* not matched */  
  26.     subs r9, r9, #4   
  27.     bne 1b   
  28. 4:  mov lr, r10                     /* all is OK */  
  29.     mov pc, lr   
  30.       
  31. copy_failed:   
  32.     nop                             /* copy from nand failed */  
  33.     b copy_failed   
  34.       
  35. compare_failed:   
  36.     nop                             /* compare failed */  
  37.     b compare_failed  

在这段代码里面,就是调整了下sp,为了能调用c函数 copy_uboot_to_ram,那么重点就是这个函数了..这个函数在nand_cp.c中.

<Ps:这个错误由以为网友提出,在此表示感谢....希望更多的网友能够支持.谢谢>

这个文件比较大,分析篇我会重点分析,究竟nand是如何搬移数据的.这里我们只要复制下好了...

[cpp] plain copy
  1. #include <common.h>  
  2. #ifdef CONFIG_S3C64XX  
  3. #include <asm/io.h>  
  4. #include <linux/mtd/nand.h>  
  5. #include <asm/arch/s3c6400.h>  
  6.   
  7. static int nandll_read_page(uchar * buf, ulong addr, int large_block)  
  8. {  
  9.     int i;  
  10.     int page_size = 512;  
  11.   
  12.     if (large_block == 1)  
  13.         page_size = 2048;  
  14.     if (large_block == 2)  
  15.         page_size = 4096;  
  16.   
  17.     NAND_ENABLE_CE();  
  18.   
  19.     NFCMD_REG = NAND_CMD_READ0;  
  20.   
  21.     /* Write Address */  
  22.     NFADDR_REG = 0;  
  23.   
  24.     if (large_block)  
  25.         NFADDR_REG = 0;  
  26.   
  27.     NFADDR_REG = (addr) & 0xff;  
  28.     NFADDR_REG = (addr >> 8) & 0xff;  
  29.     NFADDR_REG = (addr >> 16) & 0xff;  
  30.   
  31.     if (large_block)  
  32.         NFCMD_REG = NAND_CMD_READSTART;  
  33.   
  34.     NF_TRANSRnB();  
  35.   
  36.     /* for compatibility(2460). u32 cannot be used. by scsuh */  
  37.     for (i = 0; i < page_size; i++) {  
  38.         *buf++ = NFDATA8_REG;  
  39.     }  
  40.   
  41.     NAND_DISABLE_CE();  
  42.     return 0;  
  43. }  
  44.   
  45. static int nandll_read_blocks(ulong dst_addr, ulong size, int large_block)  
  46. {  
  47.     uchar *buf = (uchar *) dst_addr;  
  48.     int i;  
  49.     uint page_shift = 9;  
  50.   
  51.     if (large_block == 1)  
  52.         page_shift = 11;  
  53.   
  54.     /* Read pages */  
  55.     if (large_block == 2)  
  56.         page_shift = 12;  
  57.   
  58.     if (large_block == 2) {  
  59.         /* Read pages */  
  60.         for (i = 0; i < 4; i++, buf += (1 << (page_shift - 1))) {  
  61.             nandll_read_page(buf, i, large_block);  
  62.         }  
  63.         /* Read pages */  
  64.         for (i = 4; i < (0x60000 >> page_shift);i++, buf += (1 << page_shift)) {  
  65.             nandll_read_page(buf, i, large_block);  
  66.         }  
  67.     } else {  
  68.         for (i = 0; i < (0x60000 >> page_shift);i++, buf += (1 << page_shift)) {  
  69.             nandll_read_page(buf, i, large_block);  
  70.         }  
  71.     }  
  72.   
  73.     return 0;  
  74. }  
  75.   
  76. int copy_uboot_to_ram(void)  
  77. {  
  78.     int large_block = 0;  
  79.     int i;  
  80.     vu_char id;  
  81.   
  82.     NAND_ENABLE_CE();  
  83.     NFCMD_REG = NAND_CMD_READID;  
  84.     NFADDR_REG = 0x00;  
  85.   
  86.     /* wait for a while */  
  87.     for (i = 0; i < 200; i++) ;  
  88.         id = NFDATA8_REG;  
  89.     id = NFDATA8_REG;  
  90.   
  91.     if (id > 0x80)  
  92.         large_block = 1;  
  93.     if (id == 0xd5)  
  94.         large_block = 2;  
  95.   
  96.     /* read NAND Block. 
  97.      * 128KB ->240KB because of U-Boot size increase. by scsuh 
  98.      * So, read 0x3c000 bytes not 0x20000(128KB). 
  99.      */  
  100.     return nandll_read_blocks(CONFIG_SYS_PHY_UBOOT_BASE, 0x60000,large_block);  
  101. }  
  102.   
  103. #endif  
然后修改 Makefile 把我们的 nand_cp.c添加到 uboot中去编译

最后 make下.你会发现.编译好了....编译器记得重新 make smdk6410_config下.因为我们修改了头文件,需要重新生成 .mk文件

今天的任务基本完成了,今天比较轻松,接着我们稍微修改下 smdk6410.h中的配置.
主要是改几个名字,把什么 6400的改成 6410就好了..
没错,你只要查找替换就行了...因为我们现在编译的已经是 6410了.不是 6400了...

修改完之后,有一个地方得稍微改下.
cpu/arm1176/s3c64xx/Makefile

6400改成 64XX因为,我们的配置文件里面已经没有 6400了....
这个请查看头文件中的配置定义...


继续修改此篇:

到此眼看就已经结束了...好了,make吧....啥有一个错误,天哪....

[cpp] plain copy
  1. arm-linux-gcc -E -g  -Os   -fno-common -ffixed-r8 -msoft-float  -fno-common -ffixed-r8 -msoft-float  -D__KERNEL__ -DTEXT_BASE=0   
  2. -I/media/LvApp/u-boot-2010.03/include -fno-builtin -ffreestanding -nostdinc -isystem   
  3. /usr/local/arm/4.4.1/bin/../lib/gcc/arm-none-linux-gnueabi/4.4.1/include -pipe  -DCONFIG_ARM -D__ARM__   
  4. -marm  -mabi=aapcs-linux -mno-thumb-interwork -march=armv5t -march=armv5t  -ansi -D__ASSEMBLY__   
  5. -P - </media/LvApp/u-boot-2010.03/nand_spl/board/samsung/smdk6410/u-boot.lds >/media/LvApp/u-boot-2010.03/nand_spl/u-boot.lds  
  6. cd /media/LvApp/u-boot-2010.03/nand_spl/board/samsung/smdk6410 && arm-linux-ld -Bstatic -T   
  7. /media/LvApp/u-boot-2010.03/nand_spl/u-boot.lds -Ttext 0  start.o cpu_init.o lowlevel_init.o nand_boot.o nand_ecc.o s3c64xx.o \  
  8.         -Map /media/LvApp/u-boot-2010.03/nand_spl/u-boot-spl.map \  
  9.         -o /media/LvApp/u-boot-2010.03/nand_spl/u-boot-spl  
  10. start.o: In function `copy_from_nand':  
  11. /media/LvApp/u-boot-2010.03/nand_spl/board/samsung/smdk6410/start.S:302: undefined reference to `copy_uboot_to_ram'  
  12. make[1]: *** [/media/LvApp/u-boot-2010.03/nand_spl/u-boot-spl] Error 1  
  13. make[1]: Leaving directory `/media/LvApp/u-boot-2010.03/nand_spl/board/samsung/smdk6410'  
  14. make: *** [nand_spl] Error 2  
别急别急,,,小错而已..是吧....我们仔细查看,这是一个链接错误,为嘛会链接出错了..在此看到有这一行

start.o cpu_init.o lowlevel_init.o nand_boot.o nand_ecc.o s3c64xx.o

看到这一行,内心就暗自偷笑下吧..找到问题所在了...为啥?copy_uboot_to_ram这个函数不就是在start.o中内调用的嘛...所以这里没有nand_cp.o被链接进来,铁定

链接错误的...那要怎么改..直接定位到这个错误的目录下u-boot-2010.03/nand_spl/board/samsung/smdk6410修改该目录下Makefile 添加如下所示:

[cpp] plain copy
  1. COBJS   = nand_boot.o nand_ecc.o s3c64xx.o nand_cp.o 后面得加上nand_cp.o  

接着我们得模仿后面的写法,为nand_cp.o添加目标生成方法

[cpp] plain copy
  1. # from SoC directory  
  2. $(obj)cpu_init.S:  
  3.     @rm -f $@  
  4.     @ln -s $(TOPDIR)/cpu/arm1176/s3c64xx/cpu_init.S $@  
  5.   
  6.   
  7. $(obj)nand_cp.c:  
  8.     @rm -f $@  
  9.     @ln -s $(TOPDIR)/cpu/arm1176/nand_cp.c $@  

至此,,编译应该就没有问题啦....


难不成这就行了???你下载进去试试不就知道了...

不行?运行不了?为什么呢....首先我们分析下,启动的过程...arm上电之后开始0地址指令..0地址的指令(此处假设时钟是nand启动,,这里就是讨论这个问题)是由arm自主加载的..从nand

的前8k,那么前8K的代码也就是0---0x2000 的这一段了..在start.S 这个文件,我们都知道是第一条指令的位置,那么这个文件就必须要被拷贝到0地址对应起来咯...这样才能被正常执行.

这些是不是都同意呢?不同意....咱们私下讨论.联系我...同意的,咱们继续.往下分析

既然知道了start.s为开始的地方,那么这里面也是第一部分的引导代码,而大家都知道第一部分的代码其实不全的,,,启动部分只有一下部分被arm搬移,剩余的大部分其实还在nand中..

那么既然不全,也就是跳转啊,函数调用啊...都必须在0---0x2000 的位置内才能到访问到.而且还不能是跟符号相关的跳转.因为符号跳转是根据链接地址跳转的..链接地址大家应该都知道

是被链接到一个很高的内存地址处去了...0x5e000啥的那个地址...

继续啊...不能符号跳转,就必须是相对跳转了...只要保证第一部分中所有的函数调用,符号跳转都在0---0x2000中,那就没问题,正常执行....为此,我们看一下u-boot.map这个文件.发现一个问题

[cpp] plain copy
  1. Linker script and memory map  
  2.   
  3.   
  4.                 0x00000000                . = 0x0  
  5.                 0x00000000                . = ALIGN (0x4)  
  6.   
  7.   
  8. .text           0x57e00000    0x262a4  
  9.  cpu/arm1176/start.o(.text)  
  10.  .text          0x57e00000      0x440 cpu/arm1176/start.o  
  11.                 0x57e00000                _start  
  12.                 0x57e00040                _end_vect  
  13.                 0x57e00048                _armboot_start  
  14.                 0x57e0004c                _bss_start  
  15.                 0x57e00050                _bss_end  
  16.                 0x57e0010c                copy_from_nand  
  17.  cpu/arm1176/s3c64xx/cpu_init.o(.text)  
  18.  .text          0x57e00440      0x124 cpu/arm1176/s3c64xx/cpu_init.o  
  19.                 0x57e00440                mem_ctrl_asm_init  
我们只看一小部分了....在这里我们看到_start符号地址正好是那个指定的链接地址..也就是代码的起始符号...地址很高..无所谓啦...我们看看start.S中都有哪些符号的调用吧..这里直接看这个符号吧
[cpp] plain copy
  1. .text          0x57e1c268      0x1fc board/samsung/smdk6410/libsmdk6410.a(lowlevel_init.o)  
  2.                 0x57e1c26c                lowlevel_init  
这个符号其实在strat.S中是要使用的,,那么在仔细一看这个地址挺高的,,,好像不在前8k中是吧...那么在执行的时候就找不到这个符号的代码了...

问题就是在这,,得确保第一部分需要用到的代码能被arm加载进前8k就好了....那就得需要告诉连接器,,你...就你..帮我把这个链接到前面去.别放后面...不然打你...

链接器就会帮你乖乖的链接上去了...至于链接怎么听话,那就得使用链接听得懂的话了...链接脚本....使用哪个链接脚本..自己看我前面的分析文档吧....

[cpp] plain copy
  1. cpu/arm1176/u-boot.lds  
  2. SECTIONS  
  3. {  
  4.     . = 0x00000000;  
  5.   
  6.   
  7.     . = ALIGN(4);  
  8.     .text :  
  9.     {  
  10.         cpu/arm1176/start.o (.text)  
  11.         board/samsung/smdk6410/lowlevel_init.o (.text)  
  12.         cpu/arm1176/s3c64xx/cpu_init.o (.text)  
  13.         cpu/arm1176/nand_cp.o   (.text)  
  14.         *(.text)  
  15.     }  
  16. 只列出了被修改的部分...  

还有另外一个文件
[cpp] plain copy
  1. board/samsung/smdk6410/u-boot-nand.lds  
  2. SECTIONS  
  3. {  
  4.     . = 0x00000000;  
  5.   
  6.   
  7.     . = ALIGN(4);  
  8.     .text      :  
  9.     {  
  10.       cpu/arm1176/start.o   (.text)  
  11.       cpu/arm1176/s3c64xx/cpu_init.o    (.text)  
  12.       board/samsung/smdk6410/lowlevel_init.o (.text)  
  13.           cpu/arm1176/nand_cp.o   (.text)  
  14.       *(.text)  
  15.     }  

至此...最后看一下修改之后的u-boot.map
[cpp] plain copy
  1. Linker script and memory map  
  2.   
  3.   
  4.                 0x00000000                . = 0x0  
  5.                 0x00000000                . = ALIGN (0x4)  
  6.   
  7.   
  8. .text           0x57e00000    0x262a4  
  9.  cpu/arm1176/start.o(.text)  
  10.  .text          0x57e00000      0x440 cpu/arm1176/start.o  
  11.                 0x57e00000                _start  
  12.                 0x57e00040                _end_vect  
  13.                 0x57e00048                _armboot_start  
  14.                 0x57e0004c                _bss_start  
  15.                 0x57e00050                _bss_end  
  16.                 0x57e0010c                copy_from_nand  
  17.  cpu/arm1176/s3c64xx/cpu_init.o(.text)  
  18.  .text          0x57e00440      0x124 cpu/arm1176/s3c64xx/cpu_init.o  
  19.                 0x57e00440                mem_ctrl_asm_init  
  20.  board/samsung/smdk6410/lowlevel_init.o(.text)  
  21.  .text          0x57e00564      0x1fc board/samsung/smdk6410/lowlevel_init.o  
  22.                 0x57e00568                lowlevel_init  
  23.  cpu/arm1176/nand_cp.o(.text)  
  24.  .text          0x57e00760      0x1b4 cpu/arm1176/nand_cp.o  
  25.                 0x57e00814                copy_uboot_to_ram  

好了.都到前面去了..真听话.....完了..就到这吧....


完了..今天就说这么多..特别简单..
Finish!
Thanks a lot~

这篇关于u-boot2010.03 移植篇(二)-----修改start.S,支持nand启动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/747519

相关文章

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

springboot3打包成war包,用tomcat8启动

1、在pom中,将打包类型改为war <packaging>war</packaging> 2、pom中排除SpringBoot内置的Tomcat容器并添加Tomcat依赖,用于编译和测试,         *依赖时一定设置 scope 为 provided (相当于 tomcat 依赖只在本地运行和测试的时候有效,         打包的时候会排除这个依赖)<scope>provided

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包, 通常我们会使用nohup直接启动,但是还是需要手动停止然后再次启动, 那如何更优雅的在服务器上启动jar包呢,让我们一起探讨一下吧。 1、初版 第一个版本是常用的做法,直接使用nohup后台启动jar包, 并将日志输出到当前文件夹n

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud

SpringBoot项目是如何启动

启动步骤 概念 运行main方法,初始化SpringApplication 从spring.factories读取listener ApplicationContentInitializer运行run方法读取环境变量,配置信息创建SpringApplication上下文预初始化上下文,将启动类作为配置类进行读取调用 refresh 加载 IOC容器,加载所有的自动配置类,创建容器在这个过程

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor

GNSS CTS GNSS Start and Location Flow of Android15

目录 1. 本文概述2.CTS 测试3.Gnss Flow3.1 Gnss Start Flow3.2 Gnss Location Output Flow 1. 本文概述 本来是为了做Android 14 Gnss CTS 的相关环境的搭建和测试,然后在测试中遇到了一些问题,去寻找CTS源码(/cts/tests/tests/location/src/android/locat

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚: