📄 onenand.c
字号:
data_load++;
}
if (Size > (data_load*DATABUFFERSIZE)) { // data load
rOND_START_ADDR1 = DFS(block) | FBA(block);
rOND_START_ADDR8 = FPA(page) | FSA(0);
if (data_load&1)
rOND_START_BUFFER = BSA(0xc) | BSC(0); // DataRAM1
else
rOND_START_BUFFER = BSA(0x8) | BSC(0); // DataRAM0
rOND_START_ADDR2 = DBS(block);
rOND_INT_STATUS = 0;
rOND_COMMAND = OND_LD_MS_TO_BUF;
}
if (data_load > data_read) { // data read. 105 us @50MHz 8,16,cont.-words
rOND_START_ADDR2 = DBS(b_temp);
if ((Size-(data_read*DATABUFFERSIZE)) >= DATABUFFERSIZE) // edit by junon
d_size = DATABUFFERSIZE;
else
d_size = Size-(data_read*DATABUFFERSIZE);
if (g_use_dma)
{
dma_copy_done = 0;
if (data_read&0x1) // 87 us @50MHz 8,16,cont.-words
dma_memcpy( __OND_DataRAM1_BASE, (U32)Address, d_size );
else
dma_memcpy( __OND_DataRAM0_BASE, (U32)Address, d_size );
while(!dma_copy_done);
}
else
{
if (data_read&0x1) // 87 us @50MHz 8,16,cont.-words
memcpy( Address, (U32 *)__OND_DataRAM1_BASE, d_size );
//memcpy_opt( Address, (U32 *)__OND_DataRAM1_BASE, d_size );
//DMC8burstmemcpy((U32)__OND_DataRAM1_BASE, (U32)Address, d_size);
else
memcpy( Address, (U32 *)__OND_DataRAM0_BASE, d_size );
//memcpy_opt( Address, (U32 *)__OND_DataRAM0_BASE, d_size );
//DMC8burstmemcpy((U32)__OND_DataRAM1_BASE, (U32)Address, d_size);
}
Address+=(DATABUFFERSIZE>>2);
data_read++;
}
b_temp = block;
page = (page+1)&0x3f;
if (page==0) block++;
}
}
// Write-While-Program Operation, unit : page
void OND_write( U32 *Address, U32 Size, U16 block)
{
U16 page;
U32 data_program;
U32 data_write;
page = 0;
data_program = 0;
data_write = 0;
if (!Size) {
printf("The size is zero!! Retry this operation!! \n");
return;
}
while( Size >= (data_program*DATABUFFERSIZE)) { // edit by junon
if (data_write > 0) {
if (page==0) {
OND_unlock_block(block);
OND_erase_block(block);
}
rOND_START_ADDR1 = DFS(block) | FBA(block);
rOND_START_ADDR8 = FPA(page) | FSA(0);
if (data_program&1)
rOND_START_BUFFER = BSA(0xc) | BSC(0);
else
rOND_START_BUFFER = BSA(0x8) | BSC(0);
rOND_INT_STATUS = 0;
rOND_COMMAND = OND_PG_MS_FR_BUF;
page = (page+1) & 0x3f;
if (page==0) block++;
}
// write data to DataRAM0 or 1
if (Size >= (data_write*DATABUFFERSIZE)) { // edit by junon
if (data_write <= (data_program+1)) {
rOND_START_ADDR2 = DBS(block);
if (g_use_dma)
{
dma_copy_done = 0;
if (data_write&1)
dma_memcpy( (U32)Address, __OND_DataRAM1_BASE, DATABUFFERSIZE );
else
dma_memcpy( (U32)Address, __OND_DataRAM0_BASE, DATABUFFERSIZE );
while(!dma_copy_done);
}
else
{
if (data_write&1)
memcpy( (U32 *)__OND_DataRAM1_BASE, Address, DATABUFFERSIZE);
// memcpy_opt( (U32 *)__OND_DataRAM1_BASE, Address, DATABUFFERSIZE);
else
memcpy( (U32 *)__OND_DataRAM0_BASE, Address, DATABUFFERSIZE);
// memcpy_opt( (U32 *)__OND_DataRAM0_BASE, Address, DATABUFFERSIZE);
}
Address+=(DATABUFFERSIZE>>2);
data_write++;
}
}
if (data_write > 1) {
while (!(rOND_INT_STATUS & (1<<15)));
if (rOND_CON_STATUS & (1<<10))
printf("ECC Fail.\n");
else
data_program++;
}
}
}
//======================== [ OneNAND test code ] ===========================
void OneNAND_ReadID( void)
{
printf("\n\n< Read OneNAND information >\n");
printf("Manufacturer ID : 0x%02x\n",rOND_MANU);
printf("Device ID : 0x%02x\n",rOND_DEV);
printf("Version ID : 0x%02x\n",rOND_VER);
printf("Data buffer size : %d KB\n",((rOND_DBUFSIZE<<1)/(rOND_BUFAMOUNT>>8))>>10);
printf("Boot buffer size : %d KB\n",((rOND_BBUFSIZE<<1)/(rOND_BUFAMOUNT&0xff))>>10);
printf("Amount of D/B buffers : %d, %d\n",rOND_BUFAMOUNT>>8,rOND_BUFAMOUNT&0xff);
printf("Technology : 0x%02x\n\n", rOND_TECH);
}
void OneNAND_Program( void)
{
U16 block;
U32 size;
printf("\nOneNAND block program from [0x%08x]\n",(_NONCACHE_STARTADDRESS+0x00500000));
printf("Enter block # to program : ");
block = GetIntNum();
printf("Enter size to program : ");
size = GetIntNum();
OND_write( (U32 *)(_NONCACHE_STARTADDRESS+0x00500000), size, block);
printf("Program complete.\n");
}
void OneNAND_Read_Page( void)
{
U16 block=0;
U16 page=0;
U32 i;
U32 *Addr;
printf("\nOneNAND block read\n");
printf("Enter block # to read : ");
block = GetIntNum();
printf("Enter page # to read : ");
page = GetIntNum();
if (OND_page_load(block,page)==0) {
Addr=(U32 *)__OND_DataRAM0_BASE;
for(i=0;i<DATABUFFERSIZE;i+=sizeof(U32)) {
if ((i&0x1f)==0)
printf("\n%08x : ",i);
printf("%08x ",*Addr++);
}
putchar('\n');
}
}
void OneNAND_Write_Page( void)
{
U16 block=0;
U16 page=0;
printf("\nOneNAND block write\n");
printf("Enter block # to write : ");
block = GetIntNum();
printf("Enter page # to write : ");
page = GetIntNum();
if (OND_page_program(block,page)==0)
printf("Block %d, page %d was writed.\n",block,page);
printf("\n");
}
void OneNAND_Erase_All( void)
{
U16 block;
printf("\nOneNAND all block erase\n");
for(block=0;block<1024;block++) {
OND_unlock_block( block);
OND_erase_block( block);
if ((block&0x3f)==0)
printf("[%d]",block);
}
printf("\nAll block was erased.\n");
printf("\n");
}
void OneNAND_Erase_Block( void)
{
U16 block=0;
printf("\nOneNAND block erase\n");
printf("Enter block # to erase : ");
block = GetIntNum();
OND_unlock_block( block);
if (OND_erase_block( block)==0)
printf("Block %d was erased.\n",block);
printf("\n");
}
void OneNAND_Unlock_Block( void)
{
U16 block=0;
printf("\nOneNAND block unlock\n");
printf("Enter block # to unlock : ");
block = GetIntNum();
OND_unlock_block( block);
printf("\n");
}
void OneNAND_Lock_Block( void)
{
U16 block=0;
printf("\nOneNAND block lock\n");
printf("Enter block # to lock : ");
block = GetIntNum();
OND_lock_block( block);
printf("\n");
}
void SMC_Config4OneNAND(U32 nBank)
{
U32 sel_sync = 2;
U32 sel_burst = 4;
U32 burst_mode = 1;
U32 mux_mode = 0;
U16 sysconfig1;
volatile SMC_REGS *pSmcRegs;
pSmcRegs = (volatile SMC_REGS *)(SMC_REG_BASE+SMC_REG_OFFSET*nBank);
g_use_dma = 0; // default setting = memcpy
printf("Select OneNAND interface mode, Demuxed mode(0-D)/Muxed mode(1) : ");
mux_mode = GetIntNum();
if (mux_mode == 1)
rSMBONETYPER |= (1<<nBank); // muxed mode
else
{
rSMBONETYPER &= ~(1<<nBank); // demuxed mode
mux_mode = 0;
}
printf("Select OneNAND sync mode, Synchronous(1)/Asynchronous(2-D) : ");
sel_sync = GetIntNum();
if (sel_sync == 1)
{
printf("Select OneNAND burst mode, no burst(0-D)/4-words(1)/8-words(2)/16-words(3)/Continuous(4) : ");
sel_burst = GetIntNum();
burst_mode = 1;
if ( (sel_burst == (U32)(-1)) || (sel_burst == 0) )
{
sel_burst = 4;
burst_mode = 0; // default no burst
}
}
// defualt setting for reading correct rOND_SYS_CONFIG1
pSmcRegs->rSmbWstRdr = 4; // read wait state. [4:0] 1 ~ 10. only 4 @ 50MHz(Mux). sync burst only 4
pSmcRegs->rSmbWstWrr = 4; // write wait state. [4:0] 1 ~ 10. min 3 @ 50MHz
pSmcRegs->rSmbWstOenr = 3; // OE assertion delay. [3:0] 1 ~ 2. min 3 @ 50MHz
pSmcRegs->rSmbWstWenr = 3; // WE assertion delay. [3:0] 1 ~ 3. min 3 @ 50MHz
// ensure that ther are no memory transfers.
rCLKDIV0 = (rCLKDIV0 & ~(1<<3)) | (1<<3); // select HALFHCLK : 0=HCLK, 1=HCLK/2
rSMCCR = (rSMCCR & ~(3<<1)) | (1<<1)|(1); // SMC MemClkRatio setting should be equal HALFHCLK of CLKDIV0
pSmcRegs->rSmbIdCyr = 0;
printf("rCLKDIV0 = 0x%x\n", rCLKDIV0);
printf("rSMBIDCYR%d = 0x%x\n", nBank, pSmcRegs->rSmbIdCyr);
// wait 4 SMC clocks
sysconfig1=rOND_SYS_CONFIG1; // reading
printf("rOND_SYS_CONFIG1 = 0x%x \n", sysconfig1);
switch(sel_sync) {
case 1: // sync.
printf("rSMBCR%d = 0x%x \n", nBank, pSmcRegs->rSmbCr);
// rOND_SYS_CONFIG1
// [15] : sync(1), async(0),
// [12:14] : Burst read latency. same as WSTRD value in demux.
// [9:11] : Continuous(0), 4word(1), 8word(2), 16word(3), 32word(4) - only burst
#if SMCLK66MHZ // @66.7MHz
rOND_SYS_CONFIG1 = (sysconfig1& ~(0x7f<<9))|(1<<15)|(4<<12)|((sel_burst%4)<<9);
#else // @50MHz
rOND_SYS_CONFIG1 = (sysconfig1& ~(0x7f<<9))|(1<<15)|(3<<12)|((sel_burst%4)<<9);
#endif
Delay(1);
printf("sync = %d, sel burst = %d, burst mode = %d\n", sel_sync, sel_burst, burst_mode);
// rSMBCR0
// [10:11] : 4word(0), 8word(1), 16word(2), continuous(3) - only burst
// [9] : sync(1), async(0)
// [8] : burst(1), no burst(0)
pSmcRegs->rSmbCr = (pSmcRegs->rSmbCr & ~((0xf<<8)|(0xf<<16)|(1<<14)|0x3))
|((sel_burst-1)<<18)|(1<<17)|(burst_mode<<16) // set SSMC write
|((sel_burst-1)<<10)|(1<<9)|(burst_mode<<8) |(0<<7) // set SSMC as read burst.
|(0<<14)|(0<<2)|(0<<1)|(1); // caution! SMWAIT polarity setting. now active low.
//rSMBCR0 = 0x333211; Burst OK setting
pSmcRegs->rSmbWstBrdr = 0;
printf("rSMBONETYPER = 0x%x\n",rSMBONETYPER);
printf("\nSynchronous access mode \n");
if (mux_mode)
{
#if SMCLK66MHZ // @66.7MHz
pSmcRegs->rSmbWstRdr = 4; // read wait state. [4:0] min 3 @ 50MHz
pSmcRegs->rSmbWstWrr = 4; // write wait state. [4:0] min 3 @ 50MHz
pSmcRegs->rSmbWstOenr = 3; // OE assertion delay. [3:0] min 2 @ 50MHz
pSmcRegs->rSmbWstWenr = 3; // WE assertion delay. [3:0] min 2 @ 50MHz
#else // @50MHz
pSmcRegs->rSmbWstRdr = 3; // read wait state. [4:0] min 3 @ 50MHz
pSmcRegs->rSmbWstWrr = 3; // write wait state. [4:0] min 3 @ 50MHz
pSmcRegs->rSmbWstOenr = 2; // OE assertion delay. [3:0] min 2 @ 50MHz
pSmcRegs->rSmbWstWenr = 2; // WE assertion delay. [3:0] min 2 @ 50MHz
#endif
}
else
{
#if SMCLK66MHZ // @66.7MHz
pSmcRegs->rSmbWstRdr = 4; // read wait state. [4:0] min 3 @ 50MHz
pSmcRegs->rSmbWstWrr = 4; // write wait state. [4:0] min 3 @ 50MHz
pSmcRegs->rSmbWstOenr = 3; // OE assertion delay. [3:0] min 2 @ 50MHz
pSmcRegs->rSmbWstWenr = 3; // WE assertion delay. [3:0] min 2 @ 50MHz
#else // @50MHz
pSmcRegs->rSmbWstRdr = 3; // read wait state. [4:0] min 3 @ 50MHz
pSmcRegs->rSmbWstWrr = 3; // write wait state. [4:0] min 3 @ 50MHz
pSmcRegs->rSmbWstOenr = 2; // OE assertion delay. [3:0] min 2 @ 50MHz
pSmcRegs->rSmbWstWenr = 2; // WE assertion delay. [3:0] min 2 @ 50MHz
#endif
}
break;
default: // async.
rOND_SYS_CONFIG1 = (sysconfig1& ~(0xf<<12))|(0<<15)|(3<<12);
pSmcRegs->rSmbCr = (pSmcRegs->rSmbCr & ~(0xf<<8))|(0<<10)|(0<<9)|(0<<8); // set SSMC as async read.
printf("Asynchronous access mode \n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -