Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2148960
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2012-05-24 23:19:54

    初始化好了sdram之后,下面就试一下把sram中的前4k搬到sdram中并跳转到链接地址处执行,这样就不用老是担心写的代码是不是位置无关(PIC)的了,下面是程序的所有文件。

点击(此处)折叠或打开

  1. root@ubuntu:~/myboot# tree
  2. .
  3. ├── main.c
  4. ├── Makefile
  5. ├── sdram.c
  6. ├── start.S
  7. └── u-boot.lds
  8. 0 directories, 5 files

1. start.S

点击(此处)折叠或打开

  1. .text
  2. .global _start
  3. _start:
  4.     /*关闭看门狗*/
  5.     ldr r0, =0x53000000    
  6.     mov r1, #0x0
  7.     str r1, [r0]

  8.     /*初始化系统时钟: FCLK=400M HCLK=100M PCLK=50M */
  9. #define COCKTIME    0x4C000000    
  10. #define MPLLCON        0x4C000004
  11. #define UPLLCON        0x4C000008
  12. #define CLKCON        0x4C00000C
  13. #define CLKSLOW        0x4C000010
  14. #define CLKDIVN     0x4C000014
  15. #define CAMDIVN     0x4C000018
  16.     /*FCLK:HCLK:PCLK=1:4:8*/
  17.     ldr r0, =CLKDIVN
  18.     mov r1, #0x05
  19.     str r1, [r0]

  20.     mrc p15, 0, r0, c1, c0, 0
  21.     orr r0, r0, #0xc0000000
  22.     mcr p15, 0, r0, c1, c0,0

  23.     /*MPLL=(2*m*Fin)/(P*(1<
  24.     /*UPLL=(m*Fin)/(P*(1<
  25.     ldr r0, =0x10000
  26. 1:
  27.     sub r0, r0, #1
  28.     bne 1b
  29.     
  30.     /*设置栈,因为下一步要调用c函数init_sdram*/
  31.     ldr sp, =1024*4
  32.     bl init_sdram

  33.     /*sdram初始化好之后,重新设置栈到内存 0x33d80000+128k*/
  34.     ldr sp, =0x33dA0000
  35.     
  36.     /*复制 steppingstone 到内存: r0=src r1=dest r2=size=4k*/
  37.     mov r0, #0x0
  38.     ldr r1, =0x33d80000
  39.     ldr r2, =1024*4

  40. copy_loop:
  41.     ldmia     {r3-r10}        /* copy from source address [r0] */
  42.     stmia     {r3-r10}        /* copy to target address [r1] */
  43.     cmp    r0, r2                    /* until source end addreee [r2] */
  44.     ble    copy_loop    
  45.     
  46.     /*跳转到main中 此处bl与ldr跳转不一样*/
  47.     /*bl main*/
  48.     ldr pc, _main
  49. loop:
  50.     b loop
  51. _main: .word main
2. main.c

点击(此处)折叠或打开

  1. #define GPBCON (*(volatile unsigned int *) 0x56000010)
  2. #define GPBDAT (*(volatile unsigned int *) 0x56000014)

  3. static inline void delay (unsigned long loops)
  4. {
  5.     __asm__ volatile ("1:\n"
  6.             "subs %0, %1, #1\n"
  7.             "bne 1b":"=r" (loops):"0" (loops));
  8. }
  9. /* 闪灯测试: sram快 sdram稍慢 */
  10. void main(void)
  11. {
  12.     int i = 1;
  13.     GPBCON = 0x15400;
  14.     while(1)
  15.     {
  16.         GPBDAT = 0x7FF&(~i<<5);
  17.         i *= 2;
  18.         if(16==i)
  19.             i = 1;
  20.         delay(400000);
  21.     }
  22.     return ;
  23. }
3. sdram.c 与 u-boot.lds都无改动
4. Makefile 中 OBJS :=  start.o main.o sdram.o
5. 把start.S中的ldr pc, _main 改为 bl main, 编译后分别烧到板子中,可以发现程序运行在sram比sdram中灯闪烁的速度快一些。
把这两个程序反汇编进行比较:

点击(此处)折叠或打开

  1. root@ubuntu:~/myboot# diff u-boot.dis_sdram u-boot.dis_sram
  2. 44c44
  3. < 33d80084:    e59ff000     ldr    pc, [pc, #0]    ; 33d8008c <_main>
  4. ---
  5. > 33d80084:    eb000008     bl    33d800ac
ldr    pc, [pc, #0] 
把当前pc地址处的值赋给pc,当前pc=(0x33d80084+8)-0x33d80000=0x008C, 0x008C处的值为0x33d800ac,所以执行这条指令后pc指向了0x33d800ac,也就是内存中main函数的入口地址。

33d80084:   eb000008    bl  33d800ac
以当前pc地址进行相对跳转,当前pc=(0x33d80084+8)-0x33d80000=0x008C,根据跳转的指令格式可知跳转到的地址为:0x8C+8<<2=0xAC,执行这条指令的后pc指向了0xAC, 还是在sram中的main函数的入口地址。


注意:1. 虽然反汇编文件中的地址都是0x33d80000,但是实现上程序并没有运行在0x33d80000,而是运行在0x0地址,所以在计算时要减去0x33d80000.同时虽然地址不吻合,但是地址里面的值却是正确的,可以放心用。
2. arm9五级流水,pc地址要加8,至于为什么可以看下面:
3. eb000008 转为二进制
   1110 1011 0000 0000 0000 0000 1000

   1110: always
   101:
   1:   说明这是一条bl指令
   0000 0000 0000 0000 1000: word 对齐,最右边两位总是0,所以省略,计算时需要向左移两位,即乘以4。
   
出自《ARM7TDMI-S Data Sheet》chapter_4 “arm instruction set”   


阅读(2797) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~