一。运行环境

  开发板: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. APP快速通过苹果AppStore审核九大诀窍

    [IT168技术]对于移动应用开发者来说, 最令人沮丧的可能莫过于辛辛苦苦开发的应用, 没能通过苹果AppStore的审核,或者在应用更新时遭遇下架.苹果的AppStore的审核流程和标准, 一向不透 ...

  2. 重新组织 vs 重新生成索引

    索引是数据库引擎中针对表(有时候也针对视图)建立的特别数据结构,用来帮助查找和整理数据.索引的重要性体现在能够使数据库引擎快速返回查询 结果.当对索引所在的基础数据表进行修改时(包括插入.删除和更新等 ...

  3. 基于html5实现的愤怒的小鸟网页游戏

    之前给大家分享一款基于html5 canvas和js实现的水果忍者网页版,今天给大家分享一款基于html5实现的愤怒的小鸟网页游戏.这款游戏适用浏览器:360.FireFox.Chrome.Safar ...

  4. Linux 必掌握的 SQL 命令

    数据库和 SQL 在本系列教程中,目前我们使用平面文本文件来存储数据.平面文本文件可能适合相对较少的数据,但它们对存储大量数据或查询该数据没有多大帮助.多年来,为该目的开发了多种数据库,包括分层和网络 ...

  5. 基于 SquashFS 构建 Linux 可读写文件系统

    转载:http://www.oschina.net/question/129540_116839 在当前的嵌入式操作系统开发中,Linux 操作系统通常被压缩成 Image 后存放在 Flash 设备 ...

  6. Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include

    来自博客园开发团队开发前线最新消息: 在Entity Framework中,如果实体A关联了实体B,你想在加载实体A的同时加载实体B.通常做法是在LINQ查询中使用Include().但是,如果你在查 ...

  7. 淘宝API Nodejs的实现

    关于<淘宝API Nodejs的实现>这是个很忧伤的故事~~ 体验了win10,目前来说还是不如意的,一些应用程序的卡顿,发热~~难以忍受了.只好重装了系统,可是可是!!! 前段时间写的n ...

  8. [转]position:relative leaves an empty space

    本文转自:http://stackoverflow.com/questions/5229081/positionrelative-leaves-an-empty-space 在使用relative进行 ...

  9. css中常用的几种居中方法

    在前端面试中,大都会问你div居中的方法: 文笔不好,就随便寥寥几句话概括了, 不过以后文笔肯定会变得更好一些的. 今天我们就细数一下几种方法: 1,使用position:absolute,设置lef ...

  10. 关于Windows® API Code Pack for Microsoft® .NET Framework

    相比之前的操作系统,Window 7(or Vista)提供了很多新特性,我们在应用实现中可以利用这些特性来提升用户体验. 这些特性主要包括以下几个方面: Shell Enhancements Dir ...