码迷,mamicode.com
首页 > 其他好文 > 详细

at91sam9g25处理器uboot移植 个人笔记一

时间:2015-08-25 19:42:36      阅读:2579      评论:0      收藏:0      [点我收藏+]

标签:arm   c   u-boot   移植   



1 生成补丁 与 打补丁


  生成补丁 diff -upNr old/ new/ > patch-x.y.z
  diff -upNr u-boot-2014.07/ u-boot-2014.07_moveto9g25/ > moveto9g25-2015.08.25-ok.patch
  打补丁   cd old
           patch -p1 < ../patch-x.y.z
----------------------------------------------------------------------------------------------
2 修改boards.cfg 与 Makefile
  Status, Arch, CPU:SPLCPU, SoC, Vendor, Board name,    Target,        Options, Maintainers
  Active  arm   arm926ejs  at91  atmel   at91sam9g25jzq at91sam9g25jzq_nandflash
         at91sam9g25jzq:AT91SAM9G25,SYS_USE_NANDFLASH    Zhaigch <zhaigcherer@qq.com>


  修改Makefile,指定CROSS_COMPILE = arm-linux-
  拷贝board/atmel/at91sam9x5ek 为 at91sam9g25jzq对应配置文件里的Board name
  拷贝include/configs/at91sam9x5ek.h 为 at91sam9g25jzq.h
  生成配置头文件 make <Target>_config
  make at91sam9g20ek_nandflash_config
  make at91sam9g25jzq_nandflash_config
  make
  make u-boot.dis //生成反汇编文件
----------------------------------------------------------------------------------------------  
3 搜索字符串命令
  grep -nR "xx" ./
  使用4.3.2交叉编译器编译时出错 armv5te指令集不兼容,使用arm-none-gnueabi-4.7.3编译顺利通过。
  
  修改 configs/at91sam9g25jzq.h 里的宏定义为“CONFIG_SYS_TEXT_BASE 0x22000000”
  使程序编译后的运行地址为22000000开始,将nand中拷贝出的程序放到该地址后,直接跳转执行。
  发现源码做的太好了,直接就跑起来了!
---------------------------------------------------------------------------------------------- 
4 启动分析一
  arch/arm/lib/vectors.S    //中断向量表,跳转到 reset,即:
  arch/arm/cpu/arm926ejs/start.S //这里如果没有分两级引导的话,这里需要进行一些必要的初始化操作
    //如关闭内部看门狗,初始化系统时钟,初始化ddr2内存,从nand中拷贝程序到内存中等操作。
    //由于我们是二级启动uboot,以上这些已经被1级引导程序完成,因此 通过宏CONFIG_SKIP_LOWLEVEL_INIT
    //直接跳过这些过程直接调用 _main
  arch/arm/lib/crt0.S  // _main在该文件中定义
    //初始化sp为 CONFIG_SYS_INIT_SP_ADDR = 0x20000000 + 4096 - GENERATED_GBL_DATA_SIZE
    //sub sp, sp, #GD_SIZE   ,接着在sp上方又分配出 GD_SIZE大小的内存
    //mov r9, sp,此时r9保存的就是GD_SIZE大小的内存的起始地址,也可以认为是某个全局变量结构体的指针
    //调用 board_init_f,根据配置头文件中的宏 CONFIG_SYS_GENERIC_BOARD,common/board_f.c被编译
    #define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r9")
  common/board_f.c  //如果没有该宏,arm/lib/board.c会被编译,该文件以后会被踢出源码,尽量不要链接它
    bl board_init_f //板初始化,完成什么操作呢?
---------------------------------------------------------------------------------------------- 
5 启动分析二
  board_init_f
    gd = &data; // gd全局数据指针指向在堆栈里定义的结构体,这里不使用上一步在堆栈外分配的内存
                // 为什么?以后再分析
    initcall_run_list(init_sequence_f) //调用init_sequence_f数组中的全部函数
