|
//以上这段,我没动,就用三星写的了,下面是主要要改的地方
/* MEMORY C0NTROLLER(MC)设置*/
add r0,pc,#MCDATA - (.+8)// r0指向MCDATA地址,那里存放着MC初始化要用到的数据
ldr r1,=BWSCON // r1指向MC控制器寄存器的首地址
add r2,r0,#52 // 复制次数,偏移52字
1: //按照偏移量进行循环复制
ldr r3,[r0],#4
str r3,[r1],#4
cmp r2,r0
bne 1b
.align 2
MCDATA:
.word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
上面这行就是BWSCON的数据,具体参数意义如下:
需要更改设置DW6 和DW7都设置成10,即32bit,DW0 设置成01,即16bit
下面都是每个BANK的控制器数据,大都是时钟相关,可以用默认值,设置完MC后,就跳到调用main函数的部分[pre]
.word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
.word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
.word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
.word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
.word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
.word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
.word 0xB2 /* REFRESH Control Register */
.word 0x30 /* BANKSIZE Register : Burst Mode */
.word 0x30 /* SDRAM Mode Register */
.align 2
.global call_main //调用main函数,函数参数都为0
call_main:
ldr sp,STACK_START
mov fp,#0 /* no previous frame, so fp=0*/
mov a1, #0 /* set argc to 0*/
mov a2, #0 /* set argv to NUL*/
bl main /* call main*/
STACK_START:
.word STACK_BASE
undefined_instruction:
software_interrupt:
prefetch_abort:
data_abort:
not_used:
irq:
fiq: [/pre]
/*以上是主要的汇编部分,实现了时钟设置,串口设置watchdog关闭,中断关闭功能(如果有需要还可以降频使用),然后转入main*/ [pre]
2410init.c file
int main(int argc,char **argv)
{
u32 test = 0;
void (*theKERNEL)(int zero, int arch, unsigned long params_addr) = (void (*)(int, int, unsigned long))RAM_COMPRESSED_KERNEL
_BASE; //压缩后的IMAGE地址
int i,k=0;
// downPt=(RAM_COMPRESSED_KERNEL_BASE);
chkBs=(_RAM_STARTADDRESS);//SDRAM开始的地方
// fromPt=(FLASH_LINUXKERNEL);
MMU_EnableICache();
ChangeClockDivider(1,1); // 1:2:4
ChangeMPllValue(M_MDIV,M_PDIV,M_SDIV); //Fin=12MHz FCLK=200MHz
Port_Init();//设置I/O端口,在使用com口前,必须调用这个函数,否则通信芯片根本得不到数据
Uart_Init(PCLK, 115200);//PCLK使用默认的200000,拨特率115200
/*******************(检查ram空间)*******************/
Uart_SendString("ntLinux S3C2410 Nor BOOTLOADERn");
Uart_SendString("ntChecking SDRAM 2410loader.c...n");
for(;chkBs<0x33FA0140;chkBs=chkBs+0x4,test++)// [/pre]
//根据我的经验,最好以一个字节为递增,我们的板子,在256byte递增检测的时候是没问题的,但是
//以1byte递增就出错了,第13跟数据线随几的会冒”1”,检测出来是硬件问题,现象如下
//用仿真器下代码测试SDRAM,开始没贴28F128A3J FLASH片子,测试结果很好,但在上了FLASH片子//之后,测试数据(data)为0x00000400
连续成批写入读出时,操作大约1k左右内存空间就会出错,//而且随机。那个出错数据总是变为0x00002400,数据总线10位和13位又没短路
发生。用其他数据//测试比如0x00000200;0x00000800没这问题。dx帮忙。
//至今没有解决,所以我用不了Flash.
{
chkPt1 = chkBs;
*(u32 *)chkPt1 = test;//写数据
if(*(u32 *)chkPt1==1024))//读数据和写入的是否一样?
{
chkPt1 += 4;
Led_Display(1);
Led_Display(2);
Led_Display(3);
Led_Display(4);
}
else
goto error;
}
Uart_SendString("ntSDRAM Check Successful!ntMemory Maping...");
get_memory_map();
//获得可用memory 信息,做成列表,后面会作为启动参数传给KERNEL
//所谓内存映射就是指在4GB 物理地址空间中有哪些地址范围被分配用来寻址系统的 RAM 单元。
Uart_SendString("ntMemory Map Successful!n");
//我用仿真器把KERNEL,RAMDISK直接放在SDRAM上,所以下面这段是不需要的,但是如果KERNEL,RAMDISK在FLASH里,那就需要. [pre]
/*******************(copy linux KERNEL)*******************/
Uart_SendString("tLoading KERNEL IMAGE from FLASH... n ");
Uart_SendString("tand copy KERNEL IMAGE to SDRAM at 0x31000000n");
Uart_SendString("ttby LEIJUN DONG dongleijun4000@hotmail.com n");
for(k = 0;k < 196608;k++,downPt += 1,fromPt += 1)//3*1024*1024/32linux KERNEL des,src,length=3M
* (u32 *)downPt = * (u32 *)fromPt;
/*******************(load RAMDISK)*******************/
Uart_SendString("ttloading COMPRESSED RAMDISK...n");
downPt=(RAM_COMPRESSED_RAMDISK_BASE);
fromPt=(FLASH_RAMDISK_BASE);
for(k = 0;k < 196608;k++,downPt += 1,fromPt += 1)//3*1024*1024/32linux KERNEL des,src,length=3M
* (u32 *)downPt = * (u32 *)fromPt;
/******jffs2文件系统,在开发中如果用不到FLASH,这段也可以不要********/
Uart_SendString("ttloading jffs2...n");
downPt=(RAM_JFFS2);
fromPt=(FLASH_JFFS2);
for(k = 0;k < (1024*1024/32);k++,downPt += 1,fromPt += 1)
* (u32 *)downPt = * (u32 *)fromPt;
Uart_SendString( "Load Success...Run...n ");
/*******************(setup param)*******************/
setup_start_tag();//开始设置启动参数
setup_memory_tags();//内存印象
setup_commandline_tag("console=ttyS0,115200n8");//启动命令行
setup_initrd2_tag();//root device
setup_RAMDISK_tag();//ramdisk image
setup_end_tag();
/*关I-cache */
asm ("mrc p15, 0, %0, c1, c0, 0": "=r" (i));
i &= ~0x1000;
asm ("mcr p15, 0, %0, c1, c0, 0": : "r" (i));
/* flush I-cache */
asm ("mcr p15, 0, %0, c7, c5, 0": : "r" (i)); [/pre]
//下面这行就跳到了COMPRESSED KERNEL的首地址
theKERNEL(0, ARCH_NUMBER, (unsigned long *)(RAM_BOOT_PARAMS));
//启动kernel时候,I-cache可以开也可以关,r0必须是0,r1必须是CPU型号
(可以从linux/arch/arm/tools/mach-types中找到),r2必须是参数的物理开始地址 [pre]
/*******************END*******************/
error:
Uart_SendString("nnPanic SDRAM check error!n");
return 0;
}
static void setup_start_tag(void)
{
params = (struct tag *)RAM_BOOT_PARAMS;//启动参数开始的地址
params->hdr.tag = ATAG_CORE;
params->hdr.size = tag_size(tag_core);
params->u.core.flags = 0;
params->u.core.pagesize = 0;
params->u.core.rootdev = 0;
params = tag_next(params);
}
static void setup_memory_tags(void)
{
int i;
for(i = 0; i < NUM_MEM_AREAS; i++) {
if(memory_map.used) {
params->hdr.tag = ATAG_MEM;
params->hdr.size = tag_size(tag_mem32);
params->u.mem.start = memory_map.start;
params->u.mem.size = memory_map.len;
params = tag_next(params);
}
}
}
static void setup_commandline_tag(char *commandline)
{
int i = 0;
/* skip non-existent command lines so the kernel will still
* use its default command line.
*/
params->hdr.tag = ATAG_CMDLINE;
params->hdr.size = 8;
//console=ttyS0,115200n8
strcpy(params->u.cmdline.cmdline, p);
params = tag_next(params);
}
static void setup_initrd2_tag(void)
{
/* an ATAG_INITRD node tells the kernel where the compressed
* ramdisk can be found. ATAG_RDIMG is a better name, actually.
*/
params->hdr.tag = ATAG_INITRD2;
params->hdr.size = tag_size(tag_initrd);
params->u.initrd.start = RAM_COMPRESSED_RAMDISK_BASE;
params->u.initrd.size = 2047;//k byte
params = tag_next(params);
}
static void setup_ramdisk_tag(void)
{
/* an ATAG_RAMDISK node tells the kernel how large the
* decompressed ramdisk will become.
*/
params->hdr.tag = ATAG_RAMDISK;
params->hdr.size = tag_size(tag_ramdisk);
params->u.ramdisk.start = RAM_DECOMPRESSED_RAMDISK_BASE;
params->u.ramdisk.size = 7.8*1024; //k byte
params->u.ramdisk.flags = 1; // automatically load ramdisk
params = tag_next(params);
}
static void setup_end_tag(void)
{
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;
} void Uart_Init(int pclk,int baud)//串口是很重要的
{
int i;
if(pclk == 0)
pclk = PCLK;
rUFCON0 = 0x0; //UART channel 0 FIFO control register, FIFO dISAble
rUMCON0 = 0x0; //UART chaneel 0 MODEM control register, AFC dISAble
//UART0
rULCON0 = 0x3; //Line control register : Normal,No parity,1 stop,8 bits
下面这段samsung好象写的不太对,但是我按照Normal,No parity,1 stop,8 bits算出来的确是0x245
// [10] [9] [8] [7] [6] [5] [4] [3:2] [1:0]
// Clock Sel, Tx Int, Rx Int, Rx Time Out, Rx err, Loop-back, Send break, Transmit Mode, Receive Mode
// 0 1 0 , 0 1 0 0 , 01 01
// PCLK Level Pulse DISAble Generate Normal Normal Interrupt or Polling
rUCON0 = 0x245; // Control register
rUBRDIV0=( (int)(PCLK/16./ baud) -1 ); //Baud rate divisior register 0
delay(10);
} [/pre] |
|