📄 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 SAMSUNG
//#define TOSHIBA
#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
// Host program苞 data & command甫 林绊罐扁 困茄 structure
extern FLASH_INFO Flash_Info;
uchar TempBuf[BLOCK_SIZE];
uchar FillBuf[PAGE_SIZE];
ulong Current_Block_No = 2;
ulong Current_Page_No = 0;
ulong BIB_Block_No = 1;
ulong LastAddr = 0;
ulong crc = 0;
ulong image_size = 0;
/* The CRC table size is based on how many bits at a time we are going
** to process through the table. Given that we are processing the data
** 8 bits at a time, this gives us 2^8 (256) entries.
*/
#define CRC_TAB_SIZE 256 /* 2^CRC_TAB_BITS */
/* CRC table for 30 bit CRC, with generator polynomial 0x6030b9c7,
** calculated 8 bits at a time, MSB first.
*/
const ulong crc30_table[ CRC_TAB_SIZE ] = {
0x00000000, 0x2030b9c7, 0x2051ca49, 0x0061738e,
0x20932d55, 0x00a39492, 0x00c2e71c, 0x20f25edb,
0x2116e36d, 0x01265aaa, 0x01472924, 0x217790e3,
0x0185ce38, 0x21b577ff, 0x21d40471, 0x01e4bdb6,
0x221d7f1d, 0x022dc6da, 0x024cb554, 0x227c0c93,
0x028e5248, 0x22beeb8f, 0x22df9801, 0x02ef21c6,
0x030b9c70, 0x233b25b7, 0x235a5639, 0x036aeffe,
0x2398b125, 0x03a808e2, 0x03c97b6c, 0x23f9c2ab,
0x240a47fd, 0x043afe3a, 0x045b8db4, 0x246b3473,
0x04996aa8, 0x24a9d36f, 0x24c8a0e1, 0x04f81926,
0x051ca490, 0x252c1d57, 0x254d6ed9, 0x057dd71e,
0x258f89c5, 0x05bf3002, 0x05de438c, 0x25eefa4b,
0x061738e0, 0x26278127, 0x2646f2a9, 0x06764b6e,
0x268415b5, 0x06b4ac72, 0x06d5dffc, 0x26e5663b,
0x2701db8d, 0x0731624a, 0x075011c4, 0x2760a803,
0x0792f6d8, 0x27a24f1f, 0x27c33c91, 0x07f38556,
0x2824363d, 0x08148ffa, 0x0875fc74, 0x284545b3,
0x08b71b68, 0x2887a2af, 0x28e6d121, 0x08d668e6,
0x0932d550, 0x29026c97, 0x29631f19, 0x0953a6de,
0x29a1f805, 0x099141c2, 0x09f0324c, 0x29c08b8b,
0x0a394920, 0x2a09f0e7, 0x2a688369, 0x0a583aae,
0x2aaa6475, 0x0a9addb2, 0x0afbae3c, 0x2acb17fb,
0x2b2faa4d, 0x0b1f138a, 0x0b7e6004, 0x2b4ed9c3,
0x0bbc8718, 0x2b8c3edf, 0x2bed4d51, 0x0bddf496,
0x0c2e71c0, 0x2c1ec807, 0x2c7fbb89, 0x0c4f024e,
0x2cbd5c95, 0x0c8de552, 0x0cec96dc, 0x2cdc2f1b,
0x2d3892ad, 0x0d082b6a, 0x0d6958e4, 0x2d59e123,
0x0dabbff8, 0x2d9b063f, 0x2dfa75b1, 0x0dcacc76,
0x2e330edd, 0x0e03b71a, 0x0e62c494, 0x2e527d53,
0x0ea02388, 0x2e909a4f, 0x2ef1e9c1, 0x0ec15006,
0x0f25edb0, 0x2f155477, 0x2f7427f9, 0x0f449e3e,
0x2fb6c0e5, 0x0f867922, 0x0fe70aac, 0x2fd7b36b,
0x3078d5bd, 0x10486c7a, 0x10291ff4, 0x3019a633,
0x10ebf8e8, 0x30db412f, 0x30ba32a1, 0x108a8b66,
0x116e36d0, 0x315e8f17, 0x313ffc99, 0x110f455e,
0x31fd1b85, 0x11cda242, 0x11acd1cc, 0x319c680b,
0x1265aaa0, 0x32551367, 0x323460e9, 0x1204d92e,
0x32f687f5, 0x12c63e32, 0x12a74dbc, 0x3297f47b,
0x337349cd, 0x1343f00a, 0x13228384, 0x33123a43,
0x13e06498, 0x33d0dd5f, 0x33b1aed1, 0x13811716,
0x14729240, 0x34422b87, 0x34235809, 0x1413e1ce,
0x34e1bf15, 0x14d106d2, 0x14b0755c, 0x3480cc9b,
0x3564712d, 0x1554c8ea, 0x1535bb64, 0x350502a3,
0x15f75c78, 0x35c7e5bf, 0x35a69631, 0x15962ff6,
0x366fed5d, 0x165f549a, 0x163e2714, 0x360e9ed3,
0x16fcc008, 0x36cc79cf, 0x36ad0a41, 0x169db386,
0x17790e30, 0x3749b7f7, 0x3728c479, 0x17187dbe,
0x37ea2365, 0x17da9aa2, 0x17bbe92c, 0x378b50eb,
0x185ce380, 0x386c5a47, 0x380d29c9, 0x183d900e,
0x38cfced5, 0x18ff7712, 0x189e049c, 0x38aebd5b,
0x394a00ed, 0x197ab92a, 0x191bcaa4, 0x392b7363,
0x19d92db8, 0x39e9947f, 0x3988e7f1, 0x19b85e36,
0x3a419c9d, 0x1a71255a, 0x1a1056d4, 0x3a20ef13,
0x1ad2b1c8, 0x3ae2080f, 0x3a837b81, 0x1ab3c246,
0x1b577ff0, 0x3b67c637, 0x3b06b5b9, 0x1b360c7e,
0x3bc452a5, 0x1bf4eb62, 0x1b9598ec, 0x3ba5212b,
0x3c56a47d, 0x1c661dba, 0x1c076e34, 0x3c37d7f3,
0x1cc58928, 0x3cf530ef, 0x3c944361, 0x1ca4faa6,
0x1d404710, 0x3d70fed7, 0x3d118d59, 0x1d21349e,
0x3dd36a45, 0x1de3d382, 0x1d82a00c, 0x3db219cb,
0x1e4bdb60, 0x3e7b62a7, 0x3e1a1129, 0x1e2aa8ee,
0x3ed8f635, 0x1ee84ff2, 0x1e893c7c, 0x3eb985bb,
0x3f5d380d, 0x1f6d81ca, 0x1f0cf244, 0x3f3c4b83,
0x1fce1558, 0x3ffeac9f, 0x3f9fdf11, 0x1faf66d6
};
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: WriteBIB();
break;
case FINIT: InitFlash();
break;
default :
Flash_Info.Result = 0;
}
}
// Flash program function
void Program(void)
{
ulong len, flen, i, fillsize, wSize;
volatile ulong status;
uchar *srcP, *bsrcP;
Flash_Info.Result = 0;
Flash_Info.TargetAddr &= 0x3FFFFFF;
wSize = 0;
if(Flash_Info.TargetAddr != LastAddr) {
fillsize = Flash_Info.TargetAddr - LastAddr;
for(i = 0; i < PAGE_SIZE; i++)
FillBuf[i] = 0xff;
while(fillsize && (Current_Block_No < BLOCK_COUNT))
{
if(!(Current_Page_No%PAGE_CNT)) {
if(!PrepareBlock())
return;
}
if(Current_Block_No >= BLOCK_COUNT)
return;
status = WriteChar(FillBuf, Current_Page_No);
if(!status) // error
return;
ReadChar(TempBuf, Current_Page_No*PAGE_SIZE, PAGE_SIZE);
if(!Verification((ulong *)TempBuf, PAGE_SIZE, (ulong *)FillBuf))
return;
Current_Page_No++;
crc = crc_30_step (crc, FillBuf, (ushort)PAGE_SIZE*8);
image_size +=PAGE_SIZE;
fillsize -= PAGE_SIZE;
AutoKick();
}
}
AutoKick();
srcP = (uchar *)Flash_Info.Buf;
len = Flash_Info.Length;
while(len && (Current_Block_No < BLOCK_COUNT))
{
if(!(Current_Page_No%PAGE_CNT)) {
if(!PrepareBlock())
return;
}
if(Current_Block_No >= BLOCK_COUNT)
return;
if(len > PAGE_SIZE)
flen = PAGE_SIZE;
else {
flen = len;
bsrcP = srcP+len;
for(i=len; i<PAGE_SIZE;i++)
*bsrcP++ = 0xff;
}
status = WriteChar(srcP, Current_Page_No);
if(!status) // error
return;
// ReadChar(TempBuf, Current_Page_No*PAGE_SIZE, PAGE_SIZE);
// if(!Verification((ulong *)TempBuf, PAGE_SIZE, (ulong *)srcP))
// return;
Current_Page_No++;
crc = crc_30_step (crc, srcP, (ushort)PAGE_SIZE*8);
wSize +=PAGE_SIZE;
image_size +=PAGE_SIZE;
len -= flen;
srcP += PAGE_SIZE;
AutoKick();
}
LastAddr = Flash_Info.TargetAddr+wSize;
Flash_Info.Result = 1;
}
// Chip erase function
void EraseAll(void)
{
Flash_Info.Result = 1; // 8Mbyte
}
// Sector erase function
void EraseSector(void)
{
Flash_Info.Result = 1;
}
void WriteBIB(void)
{
struct boot_info_block *bib;
ulong i, bib_size, status;
Flash_Info.Result = 0;
bib = (struct boot_info_block *)Flash_Info.Buf;
bib->magic1 = MAGIC1;
bib->magic2 = MAGIC2;
bib->version = BIB_VERSION;
bib->crc = crc;
bib->startaddr = 0x0;
bib->length = image_size;
bib_size = sizeof(struct boot_info_block);
for(i=bib_size; i<PAGE_SIZE; i++)
Flash_Info.Buf[i] = 0xff;
OneBlockErase(BIB_Block_No);
status = WriteChar(Flash_Info.Buf, BIB_Block_No*PAGE_CNT);
if(!status)
return;
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;
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)
;
/* 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;
}
ulong PrepareBlock(void)
{
while(!Bad_Block_Check(++Current_Block_No))
;
if(Current_Block_No >= BLOCK_COUNT)
return 0;
if(!OneBlockErase(Current_Block_No))
return 0;
Current_Page_No = Current_Block_No*PAGE_CNT;
return 1;
}
int BlankCheck(ulong *targetP,ulong targetSize)
{
ulong i;
for(i=0; i<targetSize; i+=4)
if(*targetP++ != 0xffffffff)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -