OSDN Git Service

am29f040b の erase 後の wait をデータシート準拠の 8 sec に変更
[unagi/old-svn-converted.git] / client / trunk / flashmemory.c
index fcb6c73..ec7c6ad 100644 (file)
@@ -2,7 +2,7 @@
 famicom ROM cartridge utility - unagi
 flash memory driver
 
-Copyright (C) 2008  sato_tiff
+Copyright (C) 2008 ±·³«È¯¶¨Æ±Áȹç
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
@@ -28,6 +28,7 @@ flashmemory.c 
 #include <string.h>
 #include <windows.h>
 #include "type.h"
+#include "header.h"
 #include "flashmemory.h"
 /*
 driver for Winbond W29C020, W49F002
@@ -72,7 +73,7 @@ static const struct flash_task PROTECT_ENABLE[] = {
        {ADDRESS_5555, 0x20},
        {FLASH_COMMAND_END, 0}
 };
-static const struct flash_task ERASE[] = {
+static const struct flash_task ERASE_CHIP[] = {
        {ADDRESS_5555, 0xaa},
        {ADDRESS_2AAA, 0x55},
        {ADDRESS_5555, 0x80},
@@ -82,6 +83,16 @@ static const struct flash_task ERASE[] = {
        {FLASH_COMMAND_END, 0}
 };
 
+static const struct flash_task ERASE_SECTOR[] = {
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       {ADDRESS_5555, 0x80},
+       {ADDRESS_5555, 0xaa},
+       {ADDRESS_2AAA, 0x55},
+       //¤³¤Î¤¢¤È sectoraddress ¤Ë 0x30 ¤ò write
+       {FLASH_COMMAND_END, 0}
+};
+
 static const struct flash_task PP[] = {
        {ADDRESS_5555, 0xaa},
        {ADDRESS_2AAA, 0x55},
@@ -117,6 +128,7 @@ static void command_set(const struct flash_order *d, const struct flash_task *t)
 /*
 ---- product ID check ----
 */
