Am 31.01.2012 06:51 schrieb Stefan Tauner:
This is just a quick hack, that could be expanded. What do you think?
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at
Very good idea!
--- a/dummyflasher.c +++ b/dummyflasher.c @@ -55,6 +55,7 @@ static unsigned int emu_jedec_be_52_size = 0; static unsigned int emu_jedec_be_d8_size = 0; static unsigned int emu_jedec_ce_60_size = 0; static unsigned int emu_jedec_ce_c7_size = 0; +static uint8_t emu_status = 0; #endif #endif
@@ -126,6 +127,9 @@ int dummy_init(void) { char *bustext = NULL; char *tmp = NULL; +#if EMULATE_SPI_CHIP
- char *status = NULL;
+#endif #if EMULATE_CHIP struct stat image_stat; #endif @@ -178,6 +182,14 @@ int dummy_init(void) goto dummy_init_out; } #if EMULATE_SPI_CHIP
- status = extract_programmer_param("status");
- if (status) {
emu_status = atoi(status);
msg_pdbg("Initial status register is set to 0x%02x.\n",
emu_status);
free(status);
- }
- if (!strcmp(tmp, "M25P10.RES")) { emu_chip = EMULATE_ST_M25P10_RES; emu_chip_size = 128 * 1024;
@@ -385,10 +397,26 @@ static int emulate_spi_chip_response(unsigned int writecnt, if (readcnt > 2) readarr[2] = 0x4a; break;
- case JEDEC_RDSR:
memset(readarr, 0, readcnt);
- case JEDEC_RDSR: {
if (aai_active)uint8_t tmp_status = emu_status;
memset(readarr, 1 << 6, readcnt);
tmp_status |= 1 << 6;
The WIP (write in progress) / WEL (write enable latch) /AIP (AAI in progress) logic should be moved to the respective commands so RDSR just does memset(readarr, emu_status, readcnt);
memset(readarr, tmp_status, readcnt);
break;
- }
- case JEDEC_WREN:
emu_status |= (1 << 1);
break;
- case JEDEC_WRSR:
if (!(emu_status & (1 << 1))) {
msg_perr("WRSR attempted, but WEL is 0!\n");
return 1;
Don't return 1 because a real chip wouldn't return an error either, it would just ignore the command.
}
if (aai_active) {
msg_perr("WRSR attempted during AAI sequence!\n");
return 1;
dito.
}
break; case JEDEC_READ: offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3];emu_status = writearr[1] & 0xFC; /* resets WEL and WIP */
After the end of the switch statement we should clear WEL if the command was not WREN/EWSR.
Regards, Carl-Daniel
TODO: man page
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at --- dummyflasher.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++-------- it87spi.c | 2 +- spi.h | 6 ++++- spi25.c | 24 ++++++++++---------- 4 files changed, 74 insertions(+), 24 deletions(-)
diff --git a/dummyflasher.c b/dummyflasher.c index 6281ff8..33f3ed7 100644 --- a/dummyflasher.c +++ b/dummyflasher.c @@ -21,6 +21,7 @@ #include <stdlib.h> #include <stdio.h> #include <ctype.h> +#include <errno.h> #include "flash.h" #include "chipdrivers.h" #include "programmer.h" @@ -61,6 +62,7 @@ unsigned char spi_blacklist[256]; unsigned char spi_ignorelist[256]; int spi_blacklist_size = 0; int spi_ignorelist_size = 0; +static uint8_t emu_status = 0; #endif #endif
@@ -133,6 +135,9 @@ int dummy_init(void) char *bustext = NULL; char *tmp = NULL; int i; +#if EMULATE_SPI_CHIP + char *status = NULL; +#endif #if EMULATE_CHIP struct stat image_stat; #endif @@ -299,6 +304,23 @@ int dummy_init(void) return 1; }
+#ifdef EMULATE_SPI_CHIP + status = extract_programmer_param("status"); + if (status) { + char *endptr; + errno = 0; + emu_status = strtoul(status, &endptr, 0); + free(status); + if (errno != 0 || status == endptr) { + msg_perr("Error: initial status register specified, " + "but the value could not be converted.\n"); + return 1; + } + msg_pdbg("Initial status register is set to 0x%02x.\n", + emu_status); + } +#endif + msg_pdbg("Filling fake flash chip with 0xff, size %i\n", emu_chip_size); memset(flashchip_contents, 0xff, emu_chip_size);
@@ -419,7 +441,6 @@ static int emulate_spi_chip_response(unsigned int writecnt, { unsigned int offs, i; static int unsigned aai_offs; - static int aai_active = 0;
if (writecnt == 0) { msg_perr("No command sent to the chip!\n"); @@ -443,6 +464,17 @@ static int emulate_spi_chip_response(unsigned int writecnt, return 0; } } + + if (emu_max_aai_size && (emu_status & SPI_SR_AAI)) { + if (writearr[0] != JEDEC_AAI_WORD_PROGRAM && + writearr[0] != JEDEC_WRDI && + writearr[0] != JEDEC_RDSR) { + msg_perr("Forbidden opcode (0x%02x) attempted during " + "AAI sequence!\n", writearr[0]); + return 0; + } + } + switch (writearr[0]) { case JEDEC_RES: if (emu_chip != EMULATE_ST_M25P10_RES) @@ -471,10 +503,23 @@ static int emulate_spi_chip_response(unsigned int writecnt, if (readcnt > 2) readarr[2] = 0x4a; break; - case JEDEC_RDSR: - memset(readarr, 0, readcnt); - if (aai_active) - memset(readarr, 1 << 6, readcnt); + case JEDEC_RDSR: { + memset(readarr, emu_status, readcnt); + break; + } + /* FIXME: this should be chip-specific. */ + case JEDEC_EWSR: + case JEDEC_WREN: + emu_status |= SPI_SR_WEL; + break; + case JEDEC_WRSR: + if (!(emu_status & SPI_SR_WEL)) { + msg_perr("WRSR attempted, but WEL is 0!\n"); + break; + } + /* FIXME: add some reasonable simulation of the busy flag */ + emu_status = writearr[1] & ~SPI_SR_WIP; + msg_pdbg2("WRSR wrote 0x%02x.\n", emu_status); break; case JEDEC_READ: offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; @@ -500,7 +545,7 @@ static int emulate_spi_chip_response(unsigned int writecnt, case JEDEC_AAI_WORD_PROGRAM: if (!emu_max_aai_size) break; - if (!aai_active) { + if (!(emu_status & SPI_SR_AAI)) { if (writecnt < JEDEC_AAI_WORD_PROGRAM_OUTSIZE) { msg_perr("Initial AAI WORD PROGRAM size too " "short!\n"); @@ -511,7 +556,7 @@ static int emulate_spi_chip_response(unsigned int writecnt, "long!\n"); return 1; } - aai_active = 1; + emu_status |= SPI_SR_AAI; aai_offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; /* Truncate to emu_chip_size. */ @@ -534,9 +579,8 @@ static int emulate_spi_chip_response(unsigned int writecnt, } break; case JEDEC_WRDI: - if (!emu_max_aai_size) - break; - aai_active = 0; + if (emu_max_aai_size) + emu_status &= ~SPI_SR_AAI; break; case JEDEC_SE: if (!emu_jedec_se_size) @@ -623,6 +667,8 @@ static int emulate_spi_chip_response(unsigned int writecnt, /* No special response. */ break; } + if (writearr[0] != JEDEC_WREN && writearr[0] != JEDEC_EWSR) + emu_status &= ~SPI_SR_WEL; return 0; } #endif diff --git a/it87spi.c b/it87spi.c index f089d78..a2a98f1 100644 --- a/it87spi.c +++ b/it87spi.c @@ -335,7 +335,7 @@ static int it8716f_spi_page_program(struct flashctx *flash, uint8_t *buf, /* Wait until the Write-In-Progress bit is cleared. * This usually takes 1-10 ms, so wait in 1 ms steps. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(1000); return 0; } diff --git a/spi.h b/spi.h index b908603..16fd280 100644 --- a/spi.h +++ b/spi.h @@ -90,7 +90,11 @@ #define JEDEC_RDSR 0x05 #define JEDEC_RDSR_OUTSIZE 0x01 #define JEDEC_RDSR_INSIZE 0x01 -#define JEDEC_RDSR_BIT_WIP (0x01 << 0) + +/* Status Register Bits */ +#define SPI_SR_WIP (0x01 << 0) +#define SPI_SR_WEL (0x01 << 1) +#define SPI_SR_AAI (0x01 << 6)
/* Write Status Enable */ #define JEDEC_EWSR 0x50 diff --git a/spi25.c b/spi25.c index 3ce7f08..22ab1ee 100644 --- a/spi25.c +++ b/spi25.c @@ -479,7 +479,7 @@ int spi_chip_erase_60(struct flashctx *flash) * This usually takes 1-85 s, so wait in 1 s steps. */ /* FIXME: We assume spi_read_status_register will never fail. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(1000 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -515,7 +515,7 @@ int spi_chip_erase_c7(struct flashctx *flash) * This usually takes 1-85 s, so wait in 1 s steps. */ /* FIXME: We assume spi_read_status_register will never fail. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(1000 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -557,7 +557,7 @@ int spi_block_erase_52(struct flashctx *flash, unsigned int addr, /* Wait until the Write-In-Progress bit is cleared. * This usually takes 100-4000 ms, so wait in 100 ms steps. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(100 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -604,7 +604,7 @@ int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, /* Wait until the Write-In-Progress bit is cleared. * This usually takes 100-4000 ms, so wait in 100 ms steps. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(100 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -649,7 +649,7 @@ int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, /* Wait until the Write-In-Progress bit is cleared. * This usually takes 100-4000 ms, so wait in 100 ms steps. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(100 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -692,7 +692,7 @@ int spi_block_erase_20(struct flashctx *flash, unsigned int addr, /* Wait until the Write-In-Progress bit is cleared. * This usually takes 15-800 ms, so wait in 10 ms steps. */ - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(10 * 1000); /* FIXME: Check the status register for errors. */ return 0; @@ -776,7 +776,7 @@ static int spi_write_status_register_ewsr(struct flashctx *flash, int status) * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed. */ programmer_delay(100 * 1000); - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) { + while (spi_read_status_register(flash) & SPI_SR_WIP) { if (++i > 490) { msg_cerr("Error: WIP bit after WRSR never cleared\n"); return TIMEOUT_ERROR; @@ -824,7 +824,7 @@ static int spi_write_status_register_wren(struct flashctx *flash, int status) * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed. */ programmer_delay(100 * 1000); - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) { + while (spi_read_status_register(flash) & SPI_SR_WIP) { if (++i > 490) { msg_cerr("Error: WIP bit after WRSR never cleared\n"); return TIMEOUT_ERROR; @@ -1053,7 +1053,7 @@ int spi_write_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, rc = spi_nbyte_program(flash, starthere + j, buf + starthere - start + j, towrite); if (rc) break; - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(10); } if (rc) @@ -1080,7 +1080,7 @@ int spi_chip_write_1(struct flashctx *flash, uint8_t *buf, unsigned int start, result = spi_byte_program(flash, i, buf[i - start]); if (result) return 1; - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(10); }
@@ -1175,7 +1175,7 @@ int spi_aai_write(struct flashctx *flash, uint8_t *buf, unsigned int start, */ return result; } - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(10);
/* We already wrote 2 bytes in the multicommand step. */ @@ -1187,7 +1187,7 @@ int spi_aai_write(struct flashctx *flash, uint8_t *buf, unsigned int start, cmd[2] = buf[pos++ - start]; spi_send_command(flash, JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL); - while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) + while (spi_read_status_register(flash) & SPI_SR_WIP) programmer_delay(10); }