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

📄 j_flash.cpp

📁 JFFS的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <string.h>
#include <io.h>			//livefall

#include "../hdinit/nucleus.h"
#include "../hdinit/checkfunc.h"
#include "../jffs/errno.h"
#include "../jffs/jffs_fm.h"
#include "../jffs/j_flash.h"
//#include "../../comm/cmd.h"	livefall

//#include "../../bsp/const.h"
//#include "../../bsp/bsp.h"

/*#define DEBUG*/

int sys_init_done;
/*系统初始化完成前, 直接清看门狗*/
			
#ifdef DEBUG
#define FDEBUG(x) x
#else
#define FDEBUG(x)
#endif

#define D(x) x

#define printk printf

#if 0/*livefall@163.com 2005.01.09*/
#define MAX_CHIPS 1
#define MAX_PARTITIONS 8
#endif
#define MAX_CHIPS 1
#define MAX_PARTITIONS 16

enum {  D5_MASK           = 0x20,
		D6_MASK           = 0x40 };
#if 0/*livefall@163.com 2005.01.09*/
enum {  maxNumberOfBootSectors = 8 };
#endif
enum {  maxNumberOfBootSectors = 16 };

/*!!!unlockAddress定义与原来不一样*/
/* 8-bit wide Flash-ROM */	
enum {  unlockAddress1          = 0x5555,
        unlockData1             = 0xAA,
        unlockAddress2          = 0x2AAA,
        unlockData2             = 0x55,
        manufacturerUnlockData  = 0x90,
        manufacturerAddress     = 0x00,
        deviceIdAddress         = 0x01,
        programUnlockData       = 0xA0,
        resetData               = 0xF0,
        sectorEraseUnlockData   = 0x80,
        sectorEraseUnlockData2  = 0x30 };

enum {  ManufacturerAMD   = 0x01,
	AM29F040          = 0x2200,
	AM29F800BB        = 0x2258,
	AM29F800BT        = 0x22D6,
	AM29LV800BB       = 0x225B,
	AM29LV800BT       = 0x22DA,
	AM29LV160BT       = 0x22C4
};
#if 0/*livefall@163.com 2005.01.09*/
enum {	/*该处定义为Am29F040*/
	C_ERASE_TIMEOUT = 8000, //整片擦除,毫秒: typ=8s, max=64s 
	S_ERASE_TIMEOUT = 2000, //扇区擦除,毫秒: typ=1s, max=8s
	PROGRAM_TIMEOUT = 5,	//字节编程,循环次数, typ = 7us, 一次循环为3.125us
	DELAY_90NS_LOOP	= 1     //等待Flash管脚busy有效
};
#endif	
enum {	/*该处定义为Am29F080*/
	C_ERASE_TIMEOUT = 16000, //整片擦除,毫秒: typ=16s, max=128s 
	S_ERASE_TIMEOUT = 2000, //扇区擦除,毫秒: typ=1s, max=8s
	PROGRAM_TIMEOUT = 5,	//字节编程,循环次数, typ = 7us, 一次循环为3.125us
	DELAY_90NS_LOOP	= 1     //等待Flash管脚busy有效
};

typedef volatile unsigned char *flashptr;

struct flashchip {
	unsigned char *start;
	unsigned char *bootsector;
	unsigned int bootsectorsize[maxNumberOfBootSectors];
	unsigned short manufacturer_id;
	unsigned short device_id;
	unsigned short isValid;
	int size, sectorsize;
	/* to block accesses during erase and writing etc */
	int busy;
	/*TODO: struct wait_queue *wqueue;*/
};

struct flashpartition {
	struct flashchip *chip;   /* the chip we reside in */
	unsigned char *start;     /* starting flash mem address */
	int size;                 /* size of partition in bytes */
	unsigned int flags;       /* protection bits etc */
	unsigned short type;      /* type of partition */
};


static struct flashchip chips[MAX_CHIPS];
static struct flashpartition partitions[MAX_PARTITIONS];


