mini2440 使用sdram

发布者:MysticMoon最新更新时间:2024-06-17 来源: elecfans关键字:mini2440  sdram  地址空间 手机看文章 扫描二维码
随时随地手机看文章

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

韦东山《嵌入式Linux应用开发完全手册》PDF光盘源代码等全套 http://www.linuxidc.com/Linux/2011-01/31114.htm

《嵌入式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(0x56000010);

*gpbcon = 0x15400; // enable GPB output

 

data = reinterpret_cast(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

30000004: eb000008 bl 3000002c

30000008: eb000027 bl 300000ac

3000000c: e59ff0b8 ldr pc, [pc, #184] ; 300000cc

 

30000010 :

30000010: e3a0d30d mov sp, #872415232 ; 0x34000000

30000014: eb000105 bl 30000430

 

30000018 <_end>:

30000018: eafffffe b 30000018 <_end>

......

300000ac :

300000ac: e3a00000 mov r0, #0 ; 0x0

300000b0: e3a01203 mov r1, #805306368 ; 0x30000000

300000b4: e3a02a01 mov r2, #4096 ; 0x1000

 

300000b8 :

300000b8: e4903004 ldr r3, [r0], #4

300000bc: e4813004 str r3, [r1], #4

300000c0: e1500002 cmp r0, r2

300000c4: 1afffffb bne 300000b8

300000c8: e1a0f00e mov pc, lr

300000cc: 30000010 .word 0x30000010

300000d0: 22111112 .word 0x22111112

300000d4: 00018009 .word 0x00018009

300000d8: 008e04eb .word 0x008e04eb

......

30000430

:

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

 

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

3000000c: e59ff0b8 ldr pc, [pc, #184] ; 300000cc

 

而 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

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:

.

(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了。

[1] [2]
关键字:mini2440  sdram  地址空间 引用地址:mini2440 使用sdram

上一篇:MINI2440-SDRAM
下一篇:u-boot-2009.11移植到mini2440

推荐阅读最新更新时间:2026-03-25 03:50

MINI2440裸机实验之SDRAM
程序编写 本次实验将实现初始化SDRAM并将程序自身复制到SDRAM中然后跳转至SDRAM中继续执行流水灯。 依然是在上次程序的基础上进行修改,本次需要修改的文件包括”start.S”和”Makefile”,修改后的文件内容如下: /* start.S */ .text .global _start _start: #define MDIV 0x7f 12 #define PSDIV 0x21 ldr r0, =0x53000000 mov r1, #0x00 str r1, /* disable the watchdog timer */ bl mpll_setup bl mem_setup
[单片机]
S3C2440存储控制器的地址空间与MMU分析介绍
一、S3C2440存储控制器 如果大家写过S3C2440的ARM裸机程序都应该知道通常SDRAM的起始地址是0X30000000,但是大家有没有想过为什么呢?下面我将给大家做一个简要的介绍。 查S3C2440的手册可知S3C2440可寻址1G的地址范围,但是S3C2440的地址线只有27根,理论上只能寻址2的27次方等于128M的地址范围。于是S3C2440通过一个叫BANK的东东解决了这个问题。S3C2440引出了8根BANK线(对应nGCS0~ nGCS7),通过这个8根线来选通和关闭不同的存储器,这样S3C2440最多就可以连接8个128M的存储器,只要在某一时刻只选通一个BANK就可以实现1G的寻址空间每个BANK有个
[单片机]
S3C2440存储控制器的<font color='red'>地址</font><font color='red'>空间</font>与MMU分析介绍
玩转STM32(13)存储空间的开始地址
前面学习了怎么样选择不同的储存器来加载代码,也就是运行代码,决定了从哪里开始运行的问题。但是CPU选择了储存器之后,还要知道代码是从存储器哪一个位置开始读取代码?也就是从哪一个地址开始读取代码?现在就来解决这个问题。我们知道32位的CPU有4G的地址空间,因此从哪一个地址里读取代码,就有很多的选择了。至于放在什么地址,一般是由CPU的生产厂家来决定的。在这里可以查看到STM32F407的内部Flash储存器是放在0x8000000地址,更加详细的地址可以从STM32手册里查看到,如下图: 从上图可以看到代码就是写入到0x8000000,当CPU选择从内部存储器启动时,就会从这里加载代码。从这里也可以看到,如果是使用外部存储器,
[单片机]
玩转STM32(13)存储<font color='red'>空间</font>的开始<font color='red'>地址</font>
MINI2440从SD卡更新NK及nboot(一)
买了友善 MINI2440 开发板, SuperVivi 不开源,自己的板子又没有 NOR Flash ,烧入系统带来很大的困扰,无奈之下,只能自己做烧入工具来解决。大致思路,先从 SD 卡启动 WINCE ,再用工具格式化 Flash 及分区,将 Nboot 及 NK 写入相应的块。    应用程序操作 Flash ,无非就是 Read/Write/Earse Flash , CSDN 上有一牛人写 在 WinCE 下,应用程序直接读 / 写 / 擦除 flash 设备的方法 。 下面是我的部分代码: 1 BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBu
[单片机]
linux-2.6.32在mini2440开发板上移植 移植UDA1341 音频驱动
1 在初始化文件中加入UDA1341 设备结构 Linux-2.6.32.2 已经完美的支持UDA1341 音频芯片的驱动, 我们只要在arch/arm/mach-s3c2440/mach-mini2440.c 文件中注册UDA1341 平台设备的控制端口就可以了,打开mach-mini2440.c,添加如下内容: ;在文件首部添加头文件 #include sound/s3c24xx_uda134x.h ;在LCD 平台设备后面添加UDA1341 设备结构 static struct s3c24xx_uda134x_platform_data s3c24xx_uda134x_data = { .l3_clk =
[单片机]
Redboot mini2440 qemu 增加LCD功能
在ecos中增加lcd_support功能,和之前对emwin的移植略有不同 这次移植探究了如何从ram中留出一段空间作为framebuffer来用, Linux, WinCE都是这样做的。 1.开始是一样的,我们需要先找模板 参考arm9下面的aaed2000,再结合我们之前的LCD Driver部分就可以了。 2.预留内存给Framebuffer 我们主要看如何预留内存,首先需要改内存配置的h文件,增加lcd的REGION,别忘记修改heap的大小 // eCos memory layout - Fri Oct 20 05:43:59 2000 // This is a generated file - do not edit
[单片机]
Redboot <font color='red'>mini2440</font> qemu 增加LCD功能
Qt-embedded-linux-opensource-src-4.5.1移植到mini2440开发板技术说明
用过友善之臂的朋友都知道,友善之臂mini2440内置的是qt2的界面设计,但是现在q4逐渐成为主流。如何把qt4成功移植到mini2440非常不容易,本人也费了很到的功夫才完成了这样的工程。现在我把自己的经验拿出来与大家分享,希望有兴趣的朋友少走弯路。 1.我的环境及所需资源: PC机操作系统: Ubuntu 交叉编译工具:arm-linux-gcc-4.3.2.tar.gz 所需资源: tslib-1.4.tar.gz qt-embedded-linux-opensource-src-4.5.1.tar.gz qt-x11-linux-opensource-src-4.5.1.tar.gz 2.安装
[单片机]
u-boot-2011.03在mini2440/micro2440上的移植 支持DM9000
3.1 include/configs/micro2440.h 删除 #define CONFIG_CS8900 /* we have a CS8900 on-board */ #define CONFIG_CS8900_BASE 0x19000300 #define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */ #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 10.0.0.110 #define CONFIG_SERVERIP 10.0.0.1 添加 #defi
[单片机]
u-boot-2011.03在<font color='red'>mini2440</font>/micro2440上的移植 支持DM9000
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved