本次移植u-boot-2010.09是基于S3C2440的FL440板子,板子自带NANDFLASH而没有NORFLASH,所以在U-BOOT启动的过程中必须实现从NANDFLASH到SDRAM的重定向。

其中最重要的就是在U-BOOT开始的start.S汇编代码,这段代码要完成工作:

1,异常中断向量表,复位后异常向量处理

2, 跳转到代码实际执行处start_code

3,关闭看门狗WATCHDOG

3,关闭所有中断INTERRUPT

4,设置时钟分频,主要设置寄存器CLKDVN,MPLLCON,UPLLCON

5,关闭MMU和CACHE,并调用lowlevel_init.S完成SDRAM和NANDFLASH的初始化,为代码的重定向做准备

6,设置堆栈,并且跳入第二阶段的C代码

7,异常向量处理代码

以下为start.S的分析:

1,异常中断向量表,复位后异常向量处理

  1. //声明一个全局标量,在cpu/arm920t/u-boot.lds中有定义,即代码的入口地址,也是编译地址
  2. _start: b start_code
  3. ldr pc, _undefined_instruction
  4. ldr pc, _software_interrupt
  5. ldr pc, _prefetch_abort
  6. ldr pc, _data_abort
  7. ldr pc, _not_used
  8. ldr pc, _irq
  9. ldr pc, _fiq
  10.  
  11. _undefined_instruction: .word undefined_instruction //.word 定义一个32位的地址标识
  12. _software_interrupt: .word software_interrupt
  13. _prefetch_abort: .word prefetch_abort
  14. _data_abort: .word data_abort
  15. _not_used: .word not_used
  16. _irq: .word irq
  17. _fiq: .word fiq
  18.  
  19. .balignl 16,0xdeadbeef//将地址偏移为16的整数倍,空余的内容填上0xdeadbeef,这个数即“Magic Number”,可用判断当前u-boot执行位置
  20.  
  21. _TEXT_BASE:
  22. .word TEXT_BASE //在config.mk中有定义,即u-boot自启时flash从定向到sdram的地址
  23. .globl _armboot_start //声明一个全局变量,之后要调用
  24. _armboot_start:
  25. .word _start
  26.  
  27. /*
  28. * These are defined in the board-specific linker script.
  29. */
  30.  
  31. .globl _bss_start //连接脚本u-boot.lds中有定义
  32. _bss_start:
  33. .word __bss_start
  34.  
  35. .globl _bss_end //连接脚本u-boot.lds中有定义</span>
  36. _bss_end:
  37. .word _end
  38.  
  39. #ifdef CONFIG_USE_IRQ //堆栈设置
  40. /* IRQ stack memory (calculated at run-time) */
  41.  
  42. .globl IRQ_STACK_START
  43. IRQ_STACK_START:
  44. .word 0x0badc0de
  45.  
  46. /* IRQ stack memory (calculated at run-time) */
  47.  
  48. .globl FIQ_STACK_START
  49. FIQ_STACK_START:
  50. .word 0x0badc0de
  51.  
  52. #endif
  1.  

