21,600
社区成员
发帖
与我相关
我的任务
分享
#define MEM_SYS_CFG (*((volatile unsigned long *)0x7E00F120))
#define NFCONF (*((volatile unsigned long *)0x70200000))
#define NFCONT (*((volatile unsigned long *)0x70200004))
#define NFCMMD (*((volatile unsigned long *)0x70200008))
#define NFADDR (*((volatile unsigned long *)0x7020000C))
#define NFDATA (*((volatile unsigned char *)0x70200010))
#define NFSTAT (*((volatile unsigned long *)0x70200028))
void nand_select(void)
{
NFCONT &= ~(1<<1);
}
void nand_deselect(void)
{
NFCONT |= (1<<1);
}
void nand_cmd(unsigned char cmd)
{
NFCMMD = cmd;
}
void nand_addr(unsigned char addr)
{
NFADDR = addr;
}
unsigned char nand_get_data(void)
{
return NFDATA;
}
void nand_send_data(unsigned char data)
{
NFDATA = data;
}
void wait_ready(void)
{
while ((NFSTAT & 0x1) == 0);
}
void nand_reset(void)
{
/* 选中 */
nand_select();
/* 发出0xff命令 */
nand_cmd(0xff);
/* 等待就绪 */
wait_ready();
/* 取消选中 */
nand_deselect();
}
void nand_init(void)
{
/* 让xm0csn2用作nand flash cs0 片选引脚 */
MEM_SYS_CFG &= ~(1<<1);
/* 设置时间参数 */
#define TACLS 0
#define TWRPH0 1
#define TWRPH1 0
NFCONF &= ~((1<<30) | (7<<12) | (7<<8) | (7<<4));
NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4));
/* 使能nand flash controller */
NFCONT |= 1;
NFCONT &= ~(1<<16); /* 森止soft lock */
nand_reset();
}
void nand_send_addr(unsigned int addr)
{
#if 0
unsigned int page = addr / 2048;
/* 这两个地址表示从页内哪里开始 */
nand_addr(addr & 0xff);
nand_addr((addr >> 8) & 0xff);
/* 下面三个地址表示哪一页 */
nand_addr(page & 0xff);
nand_addr((page >> 8) & 0xff);
nand_addr((page >> 16) & 0xff);
#else
nand_addr(addr & 0xff); /* a0~a7 */
nand_addr((addr >> 8) & 0x1f); /* 程序的角度: a8~a12 */
nand_addr((addr >> 13) & 0xff); /* 程序的角度: a13~a20 */
nand_addr((addr >> 21) & 0xff); /* 程序的角度: a21~a28 */
nand_addr((addr >> 29) & 0x7); /* 程序的角度: a29~ */
#endif
}
int nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
unsigned int addr = nand_start;
int i = nand_start % 4096;//nand_start % 2048;
int count = 0;
unsigned char *dest = (unsigned char *)ddr_start;
/* 选中芯片 */
nand_select();
while (count < len)
{
/* 发出命令0x00 */
nand_cmd(0x00);
/* 发出地址 */
nand_send_addr(addr);
/* 发出命令0x30 */
nand_cmd(0x30);
/* 等待就绪 */
wait_ready();
/* 读数据 */
for (; i < 4096 && count < len; i++)
{
dest[count++] = nand_get_data();
addr++;
}
i = 0;
}
/* 取消片选 */
nand_deselect();
return 0;
}
int copy2ddr(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
int ret;
/* 初始化nand flash controller */
nand_init();
/* 读nand flash */
ret = nand_read(nand_start, ddr_start, len);
return ret;
}
.globl _start
_start:
/* 硬件相关的设置 */
/* Peri port setup */
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff)
/* 关看门狗 */
/* 往WTCON(0x7E004000)写0 */
ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]
/* 设置栈 */
ldr sp, =8*1024
/* 设置时钟 */
/*bl clock_init*/
/* 设置DDR */
bl ddr_init
/* 重定位 */
/* 把程序的代码段、数据段复制到它的链接地址去 */
adr r0, _start /* 获得_start指令当前所在的地址 : 0*/
ldr r1, =_start /* _start的链接地址 0x51000000 */
ldr r2, =bss_start /* bss段的起始链接地址 */
sub r2, r2, r1
cmp r0,r1
beq clean_bss
bl copy2ddr
cmp r0, #0
bne halt
/* 清BSS */
/* 把BSS段对应的内存清零 */
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
mov r3, #0
cmp r0, r1
beq on_ddr
clean_loop:
str r3, [r0], #4
cmp r0, r1
bne clean_loop
on_ddr:
ldr pc, =main
halt:
b halt
SECTIONS {
. = 0x51000000;
.text : {
start.o
sdram.o
nand.o
* (.text)
}
.rodata : {
* (.rodata)
}
.data : {
* (.data)
}
bss_start = .;
.bss ALIGN(4) : { *(.bss) *(COMMON) }
bss_end = .;
}