📄 j_flash.cpp
字号:
#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 + -