2, 跳转到代码实际执行处(设置管理模式=>关闭看门狗=>关闭所有中断=>设置时钟分频)

  1. /*
  2. * the actual start code
  3. */
  4.  
  5. start_code:
  6. /*
  7. * set the cpu to SVC32 mode
  8. */
  9. //设置管理模式 31 30 29 28 7 6 4 3 2 1 0
  10. mrs r0, cpsr // CPSR N Z C V I F M4 M3 M2 M1 M0
  11. bic r0, r0, #0x1f // 1 0 0 1 1
  12. orr r0, r0, #0xd3
  13. msr cpsr, r0 // CPSR为状态寄存器,用于设置系统运行状态,只能用MSR MRS指令
  14.  
  15. #if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) //系统中断重定向于RAM中,以便快速响应中断,搬运的代码为4*16bytes
  16. /* relocate exception table */
  17. ldr r0, =_start
  18. ldr r1, =0x0
  19. mov r2, #16
  20. copyex:
  21. subs r2, r2, #1
  22. ldr r3, [r0], #4
  23. str r3, [r1], #4
  24. bne copyex
  25. #endif
  26.  
  27. //关闭看门狗
  28. #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
  29. /* turn off the watchdog */
  30.  
  31. #if defined(CONFIG_S3C2400)
  32. #define pWTCON 0x15300000
  33. #define INTMSK 0x14400008 /* Interupt-Controller base addresses */
  34. #define CLKDIVN 0x14800014 /* clock divisor register */
  35. #else //查阅s3c2440的datesheet中指出寄存器地址
  36. #define pWTCON 0x53000000
  37. #define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
  38. #define INTSUBMSK 0x4A00001C
  39. #define CLKDIVN 0x4C000014 /* clock divisor register */
  40. #endif
  41.  
  42. #define CLK_CTL_BASE 0x4C000000 //添加时钟分频寄存器地址,用于时钟分频设置
  43. #define MDIV_405 0x7f<<12
  44. #define PSDIV_405 0x21
  45. #define MDIV_200 0xa1<<12
  46. #define PSDIV_200 0x31 </span>
  47. ldr r0, =pWTCON
  48. mov r1, #0x0
  49. str r1, [r0] /* mask all IRQs by setting all bits in the INTMR - default */
  50. mov r1, #0xffffffff //ARM920T有32个中断源,禁止所有中断,32位中断屏蔽寄存器置位
  51. ldr r0, =INTMSK
  52. str r1, [r0]
  53. #if defined(CONFIG_S3C2440)||defined(CONFIG_S3C2410) /* add by zhou */
  54. ldr r1, =0x7ff<span style="white-space:pre"> //屏蔽所有的中断源,S3C2440中寄存器只有前15位有效,故0x7ff置位INTSUNMSK
  55. ldr r0, =INTSUBMSK
  56. str r1, [r0]
  57. #endif
  58. //设置时钟频率
  59. #if defined(CONFIG_S3C2440)
  60. mov r1, #5
  61. str r1, [r0]
  62.  
  63. mrc p15, 0, r1, c1, c0, 0
  64. orr r1, r1, #0xc0000000
  65. mcr p15, 0, r1, c1, c0, 0
  66.  
  67. mov r1, #CLK_CTL_BASE //S3C2440系统主频为405MHZ,USB为48MHZ,要求MPLLCON = (0x7f<<12) | (0x02<<4) | (0x01) = 0x7f021
  68. mov r2, #MDIV_405
  69. add r2, r2, #PSDIV_405
  70. str r2, [r1, #0x04]
  71. #else
  72.  
  73. /* FCLK:HCLK:PCLK = 1:2:4 */
  74. /* default FCLK is 120 MHz ! */
  75. ldr r0, =CLKDIVN
  76. mov r1, #3
  77. str r1, [r0]
  78.  
  79. mrc p15, 0, r1, c1, c0, 0
  80. orr r1, r1, #0xc0000000
  81. mcr p15, 0, r1, c1, c0, 0
  82.  
  83. mov r1, #CLK_CTL_BASE
  84. mov r2, #MDIV_200
  85. add r2, r2,#PSDIV_200
  86. str r2, [r1,#0x04]
  87.  
  88. #endif
  89. #endif /* (CONFIG_S3C2400) || (CONFIG_S3C2410) || (CONFIG_S3C2440) */





3,关闭MMU和CACHE,并调用lowlevel_init.S完成SDRAM和NANDFLASH的初始化,为代码的重定向做准备

  1. /*******************************************
  2. * we do sys-critical inits only at reboot,
  3. * not when booting from ram!
  4. ******************************************/
  5.  
  6. #ifndef CONFIG_SKIP_LOWLEVEL_INIT
  7. bl cpu_init_crit //关闭MMU和CACHE,并调用lowlevel_init.S完成SDRAM和NANDFLASH的初始化
  8. #endif
  9. ...........
  10. ...........
  11. ...........
  12. /*
  13. *************************************************************************
  14. *
  15. * CPU_init_critical registers
  16. *
  17. * setup important registers
  18. * setup memory timing
  19. *
  20. *************************************************************************
  21. */
  22.  
  23. #ifndef CONFIG_SKIP_LOWLEVEL_INIT
  24. cpu_init_crit:
  25. /*
  26. * flush v4 I/D caches
  27. */
  28. mov r0, #0 //具体设置看下图,详细参考CP15指令:http://blog.csdn.net/gooogleman/article/details/3635238
  29. mcr p15, 0, r0, c7, c7, 0 //向c7写入0将使ICache与DCache 无效flush v3/v4 cache
  30. mcr p15, 0, r0, c8, c7, 0 //向c8写入0将使TLB失效 flush v4 TLB
  31.  
  32. /*
  33. * disable MMU stuff and caches <span style="color:#ff0000;"> //协处理器CP15的C1处理器可以设置MMU和caches,具体参考下图
  34. */
  35. mrc p15, 0, r0, c1, c0, 0
  36. bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
  37. bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
  38. orr r0, r0, #0x00000002 @ set bit 2 (A) Align
  39. orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
  40. mcr p15, 0, r0, c1, c0, 0
  41.  
  42. /*
  43. * before relocating, we have to setup RAM timing
  44. * because memory timing is board-dependend, you will
  45. * find a lowlevel_init.S in your board directory.
  46. */
  47. mov ip, lr //由于有两层调用,需要把lr保存到ip,以防止破坏
  48.  
  49. bl lowlevel_init //调用c函数,初始化FLASH和SDRAM,为代码重定向做准备
  50.  
  51. mov lr, ip
  52. mov pc, lr //返回
  53. #endif /* CONFIG_SKIP_LOWLEVEL_INIT */

代码重定向基本思路:

1.内存运行与否,是则设置堆栈,跳入c函数阶段

2.若不在内存运行,判断是在norflash还在nandflash运行

  1. //代码重定向部分
  2. /***************CHECK_CODE_POSITION******************************/
  3.  
  4. adr r0, _start /* r0 <- current position of code */ //检查代码是否在已经SDRAM中运行,是则设置堆栈,并跳入c代码部分
  5. ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ //_start为u-boot的真正运行地址,_TEXT_BASE为FLASH加载到SDRAM的地址,在config.mk中定义为0x33f80000
  6. cmp r0, r1 /* don't reloc during debug */ //若相等,说明已经在SDRAM中运行,设置堆栈,并且调转到第二阶段的C函数
  7. beq stack_setup //若不相等,则要判断是从NORFLASF或NANDFLASH启动
  8.  
  9. /***************CHECK_CODE_POSITION******************************/
  10.  
  11. /***************CHECK_BOOT_FLASH********************************/
  12.  
  13. ldr r1, =((4<<28)|(3<<4)|(3<<2)) /*address in 4000003c*/
  14. mov r0, #0 //NANDFLASH的启动原理,启动时4K SRAM,即Stepping Stone,会映射到nGCS0,0x0000 0000地址,同时它还是会被映射到0x4000 0000地址
  15. str r0,[r1] //而NORFLASH支持片上运行,并会被一直挂载到nGCS0,0x0000 0000,具体可以参照NANDFLASH启动原理
  16.  
  17. mov r1, #0x3c /*address in 0x3c*/ //NANDFLASH启动时,因为地址为16倍数对齐,此时0x0000 003c 和 0x4000 003c都为唯一确定的0xdeadbeef,即"Magic Mumber"
  18. ldr r0, [r1] //当0x4000 003c清零,若0x0000 003c读出也是零,则u-boot代码从NANDFLASH启动,否则从NORFLASH
  19. cmp r0, #0
  20. bne relocate
  21.  
  22. /*recover 0x4000003c */
  23. ldr r0, =(0xdeadbeef) //若在NANDFLASH启动,必须保证代码和前4K拷贝到SRAM一致,否则会进入死循环
  24. ldr r1, =((4<<28)|(3<<4)|(3<<2))
  25. str r0, [r1]
  26.  
  27. /***************CHECK_BOOT_FLASH********************************/
  28.  
  29. /***************NAND_BOOT********************************/
  30.  
  31. #ifdef CONFIG_S3C2440 //支持S3C2440的NANDFLASH
  32. #define LENGTH_UBOOT 0x60000
  33. #define NAND_CTL_BASE 0x4E000000
  34.  
  35. /* Offset */
  36. #define oNFCONF 0x00
  37. #define oNFCONT 0x04
  38. #define oNFCMD 0x08
  39. #define oNFSTAT 0x20
  40.  
  41. mov r1, #NAND_CTL_BASE //NAND Flash配置寄存器设置
  42. ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
  43. str r2, [r1, #oNFCONF]
  44. ldr r2, [r1, #oNFCONF]
  45.  
  46. ldr r2, =( (1<<4)|(0<<1)|(1<<0) ) /* @ Active low CE Control */
  47. str r2, [r1, #oNFCONT] //NAND Flash控制寄存器设置
  48. ldr r2, [r1, #oNFCONT]
  49.  
  50. ldr r2, =(0x6) /* @ RnB Clear */ //NAND Flash状态寄存器设置
  51. str r2, [r1, #oNFSTAT]
  52. ldr r2, [r1, #oNFSTAT]
  53.  
  54. mov r2, #0xff //NAND Flash命令寄存器设置
  55. strb r2, [r1, #oNFCMD]
  56. mov r3, #0
  57.  
  58. nand1:
  59. add r3, r3, #0x1
  60. cmp r3, #0xa
  61. blt nand1
  62.  
  63. nand2:
  64. ldr r2, [r1, #oNFSTAT]
  65. tst r2, #0x4
  66. beq nand2
  67. ldr r2, [r1, #oNFCONT]
  68. orr r2, r2, #0x2
  69. str r2, [r1, #oNFCONT]
  70.  
  71. /* get read to call C functions (for nand_read()) */
  72. ldr sp, DW_STACK_START
  73. mov fp, #0
  74.  
  75. /* copy U-Boot to RAM */
  76. ldr r0, =TEXT_BASE //汇编调用c函数nand_read_ll,第一个参数存于r0搬运到内存地址
  77. mov r1, #0x0 //第二个参数存于r1,NANDFLASH中u-boot地址
  78. mov r2, #LENGTH_UBOOT /第三个参数存于r2,u-boot的总大小
  79. bl nand_read_ll //在nand_read.c定义,支持不同NANDFLASH芯片代码拷贝
  80. tst r0, #0x0 //r0是存放函数返回的参数,返回值为0则正确拷贝,否则进入死循环
  81. beq ok_nand_read
  82.  
  83. bad_nand_read:
  84. loop2:
  85. b loop2
  86. ok_nand_read: //前4K代码比较,即判定Stepping Stone中4k代码和c函数搬运的代码是否一致
  87. mov r0, #0
  88. ldr r1, =TEXT_BASE
  89. mov r2, #0x400 /* 4 bytes * 1024 = 4Kbytes */
  90. go_next:
  91. ldr r3, [r0], #4 //r3存放NANDFLASH上u-boot的代码
  92. ldr r4, [r1], #4 //r4为在内存中的u-boot代码
  93. teq r3, r4
  94. bne notmatch //不一致则进入死循环
  95. subs r2, r2, #4
  96. beq stack_setup
  97. bne go_next
  98.  
  99. notmatch:
  100. loop3:
  101. b loop3
  102. #endif
  103.  
  104. #ifdef CONFIG_S3C2410
  105. /* Offset */
  106. #define oNFCONF 0x00
  107. #define oNFCMD 0x04
  108. #define oNFSTAT 0x10
  109.  
  110. mov r1, #NAND_CTL_BASE
  111. ldr r2, =0xf830
  112. str r2, [r1, #oNFCONF]
  113. ldr r2, [r1, #oNFCONF]
  114. bic r2, r2, #0x800 /* enable chip */
  115. str r2, [r1, #oNFCONF]
  116. mov r2, #0xff /* @ RESET command + strb r2, [r1, #oNFCMD] */
  117. strb r2, [r1, #oNFCMD]
  118. mov r3, #0
  119.  
  120. nand1:
  121. add r3, r3, #0x1
  122. cmp r3, #0xa
  123. blt nand1
  124.  
  125. nand2:
  126. ldr r2, [r1, #oNFSTAT] /* @ wait ready */
  127. tst r2, #0x1
  128. beq nand2
  129.  
  130. ldr r2, [r1, #oNFCONF]
  131. orr r2, r2, #0x800 /*@ disable chip */
  132. str r2, [r1, #oNFCONF]
  133.  
  134. /* @ get read to call C functions (for nand_read()) */
  135. ldr sp, DW_STACK_START /* @ setup stack pointer */
  136. mov fp, #0 /* @ no previous frame, so fp=0 */
  137.  
  138. /* @ copy U-Boot to RAM */
  139. ldr r0, =TEXT_BASE
  140. mov r1, #0x0
  141. mov r2, #LENGTH_UBOOT
  142. bl nand_read_ll
  143. tst r0, #0x0
  144. beq ok_nand_read
  145. bad_nand_read:
  146. loop2:
  147. b loop2 /*@ infinite loop */
  148.  
  149. ok_nand_read:
  150. /* @ verify */
  151. mov r0, #0
  152. ldr r1, =TEXT_BASE
  153. mov r2, #0x400 /* @ 4 bytes * 1024 = 4K-bytes */
  154.  
  155. go_next:
  156. ldr r3, [r0], #4
  157. ldr r4, [r1], #4
  158. teq r3, r4
  159. bne notmatch
  160. subs r2, r2, #4
  161. beq stack_setup
  162. bne go_next
  163.  
  164. notmatch:
  165. loop3:
  166. b loop3 /*@ infinite loop */
  167. #endif
  168.  
  169. /***************** NAND_BOOT ************************************************/</span>

3,设置堆栈,并且跳入第二阶段的C代码

  1. /* Set up the stack */
  2. stack_setup:
  3. ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
  4. sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
  5. sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */
  6. #ifdef CONFIG_USE_IRQ
  7. sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
  8. #endif
  9. sub sp, r0, #12 /* leave 3 words for abort-stack */
  10.  
  11. clear_bss: //将未初始化.bss段初始化0
  12. ldr r0, _bss_start /* find start of bss segment */
  13. ldr r1, _bss_end /* stop here */
  14. mov r2, #0x00000000 /* clear */
  15.  
  16. clbss_l:
  17. str r2, [r0] /* clear loop... */
  18. add r0, r0, #4
  19. cmp r0, r1
  20. ble clbss_l
  21.  
  22. ldr pc, _start_armboot //跳到第二阶段c函数,进一步初始化板子硬件
  23.  
  24. _start_armboot: .word start_armboot
  25.  
  26. #define STACK_BASE 0x33f00000 //为nand_read_ll函数调用设置堆栈
  27. #define STACK_SIZE 0x10000
  28.  
  29. .align 2
  30. DW_STACK_START: .word STACK_BASE+STACK_SIZE-4 </span>

4,异常向量处理代码

  1. /*************************************************************************
  2. *
  3. * Interrupt handling
  4. *
  5. *************************************************************************
  6. */
  7. ......
  1.  

详细可参考http://www.crifan.com/files/doc/docbook/uboot_starts_analysis/release/html/uboot_starts_analysis.html

u-boot移植总结(一)start.S分析的更多相关文章

  1. 【STM32H7教程】第11章 STM32H7移植SEGGER的硬件异常分析

    完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第11章       STM32H7移植SEGGER的硬 ...

  2. Spring Boot 启动(一) SpringApplication 分析

    Spring Boot 启动(一) SpringApplication 分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html ...

  3. Spring Boot 揭秘与实战 源码分析 - 工作原理剖析

    文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...

  4. Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机

    文章目录 1. 开箱即用,内藏玄机 2. 总结 3. 源代码 Spring Boot提供了很多”开箱即用“的依赖模块,那么,Spring Boot 如何巧妙的做到开箱即用,自动配置的呢? 开箱即用,内 ...

  5. Spring Boot自动装配原理源码分析

    1.环境准备 使用IDEA Spring Initializr快速创建一个Spring Boot项目 添加一个Controller类 @RestController public class Hell ...

  6. 标题:u-boot 移植步骤详解

    1 U-Boot简介U-Boot,全称Universal Boot Loader,是遵循GPL条款的开放源码项目.从FADSROM.8xxROM.PPCBOOT逐步发展演化而来.其源码目录.编译形式与 ...

  7. 从0移植uboot (一) _配置分析

    来源:Linux社区  作者:xiaojiang1025  :http://www.linuxidc.com/Linux/2017-02/141018.htm 和绝大多数源码编译安装一样,uboot的 ...

  8. Android6.0内核移植(1):分析编译日志

    在下面命令之后产生的编译日志进行分析 source build/envsetup.sh lunch sabresd_6dq-user make -j20 ======================= ...

  9. Spring Boot(五)启动流程分析

    学习过springboot的都知道,在Springboot的main入口函数中调用SpringApplication.run(DemoApplication.class,args)函数便可以启用Spr ...

  10. Spring Boot(四)@EnableXXX注解分析

    在学习使用springboot过程中,我们经常碰到以@Enable开头的注解,其实早在Spring3中就已经出现了类似注解,比如@EnableTransactionManagement.@ Enabl ...

随机推荐

  1. Python中的模块与包

    标准库的安装路径 在import模块的时候,python是通过系统路径找到这些模块的,我们可以将这些路径打印出来: >>> pprint.pprint(sys.path) ['', ...

  2. 【转】mac/linux终端光标的快捷键操作

    摘自网络:原标题是类似linux/unix命令行终端的光标及字符控制快捷键的东东. 常用的快捷键: Ctrl + d 删除一个字符,相当于通常的Delete键(命令行若无所有字符,则相当于exit:处 ...

  3. PLSQL Developer 出64位版了

    在win64环境上,一般安装oracle客户端都是64位的了,Toad 也是64位的,但是PLSQL Developer 还是32位的,只能单单为它装一个32位的oracle 客户端,现在退出64位, ...

  4. Exploring Ionic Lists

    Infinite Lists 由于手机不适合使用多页面显示posts,Infinite Lists成为各种新闻.咨询类app的标配.为了在ionic框架中使用到Infinite Lists,我们首先学 ...

  5. CSS的sprite和单位

    (1).关于css sprite技术 比方说: 有个论坛频道,其中有个一些论坛特有的小图标(火啊,顶啊之类),基于整站小图标大团结的思想,这些小图标也放在了那个icon背景图片上了.然而,数年下来,我 ...

  6. NSDictionary 的有序性 (by the key in some rule)

    NSDictionary 的有序性: (by the key in some rule) NSDictionary*myDictionary =[NSDictionary dictionaryWith ...

  7. Android事件传递机制

    http://blog.csdn.net/awangyunke/article/details/22047987 1)public boolean dispatchTouchEvent(MotionE ...

  8. 聊一聊google的Knowledge Graph

    什么是Knowledge Graph? 它是google用于增强它的搜索引擎的功能和提高搜索结果质量的一种技术.在2012年5月16日提出,除了提供基本的与主题相关的链接服务之外,它还能结构化与主题相 ...

  9. 斐波那契堆(二)之 C++的实现

    概要 上一章介绍了斐波那契堆的基本概念,并通过C语言实现了斐波那契堆.本章是斐波那契堆的C++实现. 目录1. 斐波那契堆的介绍2. 斐波那契堆的基本操作3. 斐波那契堆的C++实现(完整源码)4.  ...

  10. 【转载】利用shell脚本获取一个文件的绝对路径readlink

    转载自:http://os.chinaunix.net/a2007/1118/976/000000976787.shtml #! /bin/bash echo "Path to $(base ...