⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 k9f2816x0c_16bit.c

📁 一个nand flash管理的算法(匈牙利算法)
💻 C
字号:
#ifndef _K9F2816X0C_16bit_C_
#define _K9F2816X0C_16bit_C_

/****************************************************************************
 *
 *            Copyright (c) 2005 by HCC Embedded 
 *
 * This software is copyrighted by and is the sole property of 
 * HCC.  All rights, title, ownership, or other interests
 * in the software remain the property of HCC.  This
 * software may only be used in accordance with the corresponding
 * license agreement.  Any unauthorized use, duplication, transmission,  
 * distribution, or disclosure of this software is expressly forbidden.
 *
 * This Copyright notice may not be removed or modified without prior
 * written consent of HCC.
 *
 * HCC reserves the right to modify this software without notice.
 *
 * HCC Embedded
 * Budapest 1132
 * Victor Hugo Utca 11-15
 * Hungary
 *
 * Tel:  +36 (1) 450 1302
 * Fax:  +36 (1) 450 1303
 * http: www.hcc-embedded.com
 * email: info@hcc-embedded.com
 *
 ***************************************************************************/

#include "llayer.h"
#include "prgmacro.h"
#include "mdebug.h"


#define BLOCK_SIZE   0x4000 /* 16k */
#define BLOCK_NUM    1024   /* 1024 block all */
#define PAGE_SIZE    512    /* page size is 512 byte */
#define SPARE_SIZE   16     /* spare size is 512 byte */

/****************************************************************************
 *
 * static definitions
 *
 ***************************************************************************/


#define PAGEPERBLOCK (BLOCK_SIZE/PAGE_SIZE) /* number of pages in a block */

/****************************************************************************
 *
 * HW specific definitions
 *
 ***************************************************************************/

/* base addresses */

#define NANDCMD  (*(volatile unsigned long*)0x1000000)
#define NANDADDR (*(volatile unsigned long*)0x1000004)
#define NANDDATA (*(volatile unsigned long*)0x1000008)
#define NANDRB   (*(volatile unsigned long*)0x100000c)

/* command of device */

#define NCMD_READ1     0x00
#define NCMD_READ2     0x50
#define NCMD_READID    0x90
#define NCMD_RESET     0xFF
#define NCMD_PAGEPRG   0x80
#define NCMD_PAGEPRG2  0x10
#define NCMD_BLKERASE  0x60
#define NCMD_BLKERASE2 0xD0
#define NCMD_READST    0x70

/*  status bits  */

#define ST_ERROR 0x01
#define ST_READY 0x40
#define ST_WPROT 0x80

/****************************************************************************
 *
 * NANDcmd
 *
 * Send command to chip ( CLE-hi  ALE-lo WR-hi)
 *
 * INPUTS
 *
 * cmd - what byte command to send
 *
 ***************************************************************************/

static void NANDcmd(long cmd) {
	NANDCMD = cmd | 0xff0000;
}

/****************************************************************************
 *
 * NANDaddr
 *
 * send address to chip ( CLE-lo ALE-hi WR-hi )
 *
 * INPUTS
 *
 * addr - page number
 *
 ***************************************************************************/

static void NANDaddr(long addr) {
	addr&=0xff;
	NANDADDR = addr;
}

/****************************************************************************
 *
 * NANDwaitrb
 *
 * Wait until RB (ready/busy) signal goes high
 *
 ***************************************************************************/

static void NANDwaitrb() {
	for (;;) {
		if (NANDRB & 1) return;
	}
}

/****************************************************************************
 *
 * ll_read
 *
 * read a page 
 *
 * INPUTS
 *
 * pba - physical block address
 * ppo - physical page offset
 * buffer - page data pointer where to store data (data+spare)
 *
 * RETURNS
 *
 * LL_OK - if successfuly
 * LL_ERASED - if page is empty
 * LL_ERROR - if any error
 *
 ***************************************************************************/

