韦东山嵌入式Linux学习笔记05--存储管理器
SDRAM:
原理图如下:

jz2440 v3开发板上面用的内存芯片为钰创科技公司生产的EM63A165TS,一片内存大小为32MB大小,一共有两块,共64MB的大小.

SDRAM接的是BANK 6,所以他的起始地址是 0x30000000.
SDRAM的基本寻址关系

SDRAM的存储结构逻辑如上图, SDRAM内部是一个存储阵列,阵列就如同表格一样,将数据"填进去".和表格的检索原理一样,先指定一个行,再指定一个列,两点确定一个坐标,就可以准确地找到所需要的
单元格,这就是SDRAM寻址的基本原理.这个单元被称为存储单元,这个表格(存储阵列)就是逻辑Bank(就是L-Bank).SDRAM一般含有四个L-Bank.
对SDRAM的访问可以分为如下几个步骤:
1.CPU发出的片选信号nSCS0有效,它选中SDRAM芯片.
2.SDRAM有四个L-Bank,需要两根地址线来选中其中的一个,根据开发板的设计, 选用了ADDR24和ADDR25作为L-Bank的选择信号.
3.对被选中的芯片进行统一的行/列(存储单元)寻址.
根据SDRAM芯片的列地址线数目设置CPU的相关寄存器后,CPU就会从32位的自动分出L-Bank选择信号, 行地址信号,列地址信号,然后发出行地址信号,列地址信号. L-Bank选择信号在发出行地址信号的同时发出,并维持到列地址信号结束. 有原理图可以看出, 行列地址公用地址线ADDR2-ADDR14(因为DDR的数据位宽为32位,根据2440 datasheet可知,地址线应从A2开始.没有使用ADDR0/1.
使用nSRAS,nSCAS两个信号来区分他们.对于jz2440 v3开发板的SDRAM芯片EM63A165TS的行地址数为13,列地址数位9,所以当nSRAS信号有效时,ADDR2-ADDR14发出来的时行地址信号,它对应的
32位地址空间的bit[23:11](为什么?),当nSCAS信号有效时,ADDR2-ADDR10发出来的时列地址信号,它对应32位地址空间的bit[10:2];

4.找到存储芯片后,被选中的芯片就要进行统一的数据传输了.
开发板使用两片16位的SDRAM芯片并联组成32位的位宽,与CPU的32跟数据线相连(DATA0-DATA31).
BANK6的起始地址为0x30000000,所以SDRAM的访问地址为0x30000000-0x33FFFFFF,共64MB.

存储控制器的的寄存器的使用方法
存储控制器共有13个寄存器,BANK0-BANK5只需要设置BWSCON和BANKCONx两个寄存器,BANK6-BANK7外接SDRAM时, 除BWSCON和BANCONx外,还要设置REFLESH,BANKSIZE,MRSRB6,MRSRB7等4个寄存器.


由上图BANCON寄存器发现,每四位控制一个BANK,最高四位对应BANK7,以此类推.
STx: 启动/禁止SDRAM的数据掩码引脚,对于SDRAM,此位为0;对于SRAM,此位为1.
WSx: 是否使用寄存器的WAIT信号,通常设为0.
DWx: 使用两位来设置相应BANK的位宽,0b00对应8位,0b01应16位,0b10对应32位,0b11保留.
比较特殊的是BANK0,它没有ST0和WS0,DW0只读--由OM0和OM1上电前的电平决定,OM1一直为低,所以只有当OM0为高时,位宽为16bit, 当OM0为低时,选择Nandflash mode.


BWSCON可以设置成0010 0010 0000 0001 0001 0001 0001 0000 0x2201 1110


BANKCONx (x为0~5)
这几个寄存器用来控制BANK0-BANK5外接设备的访问时序,jz2440上使用默认的0x0700

BANKCONx (x为6~7)
在8个BANK中,只有BAN6 AND BAN7可以外接SRAM和SDRAM.BANKCON6和BANKCON7与其他BANK有所不同.

MT: 用于设置本BANK外接的时ROM/SRAM还是SDRAM.SRAM 0b00, SDRAM 0b11
当MT=0b00,此寄存器与BANKCON0---BANKCON5类似.
当MT=0b11,值如下设置
Trcd: RAS to CAS delay, 设为推荐之0b01
SCAN: SDRAM的列地址数,对于这个SDRAM来说, 为9, 所以SCAN=0b01.
这个寄存器应设为 0x00018005
刷新控制寄存器RFFRESH(REFRESH CONTROL REGISTER) 设为0x008c0000 + R_CNT
REFEN: 0= 禁止SDRAM的刷新功能, 1=开启SDRAM的刷新功能
TREFMD: SDRAM的刷新模式. 0 =CBR/auto Refresh,1=Self Refresh(一般在系统休眠时使用).
Trp: 设置为0即可.
Tsrc: 设为默认值0b11即可.
Refresh Counter: 即上述的R_CNT
R_CNT如下计算:(SDRAM时钟频率就是HCLK)
R_CNT = 2^11 + 1 - SDRAM时钟频率(Mhz) * SDRAM刷新周期(us)
如下图, 刷新周期 64ms/8192 = 7.8125us
在未使用PLL时, SDRAM时钟频率等于晶振频率12Mhz.
可以计算:
R_CNT= 2^11 + 1 - 12 * 7.8125 = 1955
所以在未使用PLL时, REFRESH = 0x008c0000 + 1955 = 0x8c07a3


BANKSIZW寄存器REFRESH (BANKSIZE REGISTER)
BURST_EN:
0: ARM核禁止突发传输
1: ARM核允许突发传输
SCKE_EN[5]:
0: 不使用信号令SDRAM进入省电模式,1使用SCKE信号令SDRAM进入省电模式.
SCKE_EN[4]:
0: 时刻发出SCLK信号,1=仅在访问SDRAM期间发出SCLK信号.
BK76MAP:
设置BANK7/6的大小.
BANK6/7对应的地址空间与BANK0-5不同. BANK0-5的地址空间大小都是固定的128MB,BANK6/7的地址空间大小都是可变的.以保持这两个空间的地址连续,即BANK7的起始地址会随它们的大小变化. BANK6/7的取值意义如下:

jz2440 v3开发板BANK6外接的时64M的SDRAM(两片32MB),令[2:0]=0b001(64M/64M),表示BANK6 BANK7的容量都是64M.虽然BANK7没有使用.
综上, BANKSIZE寄存器的值应该设为 0xB1
SDRAM模式设置寄存器MRSRBx
能修改的只有CL,这是SDRAM时序的一个时间参数; 由datasheet可知, SDRAM芯片支持CL =2或者3,开发板选择了3,所以 MRSRB6/7的值为0x30


操作实例: 使用SDRAM
从NAND Flash启动CPU时, CPU会通过内部硬件将NandFlash开始的4KB数据复制到称为Steppingston的4KB内部RAM中(起始地址为0),然后跳到地址0开始执行.

例子中先使用汇编设置好储存控制器,使外接的SDRAM可用,然后把程序本身从Steppintstone复制到SDRAM处;最后跳转到执行.
.equ MEM_CTL_BASE, 0x48000000 @命令用于把常量值设置为可以在文本段中使用的符号
.equ SDRAM_BASE, 0x30000000 .text
.global _start
_start:
bl disable_watch_dog @ 关闭WATCHDOG否则CPU会不断重启.
bl memsetup @ 拷贝之前,要先设置存储控制器,不然SDRAM用不了
bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中
ldr pc, =on_sdram @ 跳转到中继续执行
on_sdram:
ldr sp, =0x34000000 @ 随便设一个没用到的地址吗?
bl main @ 跳转到main函数
halt_loop: @ 死循环
b halt_loop disable_watch_dog:
mov r1, #0x53000000 @ 直接往这个寄存器写0就可以达到关闭看门狗的目的
mov r2, #0x0
str r2, [r1]
mov pc, lr @不会自动返回吗? 还要将PC指向跳转函数bl保存的Lr值 copy_steppingstone_to_sdram: @ 这个函数主要实现将4K大小的数据从CPU内部SRAM拷贝到SDRAM
mov r1, #0 @ 这个地址就是Steppingstone的起始地址.
ldr r2, =SDRAM_BASE @ SDRAM的起始地址
mov r3, #*1024 @ 4KB大的空间
:
ldr r4, [r1],# @ 从steppintstone中读取4字节的数据到r4中,并让r4地址加4
str r4, [r2],# @ 紧接着将刚刚刚读取到r4的数保存到r2所指向的内存单元中,r2一开始指向SDRAM的起始地址
cmp r1, r3 @ 比较是否已经拷贝4KB大小的数据了
bne 1b @ 如果不相等,说明还没由拷贝完,继续跳转到标号1处执行.
mov pc, lr @ 如果相等,函数返回. memsetup:
mov r1, #MEM_CTL_BASE @ 0x4800000000
adrl r2, mem_cfg_val @ ADRL 伪指令用于将一个地址加载到寄存器中。
add r3, r1, # @ * = 54 r3 = r1 + 52, 基于base地址需要52个字节空间. 每个寄存器大小为4字节,共有13个寄存器
:
ldr r4, [r2], # @ 将r2中存储寄存器中的地址保存到r4中, r2 = r2 + 4;指向下一个寄存器所代表的值
str r4, [r1], # @ 将r4中的值取出来写到r1中, 以达到配寄存器的目的
cmp r1, r3 @ 比较一下是否写完了
bne 1b @ 如果没有,跳转到1标号处继续执行
mov pc, lr @ 否则函数返回 .align
mem_cfg_val:
.long 0x22011110 @ BWSCON
.long 0x00000700 @ BANKCON0
.long 0x00000700 @ BANKCON1
.long 0x00000700 @ BANKCON2
.long 0x00000700 @ BANKCON3
.long 0x00000700 @ BANKCON4
.long 0x00000700 @ BANKCON5
.long 0x00018005 @ BANKCON6
.long 0x00018005 @ BANKCON7
.long 0x008C07A3 @ REFRESH
.long 0x000000B1 @ BANKSIZE
.long 0x00000030 @ MRSRB6
.long 0x00000030 @ MRSRB7
main函数, 可以不关注这个函数的功能,实现LED点亮的功能, 方便验证函数已经跑到这.
#define GPFCON (*(volatile unsigned long *)0x56000050)
#define GPFDAT (*(volatile unsigned long *)0x56000054) #define GPF4_out (1<<(4*2))
#define GPF5_out (1<<(5*2))
#define GPF6_out (1<<(6*2)) void wait(volatile unsigned long dly)
{
for(; dly > ; dly--);
} int main(void)
{
unsigned long i = ; GPFCON = GPF4_out|GPF5_out|GPF6_out; // while(){
wait();
GPFDAT = (~(i<<)); //
if(++i == )
i = ;
} return ;
}
Makefile
sdram.bin : head.S leds.c
arm-linux-gcc -c -o head.o head.S
arm-linux-gcc -c -o leds.o leds.c
arm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf
arm-linux-objcopy -O binary -S sdram_elf sdram.bin
arm-linux-objdump -D -m arm sdram_elf > sdram.dis
clean:
rm -f sdram.dis sdram.bin sdram_elf *.o
最后将程序烧录到nandflash中验证一下.
韦东山嵌入式Linux学习笔记05--存储管理器的更多相关文章
- 韦东山嵌入式Linux学习笔记02--如何给开发板烧录程序
购买韦东山嵌入式开发板jz2440 v3会标配两根usb线和一根网线,OpenJtag需要单独购买, 我暂时还没买到该工具. 下面介绍usb烧录以及通过网线烧录程序. 1.usb烧录程序: 借助DNW ...
- 韦东山嵌入式Linux学习笔记08--中断体系结构
中断是什么? 举个栗子, 系统怎么知道你什么时候插入鼠标这个设备? 可以有两种处理方式: 1. 查询方式: 轮询去检测是否有设备插入; 2. 中断的方式 当鼠标插入这个事件发生时, 置位某个寄存器,告 ...
- 韦东山嵌入式Linux学习笔记07--Nandflash
常用的flash有两种, Norflash和Nandflash, 前几年市场上的产品比较常见的方案时Norflash和Nandflash搭配使用, 因为norflash比较昂贵,相同的容量norfla ...
- 韦东山嵌入式Linux学习笔记04--点亮开发板的一个LED灯
搜索开发板原理图LED的走线 LED8是网线接口的指示灯. 在这里我们尝试用汇编代码控制D10, 也就是LED1,它连接到EINT4/GPF4,读取芯片手册 有原理图可知,如果需要 ...
- 韦东山嵌入式Linux学习笔记03--如何搭建软件环境
1. 从网上下一个虚拟机,比如vmvare station 2.下一个ubuntu镜像回来安装, 我下了14.04来安装.参考链接: https://blog.csdn.net/qq1326702 ...
- 韦东山嵌入式Linux学习笔记01--转载: 板子ping不通PC怎么办
请参考链接:https://blog.csdn.net/u013490896/article/details/71250060 我的环境: window 10 jz2440 v3 我采用的连接方式如下 ...
- 韦东山 嵌入式linux教程 笔记
@ 目录 资源链接 一.常用命令 二.shell 三.如何更改PATH? 四.路径 五.vi编辑器 六.进阶命令 七.NAT配置网络 (第2篇-P34) 八.开发板挂载 Ubuntu 的 NFS 目录 ...
- 嵌入式Linux学习笔记之第一阶段---基础篇
嵌入式Linux学习分五个阶段 第一阶段: 01嵌入式环境搭建初期 02C语言语法概述 03C语言内存操作 04c语言函数 05linux基础 06gun基础 第二阶段: 01-linux之io系统编 ...
- 嵌入式Linux学习笔记(三) 字符型设备驱动--LED的驱动开发
在成功构建了一个能够运行在开发板平台的系统后,下一步就要正式开始应用的开发(这里前提是有一定的C语言基础,对ARM体系的软/硬件,这部分有疑问可能要参考其它教程),根据需求仔细分解任务,可以发现包含的 ...
随机推荐
- 由STL map调用clear后,内存不返还给操作系统的问题出发,探讨glibc malloc/free行为(转)
1. 问题 我们的程序有几十个线程,每个线程拥有一个std::map,每个线程都要向自己的std::map中插入大量的数据,但每个数据只有几十字节:当使用完std::map,调用map.clear() ...
- Linux0.11之进程0创建进程1(1)
进程0是由linus写在操作系统文件中的,是预先写死了的.那么进程0以后的进程是如何创建的呢?本篇文章主要讲述进程0创建进程1的过程. 在创建之前,操作系统先是进行了一系列的初始化,分别为设备号.块号 ...
- Windows 和 Office 大客户激活方法
激活Windows 10 找到Powershell,然后右键管理员身份运行,依次输入下面的命令,注意将$host切换成为你组织的服务器地址: slmgr.vbs -upk slmgr.vbs -ipk ...
- 什么是maven?maven中的pom文件是做什么的?
Maven 是专门用于构建和管理Java相关项目的管理工具. 1.使用Maven管理的Java 项目都有着相同的项目结构 2.统一维护jar包 POM是项目对象模型(Project Object Mo ...
- flask 之(四) --- 扩展|缓存|会话
扩展 蓝图内置扩展 (实现的是路由的拆分) '''----------- app.py -------------''' from flask import Flask from users_view ...
- 【AMAD】django-extensions -- Django框架的自定义命令扩展集合
动机 简介 个人评分 动机 使用Django进行开发的时候,会不会感觉开发工具少了一些.比如每次进入python shell调试的时候要重新import每个model. 简介 django-exten ...
- 【DSP开发】【VS开发】PCIE设备扫描过程
初步了解完PCI总线标准之后,我们接下来正式开始PCIe设备的漫游之旅.从我们按下PC的电源按钮开始,BIOS就接管系统控制权开始工作,它会先进行一些内存和设备的初始化工作(当然,也包括我们的PCI设 ...
- C学习笔记-结构体
结构体的定义和初始化 结构体是简单数据类型的综合 struct man { char name[100]; int age; }; struct man m = { "tom", ...
- 【linux杂谈】查看centOS系统的版本号和内核号
因为种种原因,我们通常需要查看centOS系统的版本号和内核号. 这里以centOS 6为切入点,展示了几种查看版本号和内核号的方法,同时也验证了其在centOS 7上的可行性. 一.centOS 6 ...
- Centos8 安装ifconfig(net-tools.x86_64)
情况: yum search net-tools.x86_64 没有找到结果 解决: 1.yum search net-tools 2. yum install -y net-tools.x86_64 ...