嵌入式学习-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 @将r1与r2进行位与操作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位为0 第6位为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 @将r1与r2进行位与操作 cmp r1,#0x1 @与0x1进行比较 bne check_ready @不相等,跳转到check_ready mov pc,lr
菜鸟一枚,如有错误,多多指教。。。
- 嵌入式学习-uboot-lesson7-内存初始化
- 嵌入式学习-uboot-lesson6-时钟初始化
- 嵌入式学习-uboot-lesson10-MMU初始化
- 嵌入式学习-uboot-lesson4.5-外设基地址初始化
- 嵌入式学习-uboot-lesson9.1-C语言环境初始化
- 嵌入式学习-驱动开发-lesson7.2-DM9000驱动流程分析
- 嵌入式UBOOT学习
- 嵌入式 hi3518c裸板烧写uboot简记以及内存初始化寄存器修改技巧
- Uboot 内存初始化(2440)
- 嵌入式学习笔记2—S3C2440的内存初始化
- 嵌入式系统学习入门-UBOOT
- 嵌入式学习之uboot移植
- 嵌入式学习-驱动开发-lesson7.1-网卡驱动架构分析驱动及CS8900流程分析
- 嵌入式 uboot中mtest测试内存
- lesson7
- OK6410之uboot时钟初始化---嵌入式回归第十一篇
- I/O java学习 Lesson7
- C++学习笔记 lesson7 static
- Xml和Json相互转换的java
- PotPlayer清除流氓和升级
- Spark定制班第33课:Kafka内核再解密
- 配置TOMACAT
- 协方差的意义和解释(目前为止我看到的最为通俗易懂的文章)
- 嵌入式学习-uboot-lesson7-内存初始化
- mysql 给表添加唯一约束、联合唯一约束,指定唯一约束的名字
- 【Swift】Runtime动态性分析
- java反射机制
- 带缓存的字节输入输出流
- 煤矿工人成为互联网工程师的故事
- alloc init new的区别
- leetcode 37. Sudoku Solver
- 今天给大家讲个故事