实验三——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 ...
随机推荐
- python脚本初探---新手如何直接编写一个hello world模块即可执行的.py文件
废话不多说,就讲一下这个背景吧: 事情是这个样子的~ 本着好学的精神,咱就买了本书,学习python结果呢,发现python的教程都是一个样子滴,上来的第一个hello world 都是通过IDLE来 ...
- C# 制作透明窗体
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- Windows 之 CMD命令
1. ipconfig 查看 Windows IP 配置 2. ping IP地址 查看远程IP是否通畅 2. ipconfig/flushdns 刷新和重置缓存 3. netsh winsock r ...
- jQuery layer[页面弹出框]
常见接口如下: 方法名 描述 $.layer({}) 核心接口,参数是一个对象,对象属性参见上述列表.诸如layer.alert()之类的为$.layer()的包装方法. layer.v 获取版本号. ...
- TF-IDF算法扫盲2
TF-IDF算法是一种简单快捷的文档特征词抽取方法,通过统计文档中的词频来对文档进行主题分类.TF-IDF(term frequency–inverse document frequency)是一种统 ...
- UVa OJ 10055
Problem A Hashmat the brave warrior Input: standard input Output: standard output Hashmat is a brave ...
- shake震动动画
- 结合源码看nginx-1.4.0之nginx模块组织结构详解
目录 0. 摘要 1. nginx模块组织结构 2. nginx模块数据结构 3. nginx模块初始化 4. 一个简单的http模块 5. 小结 6. 参考资料 0. 摘要 nginx有五大优点:模 ...
- SQL语言简介
什么是SQL语言? 是高级非过程化语言(是沟通数据库服务器和客户端的工具) 作用:存取,查询,更新和管理关系数据库系统 SQL语言分类: 1.DDL:数据定义语言 作用:定义和管理数据当中的各种对象 ...
- 双系统Linux(ubuntu)进入windows的NTFS分区之挂载错误
自从装了双系统(ubuntu&win10)后,发现有时在ubuntu下无法进行win磁盘,于是在网上搜了点资料得以解决,并在此记录一下: 问题如下: 解决步骤: 1.ctrl+alt+t打开终 ...