嵌入式学习-uboot-lesson7-内存初始化

来源:互联网 发布:wemall java版 编辑:程序博客网 时间:2024/06/10 08:41

6410所使用的内存为DDR 210使用的是DDR2 2440使用的是SDRAM,关于他们之间的区别,我在以前的文章中ok6410内存及启动流程简单介绍过,有兴趣的可以看看。

1. 地址空间

S3C6410处理器拥32位地址总线,其寻址空间为4GB。其中高2GB为保留区,低2GB区域又可划分为两部分:主存储区和外设区。
这里写图片描述
外设区主要是与6410寄存器相关,在核心初始化—外设基地址初始化中,有说明外设的寄存器的基地址为0x70000000
这里写图片描述
下面则是主存储区的地址分布,在以前的课程中有介绍,现在贴出来加强理解
这里写图片描述
主存储区可以分为

  • Boot镜像区
  • 内部存储区
  • 静态存储区
  • 保留区
  • 动态存储区

这里写图片描述

启动镜像区

这个区域并没有固定的存储介质与之对应,也就是没有实际的映射内存。但是可以把不同的启动介质的地址映射到该区域。比如说选择了IROM 启动方式后,就把IROM映射到该区域。这在以前有介绍过。

内部存储区

这个区域对应着内部的内存地址,iROM和SRAM都是分布在这个区间。0x08000000~0x0bffffff对应着内部ROM,但是IROM实际只有32KB,选择从IROM启动的时候,首先运行就是这里面的程序BL0,这部分代码由三星固化。0x0c000000~0x0fffffff对应内部SRAM,实际就是8KB的Steppingstone。

静态存储区

这个区域用于访问挂在外部总线上的设备,比如说NOR flash、oneNand等。这个区
域被分割为6个bank,每个bank为128MB,数据宽度最大支持16bit,每个bank由片选Xm0CS[0]~Xm0CS[5] 选中。

动态存储区

该区域从0x50000000~0x6fffffff,又分为2个区间,分别占256MB,可以片选Xm1CS[0]~Xm1CS[1]来进行着2个区间的选择。我们6410开发板上256MB的DDR内存就安排在这个区域,这也就是为什么6410的内存地址是从0x50000000开始的原因。

2. 6410内存芯片连接

这里写图片描述
如上图可以看到,6410的内存是由两块128MB的内存芯片连接而成,除了每个芯片的16位数据位不同,其他均相同。

3.内存初始化编程

这里写图片描述
根据上面的DRAM控制器初始化流程,可以得到以下步骤:

  • 1.配置memc_cmd 使DRAM控制器进入 config 状态
  • 2.写 内存时序 芯片配置 id配置等寄存器
  • 3.等待200微妙,使SDRAM电压和时钟进入稳定状态,但是当cpu工作的时候,已经进入稳定的状态,因此这一步可以不做
  • 4.执行内存初始化
  • 5.配置memc_cmd 使DRAM控制器进入 ready 状态
  • 6.检查 memc_stat 是否为2b01

step1

这里写图片描述

根据上面的图,可知需要设置[2:0]位设置位0b100即可

  ldr r0,=0x7e001004      mov r1,#0x4   str r1,[r0]

step2

这一步骤的主要流程在6410的手册中并没有找到具体的过程,因此主要参考内存芯片手册和uboot相关步骤写的。

    ldr r0, =0x7e001010  @刷新寄存器地址    ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) )      @设置刷新时间    str r1, [r0]    ldr r0, =0x7e001014  @CAS latency寄存器    mov r1, #(3 << 1)    str r1, [r0]    ldr r0, =0x7e001018  @t_DQSS寄存器    mov r1, #0x1    str r1, [r0]    ldr r0, =0x7e00101c  @T_MRD寄存器    mov r1, #0x2    str r1, [r0]    ldr r0, =0x7e001020   @t_RAS寄存器    ldr r1, =( ( 45 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001024   @t_RC寄存器    ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001028   @t_RCD寄存器    ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e00102c   @t_RFC寄存器    ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001030   @t_RP寄存器    ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001034   @t_rrd寄存器    ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001038   @t_wr寄存器    ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) ) @  ldr r2, [r0]    str r1, [r0]    ldr r0, =0x7e00103c   @t_wtr寄存器    mov r1, #0x07    str r1, [r0]    ldr r0, =0x7e001040   @t_xp寄存器       mov r1, #0x02    str r1, [r0]    ldr r0, =0x7e001044   @t_xsr寄存器      ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001048   @t_esr寄存器    ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e00100c   @内存控制配置寄存器    ldr r1, =0x00010012   @配置控制器    str r1, [r0]    ldr r0, =0x7e00104c   @32位DRAM配置控制寄存器     ldr r1, =0x0b45    str r1, [r0]    ldr r0, =0x7e001200   @片选寄存器    ldr r1, =0x150f8    str r1, [r0]    ldr r0, =0x7e001304   @用户配置寄存器     mov r1, #0x0    str r1, [r0]     

