国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > php教程 > 嵌入式学习-uboot-lesson7-内存初始化

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

来源:程序员人生   发布时间:2016-07-28 09:22:00 阅读次数:2342次

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,这部份代码由3星固化。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工作的时候,已进入稳定的状态,因此这1步可以不做
  • 4.履行内存初始化
  • 5.配置memc_cmd 使DRAM控制器进入 ready 状态
  • 6.检查 memc_stat 是不是为2b01

step1

这里写图片描述

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

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

step2

这1步骤的主要流程在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,=0x7e001000 ldr r1,[r0] mov r2,#0x3 and r1,r1,r2 @将r1r2进行位与操作 cmp r1,#0x1 @与0x1进行比较 bne check_ready @不相等,跳转到check_ready

step7

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

这里写图片描述

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: clean clean: 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: @处理未定义指令异常 nop software_interrupt: @软中断 nop prefetch_abort: @预取指令异常 nop data_abort: @数据访问异常 nop not_used: @空位 nop irq: @中断 nop fiq: @快速中断 nop reset: @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 @点亮LED set_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,lr disable_interrupt: mvn r1,#0x0 @0x0 取反,给r1 ldr r0,=0x71200014 @VIC0 str r1,[r0] ldr r0,=0x71300014 @VIC1 str r1,[r0] mov pc,lr disable_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_init mem_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

菜鸟1枚,如有毛病,多多指教。。。

生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生