文档章节

mini2440 使用sdram

lanser
 lanser
发布于 2014/01/10 12:50
字数 2411
阅读 2517
收藏 15
点赞 2
评论 0

在S3C2440A user manual.pdf 的第五章有 Memory Controller的介绍。设置memory controller是为了明确各个bank(硬件决定出的地址空间)属性,包括数据位宽、WAIT信号、访问时序、刷新周期、bank起始位置和大小 (仅对bank6、7)及SDRAM模式。《嵌入式Linux应用开发完全手册》第6章对各寄存器有较详细叙述,再配上 S3C2440A user manual.pdf 各寄存器个字段含义应属明确。只可惜这些还不够,举例来说要设置SDRAM各参数,没有SDRAM数据手册是没法做的,在这个百花齐放的世界里真没什么是 通吃的。

《嵌入式Linux应用开发完全手册》对应的SDRAM是K4S561632C,我手头的mini2440开发板上的号称是 HY57V561620FTP,但芯片上的丝印被刻意划掉了,隐约看到一个M的logo和无法辨认的一串数字,而且2片还不一样!面对此情此景除了发自肺 腑的一句“你妹呀~”实在不知再说些什么。

mini2440 板子入手在nor 上已有可正常运行的 supervivi,进入它的命令行模式,输入:
mem info,它自曝了 memory controller 各寄存器设置,既然它工作正常就用这套值吧

Supervivi> mem info

RAM Information:
Default ram size: 64M
Real ram size   : 64M
Free memory     : 61M

RAM mapped to           : 0x30000000 - 0x34000000
Flash memory mapped to  : 0x10000000 - 0x12000000
Available memory region : 0x30000000 - 0x33d80000
Stack base address      : 0x33defffc
Current stack pointer   : 0x33defb6c

Memory control register vlaues
     BWSCON = 0x22111112
   BANKCON0 = 0x00000700
   BANKCON1 = 0x00000700
   BANKCON2 = 0x00000700
   BANKCON3 = 0x00000700
   BANKCON4 = 0x00000700
   BANKCON5 = 0x00000700
   BANKCON6 = 0x00018009
   BANKCON7 = 0x00018009
    REFRESH = 0x008e04eb
   BANKSIZE = 0x000000b2
     MRSRB6 = 0x00000030
     MRSRB7 = 0x00000030
     DSC0   = 0x00000000
     DSC1   = 0x00000000

准 备工作还有如何拷贝内存数据。真正有意义的是从flash 拷贝到sdram但鉴于我还没到这步,先搞点无意义的从片内ram到sdram吧,这里的重点是“位置无关指令”这个概念。如果这个解决了剩下就是位置相 关指令的定位,换言之怎么链接,怎么加载,也就是如何保证运行地址的正确性。

S3C2440A 是 ARM920T 处理器类型,属于 ARMv4T 架构,其位置无关指令包括 b bl。
假 想我有一些大个函数必须在 sdram 中调用,它们开机时是存在 flash 中的,那么必须先设置好内存控制器,然后从flash中读出这些函数的机器码写到sdram中去,然后再“跳”到sdram 中执行之。mini2440的sdram 起始地址是在bank6的(S3C2440A允许在bank7也挂sdram,但mini2440把它们都挂在bank6了)故这些大个函数在连接时必须 指定其所处段的运行地址在 0x30000000 之上。
位置相关指令要用以运行地址计算出来的绝对地址,上面那些大个函数中的绝对地址一定会在0x30000000之上,在没有初始化内存控制器之前bank6中的地址是不存在的,此时只能用位置无关指令。这些指令无论你在链接时指定的运行地址是什么都能通过相对值正确跳转。

软件分成2部分,一个汇编用于必要寄存器初始化和拷贝内存,再加设置sp和跳转main;一个cpp用于模拟大块头。
先是 head.s

.text
.global _start
_start:
    bl  kill_dog
    bl  control_mem
    bl  copy2sdram
    ldr pc, =sdram
sdram:
    mov sp, #0x34000000
    bl  main
_end:
    b   _end

kill_dog:
    mov r0, #0x53000000
    mov r1, #0
    str r1, [r0]
    mov pc, lr
        
