zoukankan      html  css  js  c++  java
  • S3C6410之uboot回炉再造(1)start.S SVC模式设置

      虽然已经写了几篇关于uboot移植的、但是觉得整体对uboot的理解还是只停留在copy的层面。

      狠下心来,从代码进行uboot的分析,并从新移植一次uboot。

      这次更侧重于记录代码分析心得。

      使用uboot的版本仍为2010.3版本。

      这里有一个很是详尽的start.S分析网站,分析过程借鉴了网站的方法,但也有一些不同的地方

    http://www.crifan.com/files/doc/docbook/uboot_starts_analysis/release/html/uboot_starts_analysis.html

      总的不同有如下

      在网站的分析中,基于代码为arm920t,即ARM9系列芯片,ARM9系列芯片的初始化过程为:

    1、设置CPU模式
    2、关闭看门狗
    3、关闭中断
    4、设置堆栈sp指针
    5、清除bss段
    6、异常中断处理

      然后我现在选择的修改模板是arm1176,即ARM11系列芯片,ARM11系列芯片的初始化过程为:

    1、设置CPU模式
    // -- 关闭看门狗
    // -- 关闭中断
    2、初始化MMU  // ++
    3、设置堆栈sp指针
    4、清除bss段
    5、异常中断处理

      两种芯片的start.S的区别一目了然。

      接着开始分析代码了。

      一切的开始:start.S  (文件路径为/cpu/arm1176/start.S)

      为了方便跳转阅读,启用行号。

      为避免误导,在此说明:

      此时我使用的是未经修改的uboot2010版本的start.S,在这篇分析中不会对它进行任何修改。

      在随后的blog中才对start.S进行修改并阐述理由,修改处必有类似 git diff 的说明

      1、头文件

     1 /*
     2  * ……
     3  */
     4 
     5 #include <config.h>
     6 #include <version.h>
     7 #ifdef CONFIG_ENABLE_MMU
     8 #include <asm/proc/domain.h>
     9 #endif
    10 #include <asm/arch/s3c6410.h>
    11 
    12 #if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE)
    13 #define CONFIG_SYS_PHY_UBOOT_BASE    CONFIG_SYS_UBOOT_BASE
    14 #endif

      头文件部分不必赘述,但是这里有一个不得不说的地方

    13 #define CONFIG_SYS_PHY_UBOOT_BASE    CONFIG_SYS_UBOOT_BASE

      为了解析这个定义,找到了 /include/configs/smdk6400.h

    /* NAND U-Boot load and start address */
    #define CONFIG_SYS_UBOOT_BASE        (CONFIG_SYS_MAPPED_RAM_BASE + 0x07e00000)

      继续跳转搜索 CONFIG_SYS_MAPPED_RAM_BASE:

    #ifdef CONFIG_ENABLE_MMU
    #define CONFIG_SYS_MAPPED_RAM_BASE    0xc0000000
    #define CONFIG_BOOTCOMMAND    "nand read 0xc0018000 0x60000 0x1c0000;" \
                    "bootm 0xc0018000"
    #else
    #define CONFIG_SYS_MAPPED_RAM_BASE    CONFIG_SYS_SDRAM_BASE
    #define CONFIG_BOOTCOMMAND    "nand read 0x50018000 0x60000 0x1c0000;" \
                    "bootm 0x50018000"
    #endif

      很显然了,在MMU工作的状态下:

    #define CONFIG_SYS_MAPPED_RAM_BASE    0xc0000000

      MMU工作就是开发板播到从NAND flash启动的状态。

      而在MMU未工作的状态下:

    #define CONFIG_SYS_MAPPED_RAM_BASE    CONFIG_SYS_SDRAM_BASE
    ....
    #define CONFIG_SYS_SDRAM_BASE  0x50000000

      从这里,可以理解在使用dnw下载的时候,Download Address为

    #define CONFIG_SYS_UBOOT_BASE        (CONFIG_SYS_MAPPED_RAM_BASE + 0x07e00000)
    // 0x5000000 + 0x07e00000 = 0x57e00000

      uboot是bootloader的一种,要更为准确地描述这两种状态可以说为

      1、启动加载(Boot loading)模式,即自主"(Autonomous)模式;

      2、下载(Downloading)模式。

      更为详细的描述可以参详

    http://blog.csdn.net/r91987/article/details/6695007

      

      接下来进入正文分析了

     1 /*
     2  *************************************************************************
     3  *
     4  * Jump vector table as in table 3.1 in [1]
     5  *
     6  *************************************************************************
     7  */
     8 
     9 .globl _start
    10 _start: b    reset      //跳转到reset处执行,即下一段代码的44行
                      //但此时不必急着看reset的执行代码,可以继续顺序往下
    11 #ifndef CONFIG_NAND_SPL   //定义NAND_SPL时
    12     ldr    pc, _undefined_instruction  //ldr = Load Register 
    13     ldr    pc, _software_interrupt    //软件中断
    14     ldr    pc, _prefetch_abort      //预取指中止
    15     ldr    pc, _data_abort         //数据中止
    16     ldr    pc, _not_used          //保留
    17     ldr    pc, _irq             //IRQ中断
    18     ldr    pc, _fiq             //FIQ中断
    19           //这里的七种异常就是ARM的七种异常处理类型,对应的声明在 20 - 33行
    20 _undefined_instruction:    //.word = 32bit , 这里可以理解为 _undef.. = &undef..
    21     .word undefined_instruction //这里将地址放入 _undef.. ,而_undef的地址又放入pc
    22 _software_interrupt:     //双层取址,所以最终送入pc的数据为 undefined_instruction
    23     .word software_interrupt //以下含义相同
    24 _prefetch_abort:       
    25     .word prefetch_abort   //pc 是 ARM 的指令寄存器
    26 _data_abort:     //将这些异常送入 pc ,意为让 ARM 运行这些指令的初始化代码(后文可见)
    27     .word data_abort
    28 _not_used:
    29     .word not_used
    30 _irq:
    31     .word irq
    32 _fiq:
    33     .word fiq
    34 _pad:
    35     .word 0x12345678 /* now 16*4=64 */
    36 #else
    37     . = _start + 64
    38 #endif
    39 
    40 .global _end_vect
    41 _end_vect:
    42     .balignl 16,0xdeadbeef  // .balignl 为对其指令,意为让以下的代码按16位对其
                       //不足为则补上0xdeadbeef
                       //很有意思的dead beef,为数不多的能用16进制表示的单词

      接下来为正式的启动指令了

    1 /*
     2  *************************************************************************
     3  *
     4  * Startup Code (reset vector)
     5  *
     6  * do important init only if we don't start from memory!
     7  * setup Memory and board specific bits prior to relocation.
     8  * relocate armboot to ram
     9  * setup stack
    10  *
    11  *************************************************************************
    12  */
    13 
    14 _TEXT_BASE:
    15     .word    TEXT_BASE  //这里是 .text 的 base ,即代码段的基址
    16 
    17 /*
    18  * Below variable is very important because we use MMU in U-Boot.
    19  * Without it, we cannot run code correctly before MMU is ON.
    20  * by scsuh.
    21  */
    22 _TEXT_PHY_BASE:      //上面的注释很清晰了
    23     .word    CONFIG_SYS_PHY_UBOOT_BASE
    24 
    25 .globl _armboot_start  //此处声明了 _armboot_start 指向 _start
    26 _armboot_start:      
    27     .word _start
    28 
    29 /*
    30  * These are defined in the board-specific linker script.
    31  */
    32 .globl _bss_start    //此处的标号其实最终指向的是链接脚本文件(.lds)中的定义
    33 _bss_start:
    34     .word __bss_start
    35 
    36 .globl _bss_end     //同上
    37 _bss_end:
    38     .word _end
    39 
    40 /*
    41  * the actual reset code
    42  */
    43 
    44 reset:        //这里就是start之后跳转的地方了
    45     /*
    46      * set the cpu to SVC32 mode
    47      */      //SVC模式也成为管理模式,是操作系统的一种保护模式
    48     mrs    r0, cpsr      //mrs为读寄存器指令 
    49     bic    r0, r0, #0x3f   //清除r0的低7位
    50     orr    r0, r0, #0xd3   //将r0置为0b1101_0011,我们只看低5位
    51     msr    cpsr, r0      //查CPSR处理器模式位知SVC模式位就是0b1_0011

      至此,CPU的SVC模式设置成功了。

      最后补充一个内容,.lds文件是编译脚本文件,展开可以看成ld script。

      这里的 ld 对应于编译器的 arm-linux-ld。

      有关于.lds文件的说明,可以参阅

    http://blog.csdn.net/pottichu/article/details/4261289

      在后面的篇幅中,也会涉及.lds文件的修改。

     

  • 相关阅读:
    Java学习笔记
    Winform中ListView设置了ColumnHeader不显示问题
    GitHub私有仓库为他人授权
    (转)一步一步教你如何在GitHub上上传自己的项目
    【转】C#中的Explicit和Implicit
    C#对象深表复制方法
    mongodb 设置 ssl
    zabbix 4.0.1部署
    redis编译安装
    VMware网络连接模式——桥接模式、NAT模式以及仅主机模式的介绍和区别
  • 原文地址:https://www.cnblogs.com/plinx/p/3032883.html
Copyright © 2011-2022 走看看