unsigned char ll_read(t_ba pba,t_po ppo, unsigned char *buffer) {
long pagenum=(long)pba*PAGEPERBLOCK+(long)ppo;
long a,b,num;
unsigned long *rp=(unsigned long*)buffer;
unsigned long ecc,eccori,ecchi,ecclo;

	ecc=0;
	num=0x0000ffff; /* 24 bit ecc  */

	NANDcmd(NCMD_READ1);
	NANDaddr(0);
	NANDaddr(pagenum);
	NANDaddr(pagenum>> 8);
	NANDwaitrb();

	for (a=0; a<PAGE_SIZE+SPARE_SIZE-4; a+=4) {  /* get whole page data */
		register long data=NANDDATA & 0xffff;
      data<<=16;
      data|=NANDDATA & 0xffff; /* 2times 16bit */

		*rp++=data;
		for (b=0; b<32; b++) {       /* calculate ECC */
			if (data&1) ecc^=num;
			num+=0x0000ffff;
			data>>=1;
		}
	}
                   
	eccori=NANDDATA & 0xffff;  /* get ecc from 1st 32bit in spare area */
   eccori<<=16;
   eccori|=NANDDATA & 0xffff; /* 2times 16bit */

	ecc^=eccori;
	if (!ecc) {
      fnPr("ReadPage: ok pba %d ppo %d\n",pba,ppo);
      return LL_OK; /* no bit error */
   }

	ecchi=ecc>>16;
	ecclo=ecc&0x0ffff;

	if ( (ecchi + ecclo) !=0x0ffffUL ) {
   	for (a=0; a<PAGE_SIZE+SPARE_SIZE-4; a++) {
	   	if (buffer[a]!=(unsigned char)0xff) {
            fnPr("ReadPage: error 1 pba %d ppo %d\n",pba,ppo);
            return LL_ERROR; /* ecc error */
         }
   	}

   	if (eccori==0xffffffffUL) {
         fnPr("ReadPage: erased pba %d ppo %d\n",pba,ppo);
         return LL_ERASED; /* erased not written */
      }

      fnPr("ReadPage: error 2 pba %d ppo %d\n",pba,ppo);
      return LL_ERROR; /* ecc error */
   }

	buffer[ ecchi >> 3] ^= (1<< (ecchi&7) ); /* correcting error */

   fnPr("ReadPage: corrected pba %d ppo %d\n",pba,ppo);
	return LL_OK;

}

/****************************************************************************
 *
 * ll_write
 *
 * write a page 
 *
 * INPUTS
 *
 * pba - physical block address
 * ppo - physical page offset
 * buffer - page data to be written (data+spare)
 *
 * RETURNS
 *
 * LL_OK - if successfuly
 * LL_ERROR - if any error
 *
 ***************************************************************************/

unsigned char ll_write(t_ba pba,t_po ppo,unsigned char *buffer) {
long pagenum=(long)pba*PAGEPERBLOCK+(long)ppo;
long io;
long a,b;
unsigned long ecc,num;
unsigned long *rp=(unsigned long*)buffer;
//unsigned char *s=(unsigned char*)data;

	ecc=0;
	num=0x0000ffff; /* 24 bit ecc  */

	NANDcmd(NCMD_READ1);
	NANDcmd(NCMD_PAGEPRG);
	NANDaddr(0);
	NANDaddr(pagenum);
	NANDaddr(pagenum>> 8);

	for (a=0; a<PAGE_SIZE+SPARE_SIZE-4; a+=4) {  /* write one page data */
		unsigned long rdata=*rp++;

		NANDDATA= (rdata>>16) & 0xffff;
		NANDDATA= rdata&0xffff; /* 2times 16bit */

		for (b=0; b<32; b++) {       /* calculate ECC */
			if (rdata&1) ecc^=num;
			num+=0x0000ffff;
			rdata>>=1;
		}

	}

	NANDDATA= (ecc>>16)& 0xffff;   /* write ecc also, but this is in spare area yet */
   NANDDATA= ecc & 0xffff;        /* 16bit */

	NANDcmd(NCMD_PAGEPRG2);
	NANDwaitrb();

	NANDcmd(NCMD_READST);
	io=NANDDATA; /* holding status */

	if (io & ST_ERROR) return LL_ERROR;

	if (!(io & ST_READY)) return LL_ERROR;

	return LL_OK;
}