control_mem:
    mov r0, #0x48000000
    ldr r1, =0x22111112
    str r1, [r0], #4
    mov r1, #0x00000700
    str r1, [r0], #4
    mov r1, #0x00000700
    str r1, [r0], #4
    mov r1, #0x00000700
    str r1, [r0], #4
    mov r1, #0x00000700
    str r1, [r0], #4
    mov r1, #0x00000700
    str r1, [r0], #4
    mov r1, #0x00000700
    str r1, [r0], #4
    ldr r1, =0x00018009
    str r1, [r0], #4
    ldr r1, =0x00018009
    str r1, [r0], #4
    ldr r1, =0x008e04eb
    str r1, [r0], #4
    mov r1, #0x000000b2
    str r1, [r0], #4
    mov r1, #0x00000030
    str r1, [r0], #4
    mov r1, #0x00000030
    str r1, [r0], #4
    mov r1, #0x00000000
    str r1, [r0], #4
    mov r1, #0x00000000
    str r1, [r0], #4
    mov pc, lr

copy2sdram:
    mov r0, #0
    mov r1, #0x30000000
    ldr r2, =0x1000
loop:  
    ldr r3, [r0], #4
    str r3, [r1], #4
    cmp r0, r2
    bne loop
    mov pc, lr

注意其中 ldr pc, =sdram

sdram.cpp 是个用LED 模拟简谱的小程序,如果谁有光感设备把LED转成声音......算了......我还是考虑mini2440上的扬声器吧:

class CNumberedMusicalNotation
{
public:
    CNumberedMusicalNotation( void );
    ~CNumberedMusicalNotation( void );

    void dao( void );
    void rai( void );
    void mi( void );
    void fa( void );
    void suo( void );
    void la( void );
    void xi( void );

private:
    void latency( void );
    unsigned long* data;
};

CNumberedMusicalNotation::CNumberedMusicalNotation()
{
    unsigned long* gpbcon = reinterpret_cast<unsigned long*>(0x56000010);
    *gpbcon = 0x15400;  // enable GPB output

    data = reinterpret_cast<unsigned long*>(0x56000014);
    *data = ~0;
}
CNumberedMusicalNotation::~CNumberedMusicalNotation()
{
    *data = ~0;
    latency();
}
void CNumberedMusicalNotation::dao()
{   // led1 - GPB5
    *data = ~(1<<5);
    latency();
}
void CNumberedMusicalNotation::rai()
{   // led2 - GPB6
    *data = ~(1<<6);
    latency();
}
void CNumberedMusicalNotation::mi()
{   // led3 - GPB7
    *data = ~(1<<7);
    latency();
}
void CNumberedMusicalNotation::fa()
{   // led4 - GPB8
    *data = ~(1<<8);
    latency();
}
void CNumberedMusicalNotation::suo()
{   // led1+3 - GPB5+7
    *data = ~(1<<5 | 1<<7);
    latency();
}
void CNumberedMusicalNotation::la()
{   // led2+4 - GPB6+8
    *data = ~(1<<6 | 1<<8);
    latency();
}
void CNumberedMusicalNotation::xi()
{   // led1+4 - GPB5+8
    *data = ~(1<<5 | 1<<8);
    latency();
}
void CNumberedMusicalNotation::latency()
{
    volatile int i;
    for ( i = 0; i < 10000; i++ );
}

int __attribute__((__long_call__)) main()
{
    CNumberedMusicalNotation n;
    
    n.dao();
    n.rai();
    n.mi();
    n.suo();
    n.suo();
    n.la();
    n.suo();
    n.mi();
    n.dao();
    n.rai();
    n.mi();
    n.mi();
    n.rai();
    n.dao();
    n.rai();

    n.dao();
    n.rai();
    n.mi();
    n.suo();
    n.suo();
    n.la();
    n.suo();
    n.mi();
    n.dao();
    n.rai();
    n.mi();
    n.mi();
    n.rai();
    n.rai();
    n.dao();

    return 0;
}

最后是Makefile

all: sdram.elf
    
sdram.elf :
    arm-linux-gcc -c -g -O2 -o head.o head.s
    arm-linux-g++ -c -g -O2 -o sdram.o sdram.cpp
    arm-linux-ld -Ttext 0x30000000 -o sdram.elf head.o sdram.o 
    arm-linux-objcopy -O binary -S sdram.elf sdram.bin
    arm-linux-objdump -D -m arm sdram.elf > sdram.dis

clean:
    rm -f *.o *.elf *.dis *.bin

注意其中 -Ttext 0x30000000

这些解释有些费劲,配合 sdram.dis 看看就好说了(节)