static void flash_init_partitions(void);
static void flash_probe(void);
static struct flashchip *getchip(unsigned char *ptr);
static int flash_is_busy(flashptr flashStart);

/*初始化flash*/
int flash_init(void)
{
	flash_probe();
	flash_init_partitions();
	
	return 0;
}

/* probe for Flash RAM's - this isn't in the init function, because this needs
 * to be done really early in the boot, so we can use the device to burn an
 * image before the system is running.
 */
static void flash_probe(void)
{
	/* start adresses for the Flash chips - these should really
	 * be settable in some other way.
	 */
	int i,j;/*livefall@163.com 2005.01.09*/
	printf("Probing flash...\n");

//	chips[0].start = 0;		livefall@163.com
	(flashptr)chips[0].start = (unsigned char *)0x200000;	/*livefall@163.com 2005.01.31.10.25*/

	for(i = 0; i < MAX_CHIPS; i++) {	/*livefall@163.com 2005.01.09*/
		struct flashchip *chip = chips + i;
		flashptr flashStart = (flashptr)chip->start;

		/*防止Flash死锁*/
		/*若Flash正处于写,完成写序列*/
		#if 0/*livefall@163.com 2005.01.09*/
		flashStart[0x7FFFF] = 0;
		#endif
		flashStart[0xFFFFF] = 0;
		
/*		int j;	livefall@163.com 2005.01.09*/
		for(j=0; j<FOR_1_MS; j++){	/*写入时间一般为7us*/
			if( (*flashStart & D6_MASK) == (*flashStart & D6_MASK) )
				break;
			if( (*flashStart & D5_MASK) == D5_MASK )
				break;
		}
		if(j >= FOR_1_MS) printf("ERROR: flash in unknow status\n");
		
		/*等D5为高时,Flash复位命令才有效*/
		flashStart[unlockAddress1] = unlockData1;
		flashStart[unlockAddress2] = unlockData2;
		flashStart[unlockAddress1] = resetData;

		chip->manufacturer_id = 0;
		chip->device_id = 0;
		chip->isValid = 1;
		#if 1/*livefall@163.com 2005.01.09*/
		chip->size = 0x100000;
		#endif
		#if 0/*livefall@163.com 2005.01.09*/
		chip->size = 0x80000;
		#endif
		chip->sectorsize = 0x10000;
		chip->busy = 0;

		/*TODO: bootsectorsize用来作什么*/
		chip->bootsector = chip->start + chip->size - chip->sectorsize;
		chip->bootsectorsize[0] = 0x0000;	
		chip->bootsectorsize[1] = 0x0000;
		chip->bootsectorsize[2] = 0x0000;
		chip->bootsectorsize[3] = 0x0000;
	}
}

void flash_safe_acquire(void *part)
{
	struct flashchip *chip = ((struct flashpartition *)part)->chip;
	/*while (chip->busy) sleep_on(&chip->wqueue);*/
	chip->busy = 1;
}

void flash_safe_release(void *part)
{
	struct flashchip *chip = ((struct flashpartition *)part)->chip;
	chip->busy = 0;
	/*wake_up(&chip->wqueue);*/
}

/* flash_safe_read and flash_safe_write are used by the JFFS flash filesystem */
int flash_safe_read(void *_part, unsigned char *fptr,
		unsigned char *buf, int count)
{
	struct flashpartition *part = (struct flashpartition *)_part;

	/* Check so it's not totally out of bounds.  */

	if(fptr + count > part->start + part->size) {
		/*printk(KERN_WARNING "flash: read request past "
		       "end of device (address: 0x%p, size: %d)\n",
		       fptr, count);*/
		return -EINVAL;
	}

	FDEBUG(printk("flash_safe_read: %d bytes from 0x%p to 0x%p\n",
		      count, fptr, buf));

	/* Actually do something, but get a lock on the chip first.  */

	flash_safe_acquire(part);

	memcpy(buf, fptr, count);

	/* Release the lock.  */

	flash_safe_release(part);

	return count; /* success */
}

