We've modified Intel's jflash program to make it a bit more robust. The modified
version erases the entire device then writes a 64Kbyte block at a time, then veri-
fies the block. If it verifies, the program moves on to the next block; otherwise
it retries the writing and verifying, up to three times.
We did this because we found we were spending about 20 minutes flashing our 1.1MByte
VxWorks app into our StrongARM, and that it was occasionally failing near the end
and making us reflash from the beginning. If you're burning large images (sometimes
there's no way around it), this can save considerable time.
This version was derived from the Asabet version, modified to work with our design
which has no CPLDs, then further modified to support the incremental flash
programming described above.
This expects to run under Windows, so it's not derived from Nico's version. The
changes to get it to work under Linux are hopefully trivial.
// Wally
// *********************************************************************************
//
// JFlashBurner.cpp : Defines the entry point for the console application.
//
// PURPOSE:
// This program burns a program into an Intel flash chip.
// We, CardioNet, modified original Intel code.
// The original Intel code would write the program to the whole
// chip and then verify it. Writing and verifying is slow.
// If you have a one megabyte file, write it, and then start to
// verify the beginning and find that it was bad you'll be irritated
// that you had to wait so long! So our modification will write an
// up to 64K block, verify it, and then go to the next 64K block.
// Also, if the verification of the block fails we will attempt the
// write and verify cycle a couple of more times before giving up.
//
// AUTHOR:
// Jonathan Spurgin
//
// First Revision Date:
// 20-FEB-2001
//
// *********************************************************************************
//JFLASH V1.2
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include "sa1110jtag.h"
#define VERSION "1.2"
#define LPT1 0x3bc // hardware base address for parallel port
#define LPT2 0x378 // the search order is LPT1 then 2 then 3
#define LPT3 0x278 // first valid address found is used (re-order if needed for multiple ports)
#define SA1110ID "**** 1001001001100001 00000001001 1" // JTAG ID-codes for the SA-1110
#define PZ3128ID "**** 0000000010001100 00000010101 1" // and the 2 CPLD also in the chain
//#define PZ3032ID "0000 0000000000011010 00000010101 1" // contains version, part, and vendor codes
//#define PZ3032AID "0000 0000100000001010 00000010101 1"
#define PZ3032SID "**** 0000*000000*1010 00000010101 1" // support both the 'A' and non 'A' versions of the part
#define READ 0 // Flags used to modify the SA-1110 JTAG chain data depending on
#define WRITE 1 // the access mode of the Flash Memory
#define SETUP 2
#define HOLD 3
#define RS 4
#define IP 0 // Flag used when accessing the parallel port
#define RP 1 // RP = 'read port', IP = 'ignore port', using IP will speed access
#define MAX_IN_LENGTH 100 // max length for user input strings
#define STATUS_UPDATE 2 // time between updates of program/verify status in seconds
int lpt_address; // Global variable assigned to parallel port address
FILE *in_file;
// 'rp' : RP (read port) or IP (ignore port).
int putp(int tdi, int tms, int rp); // writes the JTAG data on the parallel port
void id_command(void); // issues the JTAG command to read the device ID for all 3 chips
void bypass_all(void); // issues the JTAG command to put all 3 device in bypass mode
void extest(void); // issues the JTAG command EXTEST to the SA-1110
// Passes read/write/setup data for the Flash memory
// 'rw' : Can be READ or WRITE.
// 'rp' : RP (read port) or IP (ignore port).
// Returns busdat (data on bus?)
DWORD access_rom(int rw, DWORD address, DWORD data, int rp);
// Read/write access to the SA-1110 pins
// 'rw' : Can be READ or WRITE.
// 'rp' : RP (read port) or IP (ignore port).
// Returns busdat (data on bus?)
DWORD access_bus(int rw, DWORD address, DWORD data, int rp);
int test_port(void); // Looks for and finds a valid parallel port address
int check_id(char *device_id);// Compares the device IDs for the 3 JTAG chips to expected values
void error_out( char* error_string ); // Prints error and exits program
void erase_flash(DWORD base_address, DWORD fsize, DWORD block_size, DWORD max_erase_time, int block_number);
void program_flash_buf( const DWORD max_write_buffer, const DWORD base_address, const DWORD buffer[], const DWORD buffer_item_count );
bool verify_flash( const DWORD base_address, const DWORD buffer[], const DWORD buffer_item_count );
// Old versions.
void program_flash(DWORD max_write_buffer, DWORD base_address, DWORD fsize);
void verify_flash(DWORD base_address, DWORD fsize);
void test_logic_reset(void);
void test_lock_flash(DWORD base_address, DWORD fsize, DWORD block_size, DWORD max_erase_time, int block_number);
// Returns 'true' if wrote successfully, else 'false'.
bool write_a_block(
const DWORD base_address,
const DWORD last_non_zero,
const DWORD last_non_ff,
const DWORD fsize,
DWORD buffer[],
const DWORD bufferSize,
const bool initialize // set to true if you want to erase device.
);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// argc == 1 : EXE name.
// argc == 2 : Input file name.
// argc == 3 : 'P' option.
// argc == 4 : Block Number
void main( int argc, char *argv[] )
{
printf("JFLASH Version %s\n", VERSION );
printf("***** This is the CardioNet-modified version ***** \n" );
printf("***** It writes and verifies in 64K blocks ***** \n" );
//Test operating system, if WinNT or Win2000 then get device driver handle
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
HANDLE h;
h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(h == INVALID_HANDLE_VALUE)
error_out("Couldn't access 'giveio' device");
CloseHandle(h);
}
// find a valid parallel port address
lpt_address = test_port();
if(!lpt_address)
error_out("Error, unable to find parallel port");
char filename[MAX_IN_LENGTH];
if(argc >= 2)
strcpy(filename,argv[1]);
else
{
printf("enter binary file name: ");
gets(filename);
}
if( (in_file = fopen(filename, "rb" )) == NULL)
error_out("error, can not open binary input file");
// Here is looks like we read the file to set the following variables:
// 'fsize' = Number of DWORDs in the input file.
// There are cases where we will later set 'fsize' to
// 'last_non_zero' or 'last_non_ff'.
//
// 'last_non_zero' = Last DWORD place in the file where there is a non-0x00000000.
// 'last_non_ff' = Last DWORD place in the file where there is a non-0xFFFFFFFF.
//
DWORD fsize = 0;
DWORD last_non_zero = 0 ;
DWORD last_non_ff = 0;
for(;;)
{
DWORD li;
int n = fread((DWORD *)&li, sizeof(DWORD) , 1, in_file);
if(feof(in_file))break; // Any bytes not on a 4 byte boundry at end-of-file will be ignored
fsize++;
if(li != 0 && li != 0xffffffff) // Find point in file were only 0's and ff's remain
last_non_zero = fsize;
if(li != 0xffffffff) // Find point in file were only ff's remain
last_non_ff = fsize;
}
rewind(in_file);
// if(fsize * 2 > dsize)
// error_out("error, file size is bigger than device size");
fsize = last_non_ff; // Don't waste time programming ff's at the end of the file this is the erase state
char option = 'P';
if(argc >= 3)
option = toupper(*argv[2]);
// Here is where we erase and program the flash memory.
if(option == 'P')
{
// This can be up to 64K, but at the end of the file it probably be less that 64K.
const DWORD SIZE64K = 0x0000FFFF + 1;
const DWORD bufferSize = SIZE64K / sizeof(DWORD);
DWORD buffer[ bufferSize ];
DWORD address = 0x00000000;
printf("Starting to programming ...\n");
bool initialize = true;
// Keep track of the number of blocks we have written.
int iBlockCounter = 0;
// Keep looping here, reading up to 64K blocks, writing the input file to the flash.
while(1)
{
const size_t bytesRead = fread( buffer, sizeof(BYTE), SIZE64K, in_file );
if( 0 < bytesRead )
{
const DWORD bufferItemCount = bytesRead / sizeof(DWORD);
printf( "\n----- About to write %d bytes ------ Block #%d ------\n", bytesRead, iBlockCounter );
// Retry a few times if failure.
int iRetryCount = 0;
bool bWriteSuccessful = false;
while( (false == bWriteSuccessful) && (iRetryCount < 3) )
{
printf( "Flash write attempt #%d\n", iRetryCount + 1 );
bWriteSuccessful = write_a_block( address, last_non_zero, last_non_ff, fsize, buffer, bufferItemCount, initialize );
if( false == bWriteSuccessful )
{
printf( "Writing to flash failed!\n" );
}
iRetryCount++;
}
// Exit if we failed!
if( false == bWriteSuccessful )
{
error_out("Tried to re-write a block a few times and failed each!");
}
initialize = false;
address += bufferSize;
}
else
{
// At the end of the file!
break;
}
iBlockCounter++;
}
printf("Programming done!\n");
}
fclose(in_file);
}
bool write_a_block(
const DWORD base_address,
const DWORD last_non_zero,
const DWORD last_non_ff,
const DWORD fsize,
DWORD buffer[],
const DWORD bufferSize,
const bool initialize )
{
test_logic_reset();
id_command();
bypass_all();
access_rom(SETUP, 0, 0x500050L, IP); // clear status register
access_rom(WRITE, 0, 0x500050L, IP);
access_rom(HOLD, 0, 0x500050L, IP);
access_rom(SETUP, 0, 0x980098L, IP); // read query
access_rom(WRITE, 0, 0x980098L, IP);
access_rom(HOLD, 0, 0x980098L, IP);
// To read data from the Flash Memory you must first fill the SA-1110 JTAG chain
// with the Address, then pump the entire chain out.
// however while pumping data out you can be pumping the next cycle's Address in
// Therefore the JTAG chain looks like a pipeline, valid read data always coming
// out one cycle late.
// Note that both Flash Memory devices are accessed in parallel (i.e. 32 data bits)
access_rom(READ, 0x10, 0, IP); // Test to see if the Flash supports Query Structured Output
if(access_rom(READ, 0x11, 0, RP) != 0x510051L) //Q
error_out("error reading flash attribute space\ncheck cables, power and flash sockets");
if(access_rom(READ, 0x12, 0, RP) != 0x520052L) //R
error_out("error reading flash attribute space R");
if(access_rom(READ, 0x25, 0, RP) != 0x590059L) //Y
error_out("error reading flash attribute space Y\n");
DWORD max_erase_time = access_rom(READ, 0x27, 0, RP); // "n" such that the max block erase time = 2^n
if((max_erase_time & 0xffffL) != (max_erase_time >> 16)) // both devices should be the same time
error_out("error, max erase time of E11 and E12 are different");
max_erase_time = 1 << (max_erase_time & 0xffffL); // convert erase time 2^n to the number of seconds
// Device size.
DWORD dsize = access_rom(READ, 0x2a, 0, RP); // "n" such that the device size = 2^n in number of bytes
if((dsize & 0xffffL) != (dsize >> 16)) // both devices should be the same size
error_out("error, device size of E11 and E12 are different");
dsize = 1 << (dsize & 0xffffL); // convert data size from 2^n to the number of bytes
DWORD max_write_buffer = access_rom(READ, 0x2d, 0, RP); // "n" such that the max num of bytes in write buffer = 2^n
if((max_write_buffer & 0xffffL) != (max_write_buffer >> 16)) // both devices should have the same write buffer size
error_out("error, write buffer size of E11 and E12 are different");
max_write_buffer = (1 << (max_write_buffer & 0xffffL)) / 2; // convert from 2^n bytes to the number of words
// Turned out to be 16.
//printf( "max_write_buffer = %d\n" , max_write_buffer );
int nblocks = access_rom(READ, 0x2e, 0, RP); // get the number of erase blocks in Flash - 1
if((nblocks & 0xffffL) != (nblocks >> 16)) // both devices should have the same number
error_out("error, number of blocks of E11 and E12 are different");
nblocks = (nblocks & 0xffffL) + 1L; // need to add '1' for true number
const DWORD block_size = dsize / 2 / nblocks;
int block_number = 0;
// Only do the following when we are first starting.
if( true == initialize )
{
test_lock_flash( base_address, fsize, block_size, max_erase_time, block_number );
// "erase_flash()" is very quick.
erase_flash( base_address, fsize, block_size, max_erase_time, block_number );
}
DWORD address = base_address;
program_flash_buf( max_write_buffer, address, buffer, bufferSize );
// put back into read mode
access_rom( SETUP, 0, 0xff00ffL, IP );
access_rom( WRITE, 0, 0xff00ffL, IP );
access_rom( HOLD, 0, 0xff00ffL, IP );
access_rom( READ, base_address, 0x0L, IP); //extra read to get the pipeline going
const bool returnValue = verify_flash( address, buffer, bufferSize );
address += bufferSize;
test_logic_reset();
return returnValue;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void program_flash_buf( const DWORD max_write_buffer, const DWORD base_address, const DWORD buffer[], const DWORD buffer_item_count )
{
printf( "program_flash_buf @ 0x%08x, DWORD count = %d\n", base_address, buffer_item_count );
// "Write Buffer" flow.
// This uses almost half the cycles required by "word programming" flow
// Status register is not read to save time. There is also no checking to see
// if maximum "Write Buffer Program Time" is violated. However even with the
// fastest parallel port bus speed this should not be a problem
// (i.e. 16 words * 300 JTAG chain length * 4 parallel port cycles * 1uS fast
// parallel port cycle = 19mS, typical write buffer program times are in the 200uS range).
DWORD write_word_count = (max_write_buffer - 1) + ((max_write_buffer - 1) << 16);
time_t start;
time(&start);
// This is the index for 'buffer[]' , which gets incremented.
DWORD bufferIndex = 0;
for( DWORD lj = base_address; lj < buffer_item_count + base_address; lj = lj + max_write_buffer )
{
access_rom(WRITE, lj, 0xe800e8L, IP); // write buffer command
access_rom(HOLD, lj, 0xe800e8L, IP);
access_rom(WRITE, lj, write_word_count, IP); // write word count (max write buffer size)
access_rom(HOLD, lj, write_word_count, IP);
time_t now;
time(&now);
if( difftime(now,start) > STATUS_UPDATE ) // Update status every 2 seconds
{
printf("Writing flash at hex address 0x%08x, %5.2f%% done \r"
,lj,(float)(lj - base_address)/(float)buffer_item_count*100.0);
time(&start);
}
for(DWORD lk = 0; lk < max_write_buffer; lk++)
{
DWORD li = buffer[ bufferIndex++ ];
access_rom(WRITE, lj+lk, li, IP); // Write buffer data
access_rom(HOLD, lj+lk, li, IP); // New
}
access_rom(WRITE, 0, 0xd000d0L, IP); // Program Buffer to Flash Confirm
access_rom(HOLD, 0, 0xd000d0L, IP); //New
}
//printf( "\n" );
}
bool verify_flash( const DWORD base_address, const DWORD buffer[], const DWORD buffer_item_count )
{
//printf( "verify_flash @ 0x%08x, DWORD count = %d\n", base_address, buffer_item_count );
time_t start;
time(&start);
// This is the index for 'buffer[]' , which gets incremented.
DWORD bufferIndex = 0;
for(DWORD lj = base_address + 1; lj <= buffer_item_count + base_address; lj++)
{
const DWORD li = buffer[ bufferIndex++ ];
const DWORD li1 = access_rom(READ, lj, 0x0L, RP);
time_t now;
time(&now);
if( difftime(now,start) > STATUS_UPDATE ) // Update status every 2 seconds
{
printf("Verifying flash at hex address 0x%08x, %5.2f%% done \r"
,lj,(float)(lj - base_address)/(float)buffer_item_count*100.0);
time(&start);
}
if( li != li1 )
{
printf("verify error at address = 0x%08x exp_dat = 0x%08x act_dat = 0x%08x\n", lj - 1, li, li1 );
return false;
}
}
printf("Verification successful! \n");
return true;
}
int putp(int tdi, int tms, int rp)
{
// Cable used had 100 ohm resistors between the following pins
// (Cable shipped as part of SA-1110 Development Kit)
// Output pins (LPT driving)
// LPT D0 Pin 2 and TCK J10 Pin 4
// LPT D1 Pin 3 and TDI J10 Pin 11
// LPT D2 Pin 4 and TMS J10 Pin 9
//
// Input pin (SA-1110 board drives)
// LPT Busy Pin 11 and TDO J10 Pin 13
int tdo = -1;
_outp(lpt_address, tms*4+tdi*2); // TCK low
for (int i=0; i<0x7fffff;i++);
_outp(lpt_address, tms*4+tdi*2+1); // TCK high
for ( i=0; i<0x7fffff;i++);
if(rp == RP)_outp(lpt_address, tms*4+tdi*2); // TCK low
for ( i=0; i<0x7fffff;i++);
if(rp == RP)tdo = !((int)_inp(lpt_address + 1) >> 7); // get TDO data
for ( i=0; i<0x7fffff;i++);
return tdo;
}
void id_command(void)
{
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,1,IP);
putp(1,1,IP); //select IR scan
putp(1,0,IP); //capture IR
putp(1,0,IP); //shift IR
putp(0,0,IP); //SA1110 IDCODE
putp(1,0,IP); //
putp(1,0,IP); //
putp(0,0,IP); //
putp(0,1,IP); //Exit1-IR
putp(1,1,IP); //Update-IR
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,1,IP);
putp(1,0,IP);
if(check_id(SA1110ID))
error_out("failed to read device ID for the SA-1110");
putp(1,1,IP); //Exit1-DR
putp(1,1,IP); //Update-DR
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
}
void bypass_all(void)
{
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,1,IP);
putp(1,1,IP); //select IR scan
putp(1,0,IP); //capture IR
putp(1,0,IP); //shift IR
putp(1,0,IP); //SA1110 BYPASS
putp(1,0,IP); //
putp(1,0,IP); //
putp(1,0,IP); //
putp(1,1,IP); //Exit1-IR
putp(1,1,IP); //Update-IR
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
}
void extest(void)
{
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,1,IP);
putp(1,1,IP); //select IR scan
putp(1,0,IP); //capture IR
putp(1,0,IP); //shift IR
putp(0,0,IP); //SA1110 extest
putp(0,0,IP); //
putp(0,0,IP); //
putp(0,0,IP); //
putp(0,1,IP); //Exit1-IR
putp(1,1,IP); //Update-IR
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
}
DWORD access_rom(int rw, DWORD address, DWORD data, int rp)
{
// Shift Flash address making A2 the LSB
return(access_bus(rw, address << 2, data, rp));
}
DWORD access_bus(int rw, DWORD address, DWORD data, int rp)
{
// Preset SA-1110 pins to default values (all others set in sa1110jtag.h)
pin[nCS0_OUT] = 1;
pin[nCS1_OUT] = 1;
pin[nCS2_OUT] = 1;
pin[nCS3_OUT] = 1;
pin[nCS4_OUT] = 1;
pin[nCS5_OUT] = 1;
pin[nOE_OUT] = 0;
pin[nWE_OUT] = 1;
pin[RD_nWR_OUT] = 0;
pin[D31_0_EN] = 1;
for(int i = 0; i < 26; i++)
pin[i+28] = (int)((address >> i) & 1); // set address 0 thru 25
if(rw == READ)
{
pin[RD_nWR_OUT] = 1;
switch(address >> 27)
{
case 0:{pin[nCS0_OUT] = 0; break;}
case 1:{pin[nCS1_OUT] = 0; break;}
case 2:{pin[nCS2_OUT] = 0; break;}
case 3:{pin[nCS3_OUT] = 0; break;}
case 4:{pin[nCS4_OUT] = 0; break;}
case 5:{pin[nCS5_OUT] = 0; break;}
}
}
if(rw == WRITE)
{
pin[nWE_OUT] = 0;
pin[nOE_OUT] = 1;
pin[D31_0_EN] = 0; // switch data pins to drive
switch(address >> 27) // set CS pin for corresponding address
{
case 0:{pin[nCS0_OUT] = 0; break;}
case 1:{pin[nCS1_OUT] = 0; break;}
case 2:{pin[nCS2_OUT] = 0; break;}
case 3:{pin[nCS3_OUT] = 0; break;}
case 4:{pin[nCS4_OUT] = 0; break;}
case 5:{pin[nCS5_OUT] = 0; break;}
}
for(DWORD li = 0L; li < 32L; li++)
pin[dat_order[li]] = (int)((data >> li) & 1L); // set data pins
}
if(rw == SETUP || rw == HOLD) // just like a write except WE, WE needs setup time
{
pin[nOE_OUT] = 1;
pin[D31_0_EN] = 0;
for(DWORD li = 0L; li < 32L; li++)
pin[dat_order[li]] = (int)((data >> li) & 1L); // serialize data pins
}
if(rw == RS) // setup prior to RD_nWR_OUT
{
pin[nOE_OUT] = 1;
}
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,1,IP); //select DR scan
putp(1,0,IP); //capture DR
putp(1,0,IP); //shift IR
int out_dat[300];
for(i = 0; i < 291; i++) // shift write data in to JTAG port and read data out
out_dat[i] = putp(pin[i],0,rp);
// putp(0,0,IP);
// putp(0,0,IP);
putp(0,1,IP); //Exit1-DR
putp(1,1,IP); //Update-DR
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
putp(1,0,IP); //Run-Test/Idle
DWORD busdat = 0;
for(i = 0; i < 32; i++) // convert serial data to single DWORD
{
busdat = busdat | (DWORD)(out_dat[dat_order[i] - 2] << i);
}
extest();
return(busdat);
}
int test_port(void)
{
// search for valid parallel port
_outp(LPT1, 0x55);
if((int)_inp(LPT1) == 0x55)return LPT1;
_outp(LPT2, 0x55);
if((int)_inp(LPT2) == 0x55)return LPT2;
_outp(LPT1, 0x55);
if((int)_inp(LPT3) == 0x55)return LPT3;
return(0); // return zero if none found
}
int check_id(char *device_id)
{
// compare passed device ID to the one returned from the ID command
char in_id[40];
BOOL error_flag = FALSE;
for(int i = 34; i >= 0; i--)
{
if(i == 4 || i == 21 || i == 33)
{
in_id[i] = ' ';
i--;
}
if(putp(1,0,RP) == 0)
in_id[i] = '0';
else
in_id[i] = '1';
if((in_id[i] != *(device_id + i)) && (*(device_id + i) != '*'))
{
error_flag = TRUE;
}
}
in_id[35] = 0;
if(error_flag)
{
printf("error, failed to read device ID\n");
printf("check cables and power\n");
printf("ACT: %s\n",in_id);
printf("EXP: %s\n\n",device_id);
return -1;
}
if(!strcmp(device_id,SA1110ID)) // print SA-1110 device revision
{
int sa_rev =
(int)(in_id[0] - '0') * 8 +
(int)(in_id[1] - '0') * 4 +
(int)(in_id[2] - '0') * 2 +
(int)(in_id[3] - '0');
switch(sa_rev)
{
case 0: printf("SA-1110 revision A0\n"); break;
case 4: printf("SA-1110 revision B0\n"); break;
case 5: printf("SA-1110 revision B1\n"); break;
case 6: printf("SA-1110 revision B2\n"); break;
case 8: printf("SA-1110 revision B4\n"); break;
default: printf("SA-1110 revision B4 + %d\n",sa_rev - 8);
}
}
return 0;
}
void error_out(char *error_string)
{
printf("%s\n",error_string);
printf( "Press any key to exit ..." );
getchar();
exit(0);
}
void erase_flash(DWORD base_address, DWORD fsize, DWORD block_size, DWORD max_erase_time, int block_number)
{
time_t start, now;
printf("Starting erase\n");
for(DWORD lj = base_address; lj < fsize + base_address; lj = lj + block_size) // Erase only blocks to be programmed
{
access_rom(SETUP, 0, 0x200020L, IP); // Erase block command
access_rom(WRITE, 0, 0x200020L, IP);
access_rom(HOLD, 0, 0x200020L, IP);
access_rom(SETUP, lj, 0xd000d0L, IP); // Erase confirm at the block address
access_rom(WRITE, lj, 0xd000d0L, IP);
access_rom(HOLD, lj, 0xd000d0L, IP);
time(&start);
printf("Erasing block %3d \r",block_number++);
while(access_rom(RS, 0, 0, RP) != 0x800080L) // Loop until successful status return
{
access_rom(READ, 0, 0, RP);
time(&now);
if(difftime(now,start) > max_erase_time + 1) // Check for erase timeout
error_out("Error, Block erase timed out");
}
}
printf("Erasing done \n");
}
void test_logic_reset(void)
{
putp(1,1,IP); // keep TMS set to 1 force a test logic reset
putp(1,1,IP); // no matter where you are in the TAP controller
putp(1,1,IP);
putp(1,1,IP);
putp(1,1,IP);
putp(1,1,IP);
}
void test_lock_flash(DWORD base_address, DWORD fsize, DWORD block_size, DWORD max_erase_time, int block_number)
{
time_t start, now;
for(DWORD lj = base_address; lj < fsize + base_address; lj = lj + block_size) // Test only blocks to be programmed
{
access_rom(SETUP, 0, 0x900090L, IP); // Read Identifier Codes
access_rom(WRITE, 0, 0x900090L, IP);
access_rom(HOLD, 0, 0x900090L, IP);
access_rom(READ, lj + 2, 0, IP); // read lock configuration (extra read to get JTAG pipeline going)
if(access_rom(READ, lj + 2, 0, RP) == 0x10001)
{
printf("Block of Flash Memory is Write Locked, would you like to unlock it? [y/n]: ");
if(toupper(_getche()) == 'Y')
{
printf("\nblock is locked\n");
access_rom(SETUP, 0, 0x600060L, IP); // Clear block lock bit command
access_rom(WRITE, 0, 0x600060L, IP);
access_rom(HOLD, 0, 0x600060L, IP);
access_rom(SETUP, lj, 0xd000d0L, IP); // Confirm
access_rom(WRITE, lj, 0xd000d0L, IP);
access_rom(HOLD, lj, 0xd000d0L, IP);
time(&start);
printf("Unlocking block %3d \r",block_number++);
while(access_rom(RS, 0, 0, RP) != 0x800080L) // Loop until successful status return
{
access_rom(READ, 0, 0, RP);
time(&now);
if(difftime(now,start) > max_erase_time + 1) // Check for status timeout
error_out("\nError, Clear lock timed out");
}
}
else
error_out("\nUnable to program Write Locked Flash Memory Block");
}
}
}
/////////////////////////////////////////////////////////////////////////////////
// END OF FILE //
/////////////////////////////////////////////////////////////////////////////////
//JFLASH V1.0
#define SA1110_CHAIN_LENGTH 292
#define ROM_SEL_IN 0
#define nRESET_OUT_OUT 1
#define nRESET_IN 2
#define TXD_3_IN 3
#define TXD_3_OUT 4
#define TXD_3_EN 5
#define RXD_3_IN 6
#define RXD_3_OUT 7
#define RXD_3_EN 8
#define TXD_2_IN 9
#define TXD_2_OUT 10
#define TXD_2_EN 11
#define RXD_2_IN 12
#define RXD_2_OUT 13
#define RXD_2_EN 14
#define TXD_1_IN 15
#define TXD_1_OUT 16
#define TXD_1_EN 17
#define RXD_1_IN 18
#define RXD_1_OUT 19
#define RXD_1_EN 20
#define UDCp_IN 21
#define UDCp_OUT 22
#define UDCp_EN 23
#define UDCmUDCp_IN 24
#define UDCm_IN 25
#define UDCm_OUT 26
#define UDCm_EN 27
#define A0_OUT 28
#define A1_OUT 29
#define A2_OUT 30
#define A3_OUT 31
#define A4_OUT 32
#define A5_OUT 33
#define A6_OUT 34
#define A7_OUT 35
#define A8_OUT 36
#define A9_OUT 37
#define A10_OUT 38
#define A11_OUT 39
#define A12_OUT 40
#define A13_OUT 41
#define A14_OUT 42
#define A15_OUT 43
#define A16_OUT 44
#define A17_OUT 45
#define A18_OUT 46
#define A19_OUT 47
#define A20_OUT 48
#define A21_OUT 49
#define A22_OUT 50
#define A23_OUT 51
#define A24_OUT 52
#define A25_OUT 53
#define nCS0_OUT 54
#define nCS1_OUT 55
#define nCS2_OUT 56
#define nCS3_OUT 57
#define nCS4_OUT 58
#define nCS5_OUT 59
#define RDY_IN 60
#define RD_nWR_OUT 61
#define nCAS0_OUT 62
#define nCAS1_OUT 63
#define nCAS2_OUT 64
#define nCAS3_OUT 65
#define nRAS0_OUT 66
#define nRAS1_OUT 67
#define nRAS2_OUT 68
#define nRAS3_OUT 69
#define nSDCAS_OUT 70
#define nSDRAS_OUT 71
#define nOE_OUT 72
#define nWE_OUT 73
#define multiEN_EN 74
#define nPCE1_OUT 75
#define nPCE2_OUT 76
#define nPREG_OUT 77
#define nPWAIT_IN 78
#define nIOIS16_IN 79
#define PSKTSEL_OUT 80
#define nPIOW_OUT 81
#define nPIOR_OUT 82
#define nPWE_OUT 83
#define nPOE_OUT 84
#define L_FCLK_IN 85
#define L_FCLK_OUT 86
#define L_FCLK_EN 87
#define L_LCLK_IN 88
#define L_LCLK_OUT 89
#define L_LCLK_EN 90
#define L_DD7_IN 91
#define L_DD7_OUT 92
#define L_DD7_EN 93
#define L_DD6_IN 94
#define L_DD6_OUT 95
#define L_DD6_EN 96
#define L_DD5_IN 97
#define L_DD5_OUT 98
#define L_DD5_EN 99
#define L_DD4_IN 100
#define L_DD4_OUT 101
#define L_DD4_EN 102
#define L_DD3_IN 103
#define L_DD3_OUT 104
#define L_DD3_EN 105
#define L_DD2_IN 106
#define L_DD2_OUT 107
#define L_DD2_EN 108
#define L_DD1_IN 109
#define L_DD1_OUT 110
#define L_DD1_EN 111
#define L_DD0_IN 112
#define L_DD0_OUT 113
#define L_DD0_EN 114
#define L_PCLK_IN 115
#define L_PCLK_OUT 116
#define L_PCLK_EN 117
#define L_BIAS_IN 118
#define L_BIAS_OUT 119
#define L_BIAS_EN 120
#define GP0_IN 121
#define GP0_OUT 122
#define GP0_EN 123
#define GP1_IN 124
#define GP1_OUT 125
#define GP1_EN 126
#define GP2_IN 127
#define GP2_OUT 128
#define GP2_EN 129
#define GP3_IN 130
#define GP3_OUT 131
#define GP3_EN 132
#define GP4_IN 133
#define GP4_OUT 134
#define GP4_EN 135
#define GP5_IN 136
#define GP5_OUT 137
#define GP5_EN 138
#define GP6_IN 139
#define GP6_OUT 140
#define GP6_EN 141
#define GP7_IN 142
#define GP7_OUT 143
#define GP7_EN 144
#define GP8_IN 145
#define GP8_OUT 146
#define GP8_EN 147
#define GP9_IN 148
#define GP9_OUT 149
#define GP9_EN 150
#define GP10_IN 151
#define GP10_OUT 152
#define GP10_EN 153
#define GP11_IN 154
#define GP11_OUT 155
#define GP11_EN 156
#define GP12_IN 157
#define GP12_OUT 158
#define GP12_EN 159
#define GP13_IN 160
#define GP13_OUT 161
#define GP13_EN 162
#define GP14_IN 163
#define GP14_OUT 164
#define GP14_EN 165
#define GP15_IN 166
#define GP15_OUT 167
#define GP15_EN 168
#define GP16_IN 169
#define GP16_OUT 170
#define GP16_EN 171
#define GP17_IN 172
#define GP17_OUT 173
#define GP17_EN 174
#define GP18_IN 175
#define GP18_OUT 176
#define GP18_EN 177
#define GP19_IN 178
#define GP19_OUT 179
#define GP19_EN 180
#define GP20_IN 181
#define GP20_OUT 182
#define GP20_EN 183
#define GP21_IN 184
#define GP21_OUT 185
#define GP21_EN 186
#define GP22_IN 187
#define GP22_OUT 188
#define GP22_EN 189
#define GP23_IN 190
#define GP23_OUT 191
#define GP23_EN 192
#define GP24_IN 193
#define GP24_OUT 194
#define GP24_EN 195
#define GP25_IN 196
#define GP25_OUT 197
#define GP25_EN 198
#define GP26_IN 199
#define GP26_OUT 200
#define GP26_EN 201
#define GP27_IN 202
#define GP27_OUT 203
#define GP27_EN 204
#define SMROM_EN_IN 205
#define SDCKE0_OUT 206
#define SDCLK0_OUT 207
#define SDCLK1_OUT 208
#define SDCLK1_EN 209
#define SDCKE1_OUT 210
#define SDCLK2_OUT 211
#define D31_0_EN 212
#define D31_IN 213
#define D31_OUT 214
#define D23_IN 215
#define D23_OUT 216
#define D15_IN 217
#define D15_OUT 218
#define D7_IN 219
#define D7_OUT 220
#define D30_IN 221
#define D30_OUT 222
#define D22_IN 223
#define D22_OUT 224
#define D14_IN 225
#define D14_OUT 226
#define D6_IN 227
#define D6_OUT 228
#define D29_IN 229
#define D29_OUT 230
#define D21_IN 231
#define D21_OUT 232
#define D13_IN 233
#define D13_OUT 234
#define D5_IN 235
#define D5_OUT 236
#define D28_IN 237
#define D28_OUT 238
#define D20_IN 239
#define D20_OUT 240
#define D12_IN 241
#define D12_OUT 242
#define D4_IN 243
#define D4_OUT 244
#define D27_IN 245
#define D27_OUT 246
#define D19_IN 247
#define D19_OUT 248
#define D11_IN 249
#define D11_OUT 250
#define D3_IN 251
#define D3_OUT 252
#define D26_IN 253
#define D26_OUT 254
#define D18_IN 255
#define D18_OUT 256
#define D10_IN 257
#define D10_OUT 258
#define D2_IN 259
#define D2_OUT 260
#define D25_IN 261
#define D25_OUT 262
#define D17_IN 263
#define D17_OUT 264
#define D9_IN 265
#define D9_OUT 266
#define D1_IN 267
#define D1_OUT 268
#define D24_IN 269
#define D24_OUT 270
#define D16_IN 271
#define D16_OUT 272
#define D8_IN 273
#define D8_OUT 274
#define D0_IN 275
#define D0_OUT 276
#define TXD_C_IN 277
#define TXD_C_OUT 278
#define TXD_C_EN 279
#define RXD_C_IN 280
#define RXD_C_OUT 281
#define RXD_C_EN 282
#define SCLK_C_IN 283
#define SCLK_C_OUT 284
#define SCLK_C_EN 285
#define SFRM_C_IN 286
#define SFRM_C_OUT 287
#define SFRM_C_EN 288
#define PWR_EN_OUT 289
#define VDD_FAULT_IN 290
#define BATT_FAULT_IN 291
int pin[] = {
1, // ROM_SEL_IN
1, // nRESET_OUT_OUT
1, // nRESET_IN
1, // TXD_3_IN
0, // TXD_3_OUT
0, // TXD_3_EN
1, // RXD_3_IN
0, // RXD_3_OUT
0, // RXD_3_EN
1, // TXD_2_IN
0, // TXD_2_OUT
0, // TXD_2_EN
0, // RXD_2_IN
0, // RXD_2_OUT
0, // RXD_2_EN
1, // TXD_1_IN
0, // TXD_1_OUT
0, // TXD_1_EN
1, // RXD_1_IN
0, // RXD_1_OUT
0, // RXD_1_EN
0, // UDCp_IN
0, // UDCp_OUT
0, // UDCp_EN
1, // UDCmUDCp_IN
0, // UDCm_IN
0, // UDCm_OUT
0, // UDCm_EN
0, // A0_OUT
0, // A1_OUT
1, // A2_OUT
0, // A3_OUT
0, // A4_OUT
0, // A5_OUT
0, // A6_OUT
0, // A7_OUT
0, // A8_OUT
0, // A9_OUT
0, // A10_OUT
0, // A11_OUT
0, // A12_OUT
0, // A13_OUT
0, // A14_OUT
0, // A15_OUT
0, // A16_OUT
0, // A17_OUT
0, // A18_OUT
0, // A19_OUT
0, // A20_OUT
0, // A21_OUT
0, // A22_OUT
0, // A23_OUT
0, // A24_OUT
0, // A25_OUT
1, // nCS0_OUT
1, // nCS1_OUT
1, // nCS2_OUT
1, // nCS3_OUT
1, // nCS4_OUT
1, // nCS5_OUT
1, // RDY_IN
0, // RD_nWR_OUT
1, // nCAS0_OUT
1, // nCAS1_OUT
1, // nCAS2_OUT
1, // nCAS3_OUT
1, // nRAS0_OUT
0, // nRAS1_OUT
0, // nRAS2_OUT
0, // nRAS3_OUT
0, // nSDCAS_OUT
0, // nSDRAS_OUT
0, // nOE_OUT
1, // nWE_OUT
0, // multiEN_EN
1, // nPCE1_OUT
1, // nPCE2_OUT
0, // nPREG_OUT
1, // nPWAIT_IN
1, // nIOIS16_IN
0, // PSKTSEL_OUT
0, // nPIOW_OUT
0, // nPIOR_OUT
0, // nPWE_OUT
0, // nPOE_OUT
1, // L_FCLK_IN
0, // L_FCLK_OUT
0, // L_FCLK_EN
1, // L_LCLK_IN
0, // L_LCLK_OUT
0, // L_LCLK_EN
1, // L_DD7_IN
0, // L_DD7_OUT
0, // L_DD7_EN
1, // L_DD6_IN
0, // L_DD6_OUT
0, // L_DD6_EN
1, // L_DD5_IN
0, // L_DD5_OUT
0, // L_DD5_EN
1, // L_DD4_IN
0, // L_DD4_OUT
0, // L_DD4_EN
1, // L_DD3_IN
0, // L_DD3_OUT
0, // L_DD3_EN
1, // L_DD2_IN
0, // L_DD2_OUT
0, // L_DD2_EN
1, // L_DD1_IN
0, // L_DD1_OUT
0, // L_DD1_EN
1, // L_DD0_IN
0, // L_DD0_OUT
0, // L_DD0_EN
1, // L_PCLK_IN
0, // L_PCLK_OUT
0, // L_PCLK_EN
1, // L_BIAS_IN
0, // L_BIAS_OUT
0, // L_BIAS_EN
0, // GP0_IN
0, // GP0_OUT
0, // GP0_EN
1, // GP1_IN
0, // GP1_OUT
0, // GP1_EN
1, // GP2_IN
0, // GP2_OUT
0, // GP2_EN
1, // GP3_IN
0, // GP3_OUT
0, // GP3_EN
1, // GP4_IN
0, // GP4_OUT
0, // GP4_EN
1, // GP5_IN
0, // GP5_OUT
0, // GP5_EN
1, // GP6_IN
0, // GP6_OUT
0, // GP6_EN
1, // GP7_IN
0, // GP7_OUT
0, // GP7_EN
1, // GP8_IN
0, // GP8_OUT
0, // GP8_EN
1, // GP9_IN
0, // GP9_OUT
0, // GP9_EN
1, // GP10_IN
0, // GP10_OUT
0, // GP10_EN
0, // GP11_IN
0, // GP11_OUT
0, // GP11_EN
1, // GP12_IN
0, // GP12_OUT
0, // GP12_EN
1, // GP13_IN
0, // GP13_OUT
0, // GP13_EN
1, // GP14_IN
0, // GP14_OUT
0, // GP14_EN
1, // GP15_IN
0, // GP15_OUT
0, // GP15_EN
1, // GP16_IN
0, // GP16_OUT
0, // GP16_EN
0, // GP17_IN
0, // GP17_OUT
1, // GP17_EN
1, // GP18_IN
0, // GP18_OUT
0, // GP18_EN
0, // GP19_IN
0, // GP19_OUT
0, // GP19_EN
1, // GP20_IN
0, // GP20_OUT
0, // GP20_EN
0, // GP21_IN
0, // GP21_OUT
0, // GP21_EN
1, // GP22_IN
0, // GP22_OUT
0, // GP22_EN
0, // GP23_IN
0, // GP23_OUT
0, // GP23_EN
1, // GP24_IN
0, // GP24_OUT
0, // GP24_EN
1, // GP25_IN
0, // GP25_OUT
0, // GP25_EN
1, // GP26_IN
0, // GP26_OUT
0, // GP26_EN
1, // GP27_IN
0, // GP27_OUT
0, // GP27_EN
0, // SMROM_EN_IN
0, // SDCKE0_OUT
0, // SDCLK0_OUT
0, // SDCLK1_OUT
1, // SDCLK1_EN
1, // SDCKE1_OUT
0, // SDCLK2_OUT
1, // D31_0_EN
0, // D31_IN
0, // D31_OUT
0, // D23_IN
0, // D23_OUT
0, // D15_IN
0, // D15_OUT
0, // D7_IN
0, // D7_OUT
0, // D30_IN
0, // D30_OUT
0, // D22_IN
0, // D22_OUT
0, // D14_IN
0, // D14_OUT
0, // D6_IN
0, // D6_OUT
0, // D29_IN
0, // D29_OUT
0, // D21_IN
0, // D21_OUT
0, // D13_IN
0, // D13_OUT
0, // D5_IN
0, // D5_OUT
0, // D28_IN
0, // D28_OUT
0, // D20_IN
0, // D20_OUT
0, // D12_IN
0, // D12_OUT
0, // D4_IN
0, // D4_OUT
0, // D27_OUT
0, // D27_IN
0, // D19_IN
0, // D19_OUT
0, // D11_IN
0, // D11_OUT
0, // D3_IN
0, // D3_OUT
0, // D26_IN
0, // D26_OUT
0, // D18_IN
0, // D18_OUT
0, // D10_IN
0, // D10_OUT
0, // D2_IN
0, // D2_OUT
0, // D25_IN
0, // D25_OUT
0, // D17_IN
0, // D17_OUT
0, // D9_IN
0, // D9_OUT
0, // D1_IN
0, // D1_OUT
0, // D24_IN
0, // D24_OUT
0, // D16_IN
1, // D16_OUT
0, // D8_IN
0, // D8_OUT
0, // D0_IN
1, // D0_OUT
1, // TXD_C_IN
0, // TXD_C_OUT
0, // TXD_C_EN
1, // RXD_C_IN
0, // RXD_C_OUT
0, // RXD_C_EN
1, // SCLK_C_IN
0, // SCLK_C_OUT
0, // SCLK_C_EN
1, // SFRM_C_IN
0, // SFRM_C_OUT
0, // SFRM_C_EN
1, // PWR_EN_OUT
0, // VDD_FAULT_IN
0}; // BATT_FAULT_IN
//int dat_order[] = { D8_OUT, D9_OUT,D10_OUT,D11_OUT,D12_OUT,D13_OUT,D14_OUT,D15_OUT,
// D16_OUT,D17_OUT,D18_OUT,D19_OUT,D20_OUT,D21_OUT,D22_OUT,D23_OUT,
// D24_OUT,D25_OUT,D26_OUT,D27_OUT,D28_OUT,D29_OUT,D30_OUT,D31_OUT,
// D1_OUT, D2_OUT, D3_OUT, D4_OUT, D5_OUT, D6_OUT, D7_OUT,D31_0_EN};
int dat_order[] = {
D0_OUT, D1_OUT, D2_OUT, D3_OUT, D4_OUT, D5_OUT, D6_OUT, D7_OUT,
D8_OUT, D9_OUT,D10_OUT,D11_OUT,D12_OUT,D13_OUT,D14_OUT,D15_OUT,
D16_OUT,D17_OUT,D18_OUT,D19_OUT,D20_OUT,D21_OUT,D22_OUT,D23_OUT,
D24_OUT,D25_OUT,D26_OUT,D27_OUT,D28_OUT,D29_OUT,D30_OUT,D31_OUT};
/*
#define D31_OUT 214
#define D23_OUT 216
#define D15_OUT 218
#define D7_OUT 220
#define D30_OUT 222
#define D22_OUT 224
#define D14_OUT 226
#define D6_OUT 228
#define D29_OUT 230
#define D21_OUT 232
#define D13_OUT 234
#define D5_OUT 236
#define D28_OUT 238
#define D20_OUT 240
#define D12_OUT 242
#define D4_OUT 244
#define D27_OUT 246
#define D19_OUT 248
#define D11_OUT 250
#define D3_OUT 252
#define D26_OUT 254
#define D18_OUT 256
#define D10_OUT 258
#define D2_OUT 260
#define D25_OUT 262
#define D17_OUT 264
#define D9_OUT 266
#define D1_OUT 268
#define D24_OUT 270
#define D16_OUT 272
#define D8_OUT 274
#define D0_OUT 276
*/
Received on Fri Feb 23 2001 - 13:10:13 EST
This archive was generated by hypermail 2.2.0 : Mon Jul 25 2005 - 17:20:42 EDT