一。运行环境

  开发板:jz2440

  系统:  ubuntu12.04

  编译器:arm-linux-gcc

二、特殊寄存器

sdram的操作无需按照时序图来设置,只要设置好相关的13个寄存器,arm处理器里面的存储管理器会自动输出控制信号

     .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

先看BWSCON:

每四位控制一个BKNK

对于SDRAM,ST7设置为0,SRAN则设置为1

WSx通常设置为0

DBx设置为01b,这个一般按照实际情况来设置,还要参照具体开发板上面存储资源。

对于这六个寄存器,主要设置时序的,默认值就欧克

MT[16:15]设置SRAM   OR  SDRAM   ,这里设置0B11

如果是sdram,那么Trcd 设为推荐值0b10

SCAN 设置为9-bit

对于刷新寄存器,注意低11位会根据CLK不同而不同,也就是说使用PLL与否,会有不同的值

由此可算出

Refreh_count =2^12+1-12*64/8092=1955

REFRESF=0x008c0000+1955

  先看代码:这里主要有三个head.S  ,led.c ,Makefile,其中led的代码同流水灯一样,直接拷贝过来。

  此外外,代码参考韦东山先生的源码,经过烧写可验证没问题。

三。直接贴代码

先看Makefile:

 sdram.bin:head.S led.c
arm-linux-gcc -Wall -O2 -c -g -o head.o head.S
arm-linux-gcc -Wall -O2 -c -g -o led.o led.c
arm-linux-ld -Ttext 0x30000000 head.o led.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.bin sdram_elf*.o sdram.dis

再看head.h

 .equ MEM_BASE,0x48000000
.equ SDRAM_BASE,0x30000000 .text
.global _start
_start: bl close_watchdog @关闭看门狗
bl mem_set @设置存储寄存器组
bl steppingstone_sdram @复制代码到sdram ldr pc,=on_sdram
on_sdram:
ldr sp,=0x34000000
bl main
halt_loop:
b halt_loop close_watchdog:
mov r1,#0x53000000
mov r2,#0x0
str r2,[r1] mov pc,lr @返回 steppingstone_sdram: @起始地址0x00000000,目标地址0x30000000
mov r1,#
ldr r2,=SDRAM_BASE
mov r3,#* copy_loop:
ldr r4,[r1],#
str r4,[r2],# cmp r1,r3
bne copy_loop
mov pc,lr @返回 mem_set:
mov r1,#MEM_BASE adrl r2,JCQ
add r3,r1,# @* set_loop:
ldr r4,[r2],#
str r4,[r1],#
cmp r1,r3
bne set_loop mov pc,lr .align
JCQ:
.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

其实没什么改动,换些名字而已,但是自己敲的话,当然会有一些细节上面会出错,不注意的地方。

以上启动文件是以汇编编写的,下面贴出c语言版的。

head.S:

 .extern main
.text
.global _start
_start:
b reset reset:
ldr sp,= @ bl close_watchdog @关闭看门狗
bl mem_set @设置存储寄存器组
bl steppingstone_sdram @复制代码到sdram ldr pc,=on_sdram
on_sdram:
ldr sp,=0x34000000
ldr pc,=0x30000000
halt_loop:
b halt_loop

init.c:

 /*************************************************************************
> File Name: init.c
> Author: hulig
> Mail:
> Created Time: 2014年11月08日 星期六 15时52分55秒
>function:init disable watchdog ,init mem .goto main and on
>result:ok
************************************************************************/ #define WTCON (*(volatile unsigned long *)0x53000000)
#define MEM_BASE (*(volatile unsigned long *)0x48000000) void close_watchdog()
{
WTCON =; //往看门狗寄存器里写0 就可以啦
} void mem_set() //与sdram设置有关的13个寄存器写入对应的值就ok
{
unsigned long const mem_jcq[]={
0x22011110,
0x00000700,
0x00000700,
0x00000700,
0x00000700,
0x00000700,
0x00000700,
0x00018005,
0x00018005,
0x008c07a3,
0x000000b1,
0x00000030,
0x00000030,
}; int i=;
volatile unsigned long *p=(volatile unsigned long *)MEM_BASE;
for(;i<;i++)
p[i]=mem_jcq[i];
} void steppingstone_sdram(void)
{
unsigned int *pSrc=(unsigned int *); // 将steppingstone 0地址复制到sdram起始地址
unsigned int *pDes =(unsigned int *)0x30000000;//sdram起始地址 while(pSrc<(unsigned int*))
{
*pDes=*pSrc;
pDes++;
pSrc++;
} }

上面c代码并不能达到预期的效果,其主要问题点是sdram的初始化,也就是给13个寄存器赋值的时候:

 《一》。
