📄 jflash.cpp
字号:
/******************************************************************************
** FILENAME: Jflash.cpp
**
** PURPOSE: A utility to program Intel flash devices from a PC parallel port.
**
** LAST MODIFIED: 2003.06.03
******************************************************************************/
#include <stdio.h>
#include <time.h>
#ifdef __windows__
#include <windows.h>
#include <conio.h>
#else
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <sys/perm.h>
#include <errno.h>
#define _getche getchar
#define BOOL int
#define FALSE 0
#define TRUE 1
/* Some types */
typedef long DWORD;
typedef short WORD;
#endif
#include "Compile_switches.h"
#include "Jflash.h"
#include "xhyper255jtag.h"
#ifdef __linux__
/* in/out macros */
#include <asm/io.h>
#define _inp(a) inb(a)
#define _outp(a,d) outb(d,a)
#endif
/*
*******************************************************************************
Globals
*******************************************************************************
*/
int lpt_address; // Global variable assigned to parallel port address
FILE *in_file;
int out_dat[MAX_DR_LENGTH];
int WORKBUF[XHYPER255_CHAIN_LENGTH];
#ifdef __linux__
int io_access_on( unsigned long port )
{
if (ioperm (port, 3, 1)) {
perror ("ioperm()");
return 0;
}
if (ioperm (0x80, 1, 1)) {
perror ("ioperm()");
return 0;
}
return 1;
}
void io_access_off( unsigned long port )
{
ioperm (port, 3, 0);
ioperm (0x80, 1, 0);
}
#else
#define io_access_on(x) (1)
#define io_access_off(x)
#endif
/*
*******************************************************************************
Forward declarations
*******************************************************************************
*/
int putp(int,int, int); // 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 Processor
#ifdef XHYPER255A
WORD access_rom(int, DWORD, WORD, int); // Passes read/write/setup data for the Flash memory
#else
DWORD access_rom(int, DWORD, DWORD, int); // Passes read/write/setup data for the Flash memory
#endif
DWORD access_bus(int, DWORD, DWORD, int); // Read/write access to the Processor pins
int test_port(void); // Looks for and finds a valid parallel port address
int check_id(char*); // Compares the device IDs for the 3 JTAG chips to expected values
void error_out(char*); // Prints error and exits program
void erase_flash(DWORD, DWORD, DWORD, DWORD, int);
void program_flash(DWORD, DWORD, DWORD);
void verify_flash(DWORD, DWORD);
void test_logic_reset(void);
void test_lock_flash(DWORD, DWORD, DWORD, DWORD, int);
void set_lock_flash(DWORD, DWORD, DWORD, DWORD, int);
void set_address (DWORD);
int PZ_scan_code(int, int, int);
int controller_scan_code(int, int, int);
void pre_DRSCAN(void);
void post_DRSCAN(void);
void pre_IRSCAN(void);
void post_IRSCAN(void);
void mem_rw_mode(int);
void mem_data_driver(int);
void mem_write_enable(int);
void mem_output_enable(int);
void clear_chip_selects(void);
void set_chip_select(DWORD);
DWORD shift_data(int);
void set_data(DWORD);
void jtag_test(void);
void dump_chain(void);
void init_workbuf(void);
void invert_workbuf(void);
void set_pin_chip_select(DWORD);
void check_file_info(DWORD *fsize , DWORD *last_non_zero, DWORD *last_non_ff, DWORD rom_size);
void check_rom_info(DWORD *max_erase_time, DWORD * dsize, DWORD * max_write_buffer, DWORD * block_size, int * nblocks );
/*
*******************************************************************************
*
* FUNCTION: main
*
* DESCRIPTION: Entry point for utility
*
* INPUT PARAMETERS: uses optional input parameters:
* argv[1] = filename to flash (binary files only)
* argv[2] = program options, currently only 'P' for Program
* argv[3] = block number (used to compute base_address)
*
* RETURNS: void
*
*******************************************************************************
*/
//void main( int argc, char *argv[] )
int main( int argc, char *argv[] )
{
time_t start;
DWORD fsize = 0;
DWORD last_non_zero = 0 ;
DWORD last_non_ff = 0;
// DWORD li;
int block_number = 0;
DWORD i;
DWORD max_erase_time, dsize, max_write_buffer, block_size;
int nblocks;
printf("JFLASH Version %s\n",VERSION);
printf("COPYRIGHT (C) 2000, 2001 Intel Corporation\n");
#ifdef __windows__
//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);
}
#endif
lpt_address = test_port(); // find a valid parallel port address
if(!lpt_address)
error_out("Error, unable to find parallel port");
test_logic_reset();
jtag_test();
char filename[MAX_IN_LENGTH];
if(argc >= 2)
strcpy(filename,argv[1]);
else
{
printf("enter file: ");
gets(filename);
}
test_logic_reset();
id_command();
bypass_all();
//init_workbuf();
test_logic_reset();
check_rom_info(&max_erase_time, &dsize, &max_write_buffer, &block_size, &nblocks);
if( (in_file = fopen(filename, "rb" )) == NULL)
{
error_out("error, can not open binary input file");
}
check_file_info(&fsize , &last_non_zero, &last_non_ff, dsize);
// Don't wast time programming ff's at the end of the file this is the erase state
fsize = last_non_ff;
if(argc >= 4)
{
block_number = atoi(argv[3]);
}
DWORD base_address = block_number * block_size; //the block_size is byte number,
//the base_address is 16-bit word address for each device
#ifdef XHYPER255B
printf("There are two 16-bit Flash devices in parallel\n\n");
#else
printf("There is 16-bit Flash devices\n\n");
#endif
printf("Characteristics for one device:\n");
printf(" Number of blocks in device = %ld\n",nblocks);
printf(" Block size = %ld 0x%lx word(16-bit)\n",block_size,block_size);
printf(" Device size = %ld 0x%lx word(16-bit)\n\n",dsize,dsize);
printf("Sample block to address list:\n\n");
for (i = 0; i < 129; i += 40)
{
#ifdef XHYPER255B
printf(" Block %d = hex address: %08X \n", i, i * block_size * 4);
#else
printf(" Block %d = hex address: %08X \n", i, i * block_size * 2);
#endif
}
if(block_number >= nblocks || block_number < 0)
{
error_out("error specifying block number");
}
if(100 - (last_non_zero * 100)/last_non_ff > 20)
{
printf("The last %2ld percent of image file is all zeros\n",100 - (last_non_zero * 100)/last_non_ff);
printf("Would you like to save time by not programming that area? [y/n]: ");
if(toupper(_getche()) == 'Y')
fsize = last_non_zero;
}
printf("\n");
char option = 'P';
if(argc >= 3)
{
option = toupper(*argv[2]);
}
if(option == 'P')
{
test_lock_flash(base_address, fsize, block_size, max_erase_time, block_number);
erase_flash(base_address, fsize, block_size, max_erase_time, block_number);
program_flash(max_write_buffer, base_address, fsize);
}
access_rom(SETUP, 0, F_READ_ARRAY, IGNORE_PORT); // put back into read mode
access_rom(WRITE, 0, F_READ_ARRAY, IGNORE_PORT);
access_rom(HOLD, 0, F_READ_ARRAY, IGNORE_PORT);
access_rom(READ, base_address, 0x0L, IGNORE_PORT); //extra read to get the pipeline going
time(&start);
verify_flash(base_address, fsize);
fclose(in_file);
test_logic_reset();
test_logic_reset();
test_logic_reset();
}
/*
*******************************************************************************
*
* FUNCTION: get_rom_info
*
* DESCRIPTION: get the flash information such as max erase time, flash size,
* max write buffer, block number
*
*
* INPUT PARAMETERS: DWORD *max_erase_time : max erase time, number of seconds
* DWORD *dsize : each flash size, number of 16-bit word
* DWORD *max_write_buffer : each flash max write buffer, number of 16-bit word
DWORD *block_size : each block size, number of 16-bit word
* DWORD *nblocks : number of erase blocks in each Flash*
* RETURNS: None
*
* GLOBAL EFFECTS: None
*
*******************************************************************************
*/
void check_rom_info(DWORD *max_erase_time, DWORD * dsize, DWORD * max_write_buffer, DWORD * block_size, int * nblocks )
{ access_rom(SETUP, 0, F_CLEAR_STATUS, IGNORE_PORT); // clear status register
access_rom(WRITE, 0, F_CLEAR_STATUS, IGNORE_PORT);
access_rom(HOLD, 0, F_CLEAR_STATUS, IGNORE_PORT);
access_rom(SETUP, 0, F_READ_QUERY, IGNORE_PORT); // read query
access_rom(WRITE, 0, F_READ_QUERY, IGNORE_PORT);
access_rom(HOLD, 0, F_READ_QUERY, IGNORE_PORT);
// To read data from the Flash Memory you must first fill the processor 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)
// Test to see if the Flash supports Query Structured Output
access_rom(READ, 0x10, 0, IGNORE_PORT);
#ifdef DEBUG
printf("about to read flash attributes....\n");
#endif
if(access_rom(READ, 0x11, 0, READ_PORT) != F_ATTR_Q) //Q
{
error_out("error reading flash attribute space!!!\ncheck cables, power and flash sockets");
}
if(access_rom(READ, 0x12, 0, READ_PORT) != F_ATTR_R) //R
{
error_out("error reading flash attribute space R");
}
if(access_rom(READ, 0x25, 0, READ_PORT) != F_ATTR_Y) //Y
{
error_out("error reading flash attribute space Y\n");
}
// "n" such that the max block erase time = 2^n
*max_erase_time = access_rom(READ, 0x27, 0, READ_PORT);
#ifdef XHYPER255B
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");
}
#endif
// convert erase time 2^n to the number of seconds
*max_erase_time = 1 << (*max_erase_time & 0xffffL);
// "n" such that the device size = 2^n in number of bytes
*dsize = access_rom(READ, 0x2a, 0, READ_PORT);
#ifdef XHYPER255B
if((*dsize & 0xffffL) != (*dsize >> 16)) // both devices should be the same size
{
error_out("error, device size of E11 and E12 are different");
}
#endif
// convert data size from 2^n to the number of bytes
*dsize = 1 << (*dsize & 0xffffL);
// "n" such that the max num of bytes in write buffer = 2^n
*max_write_buffer = access_rom(READ, 0x2d, 0, READ_PORT);
#ifdef XHYPER255B
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");
}
#endif
// convert from 2^n bytes to the number of byte
*max_write_buffer = (1 << (*max_write_buffer & 0xffffL));
// get the number of erase blocks in Flash - 1
*nblocks = access_rom(READ, 0x2e, 0, READ_PORT);
#ifdef XHYPER255B
if((*nblocks & 0xffffL) != (*nblocks >> 16)) // both devices should have the same number
{
error_out("error, number of blocks of E11 and E12 are different");
}
#endif
*nblocks = (*nblocks & 0xffffL) + 1L; // need to add '1' for true number
*block_size = (*dsize) / (*nblocks);
//change the dsize, max_write_buffer, block_size from byte number to 16-bit word number
*dsize = *dsize / 2;
*max_write_buffer = *max_write_buffer / 2;
*block_size = *block_size / 2;
}
/*
*******************************************************************************
*
* FUNCTION: check_file_info
*
* DESCRIPTION: get the file information and check with rom size
*
*
* INPUT PARAMETERS: DWORD *fsize : file size
DWORD *last_non_zero : the point where only 0 or FF remain
DWORD *last_non_ff : the point where only ff remain
if LUBBOCK_SABINAL is defined, the upper 3 parameters are in 16-bit word number
else they are in 32-bit DWORD number
DWORD rom_size : the rom size in
* RETURNS: None
* GLOBAL EFFECTS: None
*******************************************************************************
*/
void check_file_info(DWORD *fsize , DWORD *last_non_zero, DWORD *last_non_ff, DWORD rom_size)
{ BUS_GRAIN li;
for(;;)
{
int n = fread((BUS_GRAIN *)&li, sizeof(BUS_GRAIN) , 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 != -1) // Find point in file were only 0's and ff's remain
{ // For 32 bit data bus, -1 is 0xffffffff, for 16 bit data bus -1 is 0xffff
*last_non_zero = *fsize;
}
if(li != -1) // Find point in file were only ff's remain
{
*last_non_ff = *fsize;
}
}
rewind(in_file);
#ifdef XHYPER255B
// if 32-bit data width used. It assume 2 16-bit flash installed. each flash size=fsize
if ((*fsize) * 2 > rom_size * 2)
error_out("error, file size is bigger than device size");
#else
// if SABINAL 16-bit data width used, it assume only one 16-bit flash installed
if ((*fsize) > rom_size)
error_out("error, file size is bigger than device size");
#endif
}
/*
*******************************************************************************
*
* FUNCTION: putp
*
* DESCRIPTION: Drives TCK, TDI, and TMS signals and reads TDO signal
* via _outp and _inp calls.
*
* 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
*
*
*
* INPUT PARAMETERS: int tdi - test data in
*
* RETURNS: int - TDO (Test Data Out)
*
* GLOBAL EFFECTS: None
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -