嵌入式Linux裸机开发(五)——SDRAM初始化

2019-07-12 19:01发布

嵌入式Linux裸机开发(五)——SDRAM初始化

一、SDRAM初始化流程

    S5PV210有两个独立的DRAM控制器,一个最大支持512MB,一个最大支持1024MB,但两个控制器必须支持相同类型的内存。根据三星S5PV210文档可知,DDR2类型内存的初始化流程如下:1、提供稳压电源给内存控制器和内存芯片,内存控制器必须保持CLE在低电平,此时就会提供稳压电源。注:当CKE引脚为低电平时,XDDR2SEL应该处于高电平    2、根据时钟频率正确配置PhyControl0.ctrl_start_point和PhyControl0.ctrl_inc的值。配置的PhyControl0.ctrl_dll_on值为'1'以打开PHY DLL。    3、数据选取脉DQS清除:依照时钟频率和内存的tAC参数正确设置PhyControl1.ctrl_shiftcPhyControl1.ctrl_offsetcbit位的值。    4、设置PhyControl0.ctrl_start位的值为'1'    5、设置ConControl,同时关闭auto refresh自动刷新计数器    6、设置MemControl,同时关闭所有的power down(休眠模式)。    7、设置MemConfig0寄存器。如果有两组内存芯片(比如有8片DDR,这8片DDR是分别挂在Memory Port1和Memory Port2上),再配置MemConfig1寄存器。    8、设置PrechConfig和PwrdnConfig寄存器    9、根据内存的tAC参数设置TimingAref,TimingRow, TimingData和TimingPower寄存器    10、如果需要QoS标准,配置QosControl015和QosConfig0-15寄存器    11、等待PhyStatus0.ctrl_locked位变为'1'。检查是否PHY DLL是否已锁    12、PHY DLL补偿在内存操作时由PVT(Process, Voltage and Temperature,处理器、电压和温度)变化引起的延迟量。但是,PHY DLL不能因某些可靠的内存操作而切断,除非是工作在低频率下。如果关闭PHY DLL,依照PhyStatus0.ctrl_lock_value[9:2]位的值正确配置PhyControl0.ctrl_force位的值来弥补延迟量(fix delay amount)。清除PhyControl0.ctrl_dll_on位的值来关闭PHY DLL。    13、上电后,确定最小值为200us的稳定时钟是否发出    14、使用DirectCmd寄存器发出一个NOP命令,保证CKE引脚为高电平    15、等最小400ns    16、使用DirectCmd寄存器发出一个PALL命令     17使用DirectCmd寄存器发出一个EMRS2命令,program操作参数     18使用DirectCmd寄存器发出一个EMRS3命令,program操作参数     19使用DirectCmd寄存器发出一个EMRS命令来使能内存DLLs     20使用DirectCmd寄存器发出一个MRS命令,重启内存DLL     21使用DirectCmd寄存器发出一个PALL命令     22使用DirectCmd寄存器发出两个Auto Refresh(自动刷新)命令     23使用DirectCmd寄存器发出一个MRS命令,program操作参数,不要重启内存DLL     24等待最小200时钟周期     25使用DirectCmd寄存器发出一个EMRS命令给程序的运行参数。如果OCD校正(Off-Chip Driver,片外驱动调校)没有使用,改善一个EMRS命令去设置OCD校准的默认值。在此之后,发送一个EMRS指令去退出OCD校准模式,继续program操作参数     26如果有两组DDR芯片,重复14-25步配置chip1的内存,刚刚配置的是chip0,也就是第一组内存芯片     27配置ConControlto来打开自动刷新计数器     28如果需要power down(休眠)模式,配置MemControl寄存器

二、电路原理图解读

    查阅核心板电路原理图,找到DDR相关部分,S5PV210有两个内存端口,分别为DRAM0和DRAM1,对应地址范围如下:DRAM0:0x20000000——0x3FFFFFFF512MBDRAM1:0x40000000——0x7FFFFFFF1024MBwKioL1dVh3aRwEv1AAHzn_-eH5g021.png
    Smart210开发板共有四片128MB的内存芯片,每片芯片有14根地址线Xm1ADDR[13:0]8根数据线Xm1DATA[7:0],其余为控制总线。wKiom1dVhp3w7AzKAAEnbkDJTQ8202.png
    四片内存芯片并联后逻辑上只是一片内存芯片,大小为512MB,数据线为Xm1DATA[31:0],地址线不变Xm1ADDR[13:0]。根据DRAM原理图的片选引脚nCSCKEnWE择知道,smart210开发板的四片内存芯片挂接到DMC0。

