/ ************************************************* *************************** /
/ * SPI FlashROM programmer on the PC parallel port * /
/ ************************************************* *************************** /
/ * Created: March 24, 2008 [DJGPP] * /
/ * Last modified: 28.10.2008 [DJGPP] * /
/ * Copyright (C) 2008 by RayeR / Martin Rehak * /
/ * Contact: rayer ^ en * list * /
/ ************************************************* *************************** /
# Include <stdlib.h>
# Include <stdio.h>
# Include <string.h>
# Include <ctype.h>
# Include <time.h>
# Define SPI_CS_PIN 5 / / D5 (CS #)
# Define SPI_SCK_PIN 6 / / D6 (CLK)
# Define SPI_MOSI_PIN 7 / / D7 (DIO)
# Define SPI_MISO_PIN 6 / / ACK (DO)
# Define SPI_BUFFER_SIZE 100000LU / / SPI data buffer 100kB (64kB + reserve)
/ / ***************** SPI control lines macros *************************** *****
# Define SPI_SET_CS outportb (lpt_base, inportb (lpt_base) | (1 << SPI_CS_PIN))
# Define SPI_CLR_CS outportb (lpt_base, inportb (lpt_base) & (~ (1 << SPI_CS_PIN)))
# Define SPI_SET_SCK outportb (lpt_base, inportb (lpt_base) | (1 << SPI_SCK_PIN))
# Define SPI_CLR_SCK outportb (lpt_base, inportb (lpt_base) & (~ (1 << SPI_SCK_PIN)))
# Define SPI_SET_MOSI outportb (lpt_base, inportb (lpt_base) | (1 << SPI_MOSI_PIN))
# Define SPI_CLR_MOSI outportb (lpt_base, inportb (lpt_base) & (~ (1 << SPI_MOSI_PIN)))
# Define SPI_GET_MISO ((inportb (lpt_base +1) >> SPI_MISO_PIN) & 1)
/ / ***************** SPI FlashROM command codes *************************** ***
/ / 25Xxx FlashROM description:
/ / SPI mode 0: SCK idle state = low DIO sampled on rising edge, he clocked IN falling edge, MSB first
/ / 512kB memory, total 8 per 64 KB blocks, 1 block = 16 Sectors per 4 KB, 1 sector = 16 pages per 256B
# Define SPI_FLASH_WREN 0x06 / / Enable enrollment
SPI_FLASH_WRDIS 0x04 # define / / the prohibition on registration
SPI_FLASH_RDSTAT 0x05 # define / / status register of honor; S7: 0 - bit7 = stat reg Protect bit5 = top / bot write protect, bit4: 2 = Block protect bits, bit1 = WE latch, bit0 = busy
# Define SPI_FLASH_WRSTAT 0x01 / / write status register, S7: 0
SPI_FLASH_RDDATA 0x03 # define / / credit data; A23: 16, A15: A8, A7: 0, D7: 0, DB till the next end
# Define SPI_FLASH_FASTRD 0x0B / / quick read, A23: 16, A15: A8, A7: 0, dummyB, D7: 0, DB till the next end
# Define SPI_FLASH_FASTRD2 0x3B / / fast reading 2 lines DO and DIO, A23: 16, A15: A8, A7: 0, dummyB, D7: 0 bit interleaved, next DB till the end
SPI_FLASH_PAGEPGM 0x02 # define / / Programming Site; A23: 16, A15: A8, A7: 0, D7: 0, DB till the next end
# Define SPI_FLASH_BLKERASE 0xD8 / / Delete the block (64kB for 25Xxx) A23: 16, A15: A8, A7: 0
SPI_FLASH_SECERASE 0x20 # define / / erased sector (4kB for 25Xxx) A23: 16, A15: A8, A7: 0
# Define SPI_FLASH_CHIPERASE 0xC7 / / Delete the cell FlashROM
# Define SPI_FLASH_PWRDWN 0xB9 / / Asleep
# Define SPI_FLASH_RELPWRDWN 0xAB / / of Asleep awakened; dummyB, dummyB, dummyB, ID7: 0 (10h = X10, X20 = 11h, 12h = X40, X80 = 13h)
SPI_FLASH_MIDDID 0x90 # define / / ID products and equipment; dummyB, dummyB, 0, M7: 0 (EFH = Winbond), ID7: 0 (10h = X10, X20 = 11h, 12h = X40, X80 = 13h)
# Define SPI_FLASH_JEDECID 0x9F / / JEDEC manufacturer M7: 0, ID15: 8, ID7: 0 (3011h = X10, X20 = 3012h, 3013h = X40, X80 = 3014h)
# Define SPI_FLASH_JID_ATMEL 0x1F / / Atmel
SPI_FLASH_JID_STM 0x20 # define / / ST Microelectronic
# Define SPI_FLASH_JID_SST 0xBF / / SST (Silicon Storage Technology)
# Define SPI_FLASH_JID_MACRONIX 0xC2 / / Macronix
# Define SPI_FLASH_JID_WINBOND 0xEF / / Winbond
# Define SPI_FLASH_PAGE_SIZE 256 / / page size, max unit for enrollment
# Define SPI_FLASH_SECTOR_SIZE 4096 / / sector size, min. Unit cunning
# Define SPI_FLASH_BLOCK_SIZE 65536 / / block size, larger unit for lubricated
# Define unsigned short Word
# Define unsigned long DWord
# Define byte unsigned char
# Define usleep'll do
Word lpt_base = 0x378 / / LPT1 I / O base address
Spi_sck_pulse_delay DWord = 0 / / attachments to delay the SCK pulse duration
Spi_di_buffer Byte [SPI_BUFFER_SIZE] / / SPI data input buffer
Spi_do_buffer Byte [SPI_BUFFER_SIZE] / / SPI data output buffer
Spi_flash_size DWord = 0, / / total size of FlashROM
/ / ***************** Adjustable resting SPI lines to Union level *******************
spi_init void (void)
{
SPI_SET_CS / / EN # = high
SPI_CLR_SCK / / CLK = low
SPI_CLR_MOSI / / = low MOSI
memset (spi_di_buffer, 0, SPI_BUFFER_SIZE) / / clear input data buffer
memset (spi_do_buffer, 0, SPI_BUFFER_SIZE) / / clear output data buffer
}
/ / ***************** Vypis hexadecimal and text a given number of doors in the SPI buffer
spi_print_buffer void (* Byte p_buffer, long count, long offset)
{
long i, j;
for (i = 0; i <count; i + = 16) / / 16-across all residential units
{
printf ("% 06lX:", i + offset) / / outputs the address
for (j = 0, j <16; j + +) / / over all byte in block 16B
{
if ((j & 0x7) == 0) / / at the beginning and after 8 Bytes
putchar ('') / / space delimiter
if ((j + i) <count) / / if not listed all the Byte
printf ("% 02x", p_buffer [j + i]) / / Listing 1 byte in hex
else
printf ("") / / otherwise make extracts instead of spaces
}
putchar ('') / / space delimiter
for (j = 0, j <16; j + +) / / over all byte in block 16B
if ((j + i) <count) / / if not listed all the Byte
{
if (p_buffer [j + i]> = '') / / if it is printable characters
putchar (p_buffer [j + i]) / / outputs it
else
putchar ('') / / otherwise vypis gap
}
putchar ('\ n') / / end of the line
}
}
/ / ***************** Write operation reads a byte over SPI unattended CS # signal ***
Spi_rw_byte_no_cs Byte (Byte data_out)
{
Byte data_in = 0, i;
for (i = 0; i <8; i + +) / / over all bits of the Flat
{
data_in << = 1 / / Shift to next bit input, Will Be at bit0 placed object
if ((data_out & 0x80) == 0) / / start from MSB to LSB
SPI_CLR_MOSI / / data bit is 0
else
SPI_SET_MOSI / / data bit is 1
'll do (spi_sck_pulse_delay) / / setup data delay
SPI_SET_SCK / / Slave samples the data on rising clock edge
data_in | = SPI_GET_MISO / / slave sample output, from LSB to MSB
'll do (spi_sck_pulse_delay) / / clock pulse delay
SPI_CLR_SCK / / clock back to default state
data_out << = 1 / / Shift to next output bit, MSB Will Be send
}
return (data_in) / / return byte readed
}
/ / ***************** Write operation reads a byte over SPI including the management of CS # *********
Spi_rw_byte Byte (Byte data_out)
{
Byte data_in;
SPI_CLR_SCK / / default state clock
SPI_CLR_CS / / chip select enabled
'll do (spi_sck_pulse_delay) / / wait for chip active
data_in = spi_rw_byte_no_cs (data_out) / / write / read byte
'll do (spi_sck_pulse_delay) / / wait for chip inactive
SPI_SET_CS / / chip select disabled
return (data_in);
}
/ / ***************** Write operation reads the data block including control SPI CS # *******
spi_rw_block void (* p_do_buffer Byte, Byte * p_di_buffer, DWord blk_size)
{
long i;
SPI_CLR_SCK / / default state clock
SPI_CLR_CS / / chip select enabled
'll do (spi_sck_pulse_delay) / / wait for chip active
for (i = 0; i <blk_size; i + +) / / all over the apartment block
p_di_buffer [i] = spi_rw_byte_no_cs (p_do_buffer [i]) / / write / read byte
'll do (spi_sck_pulse_delay) / / wait for chip inactive
SPI_SET_CS / / chip select disabled
}
/ / ***************** Reads the status register SPI FlashROM (bit0 = busy) *******
Byte spi_flash_status (void)
{
spi_do_buffer [0] = SPI_FLASH_RDSTAT / / command code to put output buffer
spi_rw_block (spi_do_buffer, spi_di_buffer, 2) / / execute block read / write
return (spi_di_buffer [1]) / / return second Byte read by default - the status register
}
/ / ***************** Waiting until the SPI FlashROM busy (eg for deleting) *******
spi_flash_wait_busy void (int timeout) / / timeout in milliseconds
{
while ((timeout -)> 0) / / until the timeout has not expired
{
'll do (1000);
if ((spi_flash_status () & 0x1) == 0) / / status of honor
break / / if the busy bit = 0, break
}
}
/ / ***************** Provide operations entry into the SPI FlashROM ************************** **
# Define spi_flash_write_enable () spi_rw_byte (SPI_FLASH_WREN)
/ / ***************** Prohibit the registration of the SPI FlashROM ************************** **
# Define spi_flash_write_disable () spi_rw_byte (SPI_FLASH_WRDIS)
/ / *****************-Reads manufacturer and device ID MSB-LSB SPI FlashROM ****
Word spi_flash_read_id (void)
{
memset (spi_do_buffer, 0.6) / / clear output buffer
spi_do_buffer [0] = SPI_FLASH_MIDDID / / command code to put output buffer
spi_rw_block (spi_do_buffer, spi_di_buffer, 6) / / execute block read / write
return (((Word) spi_di_buffer [4] << 8) | spi_di_buffer [5]);
}
/ / ***************** Reads JEDEC-byte2, MemType-byte1, MEMSIZE-Byte0 *****
Spi_flash_read_jid DWord (void)
{
memset (spi_do_buffer, 0.4) / / clear output buffer
spi_do_buffer [0] = SPI_FLASH_JEDECID / / command code to put output buffer
spi_rw_block (spi_do_buffer, spi_di_buffer, 4) / / execute block read / write
return (((DWord) spi_di_buffer [1] << 16) | ((DWORD) spi_di_buffer [2] << 8) | spi_di_buffer [3]);
}
/ / ***************** Block reads data from the address of the SPI FlashROM (eliminates uvodni dummy byte, the data in the buffer starting at 0)
spi_flash_read_block void (DWORD start_address, DWord blk_size)
{
long i;
if (blk_size> (SPI_BUFFER_SIZE-4))
{
printf ("ERROR: read block size (% lub) exceeds SPI read buffer (lub%) \ n", blk_size, SPI_BUFFER_SIZE);
return;
}
spi_do_buffer [0] = SPI_FLASH_RDDATA / / command code to put output buffer
spi_do_buffer [1] = (start_address >> 16) &0xFF; / / Put A23: 16 to output buffer
spi_do_buffer [2] = (start_address >> 8) &0xFF; / / Put A15: 8 to output buffer
spi_do_buffer [3] = (start_address >> 0) &0xFF; / / Put A7: 0 to output buffer
spi_rw_block (spi_do_buffer, spi_di_buffer, blk_size +4) / / execute block read / write
for (i = 0; i <blk_size; i + +) / / block of apartments all over
spi_di_buffer [i] = spi_di_buffer [i +4] / / shift the data byte by 4 down
}
/ / ***************** Reads out the whole file into SPI FlashROM ***************
spi_flash_dump int (char * file_name, DWord total_size)
{
DWord address;
FILE * fw = fopen (file_name, "wb"); / / open file for writing
if (fw == NULL) / / if the error and finish
{
printf ("ERROR: Can not create file% s \ n", file_name);
return (-1);
}
for (address = 0; address <total_size; address + = SPI_FLASH_SECTOR_SIZE)
{
/ / Across all sectors
printf ("Reading at sector:% 08lXh (% lu%%) \ r", address, 100 * (address SPI_FLASH_SECTOR_SIZE +) / total_size);
spi_flash_read_block (address, SPI_FLASH_SECTOR_SIZE) / / will read sector into buffer
if (fwrite (spi_di_buffer, 1, SPI_FLASH_SECTOR_SIZE, fw)! SPI_FLASH_SECTOR_SIZE =) / / and write to a file
{
printf ("ERROR: can not write sector% lu to file \ n", address / SPI_FLASH_SECTOR_SIZE);
return (-2);
}
}
fclose (fw) / / close file
putchar ('\ n');
return (0);
}
/ / ***************** SPI FlashROM is programmed from the file **************
spi_flash_program int (char * file_name, DWord total_size)
{
DWord address;
FILE * fr = fopen (file_name, "rb") / / open file for reading
if (fr == NULL) / / if the error and finish
{
printf ("ERROR: can not open file% s \ n", file_name);
return (-1);
}
for (address = 0; address <total_size; address + = SPI_FLASH_PAGE_SIZE)
{
/ / Through all the pages
printf ("Programming page at: 08lXh% (% lu%%) \ r", address, 100 * (address SPI_FLASH_PAGE_SIZE +) / total_size);
spi_flash_wait_busy (1000) / / Wait until busy flag is brought up
spi_flash_write_enable () / / perm foremost write, resets automatically after successfully writing pages
spi_do_buffer [0] = SPI_FLASH_PAGEPGM / / command code to put output buffer
spi_do_buffer [1] = (address >> 16) &0xFF; / / Put A23: 16 to output buffer
spi_do_buffer [2] = (address >> 8) &0xFF; / / Put A15: 8 to output buffer
spi_do_buffer [3] = (address >> 0) &0xFF; / / Put A7: 0 to output buffer
if (fread (+4.1 spi_do_buffer, SPI_FLASH_PAGE_SIZE, fr)! SPI_FLASH_PAGE_SIZE =) / / retrieves a page from a file
{
printf ("ERROR: can not read page from file% lu \ n", address / SPI_FLASH_PAGE_SIZE);
return (-2);
}
spi_rw_block (spi_do_buffer, spi_di_buffer, SPI_FLASH_PAGE_SIZE +4) / / execute block read / write
'll do (1000) / / wait a minute
}
fclose (fr) / / close file
putchar ('\ n');
return (0);
}
/ / ***************** Deletes all protect bits, make entry into the SPI FlashROM (if it allows the WP # pin)
spi_flash_unlock int (void)
{
Byte status;
spi_flash_write_enable () / / perm foremost write, resets automatically after successfully writing the status register
status = spi_flash_status () / / Check the status register
printf ("Status =% 02Xh, WE bit is% s \ n", status, ((status & 0x2) == 0)? "disabled": "enabled");
if ((status & 0x2) == 0) / / if WE nenahodil
return (-1) / / to finish
spi_do_buffer [0] = SPI_FLASH_WRSTAT / / command code to put output buffer
spi_do_buffer [1] = 0, / / status register = 0, disabled all Protections
spi_rw_block (spi_do_buffer, spi_di_buffer, 2) / / execute block read / write
printf ("Unlocking ... \ n");
spi_flash_wait_busy (5000) / / Wait until the enrollment does not
status = spi_flash_status () / / Check the status register
printf ("Status =% 02Xh", status);
if ((status & 0xBC) == 0) / / if bits protect gains no
printf ("Device is now unlocked. \ n");
else
printf ("unlock failed, set WP # pin high level \ n");
return (0);
}
/ / ***************** Completely deletes the content of SPI FlashROM (adjustable everywhere FFh) **
spi_flash_erase int (void)
{
Byte status;
spi_flash_write_enable () / / perm foremost write, resets automatically after successfully deleted
status = spi_flash_status () / / Check the status register
printf ("Status =% 02Xh, WE bit is% s \ n", status, ((status & 0x2) == 0)? "disabled": "enabled");
if ((status & 0x2) == 0) / / if WE nenahodil
return (-1) / / to finish
spi_rw_byte (SPI_FLASH_CHIPERASE) / / Run cunning cell FlashROM
printf ("Please wait ...");
spi_flash_wait_busy (20000) / / Wait until busy flag is brought up
printf ("done. \ n");
return (0);
}
/ / ***************** Reads and extracts JEDEC and type of memory and possibly the manufacturer and type of circuit
spi_flash_identify int (void)
{
Jid spi_flash_read_jid DWord = ();
printf ("SPI connected to the LPT port at I / O base address:% Xh SCK pulse width t +% LDUs \ n", lpt_base, spi_sck_pulse_delay);
printf ("FlashROM JEDEC, type:% 06lXh \ n", jid);
if (((jid >> 16) & 0xFF) == SPI_FLASH_JID_ATMEL) / / Atmel FlashROM
{
printf ("Atmel");
switch (jid & 0xFFFF)
{
case 0x4400:
printf ("AT26DF041 (512kB) \ n");
spi_flash_size = 524288;
break;
case 0x4501:
printf ("AT26DF081A (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x4601:
printf ("AT26DF161A (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x4700:
printf ("AT26DF321 (4MB) \ n");
spi_flash_size = 4194304;
break;
default:
printf ("unknown chip \ n");
return (0);
}
return (SPI_FLASH_JID_ATMEL);
}
if (((jid >> 16) & 0xFF) == SPI_FLASH_JID_MACRONIX) / / Macronix FlashROM
{
printf ("Macronix");
switch (jid & 0xFFFF)
{
case 0x2011:
printf ("MX25L1005 (128kB) \ n");
spi_flash_size = 131072;
break;
case 0x2012:
printf ("MX25L2005 (256kB) \ n");
spi_flash_size = 262144;
break;
case 0x2013:
printf ("MX25L4005 (512kB) \ n");
spi_flash_size = 524288;
break;
case 0x2014:
printf ("MX25L8005 (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x2015:
printf ("MX25L1605 (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x2016:
printf ("MX25L3205 (4MB) \ n");
spi_flash_size = 4194304;
break;
case 0x2017:
printf ("MX25L6405 (8MB) \ n");
spi_flash_size = 8388608;
break;
default:
printf ("unknown chip \ n");
return (0);
}
return (SPI_FLASH_JID_MACRONIX);
}
if (((jid >> 16) & 0xFF) == SPI_FLASH_JID_WINBOND) / / Winbond FlashROM
{
printf ("Winbond");
switch (jid & 0xFFFF)
{
case 0x3011:
printf ("W25X10 (128kB) \ n");
spi_flash_size = 131072;
break;
case 0x3012:
printf ("W25X20 (256kB) \ n");
spi_flash_size = 262144;
break;
case 0x3013:
printf ("W25X40 (512kB) \ n");
spi_flash_size = 524288;
break;
case 0x3014:
printf ("W25X80 (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x3015:
printf ("W25X16 (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x3016:
printf ("W25X32 (4MB) \ n");
spi_flash_size = 4194304;
break;
case 0x3017:
printf ("W25X64 memories was added (8MB) \ n");
spi_flash_size = 8388608;
break;
default:
printf ("unknown chip \ n");
return (0);
}
return (SPI_FLASH_JID_WINBOND);
}
if (((jid >> 16) & 0xFF) == SPI_FLASH_JID_SST) / / SST FlashROM
{
printf ("SST");
switch (jid & 0xFFFF)
{
0x49BF case:
printf ("SST25VF010 (128kB) \ n");
spi_flash_size = 131072;
break;
0x43BF case:
printf ("SST25VF020 (256kB) \ n");
spi_flash_size = 262144;
break;
0x44BF case:
printf ("SST25VF040 (512kB) \ n");
spi_flash_size = 524288;
break;
0x80BF case:
printf ("SST25VF080 (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x2541:
printf ("SST25VF016 (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x2542:
printf ("SST25VF032 (4MB) \ n");
spi_flash_size = 4194304;
break;
case 0x2543:
printf ("SST25VF064 (8MB) \ n");
spi_flash_size = 8388608;
break;
case 0x2544:
printf ("SST25VF128 (16MB) \ n");
spi_flash_size = 16777216;
break;
case 0x258E:
printf ("SST25VF080B (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x2601:
printf ("SST26VF016 (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x2602:
printf ("SST26VF032 (4MB) \ n");
spi_flash_size = 4194304;
break;
case 0x2603:
printf ("SST26VF064 (8MB) \ n");
spi_flash_size = 8388608;
break;
default:
printf ("unknown chip \ n");
return (0);
}
return (SPI_FLASH_JID_SST);
}
if (((jid >> 16) & 0xFF) == SPI_FLASH_JID_STM) / / STM FlashROM
{
printf ("ST Microelectronic");
switch (jid & 0xFFFF)
{
case 0x2011:
printf ("M25P10 (128kB) \ n");
spi_flash_size = 131072;
break;
case 0x2012:
printf ("M25P20 (256kB) \ n");
spi_flash_size = 262144;
break;
case 0x2013:
printf ("M25P40 (512kB) \ n");
spi_flash_size = 524288;
break;
case 0x2014:
printf ("M25P80 (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x2015:
printf ("M25P16 (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x2016:
printf ("M25P32 (4MB) \ n");
spi_flash_size = 4194304;
break;
case 0x2017:
printf ("M25P64 (8MB) \ n");
spi_flash_size = 8388608;
break;
case 0x2018:
printf ("M25P128 (16MB) \ n");
spi_flash_size = 16777216;
break;
default:
printf ("unknown chip \ n");
return (0);
}
return (SPI_FLASH_JID_STM);
}
printf ("Unknown Manufacturer \ n");
return (0);
}
/ / ************************************************ ***************************
spi_slow_program int (char * filename)
{
DWord address = 0L;
FILE * fr = fopen (filename, "rb") / / open file for reading
if (fr == NULL) / / if the error and finish
{
printf ("ERROR: can not open file% s \ n", filename);
return (-1);
}
printf ("Programming with% s \ n", filename);
while (fread (spi_do_buffer, 1, 1, fr) == 1)
{
if ((address% 32768) == 0)
printf ("\ n% 08lx", address);
if ((address% 1024) == 0)
printf (".");
spi_rw_byte (SPI_FLASH_WREN);
SPI_CLR_CS;
spi_rw_byte_no_cs (SPI_FLASH_PAGEPGM);
spi_rw_byte_no_cs (((address & 0xffffff) >> 16));
spi_rw_byte_no_cs (((address & 0xffff) >> 8));
spi_rw_byte_no_cs (address & 0xff);
spi_rw_byte_no_cs ((Byte) * spi_do_buffer);
SPI_SET_CS;
spi_rw_byte (SPI_FLASH_WRDIS);
'll do (1000);
address + +;
}
printf ("\ n");
fclose (fr) / / close file
return (0);
}
/ / ************************************************ ***************************
spi_program_test int (DWORD start, count DWord, Word Pattern)
{
printf ("Starting at% ld for% ld bytes set to% 02x \ n", start, count, pattern);
while (count -)
{
if ((address% 32768) == 0)
printf ("\ n% 08lx", address);
if ((address% 512) == 0)
printf (".");
spi_rw_byte (SPI_FLASH_WREN);
SPI_CLR_CS;
spi_rw_byte_no_cs (SPI_FLASH_PAGEPGM);
spi_rw_byte_no_cs (((start & 0xffffff) >> 16));
spi_rw_byte_no_cs (((start & 0xffff) >> 8));
spi_rw_byte_no_cs (start & 0xff);
spi_rw_byte_no_cs ((Byte) pattern + +);
SPI_SET_CS;
spi_rw_byte (SPI_FLASH_WRDIS);
'll do (1000);
start + +;
}
printf ("\ n");
return (0);
}
/ / Process a ballast ***************** optional parameters at the end ***********
parse_options void (int argc, int argnext, char * argv [])
{
int i;
for (i = argnext; i <argc; i + +) / / any arguments through to the last
{
if (tolower (argv [i] [1]) == 'l') / / if / l - LPT IO base
sscanf (argv [i] +2, "% = hi", & lpt_base);
if (tolower (argv [i] [1]) == 'd') / / if / d - SPI clock pulse delay
sscanf (argv [i] +2, "=% lu", & spi_sck_pulse_delay);
}
}
/ / ***************** Main program ***************************** *************
int main (int argc, char * argv [])
{
Count DWord;
DWord address;
Start_address DWord;
Blk_size DWord;
Word pattern;
Byte flash_status;
Byte i;
printf ("\ NSPI FlashROM Programmer 1.4 (C) 2008 by Martin Rehak; rayer@seznam.cz \ n");
printf ("Compiled by GCC% s at% s,% s \ n", __ VERSION__, __ TIME__, __ DATE__);
if (argc <2) / / if the line is not any parameters
{
printf ("SYNTAX: spipgm / i | r | d | e | p | t | s [/ l = iobase] [/ d = delay] \ n");
printf ("/ i - identify SPI FlashROM \ n");
printf ("/ r [address] [size] - Read & display data block (0x prefix = hex number) \ n");
printf ("/ d [filename] - Entire FlashROM dump to file \ n");
printf ("/ p [filename] - Entire FlashROM program from file (without erase) \ n");
printf ("/ e - Erase Entire FlashROM \ n");
printf ("/ u - unlock the write protection bits (may depend on WP # level) \ n");
printf ("/ t [address] [size] [pattern] - fill with pattern data block \ n");
printf ("/ s [filename] - FlashROM program with contents of file one byte at a time \ n");
printf ("/ l = [port] LPT port I / O base address (default is 378h - LPT1) \ n");
printf ("/ d = [usec] additional delay for SPI clock pulse width (default is 0) \ n");
printf ("\ nLPT the SPI pin assignment (based on BSD AVR programmer): \ n");
printf ("pin 7 = D5 -> CS # \ n");
printf ("= D6 pin 8 -> SCK (CLK) \ n");
printf ("pin 9 = D7 -> MOSI (DIO) \ n");
printf ("pin 10 = ACK -> MISO (UP) \ n");
printf ("Pin 18 = GND -> GND \ n");
return (1);
}
if (argc> 1) / / if the line is at least 1 parameter
if (tolower (argv [1] [1]) == 'i') / / if the parameter is the first i - identify
{
spi_init () / / set the SPI lines to default
parse_options (argc, 2, argv) / / Process a optional parameters from 2
spi_flash_identify () / / Identify SPI FlashROM
flash_status spi_flash_status = () / / read status
printf ("Status =% 02Xh (BPL, AAI, BP3, BP2, BP1, BP0, WEL, BSY) \ n", flash_status);
for (i = 0; i <8; i + +) / / over all status bits
printf ("% u", ((flash_status << i) & 0x80) >> 7); / / outputs a binary status
putchar ('\ n');
if ((flash_status & 0x80)! = 0) / / check bit CFP
printf ("Status register is protected, you Will need to set high WP # \ n");
}
if (argc> 3) / / if the line at least 3 parameters
if (tolower (argv [1] [1]) == 'y') / / If the first parameter r - read data block
{
spi_init () / / set the SPI lines to default
parse_options (argc, 4, argv) / / Process a optional parameters from 4
sscanf (argv [2], "% li", & start_address) / / Read the start address
sscanf (argv [3], "% li", & blk_size) / / read block size
spi_flash_identify () / / Identify SPI FlashROM
spi_flash_read_block (start_address, blk_size) / / Read block into buffer
if (blk_size <= (SPI_BUFFER_SIZE-4)) / / if the block size is smaller than can fit in the buffer
spi_print_buffer (spi_di_buffer, blk_size, start_address) / / outputs to the screen buffer
}
if (argc> 2) / / if the line is at least 2 parameters
if (tolower (argv [1] [1]) == 'd') / / If the first parameter d - FlashROM dump to file
{
spi_init () / / set the SPI lines to default
parse_options (argc, 3, argv) / / Process a optional parameters from 3
if (spi_flash_identify () == 0) / / Identify SPI FlashROM
{
/ / If not detected, enter the size manually
printf ("Enter total size in KB FlashROM");
scanf ("% if" & spi_flash_size);
spi_flash_size * = 1024; / / Read the size and transferred to the Byte
}
return (spi_flash_dump (argv [2], spi_flash_size)) / / Memory dumpuj
}
if (argc> 2) / / if the line is at least 2 parameters
if (tolower (argv [1] [1]) == 'p') / / If the first parameter p - FlashROM program from file
{
spi_init () / / set the SPI lines to default
parse_options (argc, 3, argv) / / Process a optional parameters from 3
if (spi_flash_identify () == 0) / / Identify SPI FlashROM
{
/ / If not detected, enter the size manually
printf ("Enter total size in KB FlashROM");
scanf ("% if" & spi_flash_size);
spi_flash_size * = 1024; / / Read the size and transferred to the Byte
}
return (spi_flash_program (argv [2], spi_flash_size)) / / program the memory
}
if (argc> 1) / / if the line is at least 1 parameter
if (tolower (argv [1] [1]) == 'e') / / If the first parameter e - chip erase
{
spi_init () / / set the SPI lines to default
parse_options (argc, 2, argv) / / Process a optional parameters from 2
spi_flash_identify () / / Identify SPI FlashROM
return (spi_flash_erase ()) / / delete entire contents of SPI FlashROM (adjustable cells to FFh)
}
if (argc> 1) / / if the line is at least 1 parameter
if (tolower (argv [1] [1]) == 'u') / / If the first parameter u - unlock protection
{
spi_init () / / set the SPI lines to default
parse_options (argc, 2, argv) / / Process a optional parameters from 2
spi_flash_identify () / / Identify SPI FlashROM
return (spi_flash_unlock ()) / / reset all the protection bits SPI FlashROM
}
if (argc> 1)
if (tolower (argv [1] [1]) == 't')
{
spi_init ();
parse_options (argc, 5, argv);
spi_flash_identify () / / Identify SPI FlashROM
sscanf (argv [2], "% li", & address) / / Read the start address
sscanf (argv [3], "% li", & count) / / read block size
sscanf (argv [4], "% x", & pattern);
return (spi_program_test (address, count, pattern));
}
if (argc> 1)
if (tolower (argv [1] [1] == 's'))
{
spi_init ();
parse_options (argc, 2, argv);
return (spi_slow_program (argv [2]));
}
return (0);
}
/ * SPI FlashROM programmer on the PC parallel port * /
/ ************************************************* *************************** /
/ * Created: March 24, 2008 [DJGPP] * /
/ * Last modified: 28.10.2008 [DJGPP] * /
/ * Copyright (C) 2008 by RayeR / Martin Rehak * /
/ * Contact: rayer ^ en * list * /
/ ************************************************* *************************** /
# Include <stdlib.h>
# Include <stdio.h>
# Include <string.h>
# Include <ctype.h>
# Include <time.h>
# Define SPI_CS_PIN 5 / / D5 (CS #)
# Define SPI_SCK_PIN 6 / / D6 (CLK)
# Define SPI_MOSI_PIN 7 / / D7 (DIO)
# Define SPI_MISO_PIN 6 / / ACK (DO)
# Define SPI_BUFFER_SIZE 100000LU / / SPI data buffer 100kB (64kB + reserve)
/ / ***************** SPI control lines macros *************************** *****
# Define SPI_SET_CS outportb (lpt_base, inportb (lpt_base) | (1 << SPI_CS_PIN))
# Define SPI_CLR_CS outportb (lpt_base, inportb (lpt_base) & (~ (1 << SPI_CS_PIN)))
# Define SPI_SET_SCK outportb (lpt_base, inportb (lpt_base) | (1 << SPI_SCK_PIN))
# Define SPI_CLR_SCK outportb (lpt_base, inportb (lpt_base) & (~ (1 << SPI_SCK_PIN)))
# Define SPI_SET_MOSI outportb (lpt_base, inportb (lpt_base) | (1 << SPI_MOSI_PIN))
# Define SPI_CLR_MOSI outportb (lpt_base, inportb (lpt_base) & (~ (1 << SPI_MOSI_PIN)))
# Define SPI_GET_MISO ((inportb (lpt_base +1) >> SPI_MISO_PIN) & 1)
/ / ***************** SPI FlashROM command codes *************************** ***
/ / 25Xxx FlashROM description:
/ / SPI mode 0: SCK idle state = low DIO sampled on rising edge, he clocked IN falling edge, MSB first
/ / 512kB memory, total 8 per 64 KB blocks, 1 block = 16 Sectors per 4 KB, 1 sector = 16 pages per 256B
# Define SPI_FLASH_WREN 0x06 / / Enable enrollment
SPI_FLASH_WRDIS 0x04 # define / / the prohibition on registration
SPI_FLASH_RDSTAT 0x05 # define / / status register of honor; S7: 0 - bit7 = stat reg Protect bit5 = top / bot write protect, bit4: 2 = Block protect bits, bit1 = WE latch, bit0 = busy
# Define SPI_FLASH_WRSTAT 0x01 / / write status register, S7: 0
SPI_FLASH_RDDATA 0x03 # define / / credit data; A23: 16, A15: A8, A7: 0, D7: 0, DB till the next end
# Define SPI_FLASH_FASTRD 0x0B / / quick read, A23: 16, A15: A8, A7: 0, dummyB, D7: 0, DB till the next end
# Define SPI_FLASH_FASTRD2 0x3B / / fast reading 2 lines DO and DIO, A23: 16, A15: A8, A7: 0, dummyB, D7: 0 bit interleaved, next DB till the end
SPI_FLASH_PAGEPGM 0x02 # define / / Programming Site; A23: 16, A15: A8, A7: 0, D7: 0, DB till the next end
# Define SPI_FLASH_BLKERASE 0xD8 / / Delete the block (64kB for 25Xxx) A23: 16, A15: A8, A7: 0
SPI_FLASH_SECERASE 0x20 # define / / erased sector (4kB for 25Xxx) A23: 16, A15: A8, A7: 0
# Define SPI_FLASH_CHIPERASE 0xC7 / / Delete the cell FlashROM
# Define SPI_FLASH_PWRDWN 0xB9 / / Asleep
# Define SPI_FLASH_RELPWRDWN 0xAB / / of Asleep awakened; dummyB, dummyB, dummyB, ID7: 0 (10h = X10, X20 = 11h, 12h = X40, X80 = 13h)
SPI_FLASH_MIDDID 0x90 # define / / ID products and equipment; dummyB, dummyB, 0, M7: 0 (EFH = Winbond), ID7: 0 (10h = X10, X20 = 11h, 12h = X40, X80 = 13h)
# Define SPI_FLASH_JEDECID 0x9F / / JEDEC manufacturer M7: 0, ID15: 8, ID7: 0 (3011h = X10, X20 = 3012h, 3013h = X40, X80 = 3014h)
# Define SPI_FLASH_JID_ATMEL 0x1F / / Atmel
SPI_FLASH_JID_STM 0x20 # define / / ST Microelectronic
# Define SPI_FLASH_JID_SST 0xBF / / SST (Silicon Storage Technology)
# Define SPI_FLASH_JID_MACRONIX 0xC2 / / Macronix
# Define SPI_FLASH_JID_WINBOND 0xEF / / Winbond
# Define SPI_FLASH_PAGE_SIZE 256 / / page size, max unit for enrollment
# Define SPI_FLASH_SECTOR_SIZE 4096 / / sector size, min. Unit cunning
# Define SPI_FLASH_BLOCK_SIZE 65536 / / block size, larger unit for lubricated
# Define unsigned short Word
# Define unsigned long DWord
# Define byte unsigned char
# Define usleep'll do
Word lpt_base = 0x378 / / LPT1 I / O base address
Spi_sck_pulse_delay DWord = 0 / / attachments to delay the SCK pulse duration
Spi_di_buffer Byte [SPI_BUFFER_SIZE] / / SPI data input buffer
Spi_do_buffer Byte [SPI_BUFFER_SIZE] / / SPI data output buffer
Spi_flash_size DWord = 0, / / total size of FlashROM
/ / ***************** Adjustable resting SPI lines to Union level *******************
spi_init void (void)
{
SPI_SET_CS / / EN # = high
SPI_CLR_SCK / / CLK = low
SPI_CLR_MOSI / / = low MOSI
memset (spi_di_buffer, 0, SPI_BUFFER_SIZE) / / clear input data buffer
memset (spi_do_buffer, 0, SPI_BUFFER_SIZE) / / clear output data buffer
}
/ / ***************** Vypis hexadecimal and text a given number of doors in the SPI buffer
spi_print_buffer void (* Byte p_buffer, long count, long offset)
{
long i, j;
for (i = 0; i <count; i + = 16) / / 16-across all residential units
{
printf ("% 06lX:", i + offset) / / outputs the address
for (j = 0, j <16; j + +) / / over all byte in block 16B
{
if ((j & 0x7) == 0) / / at the beginning and after 8 Bytes
putchar ('') / / space delimiter
if ((j + i) <count) / / if not listed all the Byte
printf ("% 02x", p_buffer [j + i]) / / Listing 1 byte in hex
else
printf ("") / / otherwise make extracts instead of spaces
}
putchar ('') / / space delimiter
for (j = 0, j <16; j + +) / / over all byte in block 16B
if ((j + i) <count) / / if not listed all the Byte
{
if (p_buffer [j + i]> = '') / / if it is printable characters
putchar (p_buffer [j + i]) / / outputs it
else
putchar ('') / / otherwise vypis gap
}
putchar ('\ n') / / end of the line
}
}
/ / ***************** Write operation reads a byte over SPI unattended CS # signal ***
Spi_rw_byte_no_cs Byte (Byte data_out)
{
Byte data_in = 0, i;
for (i = 0; i <8; i + +) / / over all bits of the Flat
{
data_in << = 1 / / Shift to next bit input, Will Be at bit0 placed object
if ((data_out & 0x80) == 0) / / start from MSB to LSB
SPI_CLR_MOSI / / data bit is 0
else
SPI_SET_MOSI / / data bit is 1
'll do (spi_sck_pulse_delay) / / setup data delay
SPI_SET_SCK / / Slave samples the data on rising clock edge
data_in | = SPI_GET_MISO / / slave sample output, from LSB to MSB
'll do (spi_sck_pulse_delay) / / clock pulse delay
SPI_CLR_SCK / / clock back to default state
data_out << = 1 / / Shift to next output bit, MSB Will Be send
}
return (data_in) / / return byte readed
}
/ / ***************** Write operation reads a byte over SPI including the management of CS # *********
Spi_rw_byte Byte (Byte data_out)
{
Byte data_in;
SPI_CLR_SCK / / default state clock
SPI_CLR_CS / / chip select enabled
'll do (spi_sck_pulse_delay) / / wait for chip active
data_in = spi_rw_byte_no_cs (data_out) / / write / read byte
'll do (spi_sck_pulse_delay) / / wait for chip inactive
SPI_SET_CS / / chip select disabled
return (data_in);
}
/ / ***************** Write operation reads the data block including control SPI CS # *******
spi_rw_block void (* p_do_buffer Byte, Byte * p_di_buffer, DWord blk_size)
{
long i;
SPI_CLR_SCK / / default state clock
SPI_CLR_CS / / chip select enabled
'll do (spi_sck_pulse_delay) / / wait for chip active
for (i = 0; i <blk_size; i + +) / / all over the apartment block
p_di_buffer [i] = spi_rw_byte_no_cs (p_do_buffer [i]) / / write / read byte
'll do (spi_sck_pulse_delay) / / wait for chip inactive
SPI_SET_CS / / chip select disabled
}
/ / ***************** Reads the status register SPI FlashROM (bit0 = busy) *******
Byte spi_flash_status (void)
{
spi_do_buffer [0] = SPI_FLASH_RDSTAT / / command code to put output buffer
spi_rw_block (spi_do_buffer, spi_di_buffer, 2) / / execute block read / write
return (spi_di_buffer [1]) / / return second Byte read by default - the status register
}
/ / ***************** Waiting until the SPI FlashROM busy (eg for deleting) *******
spi_flash_wait_busy void (int timeout) / / timeout in milliseconds
{
while ((timeout -)> 0) / / until the timeout has not expired
{
'll do (1000);
if ((spi_flash_status () & 0x1) == 0) / / status of honor
break / / if the busy bit = 0, break
}
}
/ / ***************** Provide operations entry into the SPI FlashROM ************************** **
# Define spi_flash_write_enable () spi_rw_byte (SPI_FLASH_WREN)
/ / ***************** Prohibit the registration of the SPI FlashROM ************************** **
# Define spi_flash_write_disable () spi_rw_byte (SPI_FLASH_WRDIS)
/ / *****************-Reads manufacturer and device ID MSB-LSB SPI FlashROM ****
Word spi_flash_read_id (void)
{
memset (spi_do_buffer, 0.6) / / clear output buffer
spi_do_buffer [0] = SPI_FLASH_MIDDID / / command code to put output buffer
spi_rw_block (spi_do_buffer, spi_di_buffer, 6) / / execute block read / write
return (((Word) spi_di_buffer [4] << 8) | spi_di_buffer [5]);
}
/ / ***************** Reads JEDEC-byte2, MemType-byte1, MEMSIZE-Byte0 *****
Spi_flash_read_jid DWord (void)
{
memset (spi_do_buffer, 0.4) / / clear output buffer
spi_do_buffer [0] = SPI_FLASH_JEDECID / / command code to put output buffer
spi_rw_block (spi_do_buffer, spi_di_buffer, 4) / / execute block read / write
return (((DWord) spi_di_buffer [1] << 16) | ((DWORD) spi_di_buffer [2] << 8) | spi_di_buffer [3]);
}
/ / ***************** Block reads data from the address of the SPI FlashROM (eliminates uvodni dummy byte, the data in the buffer starting at 0)
spi_flash_read_block void (DWORD start_address, DWord blk_size)
{
long i;
if (blk_size> (SPI_BUFFER_SIZE-4))
{
printf ("ERROR: read block size (% lub) exceeds SPI read buffer (lub%) \ n", blk_size, SPI_BUFFER_SIZE);
return;
}
spi_do_buffer [0] = SPI_FLASH_RDDATA / / command code to put output buffer
spi_do_buffer [1] = (start_address >> 16) &0xFF; / / Put A23: 16 to output buffer
spi_do_buffer [2] = (start_address >> 8) &0xFF; / / Put A15: 8 to output buffer
spi_do_buffer [3] = (start_address >> 0) &0xFF; / / Put A7: 0 to output buffer
spi_rw_block (spi_do_buffer, spi_di_buffer, blk_size +4) / / execute block read / write
for (i = 0; i <blk_size; i + +) / / block of apartments all over
spi_di_buffer [i] = spi_di_buffer [i +4] / / shift the data byte by 4 down
}
/ / ***************** Reads out the whole file into SPI FlashROM ***************
spi_flash_dump int (char * file_name, DWord total_size)
{
DWord address;
FILE * fw = fopen (file_name, "wb"); / / open file for writing
if (fw == NULL) / / if the error and finish
{
printf ("ERROR: Can not create file% s \ n", file_name);
return (-1);
}
for (address = 0; address <total_size; address + = SPI_FLASH_SECTOR_SIZE)
{
/ / Across all sectors
printf ("Reading at sector:% 08lXh (% lu%%) \ r", address, 100 * (address SPI_FLASH_SECTOR_SIZE +) / total_size);
spi_flash_read_block (address, SPI_FLASH_SECTOR_SIZE) / / will read sector into buffer
if (fwrite (spi_di_buffer, 1, SPI_FLASH_SECTOR_SIZE, fw)! SPI_FLASH_SECTOR_SIZE =) / / and write to a file
{
printf ("ERROR: can not write sector% lu to file \ n", address / SPI_FLASH_SECTOR_SIZE);
return (-2);
}
}
fclose (fw) / / close file
putchar ('\ n');
return (0);
}
/ / ***************** SPI FlashROM is programmed from the file **************
spi_flash_program int (char * file_name, DWord total_size)
{
DWord address;
FILE * fr = fopen (file_name, "rb") / / open file for reading
if (fr == NULL) / / if the error and finish
{
printf ("ERROR: can not open file% s \ n", file_name);
return (-1);
}
for (address = 0; address <total_size; address + = SPI_FLASH_PAGE_SIZE)
{
/ / Through all the pages
printf ("Programming page at: 08lXh% (% lu%%) \ r", address, 100 * (address SPI_FLASH_PAGE_SIZE +) / total_size);
spi_flash_wait_busy (1000) / / Wait until busy flag is brought up
spi_flash_write_enable () / / perm foremost write, resets automatically after successfully writing pages
spi_do_buffer [0] = SPI_FLASH_PAGEPGM / / command code to put output buffer
spi_do_buffer [1] = (address >> 16) &0xFF; / / Put A23: 16 to output buffer
spi_do_buffer [2] = (address >> 8) &0xFF; / / Put A15: 8 to output buffer
spi_do_buffer [3] = (address >> 0) &0xFF; / / Put A7: 0 to output buffer
if (fread (+4.1 spi_do_buffer, SPI_FLASH_PAGE_SIZE, fr)! SPI_FLASH_PAGE_SIZE =) / / retrieves a page from a file
{
printf ("ERROR: can not read page from file% lu \ n", address / SPI_FLASH_PAGE_SIZE);
return (-2);
}
spi_rw_block (spi_do_buffer, spi_di_buffer, SPI_FLASH_PAGE_SIZE +4) / / execute block read / write
'll do (1000) / / wait a minute
}
fclose (fr) / / close file
putchar ('\ n');
return (0);
}
/ / ***************** Deletes all protect bits, make entry into the SPI FlashROM (if it allows the WP # pin)
spi_flash_unlock int (void)
{
Byte status;
spi_flash_write_enable () / / perm foremost write, resets automatically after successfully writing the status register
status = spi_flash_status () / / Check the status register
printf ("Status =% 02Xh, WE bit is% s \ n", status, ((status & 0x2) == 0)? "disabled": "enabled");
if ((status & 0x2) == 0) / / if WE nenahodil
return (-1) / / to finish
spi_do_buffer [0] = SPI_FLASH_WRSTAT / / command code to put output buffer
spi_do_buffer [1] = 0, / / status register = 0, disabled all Protections
spi_rw_block (spi_do_buffer, spi_di_buffer, 2) / / execute block read / write
printf ("Unlocking ... \ n");
spi_flash_wait_busy (5000) / / Wait until the enrollment does not
status = spi_flash_status () / / Check the status register
printf ("Status =% 02Xh", status);
if ((status & 0xBC) == 0) / / if bits protect gains no
printf ("Device is now unlocked. \ n");
else
printf ("unlock failed, set WP # pin high level \ n");
return (0);
}
/ / ***************** Completely deletes the content of SPI FlashROM (adjustable everywhere FFh) **
spi_flash_erase int (void)
{
Byte status;
spi_flash_write_enable () / / perm foremost write, resets automatically after successfully deleted
status = spi_flash_status () / / Check the status register
printf ("Status =% 02Xh, WE bit is% s \ n", status, ((status & 0x2) == 0)? "disabled": "enabled");
if ((status & 0x2) == 0) / / if WE nenahodil
return (-1) / / to finish
spi_rw_byte (SPI_FLASH_CHIPERASE) / / Run cunning cell FlashROM
printf ("Please wait ...");
spi_flash_wait_busy (20000) / / Wait until busy flag is brought up
printf ("done. \ n");
return (0);
}
/ / ***************** Reads and extracts JEDEC and type of memory and possibly the manufacturer and type of circuit
spi_flash_identify int (void)
{
Jid spi_flash_read_jid DWord = ();
printf ("SPI connected to the LPT port at I / O base address:% Xh SCK pulse width t +% LDUs \ n", lpt_base, spi_sck_pulse_delay);
printf ("FlashROM JEDEC, type:% 06lXh \ n", jid);
if (((jid >> 16) & 0xFF) == SPI_FLASH_JID_ATMEL) / / Atmel FlashROM
{
printf ("Atmel");
switch (jid & 0xFFFF)
{
case 0x4400:
printf ("AT26DF041 (512kB) \ n");
spi_flash_size = 524288;
break;
case 0x4501:
printf ("AT26DF081A (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x4601:
printf ("AT26DF161A (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x4700:
printf ("AT26DF321 (4MB) \ n");
spi_flash_size = 4194304;
break;
default:
printf ("unknown chip \ n");
return (0);
}
return (SPI_FLASH_JID_ATMEL);
}
if (((jid >> 16) & 0xFF) == SPI_FLASH_JID_MACRONIX) / / Macronix FlashROM
{
printf ("Macronix");
switch (jid & 0xFFFF)
{
case 0x2011:
printf ("MX25L1005 (128kB) \ n");
spi_flash_size = 131072;
break;
case 0x2012:
printf ("MX25L2005 (256kB) \ n");
spi_flash_size = 262144;
break;
case 0x2013:
printf ("MX25L4005 (512kB) \ n");
spi_flash_size = 524288;
break;
case 0x2014:
printf ("MX25L8005 (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x2015:
printf ("MX25L1605 (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x2016:
printf ("MX25L3205 (4MB) \ n");
spi_flash_size = 4194304;
break;
case 0x2017:
printf ("MX25L6405 (8MB) \ n");
spi_flash_size = 8388608;
break;
default:
printf ("unknown chip \ n");
return (0);
}
return (SPI_FLASH_JID_MACRONIX);
}
if (((jid >> 16) & 0xFF) == SPI_FLASH_JID_WINBOND) / / Winbond FlashROM
{
printf ("Winbond");
switch (jid & 0xFFFF)
{
case 0x3011:
printf ("W25X10 (128kB) \ n");
spi_flash_size = 131072;
break;
case 0x3012:
printf ("W25X20 (256kB) \ n");
spi_flash_size = 262144;
break;
case 0x3013:
printf ("W25X40 (512kB) \ n");
spi_flash_size = 524288;
break;
case 0x3014:
printf ("W25X80 (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x3015:
printf ("W25X16 (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x3016:
printf ("W25X32 (4MB) \ n");
spi_flash_size = 4194304;
break;
case 0x3017:
printf ("W25X64 memories was added (8MB) \ n");
spi_flash_size = 8388608;
break;
default:
printf ("unknown chip \ n");
return (0);
}
return (SPI_FLASH_JID_WINBOND);
}
if (((jid >> 16) & 0xFF) == SPI_FLASH_JID_SST) / / SST FlashROM
{
printf ("SST");
switch (jid & 0xFFFF)
{
0x49BF case:
printf ("SST25VF010 (128kB) \ n");
spi_flash_size = 131072;
break;
0x43BF case:
printf ("SST25VF020 (256kB) \ n");
spi_flash_size = 262144;
break;
0x44BF case:
printf ("SST25VF040 (512kB) \ n");
spi_flash_size = 524288;
break;
0x80BF case:
printf ("SST25VF080 (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x2541:
printf ("SST25VF016 (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x2542:
printf ("SST25VF032 (4MB) \ n");
spi_flash_size = 4194304;
break;
case 0x2543:
printf ("SST25VF064 (8MB) \ n");
spi_flash_size = 8388608;
break;
case 0x2544:
printf ("SST25VF128 (16MB) \ n");
spi_flash_size = 16777216;
break;
case 0x258E:
printf ("SST25VF080B (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x2601:
printf ("SST26VF016 (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x2602:
printf ("SST26VF032 (4MB) \ n");
spi_flash_size = 4194304;
break;
case 0x2603:
printf ("SST26VF064 (8MB) \ n");
spi_flash_size = 8388608;
break;
default:
printf ("unknown chip \ n");
return (0);
}
return (SPI_FLASH_JID_SST);
}
if (((jid >> 16) & 0xFF) == SPI_FLASH_JID_STM) / / STM FlashROM
{
printf ("ST Microelectronic");
switch (jid & 0xFFFF)
{
case 0x2011:
printf ("M25P10 (128kB) \ n");
spi_flash_size = 131072;
break;
case 0x2012:
printf ("M25P20 (256kB) \ n");
spi_flash_size = 262144;
break;
case 0x2013:
printf ("M25P40 (512kB) \ n");
spi_flash_size = 524288;
break;
case 0x2014:
printf ("M25P80 (1MB) \ n");
spi_flash_size = 1048576;
break;
case 0x2015:
printf ("M25P16 (2MB) \ n");
spi_flash_size = 2097152;
break;
case 0x2016:
printf ("M25P32 (4MB) \ n");
spi_flash_size = 4194304;
break;
case 0x2017:
printf ("M25P64 (8MB) \ n");
spi_flash_size = 8388608;
break;
case 0x2018:
printf ("M25P128 (16MB) \ n");
spi_flash_size = 16777216;
break;
default:
printf ("unknown chip \ n");
return (0);
}
return (SPI_FLASH_JID_STM);
}
printf ("Unknown Manufacturer \ n");
return (0);
}
/ / ************************************************ ***************************
spi_slow_program int (char * filename)
{
DWord address = 0L;
FILE * fr = fopen (filename, "rb") / / open file for reading
if (fr == NULL) / / if the error and finish
{
printf ("ERROR: can not open file% s \ n", filename);
return (-1);
}
printf ("Programming with% s \ n", filename);
while (fread (spi_do_buffer, 1, 1, fr) == 1)
{
if ((address% 32768) == 0)
printf ("\ n% 08lx", address);
if ((address% 1024) == 0)
printf (".");
spi_rw_byte (SPI_FLASH_WREN);
SPI_CLR_CS;
spi_rw_byte_no_cs (SPI_FLASH_PAGEPGM);
spi_rw_byte_no_cs (((address & 0xffffff) >> 16));
spi_rw_byte_no_cs (((address & 0xffff) >> 8));
spi_rw_byte_no_cs (address & 0xff);
spi_rw_byte_no_cs ((Byte) * spi_do_buffer);
SPI_SET_CS;
spi_rw_byte (SPI_FLASH_WRDIS);
'll do (1000);
address + +;
}
printf ("\ n");
fclose (fr) / / close file
return (0);
}
/ / ************************************************ ***************************
spi_program_test int (DWORD start, count DWord, Word Pattern)
{
printf ("Starting at% ld for% ld bytes set to% 02x \ n", start, count, pattern);
while (count -)
{
if ((address% 32768) == 0)
printf ("\ n% 08lx", address);
if ((address% 512) == 0)
printf (".");
spi_rw_byte (SPI_FLASH_WREN);
SPI_CLR_CS;
spi_rw_byte_no_cs (SPI_FLASH_PAGEPGM);
spi_rw_byte_no_cs (((start & 0xffffff) >> 16));
spi_rw_byte_no_cs (((start & 0xffff) >> 8));
spi_rw_byte_no_cs (start & 0xff);
spi_rw_byte_no_cs ((Byte) pattern + +);
SPI_SET_CS;
spi_rw_byte (SPI_FLASH_WRDIS);
'll do (1000);
start + +;
}
printf ("\ n");
return (0);
}
/ / Process a ballast ***************** optional parameters at the end ***********
parse_options void (int argc, int argnext, char * argv [])
{
int i;
for (i = argnext; i <argc; i + +) / / any arguments through to the last
{
if (tolower (argv [i] [1]) == 'l') / / if / l - LPT IO base
sscanf (argv [i] +2, "% = hi", & lpt_base);
if (tolower (argv [i] [1]) == 'd') / / if / d - SPI clock pulse delay
sscanf (argv [i] +2, "=% lu", & spi_sck_pulse_delay);
}
}
/ / ***************** Main program ***************************** *************
int main (int argc, char * argv [])
{
Count DWord;
DWord address;
Start_address DWord;
Blk_size DWord;
Word pattern;
Byte flash_status;
Byte i;
printf ("\ NSPI FlashROM Programmer 1.4 (C) 2008 by Martin Rehak; rayer@seznam.cz \ n");
printf ("Compiled by GCC% s at% s,% s \ n", __ VERSION__, __ TIME__, __ DATE__);
if (argc <2) / / if the line is not any parameters
{
printf ("SYNTAX: spipgm / i | r | d | e | p | t | s [/ l = iobase] [/ d = delay] \ n");
printf ("/ i - identify SPI FlashROM \ n");
printf ("/ r [address] [size] - Read & display data block (0x prefix = hex number) \ n");
printf ("/ d [filename] - Entire FlashROM dump to file \ n");
printf ("/ p [filename] - Entire FlashROM program from file (without erase) \ n");
printf ("/ e - Erase Entire FlashROM \ n");
printf ("/ u - unlock the write protection bits (may depend on WP # level) \ n");
printf ("/ t [address] [size] [pattern] - fill with pattern data block \ n");
printf ("/ s [filename] - FlashROM program with contents of file one byte at a time \ n");
printf ("/ l = [port] LPT port I / O base address (default is 378h - LPT1) \ n");
printf ("/ d = [usec] additional delay for SPI clock pulse width (default is 0) \ n");
printf ("\ nLPT the SPI pin assignment (based on BSD AVR programmer): \ n");
printf ("pin 7 = D5 -> CS # \ n");
printf ("= D6 pin 8 -> SCK (CLK) \ n");
printf ("pin 9 = D7 -> MOSI (DIO) \ n");
printf ("pin 10 = ACK -> MISO (UP) \ n");
printf ("Pin 18 = GND -> GND \ n");
return (1);
}
if (argc> 1) / / if the line is at least 1 parameter
if (tolower (argv [1] [1]) == 'i') / / if the parameter is the first i - identify
{
spi_init () / / set the SPI lines to default
parse_options (argc, 2, argv) / / Process a optional parameters from 2
spi_flash_identify () / / Identify SPI FlashROM
flash_status spi_flash_status = () / / read status
printf ("Status =% 02Xh (BPL, AAI, BP3, BP2, BP1, BP0, WEL, BSY) \ n", flash_status);
for (i = 0; i <8; i + +) / / over all status bits
printf ("% u", ((flash_status << i) & 0x80) >> 7); / / outputs a binary status
putchar ('\ n');
if ((flash_status & 0x80)! = 0) / / check bit CFP
printf ("Status register is protected, you Will need to set high WP # \ n");
}
if (argc> 3) / / if the line at least 3 parameters
if (tolower (argv [1] [1]) == 'y') / / If the first parameter r - read data block
{
spi_init () / / set the SPI lines to default
parse_options (argc, 4, argv) / / Process a optional parameters from 4
sscanf (argv [2], "% li", & start_address) / / Read the start address
sscanf (argv [3], "% li", & blk_size) / / read block size
spi_flash_identify () / / Identify SPI FlashROM
spi_flash_read_block (start_address, blk_size) / / Read block into buffer
if (blk_size <= (SPI_BUFFER_SIZE-4)) / / if the block size is smaller than can fit in the buffer
spi_print_buffer (spi_di_buffer, blk_size, start_address) / / outputs to the screen buffer
}
if (argc> 2) / / if the line is at least 2 parameters
if (tolower (argv [1] [1]) == 'd') / / If the first parameter d - FlashROM dump to file
{
spi_init () / / set the SPI lines to default
parse_options (argc, 3, argv) / / Process a optional parameters from 3
if (spi_flash_identify () == 0) / / Identify SPI FlashROM
{
/ / If not detected, enter the size manually
printf ("Enter total size in KB FlashROM");
scanf ("% if" & spi_flash_size);
spi_flash_size * = 1024; / / Read the size and transferred to the Byte
}
return (spi_flash_dump (argv [2], spi_flash_size)) / / Memory dumpuj
}
if (argc> 2) / / if the line is at least 2 parameters
if (tolower (argv [1] [1]) == 'p') / / If the first parameter p - FlashROM program from file
{
spi_init () / / set the SPI lines to default
parse_options (argc, 3, argv) / / Process a optional parameters from 3
if (spi_flash_identify () == 0) / / Identify SPI FlashROM
{
/ / If not detected, enter the size manually
printf ("Enter total size in KB FlashROM");
scanf ("% if" & spi_flash_size);
spi_flash_size * = 1024; / / Read the size and transferred to the Byte
}
return (spi_flash_program (argv [2], spi_flash_size)) / / program the memory
}
if (argc> 1) / / if the line is at least 1 parameter
if (tolower (argv [1] [1]) == 'e') / / If the first parameter e - chip erase
{
spi_init () / / set the SPI lines to default
parse_options (argc, 2, argv) / / Process a optional parameters from 2
spi_flash_identify () / / Identify SPI FlashROM
return (spi_flash_erase ()) / / delete entire contents of SPI FlashROM (adjustable cells to FFh)
}
if (argc> 1) / / if the line is at least 1 parameter
if (tolower (argv [1] [1]) == 'u') / / If the first parameter u - unlock protection
{
spi_init () / / set the SPI lines to default
parse_options (argc, 2, argv) / / Process a optional parameters from 2
spi_flash_identify () / / Identify SPI FlashROM
return (spi_flash_unlock ()) / / reset all the protection bits SPI FlashROM
}
if (argc> 1)
if (tolower (argv [1] [1]) == 't')
{
spi_init ();
parse_options (argc, 5, argv);
spi_flash_identify () / / Identify SPI FlashROM
sscanf (argv [2], "% li", & address) / / Read the start address
sscanf (argv [3], "% li", & count) / / read block size
sscanf (argv [4], "% x", & pattern);
return (spi_program_test (address, count, pattern));
}
if (argc> 1)
if (tolower (argv [1] [1] == 's'))
{
spi_init ();
parse_options (argc, 2, argv);
return (spi_slow_program (argv [2]));
}
return (0);
}