《朱老师物联网大讲堂》学习笔记
学习地址:www.zhulaoshi.org
汇编初始化SDRAM
在这里,我们的那个链接脚本中想要重定位的地址修改了,这个地址是SDRAM中的地址,
修改为0x20000000
在我们那个start.S文件中,我们在开关icache和重定位代码之间,增加了初始化SDRAM的代码,
是通过函数sdram_asm_init来实现的,
在正式讲解这个函数之前,先说明一下,
汇编实现的函数,返回要手动去做,
比如可以这样:mov pc, lr
DDR的初始化和SOC(里面的DDR控制器)有关,比如寄存器,
也和开发板使用的DDR芯片有关,不过这个问题不大,因为芯片标准比较一致,而且一般都是原厂给设置参数,
和开发板设计时的连接方式也有关,比如我们这里是4片内存芯片,不过连接方式和对内存需要会有所不同。
初始化步骤在数据手册里面,
有27个步骤,见P598.
在我们这个S5PV210开发板上,初始化分DRAM0 和DRAM1
下面的图就是设置步骤,步骤还是挺多的,不过里面涉及时序等的计算,其实已经不是我们这里的主题了。
下面是DRAM初始化的代码,很多,而且由于很多参数,我们难以去计算,
都是参考原厂提供的代码,因此能看多少是多少,
#include "s5pv210.h" #if 1 #define DMC0_MEMCONTROL 0x00202400 // MemControl BL=4, 1Chip, DDR2 Type, dynamic self refresh, force precharge, dynamic power down off #define DMC0_MEMCONFIG_0 0x20F01323 // MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed #define DMC0_MEMCONFIG_1 0x30F00312 // MemConfig1 默认值 #define DMC0_TIMINGA_REF 0x00000618 // TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E) #define DMC0_TIMING_ROW 0x28233287 // TimingRow for @200MHz #define DMC0_TIMING_DATA 0x23240304 // TimingData CL=3 #define DMC0_TIMING_PWR 0x09C80232 // TimingPower #define DMC1_MEMCONTROL 0x00202400 // MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off #define DMC1_MEMCONFIG_0 0x40F01323 // MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed #define DMC1_MEMCONFIG_1 0x60E00312 // MemConfig1 #define DMC1_TIMINGA_REF 0x00000618 // TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4 #define DMC1_TIMING_ROW 0x28233289 // TimingRow for @200MHz #define DMC1_TIMING_DATA 0x23240304 // TimingData CL=3 #define DMC1_TIMING_PWR 0x08280232 // TimingPower #endif #if 0 #define DMC0_MEMCONTROL 0x00212400 // MemControl BL=4, 1Chip, DDR2 Type, dynamic self refresh, force precharge, dynamic power down off #define DMC0_MEMCONFIG_0 0x20E01323 // MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed #define DMC0_MEMCONFIG_1 0x40F01323 // MemConfig1 #define DMC0_TIMINGA_REF 0x00000618 // TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E) #define DMC0_TIMING_ROW 0x28233287 // TimingRow for @200MHz #define DMC0_TIMING_DATA 0x23240304 // TimingData CL=3 #define DMC0_TIMING_PWR 0x09C80232 // TimingPower #define DMC1_MEMCONTROL 0x00202400 // MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off #define DMC1_MEMCONFIG_0 0x40C01323 // MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed #define DMC1_MEMCONFIG_1 0x00E01323 // MemConfig1 #define DMC1_TIMINGA_REF 0x00000618 // TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4 #define DMC1_TIMING_ROW 0x28233289 // TimingRow for @200MHz #define DMC1_TIMING_DATA 0x23240304 // TimingData CL=3 #define DMC1_TIMING_PWR 0x08280232 // TimingPower #endif .global sdram_asm_init sdram_asm_init: ldr r0, =0xf1e00000 ldr r1, =0x0 str r1, [r0, #0x0] <span style="background-color: rgb(255, 0, 0);">像这种寄存器的设置,你在数据手册中, 找不到有意义的描述, 可以理解为怎么设置都行?</span> /* DMC0 Drive Strength (Setting 2X) */ <span style="background-color: rgb(255, 0, 0);"> 设置IO端口驱动强度, 总线的物理表现就是很多个引脚, 设置合适的驱动以抗干扰, 数据手册P200</span> ldr r0, =ELFIN_GPIO_BASE <span style="background-color: rgb(255, 0, 0);"> 此处ro = 0xE0200000, 可以理解为定了一个基地址, 还有很多类似的宏定义在我们的.h文件里面 #include "s5pv210.h"</span> ldr r1, =0x0000AAAA str r1, [r0, #MP1_0DRV_SR_OFFSET] <span style="background-color: rgb(255, 0, 0);"> 0xAAAA = 1010 1010 1010 1010 高16位,没说,就设为0吧, 寄存器中对应0b10,就是2X, 这里设置为多少,我们无从去计算判断, 只能参考官方给出的参考代码,</span> ldr r1, =0x0000AAAA str r1, [r0, #MP1_1DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_2DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_3DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_4DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_5DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_6DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_7DRV_SR_OFFSET] ldr r1, =0x00002AAA str r1, [r0, #MP1_8DRV_SR_OFFSET] /* DMC1 Drive Strength (Setting 2X) */ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x0000AAAA str r1, [r0, #MP2_0DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_1DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_2DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_3DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_4DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_5DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_6DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_7DRV_SR_OFFSET] ldr r1, =0x00002AAA str r1, [r0, #MP2_8DRV_SR_OFFSET] <span style="background-color: rgb(255, 0, 0);"> 这些驱动强度的设置,设置方法都是一样的, </span> /* DMC0 initialization at single Type*/ <span style="background-color: rgb(255, 0, 0);"> 设置时钟,对着手册来看这些值,看都对应吧 这里的功能主要是开启DLL(dram pll) 然后等待锁存, 对应27步中的2~4步。</span> ldr r0, =APB_DMC_0_BASE ldr r1, =0x00101000 @PhyControl0 DLL parameter setting, manual 0x00101000 str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00000086 @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case str r1, [r0, #DMC_PHYCONTROL1] ldr r1, =0x00101002 @PhyControl0 DLL on str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00101003 @PhyControl0 DLL start str r1, [r0, #DMC_PHYCONTROL0] find_lock_val: ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register value and r2, r1, #0x7 cmp r2, #0x7 @Loop until DLL is locked bne find_lock_val and r1, #0x3fc0 mov r2, r1, LSL #18 orr r2, r2, #0x100000 orr r2 ,r2, #0x1000 orr r1, r2, #0x3 @Force Value locking str r1, [r0, #DMC_PHYCONTROL0] #if 0 /* Memory margin test 10.01.05 */ orr r1, r2, #0x1 @DLL off str r1, [r0, #DMC_PHYCONTROL0] #endif /* setting DDR2 */ ldr r1, =0x0FFF2010 @ConControl auto refresh off str r1, [r0, #DMC_CONCONTROL] ldr r1, =DMC0_MEMCONTROL @MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] ldr r1, =DMC0_MEMCONFIG_0 @MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed str r1, [r0, #DMC_MEMCONFIG0] ldr r1, =DMC0_MEMCONFIG_1 @MemConfig1 str r1, [r0, #DMC_MEMCONFIG1] ldr r1, =0xFF000000 @PrechConfig str r1, [r0, #DMC_PRECHCONFIG] ldr r1, =DMC0_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E) str r1, [r0, #DMC_TIMINGAREF] ldr r1, =DMC0_TIMING_ROW @TimingRow for @200MHz str r1, [r0, #DMC_TIMINGROW] ldr r1, =DMC0_TIMING_DATA @TimingData CL=3 str r1, [r0, #DMC_TIMINGDATA] ldr r1, =DMC0_TIMING_PWR @TimingPower str r1, [r0, #DMC_TIMINGPOWER] ldr r1, =0x07000000 @DirectCmd chip0 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00020000 @DirectCmd chip0 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00030000 @DirectCmd chip0 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x07100000 @DirectCmd chip1 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00120000 @DirectCmd chip1 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00130000 @DirectCmd chip1 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100542 @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100442 @DirectCmd chip1 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110780 @DirectCmd chip1 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x0FF02030 @ConControl auto refresh on str r1, [r0, #DMC_CONCONTROL] ldr r1, =0xFFFF00FF @PwrdnConfig str r1, [r0, #DMC_PWRDNCONFIG] ldr r1, =0x00202400 @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] // 上面是DRAM0初始化步骤 /*******************************************************************************************/ // 下面是DRAM1初始化步骤,两者没有联系,是并列的。 /* DMC1 initialization */ ldr r0, =APB_DMC_1_BASE ldr r1, =0x00101000 @Phycontrol0 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00000086 @Phycontrol1 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL1] ldr r1, =0x00101002 @PhyControl0 DLL on str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00101003 @PhyControl0 DLL start str r1, [r0, #DMC_PHYCONTROL0] find_lock_val1: ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register value and r2, r1, #0x7 cmp r2, #0x7 @Loop until DLL is locked bne find_lock_val1 and r1, #0x3fc0 mov r2, r1, LSL #18 orr r2, r2, #0x100000 orr r2, r2, #0x1000 orr r1, r2, #0x3 @Force Value locking str r1, [r0, #DMC_PHYCONTROL0] #if 0 /* Memory margin test 10.01.05 */ orr r1, r2, #0x1 @DLL off str r1, [r0, #DMC_PHYCONTROL0] #endif /* settinf fot DDR2 */ ldr r0, =APB_DMC_1_BASE ldr r1, =0x0FFF2010 @auto refresh off str r1, [r0, #DMC_CONCONTROL] ldr r1, =DMC1_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] ldr r1, =DMC1_MEMCONFIG_0 @MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed str r1, [r0, #DMC_MEMCONFIG0] ldr r1, =DMC1_MEMCONFIG_1 @MemConfig1 str r1, [r0, #DMC_MEMCONFIG1] ldr r1, =0xFF000000 str r1, [r0, #DMC_PRECHCONFIG] ldr r1, =DMC1_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4 str r1, [r0, #DMC_TIMINGAREF] ldr r1, =DMC1_TIMING_ROW @TimingRow for @200MHz str r1, [r0, #DMC_TIMINGROW] ldr r1, =DMC1_TIMING_DATA @TimingData CL=3 str r1, [r0, #DMC_TIMINGDATA] ldr r1, =DMC1_TIMING_PWR @TimingPower str r1, [r0, #DMC_TIMINGPOWER] ldr r1, =0x07000000 @DirectCmd chip0 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00020000 @DirectCmd chip0 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00030000 @DirectCmd chip0 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x07100000 @DirectCmd chip1 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00120000 @DirectCmd chip1 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00130000 @DirectCmd chip1 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110440 @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100542 @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100442 @DirectCmd chip1 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110780 @DirectCmd chip1 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x0FF02030 @ConControl auto refresh on str r1, [r0, #DMC_CONCONTROL] ldr r1, =0xFFFF00FF @PwrdnConfig str r1, [r0, #DMC_PWRDNCONFIG] ldr r1, =DMC1_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] // 函数返回 <span style="background-color: rgb(255, 0, 0);"> mov pc, lr </span>