三、SDRAM初始化

sdram_init.S源代码:#include "s5pv210.h"     // MemControlBL=4, 1Chip, DDR2 Type, dynamic self refresh, force precharge, dynamic power down off#define DMC0_MEMCONTROL0x00202400// MemConfig0256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed#define DMC0_MEMCONFIG_00x20F00313// MemConfig1#define DMC0_MEMCONFIG_10x00F00313 // TimingAref   7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E) 200MHZ=0x618#define DMC0_TIMINGA_REF        0x00000618// TimingRow    for @200MHz#define DMC0_TIMING_ROW         0x2B34438A// TimingData   CL=3#define DMC0_TIMING_DATA        0x24240000// TimingPower#define DMC0_TIMING_PWR         0x0BDC0343       .global sdram_init sdram_init://IO端口驱动强度设置// 1. 设置DMC0 Drive Strength (Setting 2X)ldrr0, =ELFIN_GPIO_BASEldrr1, =0x0000AAAAstrr1, [r0, #MP1_0DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_1DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_2DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_3DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_4DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_5DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_6DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_7DRV_SR_OFFSET]ldrr1, =0x00002AAAstrr1, [r0, #MP1_8DRV_SR_OFFSET]
// 2. 初始化PHY DLLldrr0, =APB_DMC_0_BASE//step 3: PhyControl0 DLL parameter setting, manual 0x00101000ldrr1, =0x00101000strr1, [r0, #DMC_PHYCONTROL0]//PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Caseldrr1, =0x00000086strr1, [r0, #DMC_PHYCONTROL1]
//step 2: PhyControl0 DLL onldrr1, =0x00101002strr1, [r0, #DMC_PHYCONTROL0]//step 4: PhyControl0 DLL startldrr1, =0x00101003strr1, [r0, #DMC_PHYCONTROL0] find_lock_val://Loop until DLL is lockedldrr1, [r0, #DMC_PHYSTATUS]andr2, r1, #0x7cmpr2, #0x7bnefind_lock_val //Force Value lockingandr1, #0x3fc0movr2, r1, LSL #18orrr2, r2, #0x100000orrr2 ,r2, #0x1000orrr1, r2, #0x3strr1, [r0, #DMC_PHYCONTROL0] // 3. 初始化DMC0//step 5: ConControl auto refresh offldrr1, =0x0FFF2010strr1, [r0, #DMC_CONCONTROL]//step 6: MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offldrr1, =DMC0_MEMCONTROLstrr1, [r0, #DMC_MEMCONTROL]//step 7: MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixedldrr1, =DMC0_MEMCONFIG_0strr1, [r0, #DMC_MEMCONFIG0]//MemConfig1ldrr1, =DMC0_MEMCONFIG_1strr1, [r0, #DMC_MEMCONFIG1]//step 8:PrechConfigldrr1, =0xFF000000strr1, [r0, #DMC_PRECHCONFIG]//step 9:TimingAref7.8us//133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)ldrr1, =DMC0_TIMINGA_REFstrr1, [r0, #DMC_TIMINGAREF]//TimingRowfor //200MHzldrr1, =DMC0_TIMING_ROWstrr1, [r0, #DMC_TIMINGROW]//TimingDataCL=4ldrr1, =DMC0_TIMING_DATAstrr1, [r0, #DMC_TIMINGDATA]//TimingPowerldrr1, =DMC0_TIMING_PWRstrr1, [r0, #DMC_TIMINGPOWER] // 4. 初始化DDR2 DRAM//DirectCmdchip0 Deselectldrr1, =0x07000000//NOPstrr1, [r0, #DMC_DIRECTCMD]//step 16:DirectCmdchip0 PALLldrr1, =0x01000000//strr1, [r0, #DMC_DIRECTCMD]//step 17:DirectCmdchip0 EMRS2ldrr1, =0x00020000strr1, [r0, #DMC_DIRECTCMD]//step 18:DirectCmdchip0 EMRS3ldrr1, =0x00030000strr1, [r0, #DMC_DIRECTCMD]//step 19:DirectCmdchip0 EMRS1 (MEM DLL on, DQS# disable)ldrr1, =0x00010400strr1, [r0, #DMC_DIRECTCMD]//step 20:DirectCmdchip0 MRS (MEM DLL reset) CL=4, BL=4ldrr1, =0x00000542strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 PALLldrr1, =0x01000000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 REFAldrr1, =0x05000000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 REFAldrr1, =0x05000000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 MRS (MEM DLL unreset)ldrr1, =0x00000442strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 EMRS1 (OCD default)ldrr1, =0x00010780strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 EMRS1 (OCD exit)ldrr1, =0x00010400strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 Deselectldrr1, =0x07100000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 PALLldrr1, =0x01100000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 EMRS2ldrr1, =0x00120000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 EMRS3ldrr1, =0x00130000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 EMRS1 (MEM DLL on, DQS# disable)ldrr1, =0x00110400strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 MRS (MEM DLL reset) CL=4, BL=4ldrr1, =0x00100542strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 PALLldrr1, =0x01100000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 REFAldrr1, =0x05100000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 REFAldrr1, =0x05100000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 MRS (MEM DLL unreset)ldrr1, =0x00100442strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 EMRS1 (OCD default)ldrr1, =0x00110780strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 EMRS1 (OCD exit)ldrr1, =0x00110400strr1, [r0, #DMC_DIRECTCMD]//ConControlauto refresh onldrr1, =0x0FF02030strr1, [r0, #DMC_CONCONTROL]//PwrdnConfigldrr1, =0xFFFF00FFstrr1, [r0, #DMC_PWRDNCONFIG]//MemControlBL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offldrr1, =0x00202400strr1, [r0, #DMC_MEMCONTROL] movpc, lr

