免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2185 | 回复: 2

[BootLoader] 求助: 关于S3C2440启动代码的问题。 [复制链接]

论坛徽章:
0
发表于 2013-10-21 17:33 |显示全部楼层
本帖最后由 lilinly225 于 2013-10-21 18:00 编辑

      目前正在Windows下学习ARM, 用的开发工具是MDK, 没有用Linux下的交叉编译链工具。现在我在学习启动代码相关的内容。
环境为:裸机,没有操作系统和bootloader。

在我看到的的一个代码中有一段关于入口的代码感觉很诡异,不知道怎么理解。
  1. ;定义arm汇编程序段,段名叫init段,为只读段
  2.         AREA    RESET,CODE,READONLY
  3. ;        ENTRY
  4.         EXPORT        __ENTRY     ;导出__ENTRY标号
  5. __ENTRY
  6. ResetEntry
  7.         ;1)The code, which converts to Big-endian, should be in little endian code.
  8.         ;2)The following little endian code will be compiled in Big-Endian mode.
  9.         ;  The code byte order should be changed as the memory bus width.
  10.         ;3)The pseudo instruction,DCD can not be used here because the linker generates error.
  11.        
  12.         ;判断模式改变是否定义过(ASSERT是伪指令,:DEF:lable判断lable是否定义过了)
  13.         ASSERT        :DEF:ENDIAN_CHANGE
  14.         [ ENDIAN_CHANGE                                                ;如果ENDIAN_CHANGE为真,则执行以下
  15.             ASSERT  :DEF:ENTRY_BUS_WIDTH    ;判断是否定义了总线宽度
  16.             [ ENTRY_BUS_WIDTH=32            ;如果存储器是32位的总线宽度
  17.                 b        ChangeBigEndian                 ;DCD 0xea000007
  18.             ]

  19.             [ ENTRY_BUS_WIDTH=16            ;如果存储器是16位的总线宽度
  20.                 andeq        r14,r7,r0,lsl #20           ;DCD 0x0007ea00
  21.             ]

  22.             [ ENTRY_BUS_WIDTH=8             ;如果是存储器是8位总线宽度
  23.                 streq        r0,[r0,-r10,ror #1]     ;DCD 0x070000ea
  24.             ]
  25.         |                                   ;如果总线宽度没有定义的话,就直接跳转到复位中断
  26.             b        ResetHandler                ;程序执行的地跳跳转指令;正常模式下第一条语句就是这条语句
  27.     ]
  28.         b        HandlerUndef                          ;handler for Undefined mode
  29.         b        HandlerSWI                            ;handler for SWI interrupt
  30.         b        HandlerPabort                        ;handler for PAbort
  31.         b        HandlerDabort                        ;handler for DAbort
  32.         b        .                                        ;reserved
  33.         b        HandlerIRQ                            ;handler for IRQ interrupt
  34.         b        HandlerFIQ                            ;handler for FIQ interrupt
  35. ;@0x20
  36.         b        EnterPWDN            ; Must be @0x20.  ;进入powerdown模式
复制代码
按照ARM开发者指南的说法: ENTRY 伪指令表示程序代码的最开始地方(相当于C语言中的main函数,表示程序的入口); 但是这段代码将ENTRY给注释掉
以一个__ENTRY的标识符替代了,并且将这个符号给导出了。

   然后我搜索整个工程只在 mmu.c(MMU.c 文件为MMU功能的文件)发现了下面一句:
  1. extern char __ENTRY[];        //hzh
复制代码
很显然,这里只是声明了一个外部变量。
   后面这个变量名符号 __ENTRY 被用来建立MMU转换页表的时候用了一下。
  1.   //MMU_SetMTT(int vaddrStart,int vaddrEnd,int paddrStart,int attr)
  2.     //MMU_SetMTT(0x00000000,0x07f00000,0x00000000,RW_CNB);  //bank0
  3.                           //虚拟地址   虚拟地址结束           物理地址                 映射区间属性
  4.     MMU_SetMTT(0x00000000,0x03f00000,     (int)__ENTRY,  RW_CB);  //bank0, hzh
复制代码
然后就没有在任何地方用过了。
  而MMU初始化是在 C语言代码的main函数中开始的,也就是说汇编代码的起始点运行的时候,MMU不可能运行,我的理解就是这个设置虚拟地址映射的
过程不可能与汇编代码的起始位置有关。
  1. int main(void)
  2. {       
  3.     rGPBDAT = 0x1e0;                   //关LED
  4.     rGPBCON  =0x00015400;           //设置GPB5~8为输出
  5.     rGPBUP   =0x3ff;                   //禁止上拉
  6.         LCD_Init();
  7.         Brush_Background(0xffff);
  8.         Paint_Bmp(0,0,240,320,gImage_fhand);
  9.     MMU_Init();
  10.     KeyScan_Test()        ;
复制代码
这里还有一个信息是:
              上面那个汇编代码段定义是第一个代码段定义 ,这个代码段前面有两个数据段。

  我想问的的是:
            是不是汇编文件的第一个代码段默认的地址就是为0x00000000,是否是链接到代码段的0x00000000???
否则为什么不需要  ENTRY 宏汇编 伪指令。
      
    在ARM DUI 0204IC Real View 4.0版汇编器指南的7-69页中,明确的表示一个程序至少需要一个 ENTRY 入口的。
但是上面的代码没有也可以运行。


下面为整个汇编代码到 __ENTEY 之间的汇编代码。
  1. ;=========================================
  2. ; NAME: 2440INIT.S
  3. ; DESC: C start up codes
  4. ;       Configure memory, ISR ,stacks
  5. ;        Initialize C-variables
  6. ; HISTORY:
  7. ; 2002.02.25:kwtark: ver 0.0
  8. ; 2002.03.20:purnnamu: Add some functions for testing STOP,Sleep mode
  9. ; 2003.03.14:DonGo: Modified for 2440.
  10. ;=========================================
  11.         GET option.inc
  12.         GET memcfg.inc
  13.         GET 2440addr.inc

  14. BIT_SELFREFRESH EQU        (1<<22)


  15. ;Pre-defined constants
  16. USERMODE    EQU         0x10        ;用户模式
  17. FIQMODE     EQU         0x11        ;快速中断模式
  18. IRQMODE     EQU         0x12    ;中断模式
  19. SVCMODE     EQU         0x13    ;
  20. ABORTMODE   EQU         0x17    ;
  21. UNDEFMODE   EQU         0x1b        ; 未定义模式
  22. MODEMASK    EQU         0x1f        ; 模式掩码
  23. NOINT       EQU         0xc0    ;

  24. ;定义GPB口的,寻址地址
  25. GPBCON      EQU     0x56000010
  26. GPBDAT            EQU     0x56000014

  27. ;各个异常模式的堆栈
  28. UserStack        EQU        (_STACK_BASEADDRESS-0x3800)        ;0x33ff4800 ~   
  29. SVCStack        EQU        (_STACK_BASEADDRESS-0x2800)        ;0x33ff5800 ~
  30. UndefStack        EQU        (_STACK_BASEADDRESS-0x2400)        ;0x33ff5c00 ~
  31. AbortStack        EQU        (_STACK_BASEADDRESS-0x2000)        ;0x33ff6000 ~
  32. IRQStack        EQU        (_STACK_BASEADDRESS-0x1000)        ;0x33ff7000 ~
  33. FIQStack        EQU        (_STACK_BASEADDRESS-0x0)        ;0x33ff8000 ~  堆栈的顶部



  34. ;------------------------------------------------------------------------------
  35. UND_Stack_Size  EQU     0x00000400   ;
  36. SVC_Stack_Size  EQU     0x00000400
  37. ABT_Stack_Size  EQU     0x00000400
  38. FIQ_Stack_Size  EQU     0x00000400
  39. IRQ_Stack_Size  EQU     0x00000400
  40. USR_Stack_Size  EQU     0x00004000

  41. ;堆栈的总大小为        0x5400 个字节 = 21504 字节
  42. Stack_Size      EQU     (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
  43.                          FIQ_Stack_Size + IRQ_Stack_Size + USR_Stack_Size)

  44.                 AREA    STACK, NOINIT, READWRITE, ALIGN=3

  45. Stack_Mem       SPACE   Stack_Size                 
  46. Stack_Top       EQU     Stack_Mem + Stack_Size
  47. Heap_Size       EQU     0x00000000

  48.                 AREA    HEAP, NOINIT, READWRITE, ALIGN=3
  49. Heap_Mem        SPACE   Heap_Size

  50. ;-------------------------------------------------------------------------------
  51. ;这一段是统一arm的工作状态和对应的软件编译方式(16位编译环境使用tasm.exe编译)。
  52. ;arm处理器的工作状态分为两种:32位,arm执行字对齐的arm指令集;16位,arm执行半字
  53. ;对齐的Thumb指令集。不同的工作状态,编译方式也不一样。所以下面的程序就是判断
  54. ;arm的工作方式来确定它的编译方式。
  55. ;Check if tasm.exe(armasm -16 ...@ADS 1.0) is used.
  56.         GBLL    THUMBCODE ;定义THUMBCODE 这个变量GBLL 声明一个全局逻辑变量并初始化为{FALSE}
  57.         [ {CONFIG} = 16   ;"["表示"if","|"表示"else","]"表示"endif",对于CONFIG是在ADS编译中定义的内部变量。
  58. THUMBCODE SETL  {TRUE}
  59.             CODE32
  60.                 |
  61. THUMBCODE SETL  {FALSE}
  62.     ]                  ;如果ARM是在16位的工作状态的话,就使全局变量THUMBCODE设置为ture。

  63.                 MACRO          ;这个是宏定义的关键字
  64.         MOV_PC_LR          ;作用是子程序返回
  65.                 [ THUMBCODE    ;当目标程序是Thumb时,就要使用BX跳转返回,并转换模式。
  66.             bx lr         
  67.                 |
  68. ;            mov        pc,lr      ;目标程序是ARM指令集,直接把lr赋给pc就可以了。
  69.                 bx lr
  70.                 ]
  71.         MEND               ;宏定义的结束标志。

  72.                 MACRO
  73.         MOVEQ_PC_LR        ;这个是带“相等”条件的子程序返回。和上面说的类似。
  74.                 [ THUMBCODE
  75.         bxeq lr
  76.                 |
  77.             moveq pc,lr
  78.                 ]
  79.         MEND

  80. ;//////////////////////////////////////////////////////////////////////////

  81.                 MACRO          ;这个地方定义一个宏处理器,HANDLER 为宏标识符
  82. $HandlerLabel HANDLER $HandleLabel
  83. $HandlerLabel
  84.         sub        sp,sp,#4                   
  85.         stmfd        sp!,{r0}               
  86.         ldr     r0,=$HandleLabel    ;load the address of HandleXXX to r0
  87.         ldr     r0,[r0]                    ;load the contents(service routine start address) of HandleXXX
  88.         str     r0,[sp,#4]        ;store the contents(ISR) of HandleXXX to stack
  89.         ldmfd   sp!,{r0,pc}       ;POP the work register and pc(jump to ISR)
  90.         MEND


  91. ;编译器使用下列段来记录各段的起始地址和结束地址
  92. ;|Image$RO$Base|(ADS用这种写法), |Image$ER_ROM1$RO$Base|  (MDK用这种写法)  ; RO 段起始地址
  93. ;|Image$RO$Limit|(ADS用这种写法),|Image$ER_ROM1$RO$Limit| (MDK用这种写法)  ;RO 段结束地址加1
  94. ;|Image$RW$Base| (ADS用这种写法),|Image$RW_RAM1$RW$Base|  (MDK用这种写法)  ;RW 段起始地址
  95. ;|Image$RW$Limit| (ADS用这种写法),|Image$RW_RAM1$ZI$Limit|(MDK用这种写法)  ;RW 段结束地址加1
  96. ;|Image$ZI$Base|  (ADS用这种写法),|Image$RW_RAM1$ZI$Base| (MDK用这种写法)  ; ZI 段起始地址
  97. ;|Image$ZI$Limit| (ADS用这种写法),|Image$RW_RAM1$ZI$Limit|(MDK用这种写法)  ; ZI 段结束地址加1

  98.         IMPORT  |Image$ER_ROM1$RO$Base|         ; Base of ROM code
  99.         IMPORT  |Image$ER_ROM1$RO$Limit|  ; End of ROM code (=start of ROM data)
  100.         IMPORT  |Image$RW_RAM1$RW$Base|   ; Base of RAM to initialise
  101.         IMPORT  |Image$RW_RAM1$ZI$Base|   ; Base and limit of area
  102.         IMPORT  |Image$RW_RAM1$ZI$Limit|  ; to zero initialise

  103. ;引入外部变量mmu的快速总线模式和同步总线模式两个变量
  104.         IMPORT        MMU_SetAsyncBusMode
  105.         IMPORT        MMU_SetFastBusMode        ;hzh

  106. ;引入外部标号我们所熟知的main函数
  107.         IMPORT  __main    ; The main entry of mon program
  108.         PRESERVE8
  109.        
  110. ;定义arm汇编程序段,段名叫init段,为只读段
  111.         AREA    RESET,CODE,READONLY
  112. ;        ENTRY
  113.         EXPORT        __ENTRY     ;导出__ENTRY标号
  114. __ENTRY
  115. ResetEntry
  116.         ;1)The code, which converts to Big-endian, should be in little endian code.
  117.         ;2)The following little endian code will be compiled in Big-Endian mode.
  118.         ;  The code byte order should be changed as the memory bus width.
  119.         ;3)The pseudo instruction,DCD can not be used here because the linker generates error.
  120.        
  121.         ;判断模式改变是否定义过(ASSERT是伪指令,:DEF:lable判断lable是否定义过了)
  122.         ASSERT        :DEF:ENDIAN_CHANGE
  123.         [ ENDIAN_CHANGE                                                ;如果ENDIAN_CHANGE为真,则执行以下
  124.             ASSERT  :DEF:ENTRY_BUS_WIDTH    ;判断是否定义了总线宽度
  125.             [ ENTRY_BUS_WIDTH=32            ;如果存储器是32位的总线宽度
  126.                 b        ChangeBigEndian                 ;DCD 0xea000007
  127.             ]

  128.             [ ENTRY_BUS_WIDTH=16            ;如果存储器是16位的总线宽度
  129.                 andeq        r14,r7,r0,lsl #20           ;DCD 0x0007ea00
  130.             ]

  131.             [ ENTRY_BUS_WIDTH=8             ;如果是存储器是8位总线宽度
  132.                 streq        r0,[r0,-r10,ror #1]     ;DCD 0x070000ea
  133.             ]
  134.         |                                   ;如果总线宽度没有定义的话,就直接跳转到复位中断
  135.             b        ResetHandler                ;程序执行的地跳跳转指令;正常模式下第一条语句就是这条语句
  136.     ]
  137.         b        HandlerUndef                          ;handler for Undefined mode
  138.         b        HandlerSWI                            ;handler for SWI interrupt
  139.         b        HandlerPabort                        ;handler for PAbort
  140.         b        HandlerDabort                        ;handler for DAbort
  141.         b        .                                        ;reserved
  142.         b        HandlerIRQ                            ;handler for IRQ interrupt
  143.         b        HandlerFIQ                            ;handler for FIQ interrupt
  144. ;@0x20
  145.         b        EnterPWDN            ; Must be @0x20.  ;进入powerdown模式
复制代码
求各位大神解释一下。  
    另外各位大神,有没有关于MMU和堆栈初始化的相关比较系统的资料,关于裸机设置MMU和堆栈设置的系统的解释的资料, 我搜到的资料都是
一些比较零散的资料,理解起来很难。

论坛徽章:
0
发表于 2013-10-21 23:53 |显示全部楼层
本帖最后由 crifan 于 2013-10-21 23:54 编辑

你问题太多了。
其中很多问题,下面的教程,应该可以帮你解答了:
Uboot中start.S源码的指令级的详尽解析

看完后,还有疑问,再问,我再抽空看看能否帮你解答。

论坛徽章:
0
发表于 2013-12-08 18:57 |显示全部楼层
回复 2# crifan

谢谢先。


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP