diff --git a/Linux/SNANDer b/Linux/SNANDer index e980f9f..a648e77 100755 Binary files a/Linux/SNANDer and b/Linux/SNANDer differ diff --git a/MacOSX/SNANDer.aarch64 b/MacOSX/SNANDer.aarch64 index fe4912f..c616664 100755 Binary files a/MacOSX/SNANDer.aarch64 and b/MacOSX/SNANDer.aarch64 differ diff --git a/MacOSX/SNANDer.x86_64 b/MacOSX/SNANDer.x86_64 index d63f571..9f32625 100755 Binary files a/MacOSX/SNANDer.x86_64 and b/MacOSX/SNANDer.x86_64 differ diff --git a/Windows/SNANDer.exe b/Windows/SNANDer.exe index 2bd53b7..54a7e4d 100755 Binary files a/Windows/SNANDer.exe and b/Windows/SNANDer.exe differ diff --git a/flash_support_list.txt b/flash_support_list.txt index 7e6b4b6..05413d1 100644 --- a/flash_support_list.txt +++ b/flash_support_list.txt @@ -1,5 +1,5 @@ -SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.6 by McMCC +SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.7 by McMCC SPI NAND Flash Support List: 001. GIGADEVICE GD5F1GQ4UA @@ -240,3 +240,4 @@ SPI EEPROM Support List: 008. 25128 009. 25256 010. 25512 +011. 251024 diff --git a/readme.txt b/readme.txt index ffea7df..2fdf355 100644 --- a/readme.txt +++ b/readme.txt @@ -1,4 +1,4 @@ -SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.6 by McMCC +SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.7 by McMCC Usage: -h display this message @@ -9,9 +9,10 @@ SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.6 by McMCC -i read the chip ID info -E select I2C EEPROM {24c01|24c02|24c04|24c08|24c16|24c32|24c64|24c128|24c256|24c512|24c1024} select Microwire EEPROM {93c06|93c16|93c46|93c56|93c66|93c76|93c86|93c96} (need SPI-to-MW adapter) - select SPI EEPROM 25xxx {25010|25020|25040|25080|25160|25320|25640|25128|25256|25512} + select SPI EEPROM 25xxx {25010|25020|25040|25080|25160|25320|25640|25128|25256|25512|251024} -8 set organization 8-bit for Microwire EEPROM(default 16-bit) and set jumper on SPI-to-MW adapter -f set manual address size in bits for Microwire EEPROM(default auto) + -s set page size from datasheet for fast write SPI EEPROM(default not usage) -e erase chip(full or use with -a [-l]) -l manually set length -a
manually set address @@ -25,7 +26,7 @@ Examples: igor@mcmcc-GL553VE:~/Soft/SNANDer-bin/Linux$ ./SNANDer -i -SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.6 by McMCC +SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.7 by McMCC Found programmer device: WinChipHead (WCH) - CH341A Device revision is 3.0.4 @@ -37,7 +38,7 @@ Detected SPI NAND Flash: MXIC MX35LF2G, Flash Size: 256 MB or -SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.6 by McMCC +SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.7 by McMCC Found programmer device: Winchiphead (WCH) - CH341A Device revision is 3.0.4 @@ -51,7 +52,7 @@ Detected SPI NAND Flash: WINBOND W25N01G, Flash Size: 128 MB igor@mcmcc-GL553VE:~/Soft/SNANDer-bin/Linux$ ./SNANDer -d -e -SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.6 by McMCC +SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.7 by McMCC Found programmer device: WinChipHead (WCH) - CH341A Device revision is 3.0.4 @@ -72,7 +73,7 @@ igor@mcmcc-GL553VE:~/Soft/SNANDer-bin/Linux$ igor@mcmcc-GL553VE:~/Soft/SNANDer-bin/Linux$ ./SNANDer -d -v -w ecc_2Gb_2K_64_flashimage_rfb1_ac2600.bin -SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.6 by McMCC +SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.7 by McMCC Found programmer device: WinChipHead (WCH) - CH341A Device revision is 3.0.4 @@ -96,7 +97,7 @@ Status: OK igor@igor-GL553VE:~/Soft/SNANDer-bin/Linux$ ./SNANDer -E 93c46 -r test.bin -SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.6 by McMCC +SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.7 by McMCC Found programmer device: WinChipHead (WCH) - CH341A Device revision is 3.0.4 @@ -113,7 +114,7 @@ Status: OK igor@igor-GL553VE:~/Soft/SNANDer-bin/Linux$ ./SNANDer -E 93c46 -w test.bin -v -SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.6 by McMCC +SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.7 by McMCC Found programmer device: WinChipHead (WCH) - CH341A Device revision is 3.0.4 @@ -138,14 +139,14 @@ Status: OK igor@igor-GL553VE:~/Soft/SNANDer-bin/Linux$ ./SNANDer -E 25640 -v -w test.bin -SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.6 by McMCC +SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.7 by McMCC Found programmer device: WinChipHead (WCH) - CH341A Device revision is 3.0.4 SPI EEPROM chip: 25640, Size: 8192 bytes WRITE: -Written addr = 0x0000000000000000, len = 0x0000000000002000 -Wrote 100% [8192] bytes to [25640] EEPROM address 0x00000000 +Write addr = 0x0000000000000000, len = 0x0000000000002000 +Written 100% [8192] bytes to [25640] EEPROM address 0x00000000 Elapsed time: 22 seconds Status: OK VERIFY: @@ -153,3 +154,25 @@ Read addr = 0x0000000000000000, len = 0x0000000000002000 Read 100% [8192] bytes from [25640] EEPROM address 0x00000000 Elapsed time: 2 seconds Status: OK + +7. Fast write and verify SPI EEPROM Atmel AT25640B from file with use page size. + (Find out page size from datasheet on chip!!!) + +igor@igor-GL553VE:~/Soft/SNANDer-bin/Linux$ ./SNANDer -E 25640 -v -w test.bin -s 32 + +SNANDer - Serial Nor/nAND/Eeprom programmeR v.1.7.7 by McMCC + +Found programmer device: WinChipHead (WCH) - CH341A +Device revision is 3.0.4 +SPI EEPROM chip: 25640, Size: 8192 bytes +Setting page size 32B for write. +WRITE: +Write addr = 0x0000000000000000, len = 0x0000000000002000 +Written 100% [8192] bytes to [25640] EEPROM address 0x00000000 +Elapsed time: 1 seconds +Status: OK +VERIFY: +Read addr = 0x0000000000000000, len = 0x0000000000002000 +Read 100% [8192] bytes from [25640] EEPROM address 0x00000000 +Elapsed time: 2 seconds +Status: OK diff --git a/src/main.c b/src/main.c index 5b744fc..3c44abc 100644 --- a/src/main.c +++ b/src/main.c @@ -41,17 +41,19 @@ extern char eepromname[12]; extern int eepromsize; extern int seepromsize; extern int mw_eepromsize; +extern int spage_size; extern int org; #define EHELP " -E select I2C EEPROM {24c01|24c02|24c04|24c08|24c16|24c32|24c64|24c128|24c256|24c512|24c1024}\n" \ " select Microwire EEPROM {93c06|93c16|93c46|93c56|93c66|93c76|93c86|93c96} (need SPI-to-MW adapter)\n" \ - " select SPI EEPROM 25xxx {25010|25020|25040|25080|25160|25320|25640|25128|25256|25512}\n" \ + " select SPI EEPROM 25xxx {25010|25020|25040|25080|25160|25320|25640|25128|25256|25512|251024}\n" \ " -8 set organization 8-bit for Microwire EEPROM(default 16-bit) and set jumper on SPI-to-MW adapter\n" \ - " -f set manual address size in bits for Microwire EEPROM(default auto)\n" + " -f set manual address size in bits for Microwire EEPROM(default auto)\n" \ + " -s set page size from datasheet for fast write SPI EEPROM(default not usage)\n" #else #define EHELP "" #endif -#define _VER "1.7.6" +#define _VER "1.7.7" void title(void) { @@ -94,9 +96,9 @@ int main(int argc, char* argv[]) title(); #ifdef EEPROM_SUPPORT - while ((c = getopt(argc, argv, "diIhveLl:a:w:r:o:E:f:8")) != -1) + while ((c = getopt(argc, argv, "diIhveLl:a:w:r:o:s:E:f:8")) != -1) #else - while ((c = getopt(argc, argv, "diIhveLl:a:w:r:o:")) != -1) + while ((c = getopt(argc, argv, "diIhveLl:a:w:r:o:s:")) != -1) #endif { switch(c) @@ -167,6 +169,10 @@ int main(int argc, char* argv[]) str = strdup(optarg); OOB_size = strtoll(str, NULL, *str && *(str + 1) == 'x' ? 16 : 10); break; + case 's': + str = strdup(optarg); + spage_size = strtoll(str, NULL, *str && *(str + 1) == 'x' ? 16 : 10); + break; case 'a': str = strdup(optarg); addr = strtoll(str, NULL, *str && *(str + 1) == 'x' ? 16 : 10); @@ -218,10 +224,24 @@ int main(int argc, char* argv[]) printf("Programmer not supported auto detect EEPROM!\n\n"); goto out; } + if (spage_size) { + if (!seepromsize) { + printf("Use only for SPI EEPROM!\n\n"); + goto out; + } + if (((spage_size % 8) != 0) || (spage_size > (MAX_SEEP_PSIZE / 2))){ + printf("Invalid parameter %dB for page size SPI EEPROM!\n\n", spage_size); + goto out; + } + if (op == 'r') + printf("Ignored set page size SPI EEPROM on READ.\n"); + else + printf("Setting page size %dB for write.\n", spage_size); + } #else if (op == 'i') goto out; #endif - if (op == 'o') { + if (OOB_size) { if (ECC_fcheck == 1) { printf("Ignore option -o, use with -d only!\n"); OOB_size = 0; diff --git a/src/snander.rc b/src/snander.rc index 33360f8..cc6be30 100644 --- a/src/snander.rc +++ b/src/snander.rc @@ -2,8 +2,8 @@ #include "res.h" VS_VERSION_INFO VERSIONINFO - FILEVERSION 1, 7, 6, 0 - PRODUCTVERSION 1, 7, 6, 0 + FILEVERSION 1, 7, 7, 0 + PRODUCTVERSION 1, 7, 7, 0 FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP FILESUBTYPE 0 @@ -15,11 +15,11 @@ BEGIN VALUE "FileDescription", "SNANDer - Serial Nor/nAND/Eeprom programmeR\0" VALUE "OriginalFilename", "SNANDer.exe\0" VALUE "CompanyName", "-= (c) 2018-2022 Igor Mokrushin aka McMCC =-\0" - VALUE "FileVersion", "1.7.6.0\0" + VALUE "FileVersion", "1.7.7.0\0" VALUE "InternalName", "SNANDer\0" VALUE "LegalCopyright", "Copyright (c) 2018-2022 by McMCC \0" VALUE "ProductName","SNANDer\0" - VALUE "ProductVersion","1.7.6.0\0" + VALUE "ProductVersion","1.7.7.0\0" END END BLOCK "VarFileInfo" diff --git a/src/spi_eeprom.c b/src/spi_eeprom.c index 048744f..6271378 100644 --- a/src/spi_eeprom.c +++ b/src/spi_eeprom.c @@ -26,6 +26,7 @@ extern unsigned int bsize; extern char eepromname[12]; struct spi_eeprom seeprom_info; int seepromsize = 0; +int spage_size = 0; static void wait_ready(void) { @@ -62,24 +63,30 @@ static void write_enable(void) } } -static void eeprom_write_byte(struct spi_eeprom *dev, uint16_t address, uint8_t data) +static void eeprom_write_byte(struct spi_eeprom *dev, uint32_t address, uint8_t data) { - uint8_t buf[4]; + uint8_t buf[5]; write_enable(); buf[0] = SEEP_WRITE_CMD; - if (dev->addr_bits == 9 && address > 0xff) + if (dev->addr_bits == 9 && address > 0xFF) buf[0] = buf[0] | 0x08; SPI_CONTROLLER_Chip_Select_Low(); - if (dev->addr_bits < 10) { + if (dev->addr_bits > 16) { + buf[1] = (address & 0xFF0000) >> 16; + buf[2] = (address & 0xFF00) >> 8; + buf[3] = (address & 0xFF); + buf[4] = data; + SPI_CONTROLLER_Write_NByte(buf, 5, SPI_CONTROLLER_SPEED_SINGLE); + } else if (dev->addr_bits < 10) { buf[1] = (address & 0xFF); buf[2] = data; SPI_CONTROLLER_Write_NByte(buf, 3, SPI_CONTROLLER_SPEED_SINGLE); } else { - buf[1] = (address & 0x0FF00) >> 8; - buf[2] = (address & 0x0FF); + buf[1] = (address & 0xFF00) >> 8; + buf[2] = (address & 0xFF); buf[3] = data; SPI_CONTROLLER_Write_NByte(buf, 4, SPI_CONTROLLER_SPEED_SINGLE); } @@ -88,24 +95,67 @@ static void eeprom_write_byte(struct spi_eeprom *dev, uint16_t address, uint8_t wait_ready(); } -static uint8_t eeprom_read_byte(struct spi_eeprom *dev, uint16_t address) +static void eeprom_write_page(struct spi_eeprom *dev, uint32_t address, int page_size, uint8_t *data) { - uint8_t buf[3]; + uint8_t buf[MAX_SEEP_PSIZE]; + uint8_t offs = 0; + + memset(buf, 0, sizeof(buf)); + + buf[0] = SEEP_WRITE_CMD; + if (dev->addr_bits == 9 && address > 0xFF) + buf[0] = buf[0] | 0x08; + + if (dev->addr_bits > 16) { + buf[1] = (address & 0xFF0000) >> 16; + buf[2] = (address & 0xFF00) >> 8; + buf[3] = (address & 0xFF); + offs = 4; + } else if (dev->addr_bits < 10) { + buf[1] = (address & 0xFF); + offs = 2; + } else { + buf[1] = (address & 0xFF00) >> 8; + buf[2] = (address & 0xFF); + offs = 3; + } + + memcpy(&buf[offs], data, page_size); + + write_enable(); + + SPI_CONTROLLER_Chip_Select_Low(); + SPI_CONTROLLER_Write_NByte(buf, offs + page_size, SPI_CONTROLLER_SPEED_SINGLE); + SPI_CONTROLLER_Chip_Select_High(); + + wait_ready(); +} + +static uint8_t eeprom_read_byte(struct spi_eeprom *dev, uint32_t address) +{ + uint8_t buf[4]; uint8_t data; buf[0] = SEEP_READ_CMD; - if (dev->addr_bits == 9 && address > 0xff) + if (dev->addr_bits == 9 && address > 0xFF) buf[0] = buf[0] | 0x08; SPI_CONTROLLER_Chip_Select_Low(); - if (dev->addr_bits < 10) { + if (dev->addr_bits > 16) { + buf[1] = (address & 0xFF0000) >> 16; + buf[2] = (address & 0xFF00) >> 8; + buf[3] = (address & 0xFF); + SPI_CONTROLLER_Write_NByte(buf, 4, SPI_CONTROLLER_SPEED_SINGLE); + SPI_CONTROLLER_Read_NByte(buf, 1, SPI_CONTROLLER_SPEED_SINGLE); + data = buf[0]; + } else if (dev->addr_bits < 10) { buf[1] = (address & 0xFF); SPI_CONTROLLER_Write_NByte(buf, 2, SPI_CONTROLLER_SPEED_SINGLE); SPI_CONTROLLER_Read_NByte(buf, 1, SPI_CONTROLLER_SPEED_SINGLE); data = buf[0]; } else { - buf[1] = (address & 0x0FF00) >> 8; - buf[2] = (address & 0x0FF); + buf[1] = (address & 0xFF00) >> 8; + buf[2] = (address & 0xFF); SPI_CONTROLLER_Write_NByte(buf, 3, SPI_CONTROLLER_SPEED_SINGLE); SPI_CONTROLLER_Read_NByte(buf, 1, SPI_CONTROLLER_SPEED_SINGLE); data = buf[0]; @@ -132,7 +182,7 @@ int32_t parseSEEPsize(char *seepromname, struct spi_eeprom *seeprom) int spi_eeprom_read(unsigned char *buf, unsigned long from, unsigned long len) { unsigned char *pbuf, ebuf[MAX_SEEP_SIZE]; - int i; + uint32_t i; if (len == 0) return -1; @@ -142,7 +192,7 @@ int spi_eeprom_read(unsigned char *buf, unsigned long from, unsigned long len) pbuf = ebuf; for (i = 0; i < seepromsize; i++) { - pbuf[i] = eeprom_read_byte(&seeprom_info, (uint16_t)i); + pbuf[i] = eeprom_read_byte(&seeprom_info, i); if( timer_progress() ) { printf("\bRead %d%% [%d] of [%d] bytes ", 100 * i / seepromsize, i, seepromsize); @@ -152,7 +202,7 @@ int spi_eeprom_read(unsigned char *buf, unsigned long from, unsigned long len) } memcpy(buf, pbuf + from, len); - printf("Read 100%% [%d] bytes from [%s] EEPROM address 0x%08lu\n", (int)len, eepromname, from); + printf("Read 100%% [%lu] bytes from [%s] EEPROM address 0x%08lu\n", len, eepromname, from); timer_end(); return (int)len; @@ -161,7 +211,7 @@ int spi_eeprom_read(unsigned char *buf, unsigned long from, unsigned long len) int spi_eeprom_erase(unsigned long offs, unsigned long len) { unsigned char *pbuf, ebuf[MAX_SEEP_SIZE]; - int i; + uint32_t i; if (len == 0) return -1; @@ -172,12 +222,16 @@ int spi_eeprom_erase(unsigned long offs, unsigned long len) if (offs || len < seepromsize) { for (i = 0; i < seepromsize; i++) - pbuf[i] = eeprom_read_byte(&seeprom_info, (uint16_t)i); + pbuf[i] = eeprom_read_byte(&seeprom_info, i); memset(pbuf + offs, 0xff, len); } for (i = 0; i < seepromsize; i++) { - eeprom_write_byte(&seeprom_info, (uint16_t)i, pbuf[i]); + if (spage_size) { + eeprom_write_page(&seeprom_info, i, spage_size, pbuf + i); + i = (spage_size + i) - 1; + } else + eeprom_write_byte(&seeprom_info, i, pbuf[i]); if( timer_progress() ) { printf("\bErase %d%% [%d] of [%d] bytes ", 100 * i / seepromsize, i, seepromsize); @@ -186,7 +240,7 @@ int spi_eeprom_erase(unsigned long offs, unsigned long len) } } - printf("Erased 100%% [%d] bytes of [%s] EEPROM address 0x%08lu\n", (int)len, eepromname, offs); + printf("Erased 100%% [%lu] bytes of [%s] EEPROM address 0x%08lu\n", len, eepromname, offs); timer_end(); return 0; @@ -195,7 +249,7 @@ int spi_eeprom_erase(unsigned long offs, unsigned long len) int spi_eeprom_write(unsigned char *buf, unsigned long to, unsigned long len) { unsigned char *pbuf, ebuf[MAX_SEEP_SIZE]; - int i; + uint32_t i; if (len == 0) return -1; @@ -206,12 +260,16 @@ int spi_eeprom_write(unsigned char *buf, unsigned long to, unsigned long len) if (to || len < seepromsize) { for (i = 0; i < seepromsize; i++) - pbuf[i] = eeprom_read_byte(&seeprom_info, (uint16_t)i); + pbuf[i] = eeprom_read_byte(&seeprom_info, i); } memcpy(pbuf + to, buf, len); for (i = 0; i < seepromsize; i++) { - eeprom_write_byte(&seeprom_info, (uint16_t)i, pbuf[i]); + if (spage_size) { + eeprom_write_page(&seeprom_info, i, spage_size, pbuf + i); + i = (spage_size + i) - 1; + } else + eeprom_write_byte(&seeprom_info, i, pbuf[i]); if( timer_progress() ) { printf("\bWritten %d%% [%d] of [%d] bytes ", 100 * i / seepromsize, i, seepromsize); @@ -220,7 +278,7 @@ int spi_eeprom_write(unsigned char *buf, unsigned long to, unsigned long len) } } - printf("Written 100%% [%d] bytes to [%s] EEPROM address 0x%08lu\n", (int)len, eepromname, to); + printf("Written 100%% [%lu] bytes to [%s] EEPROM address 0x%08lu\n", len, eepromname, to); timer_end(); return (int)len; diff --git a/src/spi_eeprom.h b/src/spi_eeprom.h index 421543a..c24229e 100644 --- a/src/spi_eeprom.h +++ b/src/spi_eeprom.h @@ -26,24 +26,26 @@ struct spi_eeprom { char *name; uint32_t total_bytes; /* EEPROM total memory size */ - int16_t addr_bits; /* Number of address bit */ + uint8_t addr_bits; /* Number of address bit */ }; const static struct spi_eeprom seepromlist[] = { - { "25010", 128, 7 }, - { "25020", 256, 8 }, - { "25040", 512, 9 }, - { "25080", 1024, 10 }, - { "25160", 2048, 11 }, - { "25320", 4096, 12 }, - { "25640", 8192, 13 }, - { "25128", 16384, 14 }, - { "25256", 32768, 15 }, - { "25512", 65536, 16 }, - { 0, 0, 0 } + { "25010", 128, 7 }, + { "25020", 256, 8 }, + { "25040", 512, 9 }, + { "25080", 1024, 10 }, + { "25160", 2048, 11 }, + { "25320", 4096, 12 }, + { "25640", 8192, 13 }, + { "25128", 16384, 14 }, + { "25256", 32768, 15 }, + { "25512", 65536, 16 }, + { "251024", 131072, 17 }, + { 0, 0, 0 } }; -#define MAX_SEEP_SIZE 65536 +#define MAX_SEEP_SIZE 131072 +#define MAX_SEEP_PSIZE 1024 int32_t parseSEEPsize(char *seepromname, struct spi_eeprom *seeprom);