setup_mon_len,     //填充 gd->mon_len 程序长度
setup_fdt,         //填充 gd->fdt_blob = 0
trace_early_init,  //空
arch_cpu_init,     //调用at91_clock_init,填充gd->arch 时钟相关数据
mark_bootstage,    //"board_init_f"字符串放入record[]数组记录表中
timer_init,        //初始化pit,填充gd->arch.timer_rate_hz gd->arch.tbu = gd->arch.tbl = 0
env_init,          //根据配置文件中宏 CONFIG_ENV_IS_IN_NAND, env_nand.c被编译连接
                  //env_init被调用,填充gd->env_addr环境变量存放地址
                  //填充gd->env_valid环境变量有效标识
init_baud_rate,   //填充gd->baudrate
serial_init, /* serial communications setup */
console_init_f,    //填充gd->have_console = 1,初始化print缓冲,从此可以使用printf打印功能
display_options,   //console中打印 uboot版本信息与编译日期
display_text_info, /* show debugging info if required */
print_cpuinfo,     //打印处理器型号,主时钟,系统时钟,外设时钟
announce_dram_init,//puts("DRAM:  ");
dram_init,         //填充gd->ram_size = 0x4000000
setup_dest_addr,   //填充gd->relocaddr = gd->ram_top = 0x24000000
reserve_round_4k,  //4k对齐gd->relocaddr &= ~(4096 - 1);
reserve_trace,     //null
reserve_uboot,     //gd->relocaddr -= gd->mon_len;留出uboot的代码空间 
                      //gd->relocaddr &= ~(4096 - 1);4K对齐 
                      //gd->start_addr_sp = gd->relocaddr;堆栈空间
setup_machine,     //gd->bd->bi_arch_number = CONFIG_MACH_TYPE 设置板号
reserve_global_data,//gd->start_addr_sp -= sizeof(gd_t);堆栈下移,分配空间gd_t
                  //gd->new_gd = gd->start_addr_sp 指向新分配的内存地址
reserve_fdt,       //gd->start_addr_sp -= gd->fdt_size; 为fdt分配内存空间
                  //gd->new_fdt = gd->start_addr_sp 指向新分配的fdt内存空间
reserve_stacks,    //2字节对齐,为IRQ中断分配内存
setup_dram_config, //null
show_dram_config,  //打印出dram的大小
display_new_sp,    //调试时打印 gd->start_addr_sp
reloc_fdt,         //重定位fdt,进行数据拷贝
setup_reloc,       //gd->reloc_off = gd->relocaddr - 0x22000000;
                  //memcpy(gd->new_gd, (char *)gd, sizeof(gd_t)); 将gd内的数据拷贝到新的地址
  
