⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flashw.cpp

📁 通过并口以及jtag烧写flash工作
💻 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 + -