sdram.elf:     file format elf32-littlearm

Disassembly of section .text:

30000000 <_start>:
30000000:    eb000005     bl    3000001c <kill_dog>
30000004:    eb000008     bl    3000002c <control_mem>
30000008:    eb000027     bl    300000ac <copy2sdram>
3000000c:    e59ff0b8     ldr    pc, [pc, #184]    ; 300000cc <loop+0x14>

30000010 <sdram>:
30000010:    e3a0d30d     mov    sp, #872415232    ; 0x34000000
30000014:    eb000105     bl    30000430 <main>

30000018 <_end>:
30000018:    eafffffe     b    30000018 <_end>
......
300000ac <copy2sdram>:
300000ac:    e3a00000     mov    r0, #0    ; 0x0
300000b0:    e3a01203     mov    r1, #805306368    ; 0x30000000
300000b4:    e3a02a01     mov    r2, #4096    ; 0x1000

300000b8 <loop>:
300000b8:    e4903004     ldr    r3, [r0], #4
300000bc:    e4813004     str    r3, [r1], #4
300000c0:    e1500002     cmp    r0, r2
300000c4:    1afffffb     bne    300000b8 <loop>
300000c8:    e1a0f00e     mov    pc, lr
300000cc:    30000010     .word    0x30000010
300000d0:    22111112     .word    0x22111112
300000d4:    00018009     .word    0x00018009
300000d8:    008e04eb     .word    0x008e04eb
......
30000430 <main>:
30000430:    e24dd008     sub    sp, sp, #8    ; 0x8
30000434:    e3a03000     mov    r3, #0    ; 0x0
30000438:    e58d3004     str    r3, [sp, #4]
3000043c:    e59d2004     ldr    r2, [sp, #4]
30000440:    e3a00c27     mov    r0, #9984    ; 0x2700
30000444:    e280000f     add    r0, r0, #15    ; 0xf
30000448:    e3a01456     mov    r1, #1442840576    ; 0x56000000
3000044c:    e1520000     cmp    r2, r0
30000450:    e2433021     sub    r3, r3, #33    ; 0x21
30000454:    e3a02b55     mov    r2, #87040    ; 0x15400
30000458:    e5813014     str    r3, [r1, #20]
3000045c:    e5812010     str    r2, [r1, #16]
30000460:    ca000006     bgt    30000480 <main+0x50>

_start 开始位置为何是 30000000?因为 -Ttext 0x30000000。再看 ldr pc, =sdram 被翻译成什么了?

3000000c:    e59ff0b8     ldr    pc, [pc, #184]    ; 300000cc <loop+0x14>

而 300000cc 处是什么呢?

300000cc:    30000010     .word    0x30000010

这 意味着 pc 将被赋值 0x30000010, 这显然是编译器计算出的位置相关代码。而之前都是位置无关代码,虽然他们期望的运行基址是0x30000000,但因为位置无关,放在哪里也都行了,这正 是从flash 拷贝到 sdram 所需要的,因为reset 后pc是指向 0 的。

下面是 arm-linux-gdb 的调试过程,这里需要一些“新”指令。
首先,看看你的板子从哪里启动的,这里假设是从nand,片内ram为始于0x00000000的4k。

[szs@szs mine]$ arm-linux-gdb 
GNU gdb (Sourcery G++ Lite 2008q3-72) 6.8.50.20080821-cvs
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi".
For bug reporting instructions, please see:
<https://support.codesourcery.com/GNUToolchain/>.
(gdb) target remote 127.0.0.1:3333
Remote debugging using 127.0.0.1:3333
0x00000000 in ?? ()
(gdb) load sdram.elf 
Loading section .text, size 0xc84 lma 0x30000000
Loading section .ARM.exidx, size 0x68 lma 0x30000c84
Start address 0x30000000, load size 3308
Transfer rate: 28 KB/sec, 1654 bytes/write.
(gdb) i r
r0             0x1b4    436
r1             0x200    512
r2             0xdb     219
r3             0x40     64
r4             0x57600  357888
r5             0x0      0
r6             0x60000  393216
r7             0x0      0
r8             0x33edffe0       871235552
r9             0x33fdd970       872274288
r10            0x33fd7600       872248832
r11            0x0      0
r12            0x100    256
sp             0x33f0ffd4       0x33f0ffd4
lr             0x7e0    2016
pc             0x30000000       0x30000000
fps            0x0      0
cpsr           0x800000d3       2147483859

默 认的load将.text 放在了0x30000000处,这是因为链接时指定了 -Ttext 0x30000000,pc 也被设置到了 0x30000000,但这对应一个刚刚 reset halt 过的开发板,0x30000000 显然尚不可用!!做过load后的片内ram里有什么呢

(gdb) x/16xw 0
0x0:    0xea000014      0xe59ff014      0xe59ff014      0xe59ff014
0x10:   0xe59ff014      0xe59ff014      0xe59ff014      0xe59ff014
0x20:   0x33f80260      0x33f802c0      0x33f80320      0x33f80380
0x30:   0x33f803e0      0x33f80440      0x33f80460      0xdeadbeef

对比一下sdram.bin显然不是你的机器码,这样就算把 pc 设置到0也不会运行你的程序的。how?

(gdb) load sdram.elf 0xd0000000
Loading section .text, size 0xc84 lma 0x0
Loading section .ARM.exidx, size 0x68 lma 0xc84
Start address 0x30000000, load size 3308
Transfer rate: 40 KB/sec, 1654 bytes/write.
(gdb) set $pc=0
(gdb) i r
r0             0x194    404
r1             0x200    512
r2             0xcb     203
r3             0x4e000000       1308622848
r4             0x57200  356864
r5             0x0      0
r6             0x60000  393216
r7             0x0      0
r8             0x33edffe0       871235552
r9             0x33fdd970       872274288
r10            0x33fd7200       872247808
r11            0x0      0
r12            0x100    256
sp             0x33f0ffd4       0x33f0ffd4
lr             0x7e0    2016
pc             0x0      0
fps            0x0      0
cpsr           0x800000d3       2147483859
(gdb) si
0x0000001c in ?? ()
(gdb) si
0x00000020 in ?? ()
(gdb) si
0x00000024 in ?? ()
(gdb) si
0x00000028 in ?? ()
(gdb) si
0x00000004 in ?? ()
(gdb) c
Continuing.

load sdram.elf 时加个参数 0xd0000000,为何?因为你想让gdb 帮您把运行地址为0x30000000的段装载到0位置去,你需要给它一个偏移,0x30000000加 什么能得到0呢,只有靠溢出了。随后还要

set $pc=0

如果你有兴趣再

x/16xw 0

对比一下你的 sdram.bin 吧。通过 si 可以看到 pc 再经历 0 -> 1c -> 20 -> 24 -> 28 后又回到4 了,显然是杀狗回来了。恭喜,c 后看着 LED 给你弹小调吧。

PS: 64M sdram 是如何算出的?
S3C2440A 给 sdram 的数据线有32根D0~D31,这意味着一次可以取出4个字节;但地址线只有13根A2~A14,如何寻址64M呢?原来选址不是一次完成的,先行再列,额外还有个页。先用A2~A14指定行,再以约定时序用A2~A10指定列,配合A24~A25指定的页,一个可以寻址 13 + 9 + 2 = 24 即 16M 地址空间。因为位宽是16bit,故这代表着 32MB sdram 容量,再把2片这样的 sdram 并连寻址,用D0~D31顺序连接获取输出就能得到 64M了。

© 著作权归作者所有

共有 人打赏支持
lanser
粉丝 6
博文 6
码字总数 8736
作品 0
西安
架构师
Mini2440上的第一个程序——点亮Led

手头的Mini2440搁置了两年半之后,我再次决定拿出它,重新尝试嵌入式Linux的学习。 我使用的是友善之臂的Mini2440开发板、韦东山的《嵌入式Linux应用开发完成手册》及其视频教程。所以,本篇...

icuic
07/15
0
0
试图搞懂MDK程序下载到flash(六)--DNW+supervivi+MDK下载到Nand Flash

不容易啊,终于把 将MDK程序下载到我的mini2440开发板上的nand flash的方法找到了,我是利用韦东山老师的那套方法即利用DNW和supervivi下载到nand flash的。当然,只是方法之一,因为我能隐约...

长平狐
2013/06/17
1K
0
一起学mini2440裸机开发(一)--第一个led灯点亮

开发板:mini2440, NandFlash:K9F2G08U0B 256M大小,CPU:S3C2440A 。 开发环境:MDK4.11 仿真器:Jlink v8 这是我用csdn发表的第一个文章,之前使用过arm-linux-gcc裸机开发mini2440,但是...

长平狐
2013/06/17
6.3K
1
常用u-boot命令详解(全) .

U-boot发展到现在,他的命令行模式已经非常接近Linux下的shell了,命令行模式模式下支持“Tab”键的命令补全和命令的历史记录功能。而且如果你输入的命令的前几个字符和别的命令不重复,那么...

woi66
2014/02/10
0
0
试图搞懂MDK程序下载到flash(二)--分散加载文件scatter

分散加载文件概念 对于分散加载文件的概念,在《ARM体系结构与编程》书第11章有明确介绍。 分散加载文件(即 scatter file,后缀为 .scf)是一个文本文件,通过编写一个分散加载文件来指定ARM连...

长平狐
2013/06/17
3.2K
0
MINI2440板上移植 linux kernel 2.6.32.2-----机器码一致性确认

1、内核代码中当前使用的机器码的确认 A、找到内核代码中当前使用的: gedit arch/arm/mach-s3c2440/mach-mini2440.c B、查找类似:MACHINESTART(MINI2440, "HMARM Mini2440 development bo...

宁宁爸
2015/12/03
42
0
mini2440_LCD_x35移植

从linux 2.6起引入了新一套的驱动管理和注册机制:platformdevice 和piatformdriver. (platform代表平台);设备用platformdevice表示,驱动用piatformdriver进行注册。 Linuxplatformdriver机...

hades2011
2014/10/14
0
0
ARM开发步步深入之SDRAM编程示例

实验目的:改变“点灯大法”的执行地点,从NandFlash的Steppingstone转到SDRAM中执行,借此掌握存储控制器的使用。   实验环境及说明:恒颐S3C2410开发板H2410。H2410核心板扩展有64MB的S...

慎思
2012/08/08
0
0
Linux 嵌入式驱动开发:hello world

1、代码编写,只有一个文件,内容如下 文件名为:mini2440hellomodule.c #include <linux/kernel.h> include <linux/module.h> static int init mini2440hellomodule_init(void){ printk("He......

宁宁爸
2015/12/09
103
0
IAR 和 keil 使用外部 SDRAM 的区别

当芯片内部的 SRAM 不够用时,就需要在外部扩展 SDRAM,然后在写程序时将一些比较大的 buffer 定义在外部内存中。在进行正确的配置之后,对外部 SDRAM 的使用,和芯片内部的 SRAM 是一样的,...

u011303443
03/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Mybatis收集配置

一、Mybatis取Clob数据 1、Mapper.xml配置 <resultMap type="com.test.User" id="user"> <result column="id" property="id"/> <result column="json_data" property="jsonData" ......

星痕2018
27分钟前
0
0
centos7设置以多用户模式启动

1、旧版本linux系统修改inittab文件,在新版本执行vi /etc/inittab 会有以下提示 # inittab is no longer used when using systemd. # # ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON......

haha360
59分钟前
0
0
OSChina 周日乱弹 —— 局长:怕你不爱我

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ andonny :分享周二珂的单曲《孤独她呀》 《孤独她呀》- 周二珂 手机党少年们想听歌,请使劲儿戳(这里) @孤星闵月 :没事干,看一遍红楼梦...

小小编辑
今天
158
9
Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式 Factory工厂模式 Singleton单例模式 Delegate委派模式 Strategy策略模式 Prototype原型模式 Template模板模式 Spring5 beans 接口实例化 代理Bean操作 ...

小致dad
今天
0
0
SpringBoot | 第十章:Swagger2的集成和使用

前言 前一章节介绍了mybatisPlus的集成和简单使用,本章节开始接着上一章节的用户表,进行Swagger2的集成。现在都奉行前后端分离开发和微服务大行其道,分微服务及前后端分离后,前后端开发的...

oKong
今天
10
0
Python 最小二乘法 拟合 二次曲线

Python 二次拟合 随机生成数据,并且加上噪声干扰 构造需要拟合的函数形式,使用最小二乘法进行拟合 输出拟合后的参数 将拟合后的函数与原始数据绘图后进行对比 import numpy as npimport...

阿豪boy
今天
17
0
云拿 无人便利店

附近(上海市-航南路)开了家无人便利店.特意进去体验了一下.下面把自己看到的跟大家分享下. 经得现场工作人员同意后拍了几张照片.从外面看是这样.店门口的指导里强调:不要一次扫码多个人进入....

周翔
昨天
1
0
Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
昨天
248
1
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
昨天
1
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部