📄 jflash.cpp
字号:
//JFLASH V0.3
//Changes:- Steve@steves-house.org.uk 2000/06/28
// supports SA1100 not SA1110 (trivially reversible)
// No support for CFI, LART flashes don't support this interface
// Supports only 28F160F3 Flashes. Trivially changeable
// Extra devices removed from jtag chain
// Support for plaited data bus to flash
// Erasing done in 4Kword blocks
//Issues:-
// needs tidying, but works under Linux at least...
// Erase will multiply erase some blocks (all blocks are treated as 4Kwords, but many of the blocks in the Flash are 32Kwords
// This is safe but suboptimal, it's caused by the address bus plaiting.
//Compiling:-
// gcc -O2 -s -o Jflash-linux Jflash.cpp
//
//running:-
// You need to be root
// Nothing else must be trying to use the printer port, including kernel drivers.
//cabling:-
// A hacky but functional LED cable is described later in this file.
// Do not attempt to connect the SA1100 pins directly to the printer port.
//See also:-
// Nicolas Pitres readme (Readme.Linux)
// http://www.lart.tudelft.nl/ for all things LARTy
#include <stdio.h>
#include <time.h>
//#define IODIRECT
#ifndef __linux__
#include <windows.h>
#include <conio.h>
#else
#include <unistd.h>
#include <ctype.h>
#include <sys/io.h>
#include <errno.h>
#define IODIRECT
#endif
#include "sa1100jtag.h"
#ifndef IODIRECT
#include "mmp.h"
#endif
#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 SA1100ID "X001 0001000010000100 00000110101 1" // JTAG ID-codes for the SA-1100 - don't know which way the leading X will be
#define READ 0 // Flags used to modify the SA-1100 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 //was 1
#define PLAIT 1 //use for command access to the Flash, when we care about the Flashes point of view
#define NOPLAIT 0 //use for data access to the flash, when we care about the SA1100s point of view
#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
int wom;
#ifndef IODIRECT //define IODIRECT for direct access to parallel port (DOS and Windows9x)
// define variables used to access the MMP driver (Needed for WindowsNT)
char ID[256];
PHYSICAL_MEMORY_INFO pmi;
PVOID pPartyMem = NULL;
char *aInterfaceType[] = {"Internal",
"Isa",
"Eisa",
"MicroChannel",
"TurboChannel" };
#endif
#ifdef __linux__
/* Some types */
typedef long DWORD;
/* in/out macros */
#include <asm/io.h>
#define _inp(a) inb(a)
#define _outp(a,d) outb(d,a)
#endif
int debug_jtag = 0;
FILE *in_file;
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 SA-1110
DWORD access_rom(int, DWORD, DWORD, int, int); // Passes read/write/setup data for the Flash memory
DWORD access_bus(int, DWORD, DWORD, int, int); // Read/write access to the SA-1110 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 main( int argc, char *argv[] )
{
#ifndef IODIRECT //stuff to setup the MMP driver
// OPEN up the driver
if (MMPOpen())
{
printf("ERROR: can't open driver!\n");
exit(1);
}
// GET DRIVER ID
MMPGetID(ID);
// MAP MEMORY
pmi.InterfaceType = Isa; // 1 = Isa, 2 = Eisa, 3 = Microchannel, 4 = TurboChannel
pmi.BusNumber = 0; // bus number, i.e. 0 for standard x86 ISA systems
pmi.BusAddress.QuadPart = (LONGLONG)0xD0000; // physical address to map
pmi.AddressSpace = 0; // 0 = memory, 1 = I/O
pmi.Length = 10; // length of section to map
if (MMPMapUserPhysicalMem(pmi, &pPartyMem))
{
error_out("Error: can't map memory!");
}
else
{
MMPUnmapUserPhysicalMem(pPartyMem);
}
#endif
lpt_address = test_port(); // find a valid parallel port address
if(!lpt_address)error_out("Error, unable to find parallel port");
printf("using printer port at %3x\n\r",lpt_address);
putp(1,1,IP); //
putp(1,1,IP);
putp(1,1,IP);
putp(1,1,IP);
putp(1,0,IP); //run test/idle
putp(1,0,IP); //run test/idle
char filename[MAX_IN_LENGTH];
if(argc >= 2)
strcpy(filename,argv[1]);
else
{
printf("enter binary file name: ");
gets(filename);
}
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, 0x900090L, IP, PLAIT); // read ID codes
access_rom(WRITE, 0, 0x900090L, IP, PLAIT);
access_rom(HOLD , 0, 0x900090L, IP, PLAIT);
// 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
// Therefor 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, 0x0, 0, IP, PLAIT); //ask for Manufacturer code, get crap
if(access_rom(READ, 0x1, 0, RP, PLAIT) != 0x00890089) //get Manufacturer code, ask for device code
error_out("error reading manufacturer code\n\r");
if(access_rom(READ, 0x1, 0, RP, PLAIT) != 0x88F488F4) //get Device code, ask for device code (again, discard)
error_out("error reading device code\n\r");
printf("Seems to be a pair of 28F160F3, bottom boot. Good. \n\r");
if( (in_file = fopen(filename, "rb" )) == NULL)
error_out("error, can not open binary input file");
DWORD max_erase_time = 5;
DWORD dsize = 1 * 1024 * 1024; //16Mbits per device
int nblocks = 128; //sort of a lie. There are 8 off 4Kword blocks and 31 off 32Kword blocks. Some may get erased several times (safe)...
DWORD max_write_buffer = 16; //size of a write chunk. The flash has no write buffer...
DWORD fsize = 0;
DWORD last_non_zero = 0 ;
DWORD last_non_ff = 0;
DWORD li,li1;
DWORD lj;
for(;;)
{
fread((DWORD *)&li, sizeof(DWORD) , 1, in_file);
if(feof(in_file))break;
if(li != 0)
last_non_zero = fsize;
if(li != 0xffffffff)
last_non_ff = fsize;
fsize++;
}
rewind(in_file);
if(fsize * 2 > dsize)
error_out("error, file size is bigger than device size");
fsize = last_non_ff + 1;
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(getchar()) == 'Y')
fsize = last_non_zero + 1;
}
printf("\nStarting erase for %6x bytes\n",fsize);
int block_number = 0;
time_t start, now;
for(lj = 0; lj < fsize; lj = lj + dsize / 2 / nblocks) // Erase only blocks to be programmed
{
//printf("erasing sector at %6x \n\r",lj);
access_rom(SETUP, 0, 0xFF00FFL, IP, PLAIT); // return to array read
access_rom(WRITE, 0, 0xFF00FFL, IP, PLAIT);
access_rom(HOLD, 0, 0xFF00FFL, IP, PLAIT);
access_rom(SETUP, 0, 0x200020L, IP, PLAIT); // Erase block command
access_rom(WRITE, 0, 0x200020L, IP, PLAIT);
access_rom(HOLD, 0, 0x200020L, IP, PLAIT);
access_rom(SETUP, lj, 0xd000d0L, IP, PLAIT); // Erase confirm at the block address
access_rom(WRITE, lj, 0xd000d0L, IP, PLAIT);
access_rom(HOLD, lj, 0xd000d0L, IP, PLAIT);
time(&start);
printf("Erasing block %3d \n\r",block_number++);
while(access_rom(RS, 0, 0, RP, PLAIT) != 0x800080L) // Loop until successful status return
{
access_rom(READ, 0, 0, RP, PLAIT);
time(&now);
if(difftime(now,start) > max_erase_time + 1) // Check for erase timeout
error_out("Error, Block erase timed out");
}
}
printf("Erasing done \nStarting programming\n");
DWORD write_word_count = (max_write_buffer - 1) + ((max_write_buffer - 1) << 16);
DWORD lk;
time(&start);
for(lj = 0; lj < fsize; lj = lj + max_write_buffer)
{
access_rom(READ, lj, 0, IP, PLAIT); // preload address bus with start address
time(&now);
if(difftime(now,start) > STATUS_UPDATE) // Update status every 2 seconds
{
printf("Writing flash at hex address %8lx, %5.2f%% done \n\r",lj,(float)lj/(float)fsize*100.0);
time(&start);
}
//printf("burning block %3d\n\r",lj);
for(lk = 0; lk < max_write_buffer; lk++)
{
fread((DWORD *)&li, sizeof(DWORD) , 1, in_file);
access_rom(SETUP, lj+lk, 0x400040L, IP, PLAIT); // Write command
access_rom(WRITE, lj+lk, 0x400040L, IP, PLAIT);
access_rom(HOLD , lj+lk, 0x400040L, IP, PLAIT);
access_rom(SETUP, lj+lk, li, IP, NOPLAIT); // Write data
access_rom(WRITE, lj+lk, li, IP, NOPLAIT);
access_rom(HOLD , lj+lk, li, IP, NOPLAIT);
//printf("writing %8x to %8x\n\r", li, lj + lk);
}
}
printf("Programming done \nStarting verify\n");
access_rom(SETUP, 0, 0xff00ffL, IP, PLAIT); // put back into read mode
access_rom(WRITE, 0, 0xff00ffL, IP, PLAIT);
access_rom(HOLD, 0, 0xff00ffL, IP, PLAIT);
rewind(in_file);
access_rom(READ, 0x0L, 0x0L, IP, NOPLAIT); //extra read to start to get the pipeline going
time(&start);
for(lj = 1; lj <= fsize; lj++)
{
fread((DWORD *)&li, sizeof(DWORD) , 1, in_file);
li1 = access_rom(READ, 0x0L + lj, 0x0L, RP, NOPLAIT);
time(&now);
if(difftime(now,start) > STATUS_UPDATE) // Update status every 2 seconds
{
printf("Verifying flash at hex address %8lx, %5.2f%% done \n\r",lj,(float)lj/(float)fsize*100.0);
time(&start);
}
//printf("verifying address = %lx exp_dat = %lx act_dat = %lx\n",lj,li,li1);
if(li != li1)
{
printf("verify error at address = %lx exp_dat = %lx act_dat = %lx\n",lj,li,li1);
#ifndef IODIRECT
MMPClose(); // Close WinNT parallel port driver
#endif
exit(1);
}
}
printf("Verification successful! \n");
fclose(in_file);
putp(1,1,IP); //test logic reset
putp(1,1,IP);
putp(1,1,IP);
putp(1,1,IP);
putp(1,1,IP);
putp(1,1,IP);
putp(1,1,IP);
#ifndef IODIRECT
MMPClose();
#endif
}
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -