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
master
Kolja Waschk 17 years ago
parent cd01760549
commit 04d591d21f

@ -30,28 +30,52 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#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 <width> bytes] */
NULL, /* state */
intel_28f800b3t_init, /* init() */
intel_28f800b3b_init, /* init() */
intel_28fxxxb3_capture, /* access() */
intel_28fxxxb3_update, /* access() */
intel_28fxxxb3_free /* free() */

@ -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 */
};

Loading…
Cancel
Save