step3

等待200μs 来使SDRAM 电源和时钟稳定。当 CPU 开始工作时,电源和时钟已经被稳定下来因此多余 不做。

step4

下面是step4 内存初始化中的各个步骤
这里写图片描述

step4.1

这里写图片描述
根据上图,使[19:18]位为0b011即可满足要求,因此转化为16进制为0xc0000

    ldr r0,=0x7e001008    ldr r1,=0xc0000    str r1,[r0]

step4.2

根据上图,使[19:18]位为0b000即可满足要求

    ldr r0,=0x7e001008    ldr r1,=0x0    str r1,[r0]

step4.3 step4.4

4.3 和 4.4 为相同的操作,执行两遍

这里写图片描述
根据上图,使[19:18]位为0b001即可满足要求,因此转化为16进制为0x40000

    ldr r0,=0x7e001008    ldr r1,=0x40000    str r1,[r0]    ldr r0,=0x7e001008    ldr r1,=0x40000    str r1,[r0]    

step4.5

参考自uboot源码

    ldr r0,=0x7e001008    ldr r1,=0xa0000    str r1,[r0]    

step4.6

参考自uboot源码

    ldr r0,=0x7e001008    ldr r1,=0x80032    str r1,[r0]    

step5

这里写图片描述
如上图所示,需要设置[2:0]位0b000即可,

     ldr r0,=0x7e001004    mov r1,#0x0    str r1,[r0]

step6

这里写图片描述
根据上图,需要设置其为ready状态,即[1:0]为0b10

check_ready:ldr r0,=0x7e001000ldr r1,[r0]mov r2,#0x3and r1,r1,r2  @将r1r2进行位与操作cmp r1,#0x1  @与0x1进行比较bne check_ready @不相等,跳转到check_ready

step7

在代码设置之前,需要设置DDR的管脚为数据管脚,要设置第二块内存芯片的数据引脚,如下所示
这里写图片描述

这里写图片描述

    ldr r0,=0x7e00f120  @设置为数据引脚    mov r1,#0x0    str r1,[r0]    

以下是全部代码片段:

Makefile

all: start.o mem.o    arm-linux-ld -Tgboot.lds -o gboot.elf $^    arm-linux-objcopy -O binary gboot.elf gboot.bin%.o : %.S    arm-linux-gcc -g -c $^%.o : %.c    arm-linux-gcc -g -c $^.PHONY: cleanclean:    rm *.o *.elf *.bin

start.S

@****************************@name: start.S@by  : stone@time: 2016.6.26@function: @     异常向量表@         设置SVC模式@         关闭看门狗@         关闭中断@         关闭MMU@         外设基地址初始化@         点亮LED@         时钟初始化@         内存初始化@****************************.text.global _start  @将_start声明为全局变量_start:        b   reset                               ldr pc, _undefined_instruction          ldr pc, _software_interrupt             ldr pc, _prefetch_abort                 ldr pc, _data_abort                     ldr pc, _not_used                       ldr pc, _irq                            ldr pc, _fiq_undefined_instruction: .word undefined_instruction_software_interrupt:    .word software_interrupt_prefetch_abort:    .word prefetch_abort_data_abort:        .word data_abort_not_used:      .word not_used_irq:           .word irq_fiq:           .word fiq                   undefined_instruction:  @处理未定义指令异常        nopsoftware_interrupt:     @软中断        nopprefetch_abort:         @预取指令异常        nopdata_abort:             @数据访问异常        nopnot_used:               @空位        nopirq:                    @中断        nopfiq:                    @快速中断        nopreset:                          @reset    bl set_svc              @设置为SVC模式    bl set_peri_port        @外设基地址初始化    bl disable_watchdog     @关闭看门狗    bl disable_interrupt    @关闭中断    bl disable_mmu          @关闭mmu    bl init_clock           @时钟初始化    bl mem_init             @内存初始化    bl light_led            @点亮LEDset_svc:            mrs r0, cpsr        @将值取出cpsr寄存器    bic r0, r0, #0x1f   @将后5位 即M[4:0]清零     orr r0, r0, #0xd3   @0b10011 转化为16进制为0x13 同时为了屏蔽irq和fiq,可以将其设置为0b11010011即0xd3      msr cpsr, r0        @将值送回cpsr寄存器    mov pc, lr              @返回set_peri_port:    ldr r0, =0x70000000     @基地址    orr r0, r0, #0x13       @256MB    mcr p15,0,r0,c15,c2,4   @写入cp15    mov pc, lr#define pwTCON 0x7E004000       @WTCON寄存器disable_watchdog:         ldr r0, =pwTCON         @把地址装载到R0        mov r1, #0x0            @置0,关闭看门狗        str r1,[r0]             mov pc,lrdisable_interrupt:        mvn r1,#0x0             @0x0 取反,给r1        ldr r0,=0x71200014      @VIC0        str r1,[r0]        ldr r0,=0x71300014      @VIC1        str r1,[r0]        mov pc,lrdisable_mmu:        mcr p15,0,r0,c7,c7,0    @使ICACHE 和DCACHE 无效    mrc p15,0,r0,c1,c0,0    @read control register    bic r0,r0,#0x00000007   @mmu 和 dcache置零    mcr p15,0,r0,c1,c0,0    @write control register    mov pc,lr#define CLK_DIV0 0x7e00f020#define CLK_SRC  0x7e00f01c#define OTHERS   0x7e00f900#define MPLL_CON 0X7E00F010#define APLL_CON 0X7E00F00c#define PLL_VAL ((1<<31)|(266<<16)|(3<<8)|(1<<0))#define DIV_VAL ((0X0<<0)|(0X1<<9)|(0X1<<8)|(0X3<<12))init_clock:        ldr r0,=CLK_DIV0 @设置分频系数        ldr r1,=DIV_VAL        str r1,[r0]        ldr r0,=OTHERS   @设置异步工作模式 第7位为06位为0(时钟选择器)        ldr r1,[r0]        bic r1,r1,#0xc0        str r1,[r0]        ldr r0,=APLL_CON @APLL设置为533Mhz        ldr r1,=PLL_VAL        str r1,[r0]        ldr r0,=MPLL_CON @MPLL设置为533Mhz        ldr r1,=PLL_VAL        str r1,[r0]        ldr r0, =CLK_SRC @选择时钟源为APLL MPLL还是外部        mov r1, #0x3     @APLL MPLL        str r1, [r0]                mov pc,lr#define GPMCON 0x7F008820       @控制寄存器#define GPMDAT 0x7F008824   @数据寄存器  light_led:        ldr r0,=GPMCON        ldr r1,=0x1111  @输出模式        str r1,[r0]        ldr r0,=GPMDAT        ldr r1,=0x00    @低电平点亮        str r1,[r0]         mov pc,lr

