📄 nandflash.c
字号:
/*************************************************************************/
/* */
/* FILE NAME VERSION */
/* */
/* source\flash.c 1.0 */
/* */
/* DESCRIPTION */
/* */
/* */
/* */
/* DATA STRUCTURES */
/* */
/* FUNCTIONS : Flash Fujitsu program code */
/* */
/* DEPENDENCIES */
/* */
/* */
/* */
/* Copyrigth (C) 2001 AIJISYSTEM CO.,LTD */
/*************************************************************************/
#include <stdio.h>
#include <string.h>
#include "common.h"
#define PAGE_CNT 32
#define PAGE_SIZE 512
#define BLOCK_COUNT 4096
#define BLOCK_SIZE 0x4000
#define BASE_ADDR (ulong)0x64000000
volatile ulong *data_reg = (ulong *)0x64000000;
volatile ulong *spare_data_reg = (ulong *)0x64000320;
volatile ulong *cle_reg = (ulong *)0x64000300;
volatile ulong *ale_reg = (ulong *)0x64000304;
volatile ulong *status_reg = (ulong *)0x64000308;
volatile ulong *ecc_read_reg = (ulong *)0x6400030c;
volatile ushort *flash_cfg_reg = (ushort *)0x6400031c;
volatile ulong *clear_status_reg = (ulong *)0x80000c84;
// WatchDog reset阑 规瘤窍扁 困茄 register
//volatile ushort *AutoKick_reg = (ushort *)0x3000600; //MSM3000, 3100, 5000, 5105
//volatile ushort *AutoKick_reg = (ushort *)0x3000700; //MSM5100 watch dog address
//volatile ushort *AutoKick_reg = (ushort *)0x30006d0; //MSM6050
//volatile ushort *AutoKick_reg = (ushort *)0x3001080; //MSM5500
//volatile ushort *AutoKick_reg = (ushort *)0x80000700; //MSM6100
volatile ushort *AutoKick_reg = (ushort *)0x80003404; //MSM6250
//volatile ushort *AutoKick_reg = (ushort *)0x80001b40; //MSM6500
// Host program苞 data & command甫 林绊罐扁 困茄 structure
extern FLASH_INFO Flash_Info;
uchar TempBuf[BLOCK_SIZE];
ulong Current_Block_No = 0;
ulong Current_Page_No = 0;
void Main(void)
{
switch(Flash_Info.Command)
{
case FPROGRAM: Program();
break;
case FERASEALL:
//Flash_Info.Result = 1;
EraseAll();
break;
case FERASESEC:
//Flash_Info.Result = 1;
EraseSector();
break;
case FREADID: ReadChipID();
break;
case FREADMEM: ReadMem();
break;
case FWRITE_BIB:
Flash_Info.Result = 1;
break;
case FINIT: InitFlash();
break;
default :
Flash_Info.Result = 0;
}
}
// Flash program function
void Program(void)
{
Flash_Info.Result = 1;
}
// Chip erase function
void EraseAll(void)
{
ulong i;
for(i=0; i < BLOCK_COUNT; i++)
OneBlockErase(i);
Flash_Info.Result = 1; // 8Mbyte
}
// Sector erase function
void EraseSector(void)
{
ulong sBlock, eBlock, eAddr, i;
eAddr = Flash_Info.TargetAddr + Flash_Info.Length - 1;
sBlock = Flash_Info.TargetAddr >> 14;
eBlock = eAddr >> 14;
for(i=sBlock; i <= eBlock; i++) {
if(i >= BLOCK_COUNT)
break;
OneBlockErase(i);
}
Flash_Info.Result = 1;
}
// 窍唱狼 Sector 父 Erase
int OneBlockErase(ulong block)
{
ulong status;
ulong nand_cntlr_block_addr;
int block_size_shift;
ushort no_of_shifts = 1;
AutoKick();
block_size_shift = PAGE_CNT;
while ( block_size_shift != 2 )
{
block_size_shift = block_size_shift >> 1;
no_of_shifts++;
}
/* Set the block address in Nand_Flash_Addr */
nand_cntlr_block_addr = block << (9 + no_of_shifts);
*ale_reg = nand_cntlr_block_addr;
/* Issue the block erase command */
*cle_reg = ERASE_CMD;
/* Wait for erase command to be executed */
while(*status_reg & ERASE_CMD)
AutoKick();
/* Check status after erase */
status = *status_reg;
if( (status & FS_NAND_OP_ERR_MASK != 0) ||
(status & FS_NAND_OP_RESULT_MASK != 0) )
{
return 0;
}
return 1;
}
// Read Manufacturer & Device ID
void ReadChipID(void)
{
ulong manId,devId;
*cle_reg = RESET_CMD;
*cle_reg = ID_CMD;
/* Wait for completion. */
while(*status_reg & ID_CMD)
{
*AutoKick_reg = 1;
*AutoKick_reg = 0;
}
manId = *status_reg;
devId = (manId >> 15) & 0xff;
manId = (manId >> 23) & 0xff;
Flash_Info.Result = (devId << 8) + manId;
}
int BlankCheck(ulong *targetP,ulong targetSize)
{
ulong i;
for(i=0; i<targetSize; i+=4)
if(*targetP++ != 0xffffffff)
return 0;
return 1;
}
int Verification(ulong *targetP, ulong limit, ulong *srcAddr)
{
ulong i;
// sourceP = (ushort *)srcAddr;
for(i=0; i<limit; i+=4, targetP++, srcAddr++)
if(*targetP != *srcAddr) {
return 0;
}
return 1;
}
int ReadChar(uchar *data, ulong targetAddr, ulong size)
{
ulong i, len, flen, status;
len = size;
for (i=0; i<size; i+=PAGE_SIZE) {
if(len > PAGE_SIZE)
flen = PAGE_SIZE;
else
flen = len;
*ale_reg = targetAddr & 0x01FFFE00;
*cle_reg = READ_DATA;
while(*status_reg & READ_DATA) {
*AutoKick_reg = 1;
*AutoKick_reg = 0;
}
status = *status_reg;
if( (status & FS_NAND_OP_ERR_MASK != 0) ||
(status & FS_NAND_ECC_SELF_ERR_MASK != 0) ||
(status & FS_NAND_READ_ECC_ERR_MASK != 0) )
return 0;
// for(j=0; j<flen; j++, data++)
// *data = *(data_reg+j);
memcpy((void *)data, (void *)data_reg, flen);
data += flen;
len -= PAGE_SIZE;
targetAddr += PAGE_SIZE;
AutoKick();
}
return 1;
}
int WriteChar(uchar *data, ulong page_addr)
{
ushort status;
memcpy((void *)data_reg, (void *)data, PAGE_SIZE);
*ale_reg = page_addr << 9;
*cle_reg = PROGRAM_CMD;
while(*status_reg & PROGRAM_CMD)
AutoKick();
status = *status_reg;
if( (status & FS_NAND_OP_ERR_MASK != 0) ||
(status & FS_NAND_OP_RESULT_MASK != 0) )
return 0;
return 1;
}
void ReadMem(void)
{
uchar *srcP;
srcP = (uchar *)Flash_Info.Buf;
ReadChar(srcP, Flash_Info.TargetAddr, Flash_Info.Length);
Flash_Info.Result = 1;
}
void InitFlash(void)
{
ulong status;
/* Reset NAND flash memory */
*cle_reg = RESET_CMD;
/* Software reset the controller. */
*cle_reg = RESET_CTRL;
/* Reset NAND flash memory */
*cle_reg = RESET_CMD;
/* Configure NAND flash */
*flash_cfg_reg = FS_NAND_CNFG_VAL;
/* Wait for completion. */
while(*status_reg & PROGRAM_CMD)
{
*AutoKick_reg = 1;
*AutoKick_reg = 0;
}
/* Do a id check. */
*cle_reg = ID_CMD;
/* Wait for completion. */
while(*status_reg & ID_CMD)
{
*AutoKick_reg = 1;
*AutoKick_reg = 0;
}
/* Do a status check */
*cle_reg = STATUS_CMD;
/* Wait for completion. */
while(*status_reg & STATUS_CMD)
{
*AutoKick_reg = 1;
*AutoKick_reg = 0;
}
status = *status_reg;
Current_Block_No = 0;
Current_Page_No = 0;
}
void AutoKick(void)
{
*AutoKick_reg = 1;
*AutoKick_reg = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -