实验三——SDRAM
一。运行环境
开发板: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的更多相关文章
- FPGA与simulink联合实时环路系列——实验三 按键key
实验三 按键key 实验内容 在FPGA的实验中,经常涉及到按键的使用,按键是必不可少的人机交互的器件之一,在这些实验中,有时将按键的键值读取显示到数码管.LCD或者是通过串口传送到PC的串口助手上进 ...
- Java实验三
20145113 20145102实验三 实验步骤 编码标准 编程标准包含:具有说明性的名字.清晰的表达式.直截了当的控制流.可读的代码和注释,以及在追求这些内容时一致地使用某些规则和惯用法的重要性 ...
- Verilog HDL那些事_建模篇笔记(实验三:按键消抖)
实验三:按键消抖 首先将按键消抖功能分成了两个模块,电平检查模块和10ms延迟模块.电平检测模块用来检测按键信号的变化(是否被按下),10ms延迟模块用来稳定电平检查模块的输入,进而稳定按键信号,防止 ...
- 20145229&20145316 《信息安全系统设计基础》实验三 实时系统的移植
实验封面 实验内容 1.安装ADS(安装文件在00-ads1.2目录下,破解方法00-ads1.2\Crack目录下) 2.安装GIVEIO驱动(安装文件在01-GIVEIO目录下) 3.把整个GIV ...
- 20145301&20145321&20145335实验三
20145301&20145321&20145335实验三 这次实验我的组员为:20145301赵嘉鑫.20145321曾子誉.20145335郝昊 实验内容详见:实验三
- 20145212 实验三《敏捷开发与XP实践》
20145212 实验三<敏捷开发与XP实践> 实验内容 使用git上传代码 与20145223同学一组,使用git相互更改代码 同组实验报告链接:http://www.cnblogs.c ...
- 20145213《Java程序设计》实验三敏捷开发与XP实践
20145213<Java程序设计>实验三敏捷开发与XP实践 实验要求 1.XP基础 2.XP核心实践 3.相关工具 实验内容 1.敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法 ...
- 20145206《Java程序设计》实验三实验报告
20145206<Java程序设计>实验三实验报告 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运 ...
- 20145308刘昊阳 《Java程序设计》实验三 敏捷开发与XP实践 实验报告
20145308刘昊阳 <Java程序设计>实验三 敏捷开发与XP实践 实验报告 实验名称 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 统计的PSP(Personal ...
随机推荐
- APP快速通过苹果AppStore审核九大诀窍
[IT168技术]对于移动应用开发者来说, 最令人沮丧的可能莫过于辛辛苦苦开发的应用, 没能通过苹果AppStore的审核,或者在应用更新时遭遇下架.苹果的AppStore的审核流程和标准, 一向不透 ...
- 重新组织 vs 重新生成索引
索引是数据库引擎中针对表(有时候也针对视图)建立的特别数据结构,用来帮助查找和整理数据.索引的重要性体现在能够使数据库引擎快速返回查询 结果.当对索引所在的基础数据表进行修改时(包括插入.删除和更新等 ...
- 基于html5实现的愤怒的小鸟网页游戏
之前给大家分享一款基于html5 canvas和js实现的水果忍者网页版,今天给大家分享一款基于html5实现的愤怒的小鸟网页游戏.这款游戏适用浏览器:360.FireFox.Chrome.Safar ...
- Linux 必掌握的 SQL 命令
数据库和 SQL 在本系列教程中,目前我们使用平面文本文件来存储数据.平面文本文件可能适合相对较少的数据,但它们对存储大量数据或查询该数据没有多大帮助.多年来,为该目的开发了多种数据库,包括分层和网络 ...
- 基于 SquashFS 构建 Linux 可读写文件系统
转载:http://www.oschina.net/question/129540_116839 在当前的嵌入式操作系统开发中,Linux 操作系统通常被压缩成 Image 后存放在 Flash 设备 ...
- Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include
来自博客园开发团队开发前线最新消息: 在Entity Framework中,如果实体A关联了实体B,你想在加载实体A的同时加载实体B.通常做法是在LINQ查询中使用Include().但是,如果你在查 ...
- 淘宝API Nodejs的实现
关于<淘宝API Nodejs的实现>这是个很忧伤的故事~~ 体验了win10,目前来说还是不如意的,一些应用程序的卡顿,发热~~难以忍受了.只好重装了系统,可是可是!!! 前段时间写的n ...
- [转]position:relative leaves an empty space
本文转自:http://stackoverflow.com/questions/5229081/positionrelative-leaves-an-empty-space 在使用relative进行 ...
- css中常用的几种居中方法
在前端面试中,大都会问你div居中的方法: 文笔不好,就随便寥寥几句话概括了, 不过以后文笔肯定会变得更好一些的. 今天我们就细数一下几种方法: 1,使用position:absolute,设置lef ...
- 关于Windows® API Code Pack for Microsoft® .NET Framework
相比之前的操作系统,Window 7(or Vista)提供了很多新特性,我们在应用实现中可以利用这些特性来提升用户体验. 这些特性主要包括以下几个方面: Shell Enhancements Dir ...