• <table id="MlpKg"></table><figcaption id="MlpKg"><acronym id="MlpKg"><th id="MlpKg"></th></acronym></figcaption>
      欢迎来到EDA中国!
      当前位置:网站首页 >技术专栏 > ARM

      uboot 移植全过程---基于ARM9 2410

      发布时间: 2020-03-30 07:11:56     来源: EDA中国

      uboot 移植全过程---基于ARM9 2410

      uboot@localhost ~]#mkdir -p dev_home/uboot 

      [uboot@localhost ~]#cd dev_home/uboot 

      从下面地址下载u-boot 的源代码。 

      http://sourceforge.net/projects/u-boot 

      [uboot@localhost uboot]#tar -xjvf u-boot-1.1.4.tar.bz2 

      [uboot@localhost uboot]#cd u-boot-1.1.4 

      1.3 u-boot 体系结构 

      1.3.1 u-boot 目录结构 

      1. 目录树 

      [uboot@localhost u-boot-1.1.4]#tree -L 1 -d 

      |-- board 

      |-- common 

      |-- cpu 

      |-- disk 

      |-- doc 

      |-- drivers 

      |-- dtt 

      |-- examples 

      |-- fs 

      |-- include 

      |-- lib_arm 

      |-- lib_generic 

      |-- lib_i386 

      |-- lib_m68k 

      |-- lib_microblaze 

      |-- lib_mips 

      |-- lib_nios 

      |-- lib_nios2 

      |-- lib_ppc 

      |-- net 

      |-- post 

      |-- rtc 

      `-- tools 
      2. board:和一些已有开发板有关的文件. 每一个开发板都以一个子目录出现在当前目录中,比如说:SMDK2410, 子目录中存放与开发板相关的配置文件. 
      3. common:实现u-boot 命令行下支持的命令,每一条命令都对应一个文件。例如bootm 命令对应就是 cmd_bootm.c 。 
      4. cpu:与特定CPU 架构相关目录,每一款U-boot 下支持的CPU 在该目录下对应一个子目录,比如有子目录 arm920t 等。 
      5. disk:对磁盘的支持。 
      5. doc:文档目录。U-boot 有非常完善的文档,推荐大家参考阅读。 
      6. drivers:U-boot 支持的设备驱动程序都放在该目录,比如各种网卡、支持CFI 的Flash 、串口和USB 等。 
      7. fs: 支持的文件系统,U-boot 现在支持cramfs 、fat 、fdos 、jffs2 和registerfs 。 
      8. include:U-boot 使用的头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件。该目录下configs  目录有与开发板相关的配置头文件,如smdk2410.h 。该目录下的asm  目录有与CPU 体 
      系结构相关的头文件,asm 对应的是asm-arm. 
      9. lib_xxxx: 与体系结构相关的库文件。如与ARM 相关的库放在lib_arm 中。 
      10. net:与网络协议栈相关的代码,BOOTP 协议、TFTP 协议、RARP 协议和NFS 文件系统的实现。 
      11. tools:生成U-boot 的工具,如:mkimage, crc 等等。 

      2 uboot 的启动过程及工作原理 

      2.1 启动模式介绍 

      大多数 Boot Loader 都包含两种不同的操作模式:"启动加载"模式和"下载"模式,这种区别仅对于开发人员才有意义。但从最终用户的角度看,Boot Loader 的作用就是用来加载操作系统,而并不存在所谓的启动加 载模式与下载工作模式的区别。 

          启动加载 (Boot loading)模式:这种模式也称为" 自主"       (Autonomous)模式。也即 Boot Loader 从目标机上的某个固态存储设备上将操作系统加载到 RAM 中运行,整个过程并没有用户的介入。这种模式是 Boot Loader 的正常工作模式,因此成都网站设计公司在嵌入式产品发布的时侯,Boot Loader 显然必须工作在这种模式下。 

        下载 (Downloading)模式:在这种模式下,目标机上的 Boot Loader 将通过串口连接或网络连接等通信手 段从主机 (Host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被 Boot Loader 保存到目标机的 RAM 中,然后再被 BootLoader 写到目标机上的FLASH 类固态存储设备中。Boot oader 的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用 Boot Loader 的这种工作模式。工作于这种模式下的 Boot Loader 通常都会向它的终端用户提供一个简单的命令  接口。 

         U-Boot 这样功能强大的 Boot Loader 同时支持这两种工作模式,而且允许用户在这两种工作模式之间进 

      切换。 

          大多数bootloader 都分为阶段 1(stage1)和阶段2(stage2)两大部分,u-boot 也不例外。依赖于CPU 体系结构 的代码 (如CPU 初始化代码等)通常都放在阶段 1 中且通常用汇编语言实现,而阶段2 则通常用C 语言来实 现,这样可以实现复杂的功能,而且有更好的可读性和移植性。


      2.2 阶段1 介绍 
      u-boot 的stage1 代码通常放在start.s 文件中,它用汇编语言写成,其主要代码部分如下: 

      2.2.1 定义入口 
      由于一个可执行的Image 必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0 

      地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。 
          1. board/crane2410/u-boot.lds:  ENTRY(_start) ==> cpu/arm920t/start.S: .globl _start 

           2. uboot 代码区 (TEXT_BASE = 0x33F80000)定义在board/crane2410/config.mk 

      2.2.2 设置异常向量 

      _start: b       reset                          @ 0x00000000 

              ldr     pc, _undefined_instruction     @ 0x00000004 

              ldr     pc, _software_interrupt        @ 0x00000008 

              ldr     pc, _prefetch_abort            @ 0x0000000c 

              ldr     pc, _data_abort                @ 0x00000010 

              ldr     pc, _not_used                  @ 0x00000014 

              ldr     pc, _irq                       @ 0x00000018 

              ldr     pc, _fiq                       @ 0x0000001c 


            当发生异常时,执   cpu/arm920t/interrupts.c 中定义的中断处理函数。 

      2.2.3 设置 CPU 的模式为SVC模式 
              mrs     r0,cpsr 

              bic     r0,r0,#0x1f 

              orr     r0,r0,#0xd3 

              msr     cpsr,r0 

      2.2.4 关闭看门狗 

      #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) 

              ldr     r0, =pWTCON 

              mov     r1, #0x0     @ 根据三星手册进行调置。 

              str     r1, [r0] 

      2.2.5 禁掉所有中断 
              mov     r1, #0xffffffff 

              ldr     r0, =INTMSK 

              str     r1, [r0] 

      # if defined(CONFIG_S3C2410) 

              ldr     r1, =0x3ff 

              ldr     r0, =INTSUBMSK 

              str     r1, [r0] 

      .2.6 设置以 CPU 的频率 
      默认频率为 FCLK:HCLK:PCLK = 1:2:4,默认FCLK的值为120 MHz,该值为S3C2410手册的推荐值。 

              ldr     r0, =CLKDIVN 

              mov     r1, #3 

              str     r1, [r0] 

      2.2.7 设置 CP15 

      设置CP15, 失效指令(I)Cache 和数据(D)Cache 后, 禁止MMU 与Cache 。 

      cpu_init_crit: 

              mov     r0, #0 

              mcr     p15, 0, r0, c7, c7, 0   /* 失效I/D cache, 见S3C2410手册附录的2-16 */ 

              mcr     p15, 0, r0, c8, c7, 0   /* 失效TLB, 见S3C2410手册附录的2-18 */ 

      /* 

               * 禁止 MMU 和caches, 详见S3C2410手册附录2-11 

               */ 

              mrc     p15, 0, r0, c1, c0, 0 

              bic     r0, r0, #0x00002300     /* 清除 bits 13, 9:8 (--V- --RS) 

                                       * Bit 8: Disable System Protection 

                                       * Bit 7: Disable ROM Protection 

                                       * Bit 13: 异常向量表基地址: 0x0000 0000 

                                       */ 

              bic     r0, r0, #0x00000087     /* 清除 bits 7, 2:0 (B--- -CAM) 

                                       * Bit 0: MMU disabled 

                                       * Bit 1: Alignment Fault checking disabled 

                                       * Bit 2: Data cache disabled 

                                       * Bit 7: 0 = Little-endian operation 
                                       */ 

              orr     r0, r0, #0x00000002      /* set bit 2 (A) Align, 1 = Fault checking enabled */ 

              orr     r0, r0, #0x00001000     /* set bit 12 (I) I-Cache, 1 = Instruction cache enabled  

      */ 

              mcr     p15, 0, r0, c1, c0, 0 

      2.2.8 配置内存区控制寄存器 
      配置内存区控制寄存器,寄存器的具体值通常由开发板厂商或硬件工程师提供. 如果您对总线周期及外围 

      芯片非常熟悉, 也可以自己确定, 在U-BOOT 中的设置文件是board/crane2410/lowlevel_init.S, 该文件包含 

      lowleve_init 程序段. 详细寄存器设置及值的解释见3.2.2 启动AXD 配置开发板一节中的第5 点. 

            mov     ip, lr 

              bl      lowlevel_init 

              mov     lr, ip 

      2.2.9 安装 U-BOOT使的栈空间 



          下面这段代码只对不是从Nand Flash 启动的代码段有意义,对从Nand Flash 启动的代码,没有意义。因为 

      从Nand Flash 中把UBOOT 执行代码搬移到RAM,由2.1.9 中代码完成. 

      #ifndef CONFIG_SKIP_RELOCATE_UBOOT 

      ... 

      #endif 

      stack_setup: 

             ldr     r0, _TEXT_BASE              /* 代码段的起始地址    */ 

             sub     r0, r0, #CFG_MALLOC_LEN     /* 分配的动态内存区    */ 

             sub     r0, r0, #CFG_GBL_DATA_SIZE   /* UBOOT开发板全局数据存放  */ 

      #ifdef CONFIG_USE_IRQ 

             /* 分配IRQ和FIQ栈空间 */ 

             sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 

      #endif 

             sub     sp, r0, #12                 /* 留下3个字为Abort    */ 



      2.2.10 BSS段清 0 



      clear_bss: 

             ldr     r0, _bss_start       /* BSS段的起始地址   */ 

             ldr     r1, _bss_end         /* BSS段的结束地址   */ 

             mov     r2, #0x00000000             /* BSS段置0                   */ 

      clbss_l:str    r2, [r0]             /* 循环清除BSS段 */ 

             add     r0, r0, #4 

             cmp     r0, r1 

             ble     clbss_l 



      2.2.11 搬移 Nand Flash代码 



      从Nand Flash 中, 把数据拷贝到RAM, 是由copy_myself 程序段完成, 该程序段详细解释见:第七部分的3.1 节. 

      #ifdef CONFIG_S3C2410_NAND_BOOT 

             bl    copy_myself 
            @ jump to ram 

             ldr   r1, =on_the_ram 

             add  pc, r1, #0 

             nop 

             nop 

      1:    b     1b          @ infinite loop 
      on_the_ram: 

      #endif 



      2.2.12 进入 C代码部分 



              ldr     pc, _start_armboot 

              _start_armboot: .word start_armboot 



      2.3 阶段2 的C 语言代码部分  



      lib_arm/board.c 中的start armboot 是C 语言开始的函数,也是整个启动代码中C 语言的主函数,同时还是整个 

      u-boot(armboot)的主函数,该函数主要完成如下操作: 



      2.3.1调用一系列的初始化函数 



      1. 指定初始函数表: 

      init_fnc_t *init_sequence[] = { 

             cpu_init,             /* cpu的基本设置          */ 

             board_init,           /* 开发板的基本初始化     */ 

             interrupt_init,       /* 初始化中断             */ 

             env_init,             /* 初始化环境变量         */ 

             init_baudrate,        /* 初始化波特率           */ 

             serial_init,          /* 串口通讯初始化         */ 

             console_init_f,       /* 控制台初始化第一阶段   */ 

             display_banner,       /* 通知代码已经运行到该处 */ 

             dram_init,            /* 配制可用的内存区       */ 

             display_dram_config, 

      #if defined(CONFIG_VCMA9) || defined (CONFIG_CMC_PU2) 

             checkboard, 

      #endif 

             NULL, 

      }; 

      执行初始化函数的代码如下: 

             for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { 

                     if ((*init_fnc_ptr)() != 0) { 

                            hang (); 

                     } 

             } 



      2. 配置可用的Flash 区 

         flash_init ()    

          

      3. 初始化内存分配函数 

         mem_malloc_init()   

          

      4. nand flash 初始化 

       #if (CONFIG_COMMANDS & CFG_CMD_NAND) 

                puts ("NAND:"); 

                nand_init();              /* 初始化 NAND */ 

      见第七部分3.2.3 节中的第3 点nand_init()函数. 



      5. 初始化环境变量  

        env_relocate (); 



      6. 外围设备初始化 

         devices_init() 



      7. I2C 总线初始化 

        i2c_init(); 



      8. LCD 初始化 

        drv_lcd_init(); 



      9. VIDEO 初始化 

        drv_video_init(); 



      10. 键盘初始化 

        drv_keyboard_init(); 



      11. 系统初始化 

        drv_system_init(); 



      2.3.2 初始化网络设备 



      初始化相关网络设备,填写IP 、MAC 地址等。 

      1. 设置IP 地址 



              /* IP Address */ 

              gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); 



              /* MAC Address */ 

              { 

                      int i; 

                      ulong reg; 

                      char *s, *e; 

                      uchar tmp[64]; 



                      i = getenv_r ("ethaddr", tmp, sizeof (tmp)); 

                      s = (i > 0) ? tmp : NULL; 



                      for (reg = 0; reg < 6; ++reg) { 

                              gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0; 

                              if (s) 

                                      s = (*e) ? e + 1 : e; 

                      } 

              } 



      2.3.3 进入主 UBOOT命令 



      进入命令循环 (即整个boot 的工作循环),接受用户从串口输入的命令,然后进行相应的工作。 



              for (;;) { 

                      main_loop (); /* 在common/main.c */ 

              } 


      2.4 代码搬运 



      为了支持NAND flash 起动,S3C2410 内建了内部的4k 的SRAM 缓存 “Steppingstone” 。当起动时,NAND 

      flash 最初的4k 字节将被读入”Steppingstone”然后开始执  起动代码。通常起动代码会把NAND flash 中的内容 

      拷到SDRAM 中以便执行主代码。 

      使用硬件的ECC, NAND flash 中的数据的有效性将会得到检测。 

      功能 

          1. NAND flash 模式:支持读/删除/编程 NAND Flash 

          2.  自动起动模式:在复位时起动代码将被读入”Steppingstone”中,然后开始执  起动代码。 

          3. 硬件ECC 检测模块(硬件检测,软件纠正) 

          4. “Steppingstone” 4-KB 内部SRAM 在起动后可以另外使用。 



      3 uboot 的移植过程 



      3.1 环境 


        1. 工作用户 

          uboot 

        2. u-boot 版本 1.1.4 

          获取u-boot1.1.4请看 1.2 



        3. 工具链2.95.3 



      3.2 步骤 



      我们为开发板取名叫: crane2410, 并在u-boot 中建立自己的开发板类型 



      3.2.1 修改 Makefile 



      [uboot@localhost uboot]#vi Makefile 

      #为crane2410 建立编译项 

      crane2410_config : unconfig 

         @./mkconfig $(@:_config=) arm arm920t crane2410 NULL s3c24x0 

      各项的意思如下: 

          arm:      CPU 的架构(ARCH) 

          arm920t:  CPU 的类型(CPU) ,其对应于cpu/arm920t 子目录。 

          crane2410: 开发板的型号(BOARD) ,对应于board/crane2410  目录。 

          NULL:     开发者/或经销商(vender) 。 

          s3c24x0:  片上系统(SOC) 。 


      关键字 : 2410 uboot 移植 arm9 
      获取帮助