/****************************************************************************
 *
 * ll_writedouble
 *
 * write a page from 2 buffers
 *
 * INPUTS
 *
 * pba - physical block address
 * ppo - physical page offset
 * buffer - 1st half of page data to be written
 * buffer - 2nd half of page data + spare data to be written 
 *
 * RETURNS
 *
 * LL_OK - if successfuly
 * LL_ERROR - if any error
 *
 ***************************************************************************/

unsigned char ll_writedouble(t_ba pba,t_po ppo, unsigned  char *buffer0,unsigned  char *buffer1) {
long pagenum=(long)pba*PAGEPERBLOCK+(long)ppo;
long io;
long a,b;
unsigned long ecc,num;
unsigned long *rp=(unsigned long*)buffer0;
//unsigned char *s=(unsigned char*)data;

	ecc=0;
	num=0x0000ffff; /* 24 bit ecc  */

	NANDcmd(NCMD_READ1);
	NANDcmd(NCMD_PAGEPRG);
	NANDaddr(0);
	NANDaddr(pagenum);
	NANDaddr(pagenum>> 8);

	for (a=0; a<PAGE_SIZE/2; a+=4) {  /* write one page data */
		unsigned long rdata=*rp++;

		NANDDATA= (rdata>>16) & 0xffff;
		NANDDATA= rdata&0xffff; /* 2times 16bit */

		for (b=0; b<32; b++) {       /* calculate ECC */
			if (rdata&1) ecc^=num;
			num+=0x0000ffff;
			rdata>>=1;
		}

	}

   rp=(unsigned long*)buffer1;

	for (; a<PAGE_SIZE+SPARE_SIZE-4; a+=4) {  /* write one page data */
		unsigned long rdata=*rp++;

		NANDDATA= (rdata>>16) & 0xffff;
		NANDDATA= rdata&0xffff; /* 2times 16bit */

		for (b=0; b<32; b++) {       /* calculate ECC */
			if (rdata&1) ecc^=num;
			num+=0x0000ffff;
			rdata>>=1;
		}

	}

	NANDDATA= (ecc>>16)& 0xffff;   /* write ecc also, but this is in spare area yet */
   NANDDATA= ecc & 0xffff;        /* 16bit */

	NANDcmd(NCMD_PAGEPRG2);
	NANDwaitrb();

	NANDcmd(NCMD_READST);
	io=NANDDATA; /* holding status */

	if (io & ST_ERROR) return LL_ERROR;

	if (!(io & ST_READY)) return LL_ERROR;

	return LL_OK;
}

/****************************************************************************
 *
 * ll_erase
 *
 * erase a block
 *
 * INPUTS
 *
 * pba - physical block address
 *
 * RETURNS
 *
 * LL_OK - if successfuly
 * LL_ERROR - if any error
 *
 ***************************************************************************/

unsigned char ll_erase(t_ba pba) {
long pagenum=(long)pba*PAGEPERBLOCK;
long io;

/*    fnPr("Erase: %d\n",block);    */

	NANDcmd(NCMD_BLKERASE);
	NANDaddr(pagenum);
	NANDaddr(pagenum>> 8);

	NANDcmd(NCMD_BLKERASE2);
	NANDwaitrb();

	NANDcmd(NCMD_READST);
	io=NANDDATA; /* holding status */

	if (io & ST_ERROR) return LL_ERROR;

	if (!(io & ST_READY)) return LL_ERROR;

	return LL_OK;
}

/****************************************************************************
 *
 * ll_init
 *
 * low level init function, this is called from mlayer lowinit function once
 *
 * RETURNS
 *
 * 0 - if successfuly
 * other if any error
 *
 ***************************************************************************/

unsigned char ll_init() {
long manID, devID;

	NANDcmd(NCMD_READID);
	NANDaddr(0);

	manID=NANDDATA & 0xffff;
	devID=NANDDATA & 0xffff;

	if ((manID==0x00ec) && (devID==0x0053)) {
   		return 0; /* ok */
	}

	return 1; /*  unknown type  */
}

/****************************************************************************
 *
 *  end of K9F2816X0C_16bit.c
 *
 ***************************************************************************/

#endif /* _K9F2816X0C_16bit_C_ */



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -