S3C2440 裸机 使用SDRAM实验 汇编文件分析

2019-07-12 19:23发布

源码来源《嵌入式Linux应用开发完全手册》P95 @************************************************************************* @ File:head.S @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行 @************************************************************************* .equ MEM_CTL_BASE, 0x48000000 .equ SDRAM_BASE, 0x30000000 .text .global _start _start: bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启 bl memsetup @ 设置存储控制器 bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中 ldr pc, =on_sdram @ 跳到SDRAM中继续执行 on_sdram: ldr sp, =0x34000000 @ 设置堆栈 bl main halt_loop: b halt_loop disable_watch_dog: @ 往WATCHDOG寄存器写0即可 mov r1, #0x53000000 mov r2, #0x0 str r2, [r1] mov pc, lr @ 返回 copy_steppingstone_to_sdram: @ 将Steppingstone的4K数据全部复制到SDRAM中去 @ Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000 mov r1, #0 ldr r2, =SDRAM_BASE mov r3, #4*1024 1: ldr r4, [r1],#4 @ 从Steppingstone读取4字节的数据,并让源地址加4 str r4, [r2],#4 @ 将此4字节的数据复制到SDRAM中,并让目地地址加4 cmp r1, r3 @ 判断是否完成:源地址等于Steppingstone的未地址? bne 1b @ 若没有复制完,继续 mov pc, lr @ 返回 memsetup: @ 设置存储控制器以便使用SDRAM等外设 mov r1, #MEM_CTL_BASE @ 存储控制器的13个寄存器的开始地址 adrl r2, mem_cfg_val @ 这13个值的起始存储地址 add r3, r1, #52 @ 13*4 = 52 1: ldr r4, [r2], #4 @ 读取设置值,并让r2加4 str r4, [r1], #4 @ 将此值写入寄存器,并让r1加4 cmp r1, r3 @ 判断是否设置完所有13个寄存器 bne 1b @ 若没有写成,继续 mov pc, lr @ 返回 .align 4 mem_cfg_val: @ 存储控制器13个寄存器的设置值 .long 0x22011110 @ BWSCON .long 0x00000700 @ BANKCON0 .long 0x00000700 @ BANKCON1 .long 0x00000700 @ BANKCON2 .long 0x00000700 @ BANKCON3 .long 0x00000700 @ BANKCON4 .long 0x00000700 @ BANKCON5 .long 0x00018005 @ BANKCON6 .long 0x00018005 @ BANKCON7 .long 0x008C07A3 @ REFRESH .long 0x000000B1 @ BANKSIZE .long 0x00000030 @ MRSRB6 .long 0x00000030 @ MRSRB7   分析: .equ 定义一个静态符号,相当于define,设置好后不可改动 .text 指定了后续编译出来的内容放在代码段【可执行】; .global 告诉编译器后续跟的是一个全局可见的名字【可能是变量,也可以是函数名】 _start 是一个函数的起始地址,也是编译、链接后程序的起始地址。由于程序是通过加载器来加载的,必须要找到 _start名字的函数,因此_start必须定义成全局的,以便存在于编译后的全局符合表中,供其它程序【如加载器】寻找到。 BL 是arm汇编中用来调用子程序的指令,它把BL后面一条指令的地址放到R14寄存器里,R15寄存器(PC当前指针地址)就设置成要跳往的地址。这样在这个子程序返回时,再mov PC, R14就可以返回到BL后面的地址了。
B 不一样,B是直接 mov PC, 目标地址;而不保存其后的地址到R14。
MOV 指令可以把一个寄存器的值赋给另一个寄存器,或者把一个常数赋给寄存器
例如: MOV    R1, R2           /*R1 = R2*/ MOV    R1, #0x53000000        /*R1 = 0x53000000*/
MOV AX,2000H;将16位数据2000H传送到AX寄存器
MOV AL,20H;将8位数据20H传送到AL寄存器
MOV AX,BX;将BX寄存器的16位数据传送到AX寄存器
MOV AL,[2000H];将2000H单元的内容传送到AL寄存器 STR  /  LDR STR 指令把寄存器值存入内存中 LDR 指令从内存中读取数据到寄存器 示例: LDR    R1, [R2,#4]             /*将地址为R2+4的内存单元数据读取到R1中*/ LDR    R1, [R2]                 /*将地址为R2的内存单元数据读取到R1中*/ LDR    R1, [R2],#4            /*将地址为R2的内存单元数据读取到R1中,然后R2 = R2 + 4*/ STR    R1, [R2,#4]           /*将R1数据保存到地址为R2+4的内存单元中*/ STR    R1, [R2]                /*将R1数据保存到地址为R2的内存单元中*/ STR    R1, [R2],#4          /*将R1数据保存到地址为R2的内存单元中,然后 R2 = R2 + 4*/   .align num 该指令告诉编译器,下面的数据按照num个字节单位分配空间 num必须是2的倍数