四、重定位至SDRAM实践

程序源码文件包含:start.S:程序主函数sdram_init.S:初始化SDRAM的函数led_blink.c:led闪烁函数Makefile和link.lds start.S://#define WDTCON0xE2700000#define SVC_SP0xD0037D80 .global _start _start://C语言运行时栈设置SVC模式下的栈 CPU复位后为SVC模式,DRAM尚未初始化,//只有SRAM可用,0xD00377800xD0037D80,大小1.5Kldr sp,=SVC_SP       

//初始化SDRAMbl sdram_init
//重定位adr r0,_start//加载_start当前运行地址ldr r1,=_start//加载_start的链接地址ldr r2,=bss_start//加载bss段的起始地址cmp r0,r1//比较运行地址和链接地址是否相等beq clean_bss//相等则表明不需要重定位 //拷贝text段和datacopy_loop:ldr r3,[r0],#4str r3,[r1],#4cmp r1,r2bne copy_loop //清除bss段满足C语言运行时要求,编译器会负责清除bss段,//编译器清除了运行时地址的bss段,链接地址的bss段未清除   clean_bss:ldr r0,=bss_startldr r1,=bss_endcmp r0,r1beq run_on_dram//相等则bss为空mov r2,#0clear_loop:str r2,[r0],#4//现将r2放入r0的值对应的内存地址中,然后r0=r0+4cmp r0,r1bne clear_loop
run_on_dram:ldr pc,=led_blink
.end sdram_init.S源码:#include "s5pv210.h" // MemControlBL=4, 1Chip, DDR2 Type, dynamic self refresh, force precharge, dynamic power down off#define DMC0_MEMCONTROL0x00202400// MemConfig0256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed#define DMC0_MEMCONFIG_00x20F00313// MemConfig1#define DMC0_MEMCONFIG_10x00F00313 // TimingAref   7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)#define DMC0_TIMINGA_REF        0x00000618// TimingRow    for @200MHz#define DMC0_TIMING_ROW         0x2B34438A// TimingData   CL=3#define DMC0_TIMING_DATA        0x24240000// TimingPower#define DMC0_TIMING_PWR         0x0BDC0343       .globl sdram_initsdram_init:// 1. 设置DMC0 Drive Strength (Setting 2X)ldrr0, =ELFIN_GPIO_BASEldrr1, =0x0000AAAAstrr1, [r0, #MP1_0DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_1DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_2DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_3DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_4DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_5DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_6DRV_SR_OFFSET]ldrr1, =0x0000AAAAstrr1, [r0, #MP1_7DRV_SR_OFFSET]ldrr1, =0x00002AAAstrr1, [r0, #MP1_8DRV_SR_OFFSET] // 2. 初始化PHY DLLldrr0, =APB_DMC_0_BASE//step 3: PhyControl0 DLL parameter setting, manual 0x00101000ldrr1, =0x00101000strr1, [r0, #DMC_PHYCONTROL0]//PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Caseldrr1, =0x00000086strr1, [r0, #DMC_PHYCONTROL1]
//step 2: PhyControl0 DLL onldrr1, =0x00101002strr1, [r0, #DMC_PHYCONTROL0]//step 4: PhyControl0 DLL startldrr1, =0x00101003strr1, [r0, #DMC_PHYCONTROL0] find_lock_val://Loop until DLL is lockedldrr1, [r0, #DMC_PHYSTATUS]andr2, r1, #0x7cmpr2, #0x7bnefind_lock_val //Force Value lockingandr1, #0x3fc0movr2, r1, LSL #18orrr2, r2, #0x100000orrr2 ,r2, #0x1000orrr1, r2, #0x3strr1, [r0, #DMC_PHYCONTROL0] // 3. 初始化DMC0//step 5: ConControl auto refresh offldrr1, =0x0FFF2010strr1, [r0, #DMC_CONCONTROL]//step 6: MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offldrr1, =DMC0_MEMCONTROLstrr1, [r0, #DMC_MEMCONTROL]//step 7: MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixedldrr1, =DMC0_MEMCONFIG_0strr1, [r0, #DMC_MEMCONFIG0]//MemConfig1ldrr1, =DMC0_MEMCONFIG_1strr1, [r0, #DMC_MEMCONFIG1]//step 8:PrechConfigldrr1, =0xFF000000strr1, [r0, #DMC_PRECHCONFIG]//step 9:TimingAref7.8us//133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)ldrr1, =DMC0_TIMINGA_REFstrr1, [r0, #DMC_TIMINGAREF]//TimingRowfor //200MHzldrr1, =DMC0_TIMING_ROWstrr1, [r0, #DMC_TIMINGROW]//TimingDataCL=4ldrr1, =DMC0_TIMING_DATAstrr1, [r0, #DMC_TIMINGDATA]//TimingPowerldrr1, =DMC0_TIMING_PWRstrr1, [r0, #DMC_TIMINGPOWER] // 4. 初始化DDR2 DRAM//DirectCmdchip0 Deselectldrr1, =0x07000000strr1, [r0, #DMC_DIRECTCMD]//step 16:DirectCmdchip0 PALLldrr1, =0x01000000strr1, [r0, #DMC_DIRECTCMD]//step 17:DirectCmdchip0 EMRS2ldrr1, =0x00020000strr1, [r0, #DMC_DIRECTCMD]//step 18:DirectCmdchip0 EMRS3ldrr1, =0x00030000strr1, [r0, #DMC_DIRECTCMD]//step 19:DirectCmdchip0 EMRS1 (MEM DLL on, DQS# disable)ldrr1, =0x00010400strr1, [r0, #DMC_DIRECTCMD]//step 20:DirectCmdchip0 MRS (MEM DLL reset) CL=4, BL=4ldrr1, =0x00000542strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 PALLldrr1, =0x01000000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 REFAldrr1, =0x05000000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 REFAldrr1, =0x05000000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 MRS (MEM DLL unreset)ldrr1, =0x00000442strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 EMRS1 (OCD default)ldrr1, =0x00010780strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip0 EMRS1 (OCD exit)ldrr1, =0x00010400strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 Deselectldrr1, =0x07100000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 PALLldrr1, =0x01100000strr1, [r0, #DMC_DIRECTCMD]//DirectCmdchip1 EMRS2ldrr1, =0x00120000strr1, [r0, #DMC_DIRECTCMD]