学习ARM开发(8)x

时间:2022-06-22 11:40:04 浏览量:

 学习 ARM 开发(8) 上一次看了数据区,这次要看从引导那里跳到这里执行时,运行什么东西了。

 /* * 实际运行的复位代码。从一开始运行的代码,就跳到这里运行。

 */

 reset:

  /*

 * 设置 cpu 运行在 SVC32 模式。

 */

  mrs

 r0,cpsr

  bic

 r0,r0,#0x1f

  orr

 r0,r0,#0x13

  msr

 cpsr,r0

 具体分析如下:

 /* * 实际运行的复位代码。从一开始运行的代码,就跳到这里运行。

 */

 reset:

  /*

 * 设置 cpu 运行在 SVC32 模式。S3C44B0 共有 7 种模式。

 */

  mrs

 r0,cpsr 取得当前程序状态寄存器 cpsr 到 r0。

  bic

 r0,r0,#0x1f 这里使用位清除指令,把中断全部清除,只置位模式控制位。

  orr

 r0,r0,#0x13 计算为超级保护模式。

  msr

 cpsr,r0 设置 cpsr 为超级保护模式。

 通过设置 ARM 的 CPSR 寄存器,让 CPU 运行在操作系统模式,为后面进行其它操作作好准备了。后面的代码如下:

 /*

 当是从 FLASH 启动时,就要进行内存测试,当

 是从 RAM 启动时,一般就是开发本源程序时,就

 可以跳过。

 *

 */

  #ifdef CONFIG_INIT_CRITICAL

  bl

 cpu_init_crit

  /*

 在重新定位之前,要进行 RAM 访问时间测试,因为每个开发

 都是不一样的。

 * 可以在文件 memsetup.S 里看到它的说明。

  */

  bl

 memsetup #endif

 /* 进行重定位 */ relocate:

 /* 重定位 Boot 代码到 RAM 内存,比如从 FLASH 移到RAM

 */

  adr

 r0, _start

 /* 把_start 的相对地址移到 r0

 */

  ldr

 r1, _TEXT_BASE

 /* 把_TEXT_BASE 地址,就是 BOOT 在 RAM 中运行地址 */

  cmp

  r0, r1

  /*

 比较两个地址是否相同,如果相同,就已经在 RAM 运行,否则就是 FLASH 中运行。

 */

  beq

  stack_setup

 /* 是在 FLASH 中运行,要把 FLASH 中的 BOOT 代码移到 RAM 中,然后再运行. */

  2armboot_start

  ldr

 r3, _bss_start

  sub

 r2, r3, r2

 /* 大小

 */

  add

 r2, r0, r2

 /* r2 保存引导代码最后地址

  */

 copy_loop:

  ldmia

 r0!, {r3-r10}

 /* 从源地址[r0]读取 8 个字节到寄存器,每读一个就更新一次 r0 地址 */

  stmia

 r1!, {r3-r10}

 /* 拷贝寄存器 r3-r10 的值保存到 [r1]指明的地址,每写一个字节,就增加 1.

 */

  cmp

 r0, r2

 /* 判断是否拷贝到[r2]地址,就是引导代码结束位置。

  */

  ble

 copy_loop

  /* 循环拷贝 */

 /*

  拷贝中断向量表,实际是建立起二级中断向量表,当 CPU 中断时,先运行FLASH 中断,接着就转移到实际中向表执行中断程序。

 */

  r

 r0, real_vectors

  add

 r2, r0, #1024

 ldr

 r1, =0x0c000000

  add

 r1, r1, #0x08 vector_copy_loop:

  ld

  r0!, }

  stmia

 r1!, {r3-r10}

  cmp

 r0, r2

  ble

 vector_copy_loop

 /* 建立起堆栈

 */ stack_setup:

  ldr

 r0, _TEXT_BASE

 /* upper 128 KiB: located uboot

  */

  MALLOC_LEN

 /* malloc area

 */

  sub

 r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo

 */ #ifdef CONFIG_USE_IRQ

  sub

 r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif

  sub

 sp, r0, #12

 /* leave 3 words for abort-stack

 */

 ldr

 pc, _start_armboot /* 已经准备好了堆栈,就可跳到 C 写的代码里,

  由于我的代码是 ARM,就是跳到

  lib_arm/board.c(208):void start_armboot (void)中运行。

 */

 _start_armboot:

 .word start_armboot

  /* ************************************************************************* CPU_init_critical 临界区寄存器 设置一些重要的寄存器,并进行内存测试。

 * ************************************************************************* */

 CON 0) /器 */ INTMSK (0x01c00+0x20000c) /* 中断控制屏蔽寄存器 */ LOCKTIME (0x01c00+0x180c) PLLCON (0x01c00000+0x180000) CLKCON (0x01c00000+0x180004) #defe WTCON (0x01c00000+0x130000) cpu_init_crit:

  /* 关闭看门狗 */

  ldr

  r0, =WTCON

 ldr

 , =0x0

  str

 r1, [r0]

 /*

 * 清除所有中断位,设置 INTMRs 实现。

 */

  1,=INTMSK

  ldr

 , =0x03fffeff

  str

 r0, [r1]

 1INTCON

  ldr

 , =0x05

  str

 r0, [r1]

 /* 设置时钟控制寄存器 */

 r1, =LOCKTIME

  ld

  , =800

  strb

 r0, [r1]

 /* 设置锁相环,控制 CPU 运行速度。

 */

  ldr

 r1, =PLLCON

 #if CONFIG_S3C44B0_CLOCK_SPEED==66

  ldr

 r0, =0x34031

  /* 66MHz (Quartz=11MHz) */ #elif CONFIG_S3C44B0_CLOCK_SPEED==75

  ldr

 r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz

 */ #else # error CONFIG_S3C44B0_CLOCK_SPEED undefined #endif

 str

 r0, [r1]

 1,=CLKCON

  ldr

 , =0x7ff8

  str

 r0, [r1]

 /* 调用子函数返回 */

  mov

 pc, lr

  ************************************************/

 实际的中断向量表

 */ /*************************************************/ real_vectors:

  b

 reset

 undefined_instruction

  software_interrupt

  prefetch_abort

  data_abort

  not_used

  irq

  b

 fiq

 /*************************************************/

 undefined_instruction:

  mov

 r6, #3

  b

 reset

 software_interrupt:

  mov

 r6, #4

  b

 reset

 prefetch_abort:

  mov

 r6, #5

  b

 reset

 data_abort:

  mov

 r6, #6

  b

 reset

 not_used:

  /* we *should* never reach this */

  mov

 r6, #7

  b

 reset

 irq:

  mov

 r6, #8

  b

 reset

 fiq:

  mov

 r6, #9

  b

 reset

相关热词搜索: 开发 学习 ARM