From 04d591d21fc37a91059278eb6a26e6909ef760d8 Mon Sep 17 00:00:00 2001 From: Kolja Waschk Date: Sat, 26 Jan 2008 18:40:31 +0000 Subject: [PATCH] Implemented actual programming and most of erase state machine in JIM's 28F800 flash. git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@952 b68d4a1b-bc3d-0410-92ed-d4ac073336b7 --- jtag/src/jim/intel_28f800b3.c | 234 ++++++++++++++++++++++++++++++---- jtag/src/jim/some_cpu.c | 4 +- 2 files changed, 211 insertions(+), 27 deletions(-) diff --git a/jtag/src/jim/intel_28f800b3.c b/jtag/src/jim/intel_28f800b3.c index 207e2cfd..43554bab 100644 --- a/jtag/src/jim/intel_28f800b3.c +++ b/jtag/src/jim/intel_28f800b3.c @@ -30,28 +30,52 @@ #include #include #include +#include +#include + +#undef VERBOSE typedef enum { - READ_ARRAY, - READ_STATUS, - READ_ID, - PROG_SETUP, - PROG_CONTINUE, - PROG_SUSP_TO_READ_STATUS, - PROG_SUSP_TO_READ_ARRAY, - PROG_SUSP_TO_READ_ID, - PROG_COMPLETE, - ERASE_SETUP, - ERASE_ERROR, - ERASE_CONTINUE, - ERASE_SUSP_TO_READ_STATUS, - ERASE_SUSP_TO_READ_ARRAY, - ERASE_SUSP_TO_READ_ID, - ERASE_COMPLETE + READ_ARRAY = 0, + READ_STATUS = 1, + READ_ID = 2, + PROG_SETUP = 3, + PROG_CONTINUE = 4, + PROG_SUSP_TO_READ_STATUS = 5, + PROG_SUSP_TO_READ_ARRAY = 6, + PROG_SUSP_TO_READ_ID = 7, + PROG_COMPLETE = 8, + ERASE_SETUP = 9, + ERASE_ERROR = 10, + ERASE_CONTINUE = 11, + ERASE_SUSP_TO_READ_STATUS = 12, + ERASE_SUSP_TO_READ_ARRAY = 13, + ERASE_SUSP_TO_READ_ID = 14, + ERASE_COMPLETE = 15 } intel_f28xxxb3_op_state_t; +const char *intel_28fxxx_opstate_name[16] = +{ + "READ_ARRAY", + "READ_STATUS", + "READ_ID", + "PROG_SETUP", + "PROG_CONTINUE", + "PROG_SUSP_TO_READ_STATUS", + "PROG_SUSP_TO_READ_ARRAY", + "PROG_SUSP_TO_READ_ID", + "PROG_COMPLETE", + "ERASE_SETUP", + "ERASE_ERROR", + "ERASE_CONTINUE", + "ERASE_SUSP_TO_READ_STATUS", + "ERASE_SUSP_TO_READ_ARRAY", + "ERASE_SUSP_TO_READ_ID", + "ERASE_COMPLETE" +}; + typedef enum { TOP = 0, @@ -59,13 +83,26 @@ typedef enum } b3_boot_type_t; +#define I28F_WSM_READY 0x80 +#define I28F_ERASE_SUSPENDED 0x40 +#define I28F_ERASE_ERROR 0x20 +#define I28F_PROG_ERROR 0x10 +#define I28F_VPP_LOW 0x08 +#define I28F_PROG_SUSPENDED 0x04 +#define I28F_BLOCK_LOCKED 0x02 +#define I28F_RESERVED 0x01 + + typedef struct { uint16_t identifier; + uint32_t data_buffer; + uint32_t address_buffer; uint32_t control_buffer; uint8_t status, status_buffer; intel_f28xxxb3_op_state_t opstate; b3_boot_type_t boot_type; + struct timeval prog_start_time; } intel_f28xxxb3_state_t; @@ -84,7 +121,7 @@ void intel_28fxxxb3_init(jim_bus_device_t *d, uint16_t id, b3_boot_type_t bt) } } -void intel_28f800b3t_init(jim_bus_device_t *d) +void intel_28f800b3b_init(jim_bus_device_t *d) { intel_28fxxxb3_init(d, 0x8893, BOTTOM); } @@ -103,28 +140,46 @@ uint32_t intel_28fxxxb3_capture(jim_bus_device_t *d, if((control&7) == 5) /* OE and CS: READ */ { intel_f28xxxb3_state_t *is = d->state; + switch(is->opstate) { case READ_STATUS: + case PROG_CONTINUE: + case ERASE_CONTINUE: + case PROG_SUSP_TO_READ_STATUS: + case ERASE_SUSP_TO_READ_STATUS: data = is->status_buffer; break; + case READ_ID: + case PROG_SUSP_TO_READ_ID: + case ERASE_SUSP_TO_READ_ID: if(address == 1) data = is->identifier; else if(address == 0) data = 0x0089; break; + case READ_ARRAY: + case PROG_SUSP_TO_READ_ARRAY: + case ERASE_SUSP_TO_READ_ARRAY: data = shmem[(address<<1)]<<8; data |= shmem[(address<<1)]+1; break; + default: break; } +#ifdef VERBOSE + printf("i28fxxxb3: read %04X from %08X (in %s)\n", + data & 0xFFFF, address, intel_28fxxx_opstate_name[is->opstate]); +#endif } +#if 0 printf("capture A=%08X, D=%08X%s%s%s\n", address, data, (control & 1) ? ", OE":"", (control & 2) ? ", WE":"", (control & 4) ? ", CS":""); +#endif return data; } @@ -133,10 +188,12 @@ void intel_28fxxxb3_update(jim_bus_device_t *d, uint32_t address, uint32_t data, uint32_t control, uint8_t *shmem, size_t shmem_size) { +#if 0 printf("update A=%08X, D=%08X%s%s%s\n", address, data, (control & 1) ? ", OE":"", (control & 2) ? ", WE":"", (control & 4) ? ", CS":""); +#endif if(d->state != NULL) { @@ -144,6 +201,40 @@ void intel_28fxxxb3_update(jim_bus_device_t *d, if( (((is->control_buffer&1)==0) && ((control&1)==1)) /* OE rise */ ||(((is->control_buffer&4)==0) && ((control&4)==1))) /* CS rise */ { + if(is->opstate == PROG_CONTINUE || is->opstate == ERASE_CONTINUE) + { + long dusecs; + struct timeval yet, diff; + gettimeofday(&yet, NULL); + + diff.tv_sec = yet.tv_sec - is->prog_start_time.tv_sec; + if(yet.tv_usec >= is->prog_start_time.tv_usec) + { + diff.tv_usec = yet.tv_usec - is->prog_start_time.tv_usec; + } + else + { + diff.tv_usec = yet.tv_usec + 1E6 - is->prog_start_time.tv_usec; + diff.tv_sec --; + } + dusecs = 1E6 * diff.tv_sec + diff.tv_usec; + if(is->opstate == PROG_CONTINUE) + { + if(dusecs > 40) + { + shmem[(is->address_buffer<<1)] &= ((data >> 8) & 0xFF); + shmem[(is->address_buffer<<1) + 1] &= (data & 0xFF); + is->status |= I28F_WSM_READY; + } + } + else if(is->opstate == ERASE_CONTINUE) + { + if(dusecs > 600E3) + { + is->status |= I28F_WSM_READY; + } + } + } is->status_buffer = is->status; /* latch status */ }; @@ -151,10 +242,21 @@ void intel_28fxxxb3_update(jim_bus_device_t *d, { intel_f28xxxb3_state_t *is = d->state; uint8_t dl = data & 0xFF; + +#ifdef VERBOSE + printf("i28fxxxb3: write %04X to %08X (in %s)\n", + data & 0xFFFF, address, intel_28fxxx_opstate_name[is->opstate]); +#endif + + if(dl == 0x50) + { + is->status &= ~(I28F_BLOCK_LOCKED|I28F_VPP_LOW|I28F_PROG_ERROR|I28F_ERASE_ERROR); + } + switch(is->opstate) { - case READ_ARRAY: case READ_STATUS: + case READ_ARRAY: case READ_ID: switch(dl) { @@ -163,14 +265,96 @@ void intel_28fxxxb3_update(jim_bus_device_t *d, case 0x20: is->opstate = ERASE_SETUP; break; case 0x70: is->opstate = READ_STATUS; break; case 0x90: is->opstate = READ_ID; break; - case 0xD0: is->opstate = READ_ARRAY; break; - case 0xB0: is->opstate = READ_ARRAY; break; - case 0xFF: is->opstate = READ_ARRAY; break; - default: is->opstate = READ_ARRAY; break; } break; - default: + + case PROG_SETUP: + if(dl != 0x10 && dl != 0x40) + { + is->status |= I28F_PROG_ERROR | I28F_ERASE_ERROR; + is->opstate = READ_STATUS; + } + else + { + is->status &= ~I28F_WSM_READY; + is->data_buffer = data; + is->address_buffer = address; + is->opstate = PROG_CONTINUE; + gettimeofday(&(is->prog_start_time), NULL); + } + break; + + case PROG_CONTINUE: + if(dl == 0xB0) + { + is->opstate = PROG_SUSP_TO_READ_STATUS; + is->status |= I28F_PROG_SUSPENDED; + } + break; + + case PROG_SUSP_TO_READ_STATUS: + case PROG_SUSP_TO_READ_ARRAY: + case PROG_SUSP_TO_READ_ID: + switch(dl) + { + case 0xD0: is->status &= ~I28F_PROG_SUSPENDED; + is->opstate = PROG_CONTINUE; break; + case 0x70: is->opstate = PROG_SUSP_TO_READ_STATUS; break; + case 0x90: is->opstate = PROG_SUSP_TO_READ_ID; break; + default: is->opstate = PROG_SUSP_TO_READ_ARRAY; break; + } + break; + + case ERASE_SETUP: + if(dl != 0xD0) + { + is->status |= I28F_PROG_ERROR | I28F_ERASE_ERROR; + is->opstate = READ_STATUS; + } + else + { + is->status &= 0x7F; + is->data_buffer = data; + is->address_buffer = address; + is->opstate = ERASE_CONTINUE; + gettimeofday(&(is->prog_start_time), NULL); + } + break; + + case ERASE_CONTINUE: + if(dl == 0xB0) + { + is->opstate = ERASE_SUSP_TO_READ_STATUS; + is->status |= I28F_ERASE_SUSPENDED; + }; + break; + + case ERASE_SUSP_TO_READ_STATUS: + case ERASE_SUSP_TO_READ_ARRAY: + case ERASE_SUSP_TO_READ_ID: + switch(dl) + { + case 0xD0: is->status &= ~I28F_ERASE_SUSPENDED; + is->opstate = ERASE_CONTINUE; break; + case 0x70: is->opstate = ERASE_SUSP_TO_READ_STATUS; break; + case 0x90: is->opstate = ERASE_SUSP_TO_READ_ID; break; + default: is->opstate = ERASE_SUSP_TO_READ_ARRAY; break; + } + break; + + case PROG_COMPLETE: + case ERASE_ERROR: + case ERASE_COMPLETE: + switch(dl) + { + case 0x10: + case 0x40: is->opstate = PROG_SETUP; break; + case 0x20: is->opstate = ERASE_SETUP; break; + case 0x70: is->opstate = READ_STATUS; break; + case 0x90: is->opstate = READ_ID; break; + default: is->opstate = READ_ARRAY; break; + } break; } }; @@ -178,12 +362,12 @@ void intel_28fxxxb3_update(jim_bus_device_t *d, } } -jim_bus_device_t intel_28f800b3t = +jim_bus_device_t intel_28f800b3b = { 2, /* width [bytes] */ 0x80000, /* size [words, each bytes] */ NULL, /* state */ - intel_28f800b3t_init, /* init() */ + intel_28f800b3b_init, /* init() */ intel_28fxxxb3_capture, /* access() */ intel_28fxxxb3_update, /* access() */ intel_28fxxxb3_free /* free() */ diff --git a/jtag/src/jim/some_cpu.c b/jtag/src/jim/some_cpu.c index 512c3dc9..6cc53b46 100644 --- a/jtag/src/jim/some_cpu.c +++ b/jtag/src/jim/some_cpu.c @@ -30,7 +30,7 @@ #undef VERBOSE -extern jim_bus_device_t intel_28f800b3t; +extern jim_bus_device_t intel_28f800b3b; jim_attached_part_t some_cpu_attached[] = { @@ -39,7 +39,7 @@ jim_attached_part_t some_cpu_attached[] = * 3. Data shift: Distance between D0 of device and CPU e.g. 0, 8, 16 or 24 bits * 4. Part: Pointer to part structure */ - { 0x00000000, 1, 0, &intel_28f800b3t }, + { 0x00000000, 1, 0, &intel_28f800b3b }, { 0xFFFFFFFF, 0, 0, NULL } /* Always end list with part == NULL */ };