MINI2440-SDRAM


目的:Norflash前4K的内容到SDRAM,并且成功点亮LED;

过程:

1.程序(main.c    startup.s    Makefile)

  1.1.main.c

#define GPBCON    (*(volatile unsigned long*)0x56000010)
#define GPBDAT    (*(volatile unsigned long*)0x56000014)


#define GPB_OUTPUT 01
#define GPB_CONFIG(IO,CONFIG) (CONFIG << (IO*2))   

int main()
{
   
    GPBCON |=  GPB_CONFIG(5,GPB_OUTPUT)
            | GPB_CONFIG(6,GPB_OUTPUT)
            | GPB_CONFIG(7,GPB_OUTPUT)
            | GPB_CONFIG(8,GPB_OUTPUT);
   
    GPBDAT  =  0X00000000;

    return 0;
}

1.2.startup.s 

.equ    MEM_CTL_BASE,    0x48000000   
.equ    SDRAM_BASE,        0x30000000

.text
.global _start
_start:

    bl  disable_watch_dog
    bl  sdram_init
    bl  copy_steppingstone_to_sdram
       
    ldr  pc, =on_sdram

on_sdram:
    ldr  sp, =0x34000000
    bl  main

halt_loop:
    b halt_loop

disable_watch_dog:
    mov  r1, #0x53000000
    mov  r2, #0x0
    str  r2, [r1]
    mov  pc, lr

copy_steppingstone_to_sdram:
    mov  r1, #0
    ldr  r2, =SDRAM_BASE
    mov  r3, #1024*4
1:
    ldr  r4, [r1],#4
    str  r4, [r2],#4
    cmp  r1, r3
    bne  1b
    mov  pc, lr

sdram_init:
    mov  r1, #MEM_CTL_BASE
    adrl r2, mem_cfg_val
    add  r3, r1,#52
1:
    ldr  r4, [r2],#4
    str  r4, [r1],#4
    cmp  r1, r3
    bne  1b
    mov  pc, lr

.align 4
mem_cfg_val:
   
    .long 0x22011110;
    .long 0x00000700;
    .long 0x00000700;
    .long 0x00000700;
    .long 0x00000700;
    .long 0x00000700;
    .long 0x00000700;
    .long 0x00018005;
    .long 0x00018005;   
    .long 0x008c07a3;
    .long 0x000000b1;
    .long 0x00000030;
    .long 0x00000030;

1.2.1.关看门狗;

    1.2.2.初始化SDRAM;

    1.2.3.复制Norflash前4K内容到SDRAM;

    1.2.4.设置栈;

    1.2.5.跳转到main

  1.3.Makefile

Main.bin : startup.s main.c
    arm-linux-gcc -g -c -o startup.o startup.s
    arm-linux-gcc -g -c -o main.o  main.c
    arm-linux-ld -Ttext 0x30000000 startup.o main.o -o main_elf
    arm-linux-objcopy -O binary -S main_elf main.bin

clean:
    rm -f main.bin main_elf *.o

2.startup.s详解:

  编译链接出来的文件main.bin是烧录到Norflash中0x00000000地址开始的一片内存,但是Makefile中指定的代码段链接地址为0x30000000,代码是如何被执行的?

     位置无关的相对跳转指令概念:    

    1.位置无关的程序跳转。使用相对跳转指令实现程序跳转。指令中所跳转的目标地址用基于当前PC的偏移量来表示,与链接时分配给地址标号的绝对地址值无关,因而代码可以在任何位置进行跳转,实现位置无关性。

    2.位置无关的常量访问。在应用程序中,经常要读写相关寄存器以完成必要的硬件初始化。为增强程序的可读性,利用EQU伪指令对一些常量进行赋值,但在访问过程中,必须实现位置无关性。

    3.使用绝对地址进行跳转,一般是在不同的位置无关代码段之间跳转。

  代码:   

    bl disable_watch_dog                     //链接地址:0x30000000,位置无关型
    bl sdram_init                                 //链接地址:0x30000004,位置无关型
    bl copy_steppingstone_to_sdram    //链接地址:0x30000008,位置无关型
    ldr pc, =on_sdram                         //链接地址:0x3000000b   

           on_sdram:                                    //链接地址:0x30000010
    ldr sp, =0x34000000
    bl main

  所以, 代码是经过一系列动作之后再跳转到0x30000010处的.其中经过关看门狗,初始化SDRAM,复制内容, 然后跳转,最后执行main函数中的点亮LED操作。

 

具体参考:

 

《嵌入式Linux应用开发完全手册》 

程序运行地址和加载地址-为什么使用位置无关指令 

 

关于相对跳转与绝对跳转指令的部分内容   

本文永久更新链接地址

相关内容