📄 flashw.cpp
字号:
/*
*********************************************************************
*This test program can read data from FLASH with JTAG
*It can be modified little to write data to FLASH
*********************************************************************
*/
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include "flashw.h"
int lpt_address;// Global variable assigned to parallel port address
FILE *file;
int test_port(void);
void test_logic_reset(void);
void check_file_info(DWORD*, DWORD*, DWORD*);
void check_rom_info(DWORD*, DWORD*, DWORD*, DWORD*, int*);
void test_lock_flash(DWORD, DWORD, DWORD, DWORD, int);
void erase_flash(DWORD, DWORD, DWORD, DWORD, int);
DWORD access_bus(int, DWORD, DWORD, int);
void write_flash(DWORD, DWORD, DWORD);
void verify_flash(DWORD, DWORD);
void set_address(DWORD);
void set_data(int);
int putp(int, int, int);
void extest(void);
void pre_IRSCAN(void);
void controller_scan_code(int, int);
void post_IRSCAN(void);
void main(int argc, char *argv[])
{
if (argc != 3)
{
printf("Parameter error!");
exit(0);
}
HANDLE h;
DWORD fsize = 0, last_non_zero = 0, last_non_ff = 0;
DWORD max_erase_time, dsize, max_write_buffer, block_size;
int nblocks, block_number;
char file_name[MAX_PATH];
strcpy(file_name, argv[1]);
block_number = atoi(argv[2]);
h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
CloseHandle(h);
lpt_address = test_port();// find a valid parallel port address
test_logic_reset();
pin[nCS0_OUT] = 0;//set_pin_chip_select
pin[nCS1_OUT] = 1;
pin[nCS2_OUT] = 1;
pin[nCS3_OUT] = 1;
pin[nCS4_OUT] = 1;
pin[nCS5_OUT] = 1;
file = fopen(file_name, "rb");
check_file_info(&fsize , &last_non_zero, &last_non_ff);
fsize = last_non_ff;
check_rom_info(&max_erase_time, &dsize, &max_write_buffer, &block_size, &nblocks);
test_lock_flash((DWORD)block_number*256*1024, fsize, block_size, max_erase_time, block_number);
erase_flash((DWORD)block_number*256*1024, fsize, block_size, max_erase_time, block_number);
printf("Write FLASH,please wait!\n");
write_flash(max_write_buffer, (DWORD)block_number*256*1024, fsize);
printf("Done\n");
rewind(file);
access_bus(SETUP, 0, F_READ_ARRAY, IGNORE_PORT); // put back into read mode
access_bus(WRITE, 0, F_READ_ARRAY, IGNORE_PORT);
access_bus(HOLD, 0, F_READ_ARRAY, IGNORE_PORT);
access_bus(READ, (DWORD)block_number*256*1024, 0x0L, IGNORE_PORT); //extra read to get the pipeline going
verify_flash((DWORD)block_number*256*1024, fsize);
fclose(file);
}
int test_port(void)
{
_outp(LPT1, 0x55);
if ((int)_inp(LPT1) == 0x55)
return LPT1;
_outp(LPT2, 0x55);
if ((int)_inp(LPT2) == 0x55)
return LPT2;
_outp(LPT3, 0x55);
if ((int)_inp(LPT3) == 0x55)
return LPT3;
return 0;
}
void test_logic_reset(void)
{
putp(1,1,IGNORE_PORT);// keep TMS set to 1 force a test logic reset
putp(1,1,IGNORE_PORT);// no matter where you are in the TAP controller
putp(1,1,IGNORE_PORT);
putp(1,1,IGNORE_PORT);
putp(1,1,IGNORE_PORT);
putp(1,1,IGNORE_PORT);
}
void check_file_info(DWORD *fsize , DWORD *last_non_zero, DWORD *last_non_ff)
{
printf("Check file info\n");
DWORD li;
for(;;)
{
int n = fread((DWORD *)&li, sizeof(DWORD), 1, file);
if(feof(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(file);
printf("Check file_info Done!\n");
}
void check_rom_info(DWORD *max_erase_time, DWORD *dsize, DWORD *max_write_buffer, DWORD *block_size, int *nblocks)
{
printf("Check rom info\n");
access_bus(SETUP, 0, F_CLEAR_STATUS, IGNORE_PORT); // clear status register
access_bus(WRITE, 0, F_CLEAR_STATUS, IGNORE_PORT);
access_bus(HOLD, 0, F_CLEAR_STATUS, IGNORE_PORT);
access_bus(SETUP, 0, F_READ_QUERY, IGNORE_PORT); // read query
access_bus(WRITE, 0, F_READ_QUERY, IGNORE_PORT);
access_bus(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_bus(READ, 0x25, 0, IGNORE_PORT);
/*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_bus(READ, 0x27, 0, READ_PORT);
// 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_bus(READ, 0x2a, 0, READ_PORT);
// 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_bus(READ, 0x2d, 0, READ_PORT);
// 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_bus(READ, 0x2e, 0, READ_PORT);
*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;
printf("Check rom_info Done!\n");
}
void test_lock_flash(DWORD base_address, DWORD fsize, DWORD block_size,
DWORD max_erase_time, int block_number)
{
printf("Test lock flash\n");
DWORD lockstatus;
for(DWORD lj = base_address; lj < fsize + base_address; lj = lj + block_size) // Test only blocks to be programmed
{
access_bus(SETUP, 0, F_READ_IDCODES, IGNORE_PORT); // Read Identifier Codes
access_bus(WRITE, 0, F_READ_IDCODES, IGNORE_PORT);
access_bus(HOLD, 0, F_READ_IDCODES, IGNORE_PORT);
access_bus(READ, lj + 2, 0, IGNORE_PORT); // read lock configuration (extra read to get JTAG pipeline going)
lockstatus = access_bus(READ, lj + 2, 0, READ_PORT);
if((lockstatus == 0x10001) || (lockstatus == 0x10000) || (lockstatus == 0x00001))
//if(lockstatus == F_BLOCK_LOCKED )
{
printf("Block of Flash Memory is Write Locked, now unlock it!\n");
access_bus(SETUP, 0, F_CLEAR_BLOCK_LOCK, IGNORE_PORT); // Clear block lock bit command
access_bus(WRITE, 0, F_CLEAR_BLOCK_LOCK, IGNORE_PORT);
access_bus(HOLD, 0, F_CLEAR_BLOCK_LOCK, IGNORE_PORT);
access_bus(SETUP, lj, F_CLEAR_BLOCK_LOCK_2ND, IGNORE_PORT); // Confirm
access_bus(WRITE, lj, F_CLEAR_BLOCK_LOCK_2ND, IGNORE_PORT);
access_bus(HOLD, lj, F_CLEAR_BLOCK_LOCK_2ND, IGNORE_PORT);
while(access_bus(RS, 0, 0, READ_PORT) != F_STATUS_READY) // Loop until successful status return 0x0080
access_bus(READ, 0, 0, READ_PORT);
}
}
printf("Test lock_flash Done!\n");
}
void erase_flash(DWORD base_address, DWORD fsize, DWORD block_size, DWORD max_erase_time, int block_number)
{
printf("Starting erase\n");
for(DWORD lj = base_address; lj < fsize + base_address; lj = lj + block_size) // Erase only blocks to be programmed
{
access_bus(SETUP, 0, F_BLOCK_ERASE, IGNORE_PORT); // Erase block command
access_bus(WRITE, 0, F_BLOCK_ERASE, IGNORE_PORT);
access_bus(HOLD, 0, F_BLOCK_ERASE, IGNORE_PORT);
access_bus(SETUP, lj, F_BLOCK_ERASE_2ND, IGNORE_PORT); // Erase confirm at the block address
access_bus(WRITE, lj, F_BLOCK_ERASE_2ND, IGNORE_PORT);
access_bus(HOLD, lj, F_BLOCK_ERASE_2ND, IGNORE_PORT);
while(access_bus(RS, 0, 0, READ_PORT) != F_STATUS_READY) // Loop until successful status return
{
access_bus(READ, 0, 0, READ_PORT);
}
}
printf("Erasing done!\n");
}
DWORD access_bus(int rw, DWORD address, DWORD data, int rp)
{
int i;
// Preset SA-1110 or Cotulla pins to default values (all others set in Cotullajtag.h)
pin[nOE_OUT] = 0;//mem_output_enable
pin[nWE_OUT] = 1;//mem_write_disable
pin[RD_nWR_OUT] = 0;//mem_write_mode
pin[mdupper_ctrl] = 0;//mem_data_driver(HIZ)
pin[mdlower_ctrl] = 0;
set_address(address << 2);
//----------------------------------------------
if (rw == READ)
pin[RD_nWR_OUT] = 1;//mem_read_mode
//----------------------------------------------
if(rw == WRITE)
{
pin[nWE_OUT] = 0;//mem_write_enable
pin[nOE_OUT] = 1;//mem_output_disable
pin[mdupper_ctrl] = 1;//mem_data_driver(DRIVE);
pin[mdlower_ctrl] = 1;
set_data(data);
}
//----------------------------------------------
if(rw == SETUP || rw == HOLD)// just like a write except WE, WE needs setup time
{
pin[nOE_OUT] = 1;//mem_output_disable
pin[mdupper_ctrl] = 1;//mem_data_driver(DRIVE);
pin[mdlower_ctrl] = 1;
set_data(data);
}
//----------------------------------------------
if(rw == RS)// setup prior to RD_nWR_OUT
pin[nOE_OUT] = 1;//mem_output_disable
// Common finish
putp(1,0,0); //Run-Test/Idle
putp(1,0,0); //Run-Test/Idle
putp(1,0,0); //Run-Test/Idle
putp(1,0,0); //Run-Test/Idle
putp(1,1,0); //select DR scan
putp(1,0,0); //capture DR
putp(1,0,0); //shift DR
int out_dat[420];
for(i = 1; i < 409; i++) // shift write data in to JTAG port and read data out
out_dat[i] = putp(pin[i],0,rp);
// fudge factor because chain appears to be shifted by 1
// DEBUG LATER
putp(0,1,0); //Exit1-DR
putp(1,1,0); //Update-DR
putp(1,0,0); //Run-Test/Idle
putp(1,0,0); //Run-Test/Idle
putp(1,0,0); //Run-Test/Idle
DWORD busdat = 0;
for(i = 0; i < 32; i++) // convert serial data to single DWORD
{
busdat = busdat | ((DWORD)(out_dat[input_dat_order[i]] << i));
}
extest();
return busdat;
}
void write_flash(DWORD max_write_buffer, DWORD base_address, DWORD fsize)
{
DWORD li;
// "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);
for(DWORD lj = base_address; lj < fsize + base_address; lj = lj + max_write_buffer)
{
access_bus(WRITE, lj, F_WRITE_BUFFER, IGNORE_PORT); // write buffer command
access_bus(HOLD, lj, F_WRITE_BUFFER, IGNORE_PORT);
access_bus(WRITE, lj, write_word_count, IGNORE_PORT); // write word count (max write buffer size)
access_bus(HOLD, lj, write_word_count, IGNORE_PORT);
for(DWORD lk = 0; lk < max_write_buffer; lk++)
{
fread((DWORD *)&li, sizeof(DWORD) , 1, file);
access_bus(WRITE, lj+lk, li, IGNORE_PORT); // Write buffer data
access_bus(HOLD, lj+lk, li, IGNORE_PORT); // New
}
access_bus(WRITE, 0, 0xd000d0L, IGNORE_PORT); // Program Buffer to Flash Confirm
access_bus(HOLD, 0, 0xd000d0L, IGNORE_PORT); //New
}
}
void verify_flash(DWORD base_address, DWORD fsize)
{
DWORD li, li1;
printf("Starting Verify\n");
for(DWORD lj = base_address + 1; lj <= fsize + base_address; lj++)
{
fread((DWORD *)&li, sizeof(DWORD), 1, file);
li1 = access_bus(READ, lj, 0x0L, READ_PORT);
if(li != li1)
{
printf("verify error at address = %lx exp_dat = %lx act_dat = %lx\n",lj - 1,li,li1);
exit(1);
}
}
printf("Verification successful!\n");
}
void set_address(DWORD address)
{
unsigned int i;
for (i = 0; i < 26; i++)
pin[addr_order[i]] = (int)((address >> i) & 1);
}
void set_data(int data)
{
int i;
for(i = 0; i < 32; i++)
pin[dat_order[i]] = (data >> i) & 1;// set data pins
}
int putp(int tdi, int tms, int rp)
{
int tdo = -1;
// TMS is D2, TDI is D1, and TCK is D0, so construct an output by creating a
// rising edge on TCK with TMS and TDI data set.
_outp(lpt_address, tms*4+tdi*2+8); // TCK low
_outp(lpt_address, tms*4+tdi*2+1+8); // TCK high
// if we want to read the port, set TCK low because TDO is sampled on the
// TCK falling edge.
if (rp == 1)
{
_outp(lpt_address, tms*4+tdi*2+8); // TCK low
tdo = !((int)_inp(lpt_address + 1) >> 7); // get TDO data
}
return tdo;
}
void extest(void)
{
pre_IRSCAN();
controller_scan_code(COT_EXTEST, IGNORE_PORT);
post_IRSCAN();
}
void pre_IRSCAN()
{
putp(1,0,IGNORE_PORT); //Run-Test/Idle
putp(1,0,IGNORE_PORT); //Run-Test/Idle
putp(1,0,IGNORE_PORT); //Run-Test/Idle
putp(1,0,IGNORE_PORT); //Run-Test/Idle
putp(1,1,IGNORE_PORT); //select DR scan
putp(1,1,IGNORE_PORT); //select IR scan
putp(1,0,IGNORE_PORT); //capture IR
putp(1,0,IGNORE_PORT); //shift IR
}
void controller_scan_code(int code, int rp)
{
int i;
int tms = 0;
for (i = 0; i < 5; i++)
{
if (i == 4)
tms = 1;
putp(((code & (1 << i)) >> i), tms, rp);
}
}
void post_IRSCAN()
{
//putp(1,1,IGNORE_PORT); //Exit1-IR
putp(1,1,IGNORE_PORT); //Update-IR
putp(1,0,IGNORE_PORT); //Run-Test/Idle
putp(1,0,IGNORE_PORT); //Run-Test/Idle
putp(1,0,IGNORE_PORT); //Run-Test/Idle
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -