韦东山嵌入式Linux学习----008 SDRAM自定义

SDRAM自定义操作

**注:本文章是基于韦东山老师arm裸机第一期视频教程
**硬件平台:嵌入式Linux开发板s3c2440
**软件平台:运行于VMware Workstation 12 Player下的UbuntuLTS16.04_x64 系统
**参考资料:《高手进阶,终极内存技术指南——完整/进阶版》、S3C2440芯片手 册、EM63A165TS(SDRAM)芯片手册、开发版电路原理图

一、基础知识点

  • 物理 Bank
      传统内存系统为了保证 CPU 的正常工作,必须一次传输完 CPU 在一个传输周期内所需要的数据。而 CPU 在一个传输周期能接受的数据容量就是 CPU 数据总线的位宽,单位是 bit(位)。当时控制内存与 CPU 之间数据交换的北桥芯片也因此将内存总线的数据位宽等同于 CPU 数据总线的位宽,而这个位宽就称之为物理Bank(Physical Bank,简称 P-Bank)的位宽。
  • 芯片位宽
      每个内存芯片也有自己的位宽,即每个传输周期能提供的数据量
  • 存储单元数量(容量)
      存储单元数量=行数×列数(得到一个 L-Bank 的存储单元数量)×L-Ban的数量
      常用方式:M×W
      {
         M 是该芯片中存储单元的总数,单位是兆
         W 代表每个存储单元的容量,也就是 SDRAM 芯片的位宽(Width),单位是 bit
      }

二、SDRAM概念

  • 英文全称:Synchronous Dynamic Random Access Memory
  • 中文名字:同步动态随机存储器———拆分理解

  -同步:其时钟频率与CPU前端总线的系统时钟频率相同(如开发实例中:SDRAM时钟频率为CPU的HCLK)
  -动态:存储阵列需要不断的刷新来保证数据不丢失
  -随机:数据不是线性一次存储,而是自由指定地址进行数据的读写

  • 内存控制器的执行流程
    如指令: ldr r1, [r0] /* 读内存的数据 */
    a.CPU将地址发送给内存控制器
    b. 内存控制器根据地址发出片选信号nGCS6
    c.根据接的类型是SDRAM,拆分地址(BANK地址、发出行地址、发出列地址)

三、寄存器配置

  1. 查看电路原理图、S3C2440芯片手册分析

在这里插入图片描述

分析可知:两片十六位的SDRAM芯片地址位和数据位接在一起构成!32!位的芯片;
         片选信号为CS6;	       

在这里插入图片描述

分析可知:SDRAM连接HCLK,HCLK已设置为100MHZ
  1. 查看S3C2440芯片手册,配置所需寄存器
    (1)BWSCON(总线宽度和等待控制寄存器)

在这里插入图片描述
ST7 [31]=0-------Not using UB/LB (The pins are dedicated nWBE[3:0])时序图可知
WS7 [30]=0-------WAIT disable使用不到
DW7 [29:28]=10—电路图连接为32位芯片
ST6 [27]=0-------Not using UB/LB (The pins are dedicated nWBE[3:0])时序图可知
WS6 [26]=0-------WAIT disable使用不到
DW6 [25:24]=10—电路图连接为32位芯片

最终得:BWSCON = 0x22000000;

 (2)BANKCON6 BANKCON7

在这里插入图片描述
在这里插入图片描述
MT [16:15]=11----Sync. DRAM 使用外接的SDRAM
Trcd [3:2]=00----2 clock 时钟周期为10ns,2 clock=20ns,选取最大值21ns
SCAN [1:0]=01----9-bit 查SDRAM手册知道column address A0-A8

最终得:BANKCON6 = 0x00018001;
        BANKCON7 = 0x00018001;

 (3)REFRESH

在这里插入图片描述
在这里插入图片描述
REFEN [23]=1-----Enable (self or CBR/autorefresh)
TREFMD [22]=0----CBR/Auto Refresh
Trp [21:20]=00—2 clocks = 20ns
Tsrc [19:18]=01–5 clocks = 50ns Trc=Tsrc+Trp Trc查手册Trc取最大70ns 70ns=Tsrc+ 20ns(上面已经设置Trp)
Refresh Counter [10:0]=1269 --8192 refresh cycles/64ms

最终得:REFRESH = 0x8404f5;

 (4)BANKSIZE

在这里插入图片描述
URST_EN [7]=1—Enable burst operation ARM核突发操作使能,即一次访问多个字节
SCKE_EN [5]=1----SDRAM power down mode enable
SCLK_EN [4]=1-----SCLK is active only during the access (recommended)
BK76MAP [2:0]=001–64MB

扫描二维码关注公众号,回复: 9290967 查看本文章
最终得:BANKSIZE = 0x000000b1;

 (5)MRSRB6、MRSRB7

在这里插入图片描述
EM63A165TS芯片资料
CL [6:4]=010-----2 clock CAS Latency: 2, or 3

最终得:MRSRB6 = 0x00000020;
        MRSRB7 = 0x00000020;

补充知识点说明:
  ——tAC(Access Time from CLK 时钟触发后的访问时间)
  此时数据已经被触发,经过一定的驱动时间最终传向数据 I/O 总线进行输出
   !必须要小于一个时钟周期
 ——tRCD(RAS to CAS Delay(RAS 至 CAS 延迟))
  在发送列读写命令时必须要与行有效命令有一个间隔,大家也可以理解为行选通周期
 ——CL(CAS Latency,CAS 潜伏期)
  从 CAS 与读取命令发出到第一笔数据输出的这段时间
  !CL 只出现在读取操作中

四、 代码编写

sdram_init.c文件编写

#include "s3c2440_soc.h"

void sdram_init(void)
{
	BWSCON = 0x22000000;     //初始化BWSCON,选用BANK6,7
	BANKCON6 = 0x00018001;
	BANKCON7 = 0x00018001;
	REFRESH = 0x8404f5;	
	BANKSIZE = 0x000000b1;
	MRSRB6 = 0x00000020;     //设置CL为2clock,具体查手册
	MRSRB7 = 0x00000020;     //设置CL为2clock,具体查手册		
}
int sdram_test(void)
{		
	int i;
	volatile unsigned char *p = (volatile unsigned char *)0x30000000; //p指针指向sdram的地址
	
	//写数据到sdram,从0x30000000到0x30001000都写入0x22
	for(i=0;i<=1000;i++)
	{
		p[i] = 0x22;
	}

	//从sdram读数据
	for(i=0;i<=1000;i++)
	{
		if(p[i] != 0x22)
			return -1;
	}
	return 0;
}

sdram_init.h文件编写

#ifndef _SDRAM_INIT_H
#define _SDRAM_INIT_H

void sdram_init(void);	
int sdram_test(void);

#endif

main.c文件编写

#include "s3c2440_soc.h"
#include "uart.h"
#include "sdram_init.h"
#include "led.h"

int main(void)
{
	unsigned char c;
	int flag;
	
	uart0_init();
	sdram_init();
	puts("Uart0 text success!\n\r");

	flag=sdram_test();

	if(flag == 0)
	{
		while(1)
		{
			puts("Sdram init success!\n\r");
			led_test();			
	    }
	}
	else
		puts("Sdram init failure!\n\r");
	
	return 0;
}

发布了6 篇原创文章 · 获赞 0 · 访问量 219

猜你喜欢

转载自blog.csdn.net/weixin_42813232/article/details/102666245