+#define dprintf if(DEBUG==1) printf
 static int productid_check(const struct flash_order *d, const struct flash_driver *f)
 {
        u8 data[3];
@@ -132,12 +144,16 @@ static int productid_check(const struct flash_order *d, const struct flash_drive
        return OK;
 }
 
+static int productid_sram(const struct flash_order *d, const struct flash_driver *f)
+{
+       return OK;
+}
 /*
 ---- toggle check ----
 databit6
 */
 const int CHECK_RETRY_MAX = 0x10000;
-static int toggle_check(const struct flash_order *d, long address)
+static int toggle_check_d6(const struct flash_order *d, long address)
 {
        u8 predata;
        int retry = 0;
@@ -156,11 +172,44 @@ static int toggle_check(const struct flash_order *d, long address)
        return NG;
 }
 
+static int toggle_check_d2d5d6(const struct flash_order *d, long address)
+{
+       u8 predata;
+       int retry = 0;
+       d->read(address, 1, &predata);
+       predata &= 0x40;
+       do{
+               u8 data;
+               d->read(address, 1, &data);
+               //DQ6 toggle check
+               if(predata == (data & 0x40)){
+                       return OK;
+               }
+               //DQ5 == 0 ¤Ê¤é¤ä¤ê¤Ê¤ª¤·
+               if(data & 0x20){
+                       //recheck toggle bit, read twice
+                       u8 t[2];
+                       d->read(address, 1, &t[0]);
+                       d->read(address, 1, &t[1]);
+                       if((t[0] & 0x40) == (t[1] & 0x40)){
+                               return OK;
+                       }
+                       //Program/Erase operation not complete, write reset command.
+                       return NG;
+               }
+               if((retry & 0x0f) == 0){
+                       dprintf("toggle out %06x \n", (int) address);
+               }
+               retry++;
+       }while(retry < CHECK_RETRY_MAX);
+       return NG;
+}
+
 /*
 ---- polling check ----
 databit7
 */
-static int polling_check(const struct flash_order *d, long address, u8 truedata)
+static int polling_check_d7(const struct flash_order *d, long address, u8 truedata)
 {
        int retry = 0;
        
@@ -177,57 +226,102 @@ static int polling_check(const struct flash_order *d, long address, u8 truedata)
        return NG;
 }
 
-static void bootblock_lockout(const struct flash_order *d)
+static int polling_check_d5d7(const struct flash_order *d, long address, u8 truedata)
 {
-       u8 dummy[3];
-       command_set(d, PP);
-       d->read(0x8000 ,3, dummy);
-       printf("%02x %02x %02x \n", dummy[0], dummy[1], dummy[2]);
-       d->read(0xfff2 ,1, dummy);
-       command_set(d, PRODUCTID_EXIT);
+       int retry = 0;
+       
+       truedata &= 0x80;
+       do{
+               u8 data;
+               d->read(address, 1, &data);
+               if(truedata == (data & 0x80)){
+                       return OK;
+               }
+               if(data & 0x20){
+                       d->read(address, 1, &data);
+                       if(truedata == (data & 0x80)){
+                               return OK;
+                       }
+                       dprintf("%s error", __FUNCTION__);
+                       return NG;
+               }
+               retry++;
+       }while(retry < CHECK_RETRY_MAX);
+       return NG;
 }
 /*
 ---- erase ----
 */
-static void flash_erase(const struct flash_order *d)
+static void flash_erase_chip_2aaa(const struct flash_order *d)
 {
-       if(0) bootblock_lockout(d);
-       command_set(d, ERASE);
-       toggle_check(d, d->command_2aaa);
+       command_set(d, ERASE_CHIP);
+       toggle_check_d6(d, d->command_2aaa);
        Sleep(200); //Tec 0.2 sec
 }
 
+static void flash_erase_chip_02aa(const struct flash_order *d)
+{
+       u8 data;
+       d->read(d->command_2aaa, 1, &data);
+       command_set(d, ERASE_CHIP);
+       if(0){
+               toggle_check_d2d5d6(d, d->command_2aaa);
+               
+       }else{
+               polling_check_d5d7(d, d->command_2aaa, data);
+       }
+       Sleep(8000); //chip erase time 8sec, max64sec
+}
+
+#if DEBUG==1
+static void sram_erase(const struct flash_order *d)
+{
+       //bank ÀÚ¤êÂؤ¨¤¬È¼¤¦¤Î¤Ç¼ÂÁõ¤Ç¤­¤Ê¤¤
+}
+#endif
+
 /*
 ---- program ----
 */
 static int program_byte(const struct flash_order *d, long address, const u8 *data, long length)
 {
+       int retry = 0;
        while(length != 0){
                if(*data != 0xff){
+                       fflush(stdout);
                        command_set(d, PROTECT_DISABLE);
                        d->flash_write(address, *data);
-                       if(toggle_check(d, address) == NG){
-                               if(DEBUG == 1){
-                                       printf("%s NG\n", __FUNCTION__);
-                               }
+                       if(toggle_check_d6(d, address) == NG){
+                               dprintf("%s NG\n", __FUNCTION__);
                                return NG;
                        }
-                       Sleep(1);
                }
-               if((DEBUG == 1) && (address & 0x1f) == 0){
-                       printf("%s %06x\n", __FUNCTION__, (int) address);
-                       fflush(stdout);
+               u8 dummy;
+               d->read(address, 1, &dummy);
+               if(*data == dummy){
+                       address++;
+                       data++;
+                       length--;
+                       retry = 0;
+               }else if(retry > 8){
+                       dprintf("%s %06x error\n", __FUNCTION__, (int) address);
+                       address++;
+                       data++;
+                       length--;
+                       retry = 0;
+                       if(DEBUG == 0){
+                               return NG;
+                       }
+               }else{
+                       retry++;
                }
-               address++;
-               data++;
-               length--;
        }
        return OK;
 }
 
 static int program_pagewrite(const struct flash_order *d, long address, const u8 *data, long length)
 {
-       const long toggle_address = address;
+       const long toggle_address = address ;
        command_set(d, PROTECT_DISABLE);
        while(length != 0){
                d->flash_write(address, *data);
@@ -235,47 +329,16 @@ static int program_pagewrite(const struct flash_order *d, long address, const u8
                data++;
                length--;
        }
-       Sleep(15);
-       int ret = toggle_check(d, toggle_address);
+       int ret = toggle_check_d6(d, toggle_address);
        if(0){
                data--;
-               address -= 1;
-               polling_check(d, address - 1, *data);
+               polling_check_d7(d, address - 1, *data);
        }
 
-       //command_set(d, PROTECT_ENABLE);
-       //Sleep(15);
        return ret;
 }
 
 /*
----- block compare ----
-*/
-static void compare(const struct flash_order *d, long address, const u8 *data, long length)
-{
-       u8 *romdata, *r;
-       int count = 0;
-       romdata = malloc(length);
-       d->read(address, length, romdata);
-       r = romdata;
-       while(length != 0){
-               if(*r != *data){
-                       char safix = ' ';
-                       if((count & 7) == 7){
-                               safix = '\n';
-                       }
-                       count++;
-                       printf("%06x%c", (int)address, safix);
-               }
-               r++;
-               data++;
-               address++;
-               length--;
-       }
-       free(romdata);
-}
-
-/*
 ¸ÇÍ­¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð
 */
 static void w49f002_init(const struct flash_order *d)
@@ -284,105 +347,224 @@ static void w49f002_init(const struct flash_order *d)
 byte program mode ¤Ç¤Ï 1->0 ¤Ë¤¹¤ë¤À¤±¡£ 0->1 ¤Ï erase ¤Î¤ß¡£
 ¤è¤Ã¤Æ½é´ü²½»þ¤Ë¤Ï erase ¤ò¼Â¹Ô¤¹¤ë
 */
-       flash_erase(d);
+       flash_erase_chip_2aaa(d);
+}
+
+static void w49f002_write(const struct flash_order *d, long address, long length, const struct memory *m)
+{
+       program_byte(d, address, m->data, length);
+//     dprintf("write %s 0x%06x done\n", m->name, (int) m->offset);
 }
 
-static void w49f002_write(const struct flash_order *d, long address, long length, const u8 *data)
+static void am29f040_init(const struct flash_order *d)
 {
-       program_byte(d, address, data, length);
-       compare(d, address, data, length);
+       flash_erase_chip_02aa(d);
+}
+
+static void am29f040_write(const struct flash_order *d, long address, long length, const struct memory *m)
+{
+       const u8 *data;
+       data = m->data;
+       while(length != 0){
+               if(*data != 0xff){
+                       command_set(d, PROTECT_DISABLE);
+                       d->flash_write(address, *data);
+                       if(toggle_check_d2d5d6(d, address) == NG){
+                               dprintf("%s NG\n", __FUNCTION__);
+                               return;
+                       }
+               }
+               address++;
+               data++;
+               length--;
+       }
 }
 
-static void w29c020_init(const struct flash_order *d)
+static void init_nop(const struct flash_order *d)
 {
 /*
 page write mode ¤Ç¤Ï¤È¤¯¤Ë¤Ê¤·
 */
 }
 
-static void w29c020_write(const struct flash_order *d, long address, long length, const u8 *data)
+static void w29c040_write(const struct flash_order *d, long address, long length, const struct memory *m)
 {
-       const long pagesize = 0x80;
+       u8 *cmp;
+       int ngblock = 0;
        int retry = 0;
-       {
+       assert(d->pagesize != 0);
+       cmp = malloc(d->pagesize);
+       do{
                long a = address;
                long i = length;
+               long offset = m->offset;
                const u8 *dd;
-               u8 *cmp;
 
-               dd = data;
-               cmp = malloc(pagesize);
+               dd = m->data;
+               ngblock = 0;
                while(i != 0){
-                       int result = program_pagewrite(d, a, dd, pagesize);
-                       if(result == NG){
-                               printf("%s: write error\n", __FUNCTION__);
-                               free(cmp);
-                               return;
-                       }
-                       d->read(a, pagesize, cmp);
-                       if(memcmp(cmp, dd, pagesize) == 0){
-                               a += pagesize;
-                               dd += pagesize;
-                               i -= pagesize;
-                       }else{
-                               if(retry >= 0x100){
-                                       break;
+                       d->read(a, d->pagesize, cmp);
+                       if(memcmp(cmp, dd, d->pagesize) != 0){
+                               ngblock++;
+                               dprintf("write %s 0x%06x\n", m->name, (int) offset);
+                               int result = program_pagewrite(d, a, dd, d->pagesize);
+                               if(result == NG){
+                                       printf("%s: write error\n", __FUNCTION__);
+                                       free(cmp);
+                                       return;
                                }
-                               retry++;
                        }
+                       a += d->pagesize;
+                       dd += d->pagesize;
+                       offset += d->pagesize;
+                       i -= d->pagesize;
                }
-               free(cmp);
+               dprintf("%s 0x%06x, ngblock %d\n", m->name, (int) m->offset, ngblock);
+               if(retry >= 3 && ngblock >= 16){
+                       dprintf("skip\n");
+                       break;
+               }
+               else if(retry > 12){
+                       dprintf("skip\n");
+                       break;
+               }
+               retry++;
+               fflush(stdout);
+       }while(ngblock != 0);
+
+       free(cmp);
+}
+
+static void sram_write(const struct flash_order *d, long address, long length, const struct memory *m)
+{
+       const u8 *data;
+       data = m->data;
+       while(length != 0){
+               d->flash_write(address, *data);
+               address++;
+               data++;
+               length--;
        }
+}
 
-       printf("write ok. retry %d\n", retry);
-       compare(d, address, data, length);
-       Sleep(10);
+static void dummy_write(const struct flash_order *d, long address, long length, const struct memory *m)
+{
 }
 
 /*
 ¥Ç¥Ð¥¤¥¹¥ê¥¹¥È
 */
+//0x80 °Ê¹ß¤ÏËÜÅö¤Î¥Ç¥Ð¥¤¥¹½ÅÊ£¤·¤Ê¤¤¤È»×¤¦. Ã¯¤« JEDEC ¤Î¤È¤³¤ò¤·¤é¤Ù¤Æ.
+static const struct flash_driver DRIVER_SRAM256K = {
+       .name = "SRAM256K",
+       .capacity = 0x8000,
+       .pagesize = 0,
+       .id_manufacurer = FLASH_ID_DEVICE_SRAM,
+       .id_device = FLASH_ID_DEVICE_SRAM,
+       .productid_check = productid_sram,
+#if DEBUG==1
+       .erase = sram_erase,
+#endif
+       .init = init_nop,
+       .write = sram_write
+};
+
+static const struct flash_driver DRIVER_DUMMY = {
+       .name = "dummy",
+       .capacity = 0x40000,
+       .pagesize = 0,
+       .id_manufacurer = FLASH_ID_DEVICE_DUMMY,
+       .id_device = FLASH_ID_DEVICE_DUMMY,
+       .productid_check = productid_sram,
+#if DEBUG==1
+       .erase = sram_erase,
+#endif
+       .init = init_nop,
+       .write = dummy_write
+};
+
 static const struct flash_driver DRIVER_W29C020 = {
        .name = "W29C020",
        .capacity = 0x40000,
+       .pagesize = 0x80,
        .id_manufacurer = 0xda,
        .id_device = 0x45,
        .productid_check = productid_check,
 #if DEBUG==1
-       .erase = flash_erase,
+       .erase = flash_erase_chip_2aaa,
 #endif
-       .init = w29c020_init,
-       .write = w29c020_write
+       .init = init_nop,
+       .write = w29c040_write
 };
 
 static const struct flash_driver DRIVER_W29C040 = {
        .name = "W29C040",
        .capacity = 0x80000,
+       .pagesize = 0x100,
        .id_manufacurer = 0xda,
        .id_device = 0x46,
        .productid_check = productid_check,
 #if DEBUG==1
-       .erase = flash_erase,
+       .erase = flash_erase_chip_2aaa,
 #endif
-       .init = w29c020_init,
-       .write = w29c020_write
+       .init = init_nop,
+       .write = w29c040_write
 };
 
 static const struct flash_driver DRIVER_W49F002 = {
        .name = "W49F002",
        .capacity = 0x40000,
+       .pagesize = 0,
        .id_manufacurer = 0xda,
        .id_device = 0xae,
        .productid_check = productid_check,
 #if DEBUG==1
-       .erase = flash_erase,
+       .erase = flash_erase_chip_2aaa,
 #endif
        .init = w49f002_init,
        .write = w49f002_write
 };
 
+/*
+MANUFATUTER ID 0x7f1c
+EN29F002T DEVICE ID 0x7f92
+EN29F002B DEVICE ID 0x7f97
+
+command address ¤¬ 0x00555, 0x00aaa ¤Ë¤Ê¤Ã¤Æ¤ë
+*/
+static const struct flash_driver DRIVER_EN29F002T = {
+       .name = "EN29F002T",
+       .capacity = 0x40000,
+       .pagesize = 0,
+       .id_manufacurer = 0x1c,
+       .id_device = 0x92,
+       .productid_check = productid_check,
+#if DEBUG==1
+       .erase = flash_erase_chip_02aa,
+#endif
+       .init = am29f040_init,
+       .write = am29f040_write
+};
+
+static const struct flash_driver DRIVER_AM29F040B = {
+       .name = "AM29F040B",
+       .capacity = 0x80000,
+       .pagesize = 0,
+       .id_manufacurer = 0x01,
+       .id_device = 0xa4,
+       .productid_check = productid_check,
+#if DEBUG==1
+       .erase = flash_erase_chip_02aa,
+#endif
+       .init = am29f040_init,
+       .write = am29f040_write
+};
+
 static const struct flash_driver *DRIVER_LIST[] = {
-       &DRIVER_W29C020, &DRIVER_W29C040, &DRIVER_W49F002,
+       &DRIVER_W29C020, &DRIVER_W29C040, 
+       &DRIVER_W49F002, &DRIVER_EN29F002T, &DRIVER_AM29F040B,
+       &DRIVER_SRAM256K, 
+       &DRIVER_DUMMY,
        NULL
 };