mem.S

@*************************************@name : mem.S@time : 2016/06/26@function : 内存初始化相关代码@************************************.text              @代码段.global mem_initmem_init:    ldr r0,=0x7e00f120  @设置为数据引脚    mov r1,#0x0    str r1,[r0]     ldr r0,=0x7e001004   @配置寄存器 使DRAM控制器进入 config 状态    mov r1,#0x4    str r1,[r0]    ldr r0, =0x7e001010  @刷新寄存器地址    ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) )      @设置刷新时间    str r1, [r0]    ldr r0, =0x7e001014  @CAS latency寄存器    mov r1, #(3 << 1)    str r1, [r0]    ldr r0, =0x7e001018  @t_DQSS寄存器    mov r1, #0x1    str r1, [r0]    ldr r0, =0x7e00101c  @T_MRD寄存器    mov r1, #0x2    str r1, [r0]    ldr r0, =0x7e001020   @t_RAS寄存器    ldr r1, =( ( 45 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001024   @t_RC寄存器    ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001028   @t_RCD寄存器    ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e00102c   @t_RFC寄存器    ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001030   @t_RP寄存器    ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001034   @t_rrd寄存器    ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001038   @t_wr寄存器    ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) ) @  ldr r2, [r0]    str r1, [r0]    ldr r0, =0x7e00103c   @t_wtr寄存器    mov r1, #0x07    str r1, [r0]    ldr r0, =0x7e001040   @t_xp寄存器       mov r1, #0x02    str r1, [r0]    ldr r0, =0x7e001044   @t_xsr寄存器      ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e001048   @t_esr寄存器    ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )    str r1, [r0]    ldr r0, =0x7e00100c   @内存控制配置寄存器    ldr r1, =0x00010012   @配置控制器    str r1, [r0]    ldr r0, =0x7e00104c   @32位DRAM配置控制寄存器     ldr r1, =0x0b45    str r1, [r0]    ldr r0, =0x7e001200   @片选寄存器    ldr r1, =0x150f8    str r1, [r0]    ldr r0, =0x7e001304   @用户配置寄存器     mov r1, #0x0    str r1, [r0]            ldr r0,=0x7e001008    ldr r1,=0xc0000    str r1,[r0]    ldr r0,=0x7e001008    ldr r1,=0x0    str r1,[r0]    ldr r0,=0x7e001008    ldr r1,=0x40000    str r1,[r0]    ldr r0,=0x7e001008    ldr r1,=0x40000    str r1,[r0]     ldr r0,=0x7e001008    ldr r1,=0xa0000    str r1,[r0]     ldr r0,=0x7e001008    ldr r1,=0x80032    str r1,[r0]     ldr r0,=0x7e001004    mov r1,#0x0    str r1,[r0]check_ready:    ldr r0,=0x7e001000    ldr r1,[r0]    mov r2,#0x3    and r1,r1,r2    @将r1r2进行位与操作    cmp r1,#0x1     @与0x1进行比较    bne check_ready @不相等,跳转到check_ready         mov pc,lr

菜鸟一枚,如有错误,多多指教。。。

0 0
原创粉丝点击