请专家们帮我解答一下SDRAM的初始化,可回复联系方式,解决有酬谢!
本帖最后由 bafeite 于 2013-8-4 11:24 编辑坛内大侠请帮忙:
1、背景描述:自己写的简单的BootLoader,当前工作为初始化SDRAM,将代码搬移到SDRAM,看了下板子上
SDRAM的芯片上的字是:H57V2562GTR-60C
2、现象:当执行程序,先写入一个,再回读一下,不一样,怀疑SDRAM没初始化好,但是程序好像能跑,
串口还能打印
3、疑问:
a.H57V2562GTR-60C,我看芯片手册是256M(4BANKS*4M*16),但是看坛子里的朋友说是32M的
b.一般通过什么情况能验证我的SDRAM是否初始化成功
c.我以下代码比较奇怪若不拷贝到SRAM运行一切OK,但是拷贝到SRAM运行,程序虽然能跑,但是初始
打印均不对;
QQ:68075211
代码:
srat.s:
.text
.global _start
_start:
/*设置堆栈*/
/*栈是往下增长的,这里片内RAM总共4K,我们就设置到最后,前面应该用不完*/
ldr sp,=1024*4
/*调用函数*/
bl Init
bl memsetup
blcopy_steppingstone_to_sdram
ldr pc, =on_sdram
on_sdram:
ldr sp, =0x34000000
blmain
copy_steppingstone_to_sdram:
/*将Steppingstone的4K数据全部复制到SDRAM中去*/
/*Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000*/
mov r1, #0
ldr r2, =0x30000000
mov r3, #4*1024
1:
ldr r4, ,#4 /*从Steppingstone读取4字节的数据,并让源地址加4*/
str r4, ,#4 /*将此4字节的数据复制到SDRAM中,并让目地地址加4*/
cmp r1, r3 /*判断是否完成:源地址等于Steppingstone的未地址*/
bne 1b /*若没有复制完,继续*/
mov pc, lr /*返回*/ Board.h
#define CPU_REG32(addr) (*(volatile unsigned long *)(addr))/*volatile 表示告诉编译器不
要对此进行优化*/
#define U32 unsigned long
#define U8unsigned char
#define DOGCON CPU_REG32(0x53000000)
/*GPIO registers*/
#define GPBCON CPU_REG32(0x56000010)
#define GPBDAT CPU_REG32(0x56000014)
#define GPFCON CPU_REG32(0x56000050)
#define GPFDAT CPU_REG32(0x56000054)
#define GPFUP CPU_REG32(0x56000058)
#define GPGCON CPU_REG32(0x56000060)
#define GPGDAT CPU_REG32(0x56000064)
#define GPGUP CPU_REG32(0x56000068)
#define GPHCON CPU_REG32(0x56000070)
#define GPHDAT CPU_REG32(0x56000074)
#define GPHUP CPU_REG32(0x56000078)
/*UART registers*/
#define ULCON0 CPU_REG32(0x50000000)
#define UCON0 CPU_REG32(0x50000004)
#define UFCON0 CPU_REG32(0x50000008)
#define UMCON0 CPU_REG32(0x5000000c)
#define UTRSTAT0 CPU_REG32(0x50000010)
#define UTXH0 CPU_REG32(0x50000020)
#define URXH0 CPU_REG32(0x50000024)
#define UBRDIV0 CPU_REG32(0x50000028)
/*clock registers*/
#define LOCKTIME (*(volatile unsigned long *)0x4c000000)
#define MPLLCON (*(volatile unsigned long *)0x4c000004)
#define UPLLCON (*(volatile unsigned long *)0x4c000008)
#define CLKCON (*(volatile unsigned long *)0x4c00000c)
#define CLKSLOW (*(volatile unsigned long *)0x4c000010)
#define CLKDIVN (*(volatile unsigned long *)0x4c000014)
#define PCLK 50000000 // init.c中的clock_init函数设置PCLK为50MHz
#define UART_CLK PCLK //UART0的时钟源设为PCLK
#define UART_BAUD_RATE115200 // 波特率
#define UART_BRD ((UART_CLK/ (UART_BAUD_RATE * 16)) - 1)
#define TXD0READY (1<<2)
#define RXD0READY (1)
Board.c
#include "Board.h"
void Delay()
{
U32 i;
for(i=0; i<100000; i++)
{
}
}
void CloseWatchDog()
{
DOGCON = 0x00000000;
}
#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
void SetClock()
{
CLKDIVN = 0x00000003;
/* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
__asm__(
"mrc p15, 0, r1, c1, c0, 0\n" /* 读出控制寄存器 */
"orr r1, r1, #0xc0000000\n" /* 设置为“asynchronous bus mode” */
"mcr p15, 0, r1, c1, c0, 0\n" /* 写入控制寄存器 */
);
MPLLCON = S3C2440_MPLL_200MHZ;/* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
}
void uart0_init(void)
{
GPHCON|= 0xa0; // GPH2,GPH3用作TXD0,RXD0
GPHUP = 0x0c; // GPH2,GPH3内部上拉
ULCON0= 0x03; // 8N1(8个数据位,无较验,1个停止位)
UCON0 = 0x05; // 查询方式,UART时钟源为PCLK
UFCON0= 0x00; // 不使用FIFO
UMCON0= 0x00; // 不使用流控
UBRDIV0 = UART_BRD; // 波特率为115200
}
void putc(unsigned char c)
{
/* 等待,直到发送缓冲区中的数据已经全部发送出去 */
while (!(UTRSTAT0 & TXD0READY));
/* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */
UTXH0 = c;
}
U32 getc(U8* out)
{
if((UTRSTAT0 & RXD0READY))
{
*out = URXH0;
return 0;
}
else
{
return 1;
}
}
void MyPrintf(U8 *buff) //一个简单的类似于printf的实现,//参数必须都是int 类型
{
while (*buff != 0)
{
putc (*buff);
buff++;
}
}
void memsetup(void)
{
U32 TEMP = 0;
CPU_REG32(0X48000000) = 0x2201d550; //BWSCON;
CPU_REG32(0X48000004) = 0x00000700; //BANKCON0;
CPU_REG32(0X48000008) = 0x00000700; //BANKCON1;
CPU_REG32(0X4800000C) = 0x00000700; //BANKCON2;
CPU_REG32(0X48000010) = 0x00001f4c; //BANKCON3;
CPU_REG32(0X48000014) = 0x00000700; //BANKCON4;
CPU_REG32(0X48000018) = 0x00000700; //BANKCON5;
CPU_REG32(0X4800001C) = 0x00018005; //BANKCON6;
CPU_REG32(0X48000020) = 0x00018005; //BANKCON7;
CPU_REG32(0X48000024) = 0x008e04f4; //REFRESH;
CPU_REG32(0X48000028) = 0x00000032; //BANKSIZE;
CPU_REG32(0X4800002C) = 0x00000030; //MRSRB6;
CPU_REG32(0X48000030) = 0x00000030; //MRSRB7;
/*CPU_REG32(0X48000000) = 0x22011110;
CPU_REG32(0X48000004) = 0x00000700;
CPU_REG32(0X48000008) = 0x00000700;
CPU_REG32(0X4800000C) = 0x00000700;
CPU_REG32(0X48000010) = 0x00000700;
CPU_REG32(0X48000014) = 0x00000700;
CPU_REG32(0X48000018) = 0x00000700;
CPU_REG32(0X4800001C) = 0x00018005;
CPU_REG32(0X48000020) = 0x00018005;
CPU_REG32(0X48000024) = 0x008C07A3;
CPU_REG32(0X48000028) = 0x000000B1;
CPU_REG32(0X4800002C) = 0x00000030;
CPU_REG32(0X48000030) = 0x00000030;*/
CPU_REG32(0X30000000) = 0x12345678;
CPU_REG32(0X33ffffff) = 0x87654321;
if(CPU_REG32(0X30000000) == 0x12345678 && CPU_REG32(0X33ffffff) == 0x87654321)
{
MyPrintf("Init Sdram,size is 64M!\r\n");
}
else
{
MyPrintf("Init Sdram fail!\r\n");
}
TEMP = CPU_REG32(0X30000000);
putc((U8)((TEMP>>28)&0x0000000f+0x30));
putc((U8)((TEMP>>24)&0x0000000f+0x30));
putc((U8)((TEMP>>20)&0x0000000f+0x30));
putc((U8)((TEMP>>16)&0x0000000f+0x30));
putc((U8)((TEMP>>12)&0x0000000f+0x30));
putc((U8)((TEMP>>8)&0x0000000f+0x30));
putc((U8)((TEMP>>4)&0x0000000f+0x30));
putc((U8)((TEMP&0x0000000f+0x30)));
MyPrintf("\r\n");
}
void do_cmd(U8* buff)
{
U32 i = 0;
U32 TEMP = 0;
if(buff == 'v' &&buff == 'e'&&buff == 'r'&&buff == 's'&&buff ==
'i'&&buff == 'o'&&buff == 'n')
{
MyPrintf("version is 20130803003! \r\n");
MyPrintf("TQ2440#");
}
else if(*buff == '1')
{
MyPrintf("cmd is 1! \r\n");
MyPrintf("TQ2440#");
}
else if(*buff == '2')
{
MyPrintf("cmd is 2! \r\n");
MyPrintf("TQ2440#");
CPU_REG32(0X30000000+*buff) = 0X12345678;
TEMP = CPU_REG32(0X30000000+*buff);
putc((U8)((TEMP>>28)&0x0000000f+0x30));
putc((U8)((TEMP>>24)&0x0000000f+0x30));
putc((U8)((TEMP>>20)&0x0000000f+0x30));
putc((U8)((TEMP>>16)&0x0000000f+0x30));
putc((U8)((TEMP>>12)&0x0000000f+0x30));
putc((U8)((TEMP>>8)&0x0000000f+0x30));
putc((U8)((TEMP>>4)&0x0000000f+0x30));
putc((U8)((TEMP&0x0000000f+0x30)));
MyPrintf("\r\n");
}
else
{
MyPrintf("\r\n");
MyPrintf("TQ2440#");
}
/*clear*/
for(i=0; i<100; i++)
{
buff = 0;
}
}
void consonle()
{
U8 buff;
U8 ucTemp = 0;
static U32 CNT = 0;
if(getc(&ucTemp) == 0)
{
if(ucTemp != 0x0d)
{
buff = ucTemp;
if(CNT < 99)
{
CNT++;
}
else
{
CNT = 0;
}
}
else
{
CNT = 0;
do_cmd(buff);
}
}
}
void main()
{
int i;
U8 TEMP;;
U32 tmpu32 = 0;
U8 BUFF;
for(i = 0; i<10; i++)
{
/*灯*/
GPBCON = 0x00000400; // 设置GPB5为输出口, 位=0b01
GPBDAT = 0x00000000; // GPB5输出0,LED1点亮 return 0;
Delay();
GPBCON = 0x00001400; // 设置GPB5为输出口, 位=0b01
GPBDAT = 0x00000000; // GPB5输出0,LED1点亮 return 0;
Delay();
}
MyPrintf("Run My App \r\n");
MyPrintf("TQ2440#");
for(;;)
{
//consonle();
if(getc(&TEMP) == 0)
{
if(TEMP != 0x0d)
{
BUFF = TEMP;
}
else
{
if(BUFF == '1')
{
MyPrintf("version is 20130804003! \r\n");
MyPrintf("TQ2440#");
}
else if(BUFF == '2')
{
MyPrintf("cmd is 2! \r\n");
MyPrintf("TQ2440#");
CPU_REG32(0X30000000+BUFF-0x30) = 0X12345678;
tmpu32 = CPU_REG32(0X30000000+BUFF-0x30);
putc((U8)((tmpu32>>28)&0x0000000f+0x30));
putc((U8)((tmpu32>>24)&0x0000000f+0x30));
putc((U8)((tmpu32>>20)&0x0000000f+0x30));
putc((U8)((tmpu32>>16)&0x0000000f+0x30));
putc((U8)((tmpu32>>12)&0x0000000f+0x30));
putc((U8)((tmpu32>>8)&0x0000000f+0x30));
putc((U8)((tmpu32>>4)&0x0000000f+0x30));
putc((U8)((tmpu32&0x0000000f+0x30)));
MyPrintf("\r\n");
}
else
{
MyPrintf("\r\n");
MyPrintf("TQ2440#");
}
}
}
}
}
void Init()
{
/*狗*/
CloseWatchDog();
/*时钟*/
SetClock();
/*串口*/
uart0_init();
MyPrintf("Init Clock,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz!\r\n");
MyPrintf("Init Uart,Baudrate is 115200!\r\n");
//memsetup();
} makefile:
objs := start.o Board.o
BootLoader.bin : $(objs)
arm-linux-ld -TBootLoader.lds -o BootLoader_elf $^
arm-linux-objcopy -O binary -S BootLoader_elf $@
arm-linux-objdump -D -m armBootLoader_elf > BootLoader.dis
start.o : start.S
arm-linux-gcc -c -o start.o start.S
Board.o : Board.c
arm-linux-gcc -c -o Board.o Board.c
clean:
rm -fnand.dis nand.bin nand_elf *.o
BootLoader.lds
SECTIONS {
firtst 0x30000000 : {start.o Board.o}
}
检查内存初始化吧。
256Mbit=32MByte。
推荐使用uboot,省时间。可以把精力放到真正的开发中。
页:
[1]