---------------------------------------------------------------------------------------------- 
6 启动分析三
  在调用board_init_f()完成板卡与全局结构体变量 gd 的初始化后将其拷贝到在代码段下重新分配的全局结构
  体中。接下来进行sp的重新设置,将r9指向重新分配的全局变量gd,然后进行代码的重定位。
    ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
    bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
    ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
    sub r9, r9, #GD_SIZE
    
  修改代码返回值,使其值为重定位后的地址
    adr lr, here
    ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
    add lr, lr, r0
    ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
  拷贝代码到重定位的地址空间去
    b relocate_code 
  arch/arm/lib/relocate.S
  将链接脚本中代码段从 __image_copy_start 到 __image_copy_end之间的 代码段、数据段和命令行段
  拷贝到重定位的地址 gd->relocaddr 处
  拷贝完成后,还需要将从 __rel_dyn_start到 __rel_dyn_end之间的 .rel.dyn段(代码重定位时使用,默认应该
  是由编译器产生的相关寻址相关的数据)
  完成代码的重定义后,返回到重定位后的代码中
  bl c_runtime_cpu_setup //arch/arm/cpu/arm926ejs/start.S 无其它需要初始化的操作,直接返回
  接下来初始化bss段
  接下来调用board_init_r函数
    mov r0, r9 //将重定位后新的gd指针作为参数0传入函数
    ldr r1, [r9, #GD_RELOCADDR] //重定位后代码段的起始地址作为参数1传入函数
    ldr pc, =board_init_r //绝对地址跳转,由于代码重定位后,同时根据重定位后相对于之前程序的偏移值
    对程序的运行地址进行了修正,从而保证重定位后,通过绝对地址跳转时的正确运行。
---------------------------------------------------------------------------------------------- 
7 启动分析四
  board_init_r
    initcall_run_list(init_sequence_r) //循环调用结构体 init_sequence_r 中的全部函数
  initr_caches //打开处理器的数据和指令cache,需要自己添加
  board_init //与具体的板卡相关的外设的初始化,以及gd->bd相关的元素进行初始设置,需要移植修改
  initr_serial //再次初始化串口
  initr_malloc //初始化分配的堆空间内存,
  bootstage_relocate //启动阶段重定位,干嘛的 未知
  power_init_board //空,如果需要自定义相关操作
  initr_flash // nor flash的初始化,如果板上没有Nor flash需要配置宏 CONFIG_SYS_NO_FLASH
  initr_nand //nand flash的初始化,需要配置宏 CONFIG_CMD_NAND
  initr_env //初始化环境变量
    set_default_env() //如果从flash中没有读到环境变量则使用默认的的环境变量default_environment
      "bootargs=" CONFIG_BOOTARGS "\0"
      "bootcmd=" CONFIG_BOOTCOMMAND "\0"
      "nfsboot=" CONFIG_NFSBOOTCOMMAND "\0"
      "bootdelay=" __stringify(CONFIG_BOOTDELAY) "\0"
      "baudrate=" __stringify(CONFIG_BAUDRATE) "\0"
      "ethaddr=" __stringify(CONFIG_ETHADDR) "\0"
      "ipaddr=" __stringify(CONFIG_IPADDR) "\0"
      "serverip=" __stringify(CONFIG_SERVERIP) "\0"
      "gatewayip=" __stringify(CONFIG_GATEWAYIP) "\0"
      "netmask=" __stringify(CONFIG_NETMASK) "\0"
    
  initr_secondary_cpu //空,__weak标记的虚弱函数,如果编译的程序里有相同函数名的函数则用它代替自己
  stdio_init //标准输入输出初始化
  initr_jumptable //初始化跳转表,干嘛的 未知
  console_init_r //控制命令行相关的初始化操作,不需要移植,不用关心它。
  interrupt_init //中断初始化,不关心中断,能引导linux内核就行了,
  initr_ethaddr  //初始化网卡地址,需要配置宏 CONFIG_CMD_NET
  initr_net      //初始化网卡,需要配置宏 CONFIG_CMD_NET
  run_main_loop  //主循环,死循环中运行main_loop,去解析用户输入的命令行,或系统自动运行的命令
    main_loop
---------------------------------------------------------------------------------------------- 
8 启动分析五
  由于在9g25处理器的引导过程中,在uboot之前有一个初始的引导程序,该程序完成了 中断向量表的初始化
  fiq irq的中断场景记录和sp的设置,ddr内存初始化,系统时钟工作在399Mhz,外设时钟工作在133Mhz,调试
  串口bps为115200,然后将nand的0x40000开始的0x80000(512k)长的数据拷贝到ddr内存0x23000000处,然后
  通过ldr pc,=0x23000000 绝对地址跳转到23000000地址运行拷贝到些处的uboot程序.
  
  由于在uboot中会执行一些关于协处理的操作(MMU、Icache、Dcache)指令MRC(读协处理器),MCR(写协处理器),
  这两条指令必须在特权模式下执行,因此在跳转到uboot前先让处理器工作在svc管理模式,否则在执行到这
  样的命令时会触发 未定义 指令的中断。
  打补丁测试
  tar xjf u-boot-2014.07.tar.bz2 
  cd u-boot-2014.07/
  patch -p1 < ../moveto9g25-2015.08.25-ok.patch 
  make at91sam9g25jzq_nandflash_config
  make
  make u-boot.dis
  
  nfs 22000000 192.168.0.1:/home/terminal/workspace/nfs/image/uImage_1
  
  











版权声明:本文为博主原创文章,未经博主允许不得转载。

at91sam9g25处理器uboot移植 个人笔记一

标签:arm   c   u-boot   移植   

原文地址:http://blog.csdn.net/zhaigch/article/details/47980465

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!