#define BWSCON (*(volatile unsigned long * )0x48000000)
#define BANKCON0 (*(volatile unsigned long * )0x48000004)
#define BANKCON1 (*(volatile unsigned long * )0x48000008)
#define BANKCON2 (*(volatile unsigned long * )0x4800000c)
#define BANKCON3 (*(volatile unsigned long * )0x48000010)
#define BANKCON4 (*(volatile unsigned long * )0x48000014)
#define BANKCON5 (*(volatile unsigned long * )0x48000018)
#define BANKCON6 (*(volatile unsigned long * )0x4800001c)
#define BANKCON7 (*(volatile unsigned long * )0x48000020)
#define REFRESH (*(volatile unsigned long * )0x48000024)
#define BANKSIZE (*(volatile unsigned long * )0x48000028)
#define MRSRB6 (*(volatile unsigned long * )0x4800002c)
#define MRSRB7 (*(volatile unsigned long * )0x48000030) void mem_set()
{
BWSCON= 0x22011110;
BANKCON0=0x00000700;
BANKCON1=0x00000700;
BANKCON2=0x00000700;
BANKCON3=0x00000700;
BANKCON4=0x00000700;
BANKCON5=0x00000700;
BANKCON6=0x00018005;
BANKCON7=0x00018005;
REFRESH=0x008c07a3;
BANKSIZE=0x000000b1;
MRSRB6 =0x00000030;
MRSRB7= 0x00000030;
} 《二》。
void mem_set() //与sdram设置有关的13个寄存器写入对应的值就ok
{
int i=;
unsigned long *p=(unsigned long *)MEM_BASE;
unsigned long const mem_jcq[]={
0x22011110,
0x00000700,
0x00000700,
0x00000700,
0x00000700,
0x00000700,
0x00000700,
0x00018005,
0x00018005,
0x008c07a3,
0x000000b1,
0x00000030,
0x00000030,
}; for(;i<;i++)
p[i]=mem_jcq[i];
} 《三》。 #define MEM_CTL_BASE 0x48000000
#define MEM_CTL_END 0x48000034
unsigned long const mem_cfg_val[]={ // 声明数组存放内存控制器设置数据 0x22000000, //BWSCON
0x00000700, //BANKCON0
0x00000700, //BANKCON1
0x00000700, //BANKCON2
0x00000700, //BANKCON3
0x00000700, //BANKCON4
0x00000700, //BANKCON5
0x00018005, //BANKCON6
0x00018005, //BANKCON7
0x008e07a3, //REFRESH(HCLK = 12MHz,该值为0x008e07a3 //HCLK = 100MHz 0x008e04f5)
0x000000b1, //BANKSIZE
0x00000030, //MRSRB6
0x00000030, //MRSRB7
};

上面是三种写法,唯有第一种可行。why?

比较一,二,三以及查阅资料可知,其根本原因是位置无关码

注意,在复制代码到sdram之前,链接地址是0x30000000,也就是sdram的起始地址,此时若想正确执行,必须是使用跳转指令。

二和三中都是以数组的形式存储,自然不会是位置无关,因而行不通。

那么,怎么编写位置无关码呢?

先总结基本为两点

一。在汇编中,使用B/BL指令

二。在c中,避免使用static来限定范围;连续寄存器组尽量分别赋值。

附,另一个可行的办法:

 void memsetup(void)
{
volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE; /* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值
* 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到
* SDRAM之前就可以在steppingstone中运行
*/
/* 存储控制器13个寄存器的值 */
p[] = 0x22011110; //BWSCON
p[] = 0x00000700; //BANKCON0
p[] = 0x00000700; //BANKCON1
p[] = 0x00000700; //BANKCON2
p[] = 0x00000700; //BANKCON3
p[] = 0x00000700; //BANKCON4
p[] = 0x00000700; //BANKCON5
p[] = 0x00018005; //BANKCON6
p[] = 0x00018005; //BANKCON7
p[] = 0x008C07A3; //REFRESH
p[] = 0x000000B1; //BANKSIZE
p[] = 0x00000030; //MRSRB6
p[] = 0x00000030; //MRSRB7
}