/* locate the flashchip structure associated with the given adress */
static struct flashchip *getchip(unsigned char *ptr)
{
	int i;

	for (i = 0; i < MAX_CHIPS; i++) {
		if (ptr >= chips[i].start
		    && ptr < (chips[i].start + chips[i].size)) {
			return &chips[i];
		}
	}

	/*printk("flash: Illegal adress: getchip(0x%p)!\n", ptr);*/
	return (struct flashchip *)0;
}

/* Write a block of Flash. The destination Flash sectors need to be erased
 * first. If the size is larger than the Flash chip the block starts in, the
 * function will continue flashing in the next chip if it exists.
 * Returns 0 on success, -1 on error.
 */
int flash_write(unsigned char *ptr, const unsigned char *source, unsigned int size)
{
	struct flashchip *chip;
	flashptr theData = (flashptr)source;
	flashptr flashStart;
	flashptr programAddress;
	int i, fsize;
	int odd_size;
	int n;
	static int write_count = 0; /*记录连续写入的次数, 用于触发看门狗*/
	
	while(size > 0) {
		chip = getchip(ptr);

		if(!chip) {
			D(printk("Flash: illegal ptr 0x%p in flash_write.\n", ptr));
			return -EINVAL;
		}

		flashStart = (flashptr)chip->start;
		programAddress = (flashptr)ptr;
		if( (unsigned long)programAddress < JFFS_ADDR_START || (unsigned long)programAddress >= JFFS_ADDR_END ){	//!!!
			D(printk("flash_write: illegal1 ptr 0x%p in flash_write.\n", programAddress));
			return -EINVAL;
		}	
		/* if the block doesn't fit in this flash chip, clamp the size */

		fsize = (ptr + size) > (chip->start + chip->size) ?
			(chip->start + chip->size - ptr) : size;

		ptr += fsize;
		size -= fsize;
		odd_size = fsize & 1;

		/*fsize >>= 1;*/ /* We write one word at a time.  */

		FDEBUG(printk("flash_write (flash start 0x%p) %d words to 0x%p\n",
			      flashStart, fsize, programAddress));

		for (i = 0; i < fsize; i++) {
			int retries = 0;
			
			if(write_count++ > 1000){clearHW(); write_count=0;}
				
			do {
				int timeout;
				/* Start programming sequence.
				 */
#ifdef IRQ_LOCKS
				unsigned long flags;
				save_flags(flags);
				cli();
#endif
		    if( (unsigned long)programAddress < JFFS_ADDR_START || (unsigned long)programAddress >= JFFS_ADDR_END ){	//!!!
				D(printk("flash_write: illegal2 ptr 0x%p in flash_write.\n", programAddress));
				return -EINVAL;
			}

				flashStart[unlockAddress1] = unlockData1;
				flashStart[unlockAddress2] = unlockData2;
				flashStart[unlockAddress1] = programUnlockData;

				*programAddress = *theData;
				
				/* give the busy signal time to activate (tBusy, 90 ns) */
				for(n=0; n<DELAY_90NS_LOOP; n++);
				
				/* Wait for programming to finish.  */
				timeout = PROGRAM_TIMEOUT;

				while(timeout--){	/*写入时间一般为7us*/
					if( (*flashStart & D6_MASK) == (*flashStart & D6_MASK) )
						break;
					if( (*flashStart & D5_MASK) == D5_MASK )
						break;
				}
				
#ifdef IRQ_LOCKS
				restore_flags(flags);
#endif
				if( (*flashStart & D6_MASK) == (*flashStart & D6_MASK) &&
					*programAddress == *theData
					)
					break;

				if( (*flashStart & D5_MASK) == D5_MASK ){
					flashStart[unlockAddress1] = unlockData1;
					flashStart[unlockAddress2] = unlockData2;
					flashStart[unlockAddress1] = resetData;
				}	
				else
					D(printk("flash_write: in unknow status\n"));

⌨️ 快捷键说明

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