实验三——SDRAM的更多相关文章

  1. FPGA与simulink联合实时环路系列——实验三 按键key

    实验三 按键key 实验内容 在FPGA的实验中,经常涉及到按键的使用,按键是必不可少的人机交互的器件之一,在这些实验中,有时将按键的键值读取显示到数码管.LCD或者是通过串口传送到PC的串口助手上进 ...

  2. Java实验三

    20145113 20145102实验三 实验步骤 编码标准 编程标准包含:具有说明性的名字.清晰的表达式.直截了当的控制流.可读的代码和注释,以及在追求这些内容时一致地使用某些规则和惯用法的重要性 ...

  3. Verilog HDL那些事_建模篇笔记(实验三:按键消抖)

    实验三:按键消抖 首先将按键消抖功能分成了两个模块,电平检查模块和10ms延迟模块.电平检测模块用来检测按键信号的变化(是否被按下),10ms延迟模块用来稳定电平检查模块的输入,进而稳定按键信号,防止 ...

  4. 20145229&20145316 《信息安全系统设计基础》实验三 实时系统的移植

    实验封面 实验内容 1.安装ADS(安装文件在00-ads1.2目录下,破解方法00-ads1.2\Crack目录下) 2.安装GIVEIO驱动(安装文件在01-GIVEIO目录下) 3.把整个GIV ...

  5. 20145301&20145321&20145335实验三

    20145301&20145321&20145335实验三 这次实验我的组员为:20145301赵嘉鑫.20145321曾子誉.20145335郝昊 实验内容详见:实验三

  6. 20145212 实验三《敏捷开发与XP实践》

    20145212 实验三<敏捷开发与XP实践> 实验内容 使用git上传代码 与20145223同学一组,使用git相互更改代码 同组实验报告链接:http://www.cnblogs.c ...

  7. 20145213《Java程序设计》实验三敏捷开发与XP实践

    20145213<Java程序设计>实验三敏捷开发与XP实践 实验要求 1.XP基础 2.XP核心实践 3.相关工具 实验内容 1.敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法 ...

  8. 20145206《Java程序设计》实验三实验报告

    20145206<Java程序设计>实验三实验报告 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运 ...

  9. 20145308刘昊阳 《Java程序设计》实验三 敏捷开发与XP实践 实验报告

    20145308刘昊阳 <Java程序设计>实验三 敏捷开发与XP实践 实验报告 实验名称 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 统计的PSP(Personal ...

随机推荐

  1. Linux / Unix Command: bunzip2--reference

    http://linux.about.com/library/cmd/blcmdl1_bunzip2.htm NAME bzip2, bunzip2 - a block-sorting file co ...

  2. WPF 之 左键弹出操作菜单,并禁用右键菜单

    在目前的WPF版本中,很多的控件都有一个ContextMenu的属性,可以设置组件的右键菜单,这点确实是很方便,但是有些时候我们可能会需要当单击鼠标左键才弹出这个ContextMenu,而不是单击鼠标 ...

  3. bing 输入法,切换简体、繁体快捷键与myeclipse 格式化代码冲突。。

    bing 输入法,切换简体.繁体快捷键与myeclipse 格式化代码冲突...蛋碎 myeclipse 代码格式化快捷键是:ctrl+shift+F,bing输入法简体.繁体切换也是,于是蛋疼的事情 ...

  4. Java_Web使用简单的批处理操作

    之前进行Web开发的时候使用的是myeclipse,但只用过的人都知道,由于其插件太多,而且有很多插件的功能根本就接触不到.所以导致一旦工程稍微大一点就会很卡,虽然之前也对其进行优化过,但还是觉得不太 ...

  5. JAVA WEB 作用域之间的区别

    JAVA WEB 作用域 1.page属性范围(pageContext) a.在一个页面设置的属性,跳转到其他页面就无法访问了(包括重定向和). 示例:pageScopeDemo01.jsp < ...

  6. Java实现深克隆的两种方式

    序列化和依次克隆各个可变的引用类型都可以实现深克隆,但是序列化的效率并不理想 下面是两种实现深克隆的实例,并且测试类对两种方法进行了对比: 1.重写clone方法使用父类中的clone()方法实现深克 ...

  7. JQuery方法扩展

    第一种 extend <!-- extend 扩展jQuery,其实就是增加一个静态方法 --> 定义: $.extend({ sayHello:function(name) { aler ...

  8. how to build a paper's architecture?

    1. problem? what's the problem? then do some extension of the problem. 2. related works ,which means ...

  9. JDBC批处理读取指定Excel中数据到Mysql关系型数据库

    这个demo是有一个Excel中的数据,我需要读取其中的数据然后导入到关系型数据库中,但是为了向数据库中插入更多的数据,循环N次Excel中的结果. 关于JDBC的批处理还可以参考我总结的如下博文: ...

  10. hdu 4745 动态规划

    思路:特水的一个最长回文子序列动态规划.比赛时硬卡第一题,49WA后终于AC,可惜没时间做这题,结果成绩也就可想而知了.兔子跳一样权值的石头,并且一个正跳,一个反跳,这不就是个回文子序列吗?????! ...