Files
linuxcnc/5i24/utils/dos/source/NMFLASH.PAS
Thaddeus-Maximus f3953d66ae ?
2026-04-03 15:58:58 -05:00

502 lines
12 KiB
Plaintext
Executable File

program nmflash;
{$IFDEF WINDOWS}
uses synaser,synautil,synaip,blcksock,dos,crt;
var
ser:TBlockSerial;
TheComPort : string;
IPAddr : string;
Socket : TUDPBlockSocket;
{$ELSE}
uses dos,crt;
var TheComPort : word;
{$ENDIF}
{$I SELECTC}
{$I SELECTIO}
{I SELECTP}
{$I SELECTPR}
{$I INTERFCE}
const
DataStride = 4; {bytes}
procedure Error(err : integer);
begin
writeln(errorrecord[err].errstr);
halt(2);
end;
procedure Barfout(es:string);
begin
writeln;
writeln(es);
halt(2);
end;
type
configfile = file;
const
FileBufferSize = 8192;
PageSize = 256;
SPICSPort = $70;
SPISregPort = $74;
DAVMask = $04;
FallbackSA = $10000; { fallback start address is sector 1 }
BootSA = $00000; { boot start address is sector 0 }
BBSize = 64;
NSAMSBOffset = 25; { offset of Normal Start Address MS Byte in boot block }
CBootBlock : array[0..BBSize-1] of byte = ($FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,
$FF,$FF,$AA,$99,$55,$66,$31,$E1,
$FF,$FF,$32,$61,$00,$00,$32,$81,
$0B,$08,$32,$A1,$00,$00,$32,$C1,
$0B,$01,$30,$A1,$00,$00,$33,$01,
$21,$00,$32,$01,$00,$1F,$30,$A1,
$00,$0E,$20,$00,$20,$00,$20,$00,
$20,$00,$20,$00,$20,$00,$20,$00);
var
BootBlock : array[0..BBSize-1] of byte;
NormalSA : longint; { normal start address is 1/2 way up }
NSAMSB : byte;
VerifyOnly : boolean;
CardNumber : word;
Parms : word;
StartAddress : longint;
FileName : string;
CFile : configfile;
CFileSize : longint;
Timeout : longint;
Fallback : boolean;
BBuf: array[0..FileBufferSize-1] of byte;
function OpenForRead(var fp: configfile; name: string): boolean;
begin
Assign(fp,Name);
{$I-}
Reset(fp,1);
{$I+}
OpenForRead := IOResult = 0;
end { Open };
procedure Usage;
begin
writeln;
writeln(' NMFLASH - Writes config data to 5I24/5I25/6I25/7I90 EEPROM');
writeln;
writeln(' USAGE - NMFLASH file [V]');
writeln(' Where file is a VALID FPGA configuration file');
writeln(' Trailing V invoke Verify only option');
halt(2);
end;
procedure SetCSHigh;
begin
Write32(BaseAddr+SPICSPort,1);
end;
procedure SetCSLow;
begin
Write32(BaseAddr+SPICSPort,0);
end;
function WaitForSPIData : boolean;
var
loops: integer;
data : longint;
begin
data := 0;
loops := 0;
while ((data and DAVMask) = 0) and (loops < 5000) do
begin
data := Read32(BaseAddr+SPICSPort);
loops := loops +1;
end;
if loops = 5000 then WaitForSPIData := false else WaitForSPIData := true;
end;
procedure SendSPIByte( d: byte);
begin
Write32(BaseAddr+SPISRegPort,d);
if not WaitForSPIData then BarfOut('Timeout waiting for SPI Shift Register');
end;
function RecvSPIByte(d: byte) : byte;
var
data: longint;
begin
Write32(BaseAddr+SPISRegPort,d);
if not WaitForSPIData then BarfOut('Timeout waiting for SPI Shift Register');
data := Read32(BaseAddr+SPISRegPort);
RecvSPIByte := byte(data and $FF);
end;
{$I 25Mlowp.pas }
procedure Dump(sa:longint);
var
index : longint;
begin
for index := sa to sa+255 do
begin
if (index and 15) = 0 then
begin
writeln;
Hexprint(index,8);
write(': ');
end;
Hexprint(ReadByte25(index),2);
write(' ');
end;
writeln;
end;
procedure WriteBlock(add:longint;bufidx:word);
var
index : word;
begin
WriteEnable25;
Prefix25;
PutByte25(PageProgCom);
PutAddress25(add); { note that add 0..7 should be 0}
for index := 0 to PageSize -1 do
begin
PutByte25(BBuf[bufidx+index]);
end;
Suffix25;
WaitForWrite25;
end;
function NextByte(n: byte) : byte;
var
index,abyte : byte;
bytesread : word;
begin
for index := 1 to n do Blockread((CFile),abyte,1,bytesread);
NextByte := abyte;
end;
function ReadString : string;
var
sleng,count : word;
tstring : string;
abyte: byte;
begin
sleng := NextByte(1) * 256;
sleng := sleng + NextByte(1);
if (sleng > 255) then sleng := 255;
tstring := '';
for count := 1 to sleng do
begin
abyte := NextByte(1);
if (abyte <> 0) then tstring := tstring + chr(abyte);
end;
ReadString := tstring;
end;
procedure PrintBitFileHeader;
var
sleng,bytesread : word;
tstring : string;
conflength : longint;
fbyte : byte;
ft : (bit,bin,unk);
begin
ft := unk;
if (NextByte(1) = 0) then
begin
if (Nextbyte(1) = 9) then
begin
writeln('Looks like a BIT file');
fbyte := NextByte(9); {skip over 9 header bytes}
if (NextByte(1) = 0) then
begin
if (NextByte(1) = 1) then
begin
if (NextByte(1) = $61) then
begin
writeln('Design name: ',ReadString);
fbyte := NextByte(1); {Skip over 'b'}
writeln('Part name: ',ReadString);
fbyte := NextByte(1); {Skip over 'c'}
writeln('Design date: ',ReadString);
fbyte := NextByte(1); {Skip over 'd'}
writeln('Design time: ',ReadString);
fbyte := NextByte(1);; {Skip over 'e'}
conflength := longint(NextByte(1))*16777216;
conflength := conflength +longint(NextByte(1))*65536;
conflength := conflength +longint(NextByte(1))*256;
conflength := conflength +longint(NextByte(1));
writeln('Config Length: ',conflength);
ft := bit;
end; {valid bitfile header}
end;
end;
end; {starting to look like a bit file }
end; {looks like a bit file}
if ft = unk then
begin
if (NextByte(1) = $FF) and (NextByte(1) = $FF) and (NextByte(1) = $FF) and (NextByte(1) = $FF) then
begin
writeln('Looks like a BIN file');
Reset(Cfile,1);
ft := bin;
end;
end;
if ft = unk then
begin
writeln('Invalid bitfile header!');
halt(2);
end;
end;
procedure GetParms;
var
thefile : string;
begin
Fallback := false;
VerifyOnly := false;
if ParamCount < 1 then Usage;
thefile := paramStr(1);
FileName := thefile;
if Length(ParamStr(2)) <> 0 then
begin
if UpString(ParamStr(2)) = 'V' then VerifyOnly := true;
end;
if Length(ParamStr(3)) <> 0 then
begin
if UpString(ParamStr(3)) = 'V' then VerifyOnly := true;
end;
if Length(ParamStr(2)) <> 0 then
begin
if (ParamStr(2)) = 'FallBack' then Fallback := true;
end;
if Length(ParamStr(3)) <> 0 then
begin
if (ParamStr(3)) = 'FallBack' then Fallback := true;
end;
if not OpenForRead(CFile,FileName) then
begin
writeln('Can''t open configuration file');
halt(2);
end;
end;
procedure IdentifyEEPROM;
var
eepromid : byte;
begin
SetCSHigh;
eepromid:= ReadID25;
if (eepromid <> OneMegID) and (eepromid <> TwoMegID) and
(eepromid <> FourMegID) and (eepromid <> EightMegID) and
(eepromid <> SixteenMegID) then
begin
write('Bad EEPROM ID, expected ');
HexPrint(FourMegID,2);
write(' or ');
HexPrint(EightMegID,2);
write(' or ');
HexPrint(SixteenMegID,2);
write(' but got ');
HexPrint(eepromid,2);
writeln;
halt(2);
end;
if eepromid = FourMegID then
begin
writeln('4M Bit EEPROM Found');
NormalSA := $40000;
end;
if eepromid = EightMegID then
begin
writeln('8M Bit EEPROM Found');
NormalSA := $80000;
end;
if eepromid = SixteenMegID then
begin
writeln('16M Bit EEPROM Found');
NormalSA := $100000;
end;
NSAMSB := (NormalSA shr 16);
end;
procedure MakeBootBlock;
var index : word;
begin
for index := 0 to BBSize -1 do BootBlock[index] := CBootBlock[index];
BootBlock[NSAMSBOffset] := NSAMSB; { insert top address byte to match EEPROM size }
end;
procedure StartProgramming(sa: longint);
var
sectorsize,esectors,sector,secadd,esspace : longint;
begin
SetCSHigh;
sectorsize := 65536;
esspace := (NormalSA div sectorsize);
if sa = FallBackSA then esspace := esspace - 1;
writeln('About to erase EEPROM sectors => ');
esectors := (CFilesize-1) div sectorsize;
if esectors > esspace then BarfOut('File Size too large to fit');
secadd := sa;
for sector := 0 to esectors do
begin
EraseSector25(secadd);
secadd := secadd + sectorsize;
write('Sector ',sector+(sa div sectorsize),' erased ',chr(13));
end;
writeln;
if sa = FallBackSA then
writeln('Fallback area of EEPROM erased')
else
writeln('Configuration area of EEPROM erased');
SetCSHigh;
end;
procedure DoneProgramming;
begin
SetCSHigh;
end;
procedure VerifyIt;
var
index,bindex : longint;
bytesread : word;
rdata : byte;
begin
if OpenForRead(CFile,FileName) then
begin
IdentifyEEPROM;
reset(CFile,1);
CFileSize := FileSize(CFile);
PrintBitFileHeader;
if Fallback then index := FallbackSA else index := NormalSA;
while not EOF(CFile) do
begin
bytesread := 0;
blockread(CFile,BBuf,FileBufferSize,bytesread);
bindex := 0;
while bindex < bytesread do
begin
rdata := ReadByte25(bindex+index);
if BBuf[bindex] <> rdata then
begin
write('Error at ');
HexPrint(index+bindex,8);
write(' expected: ');
Hexprint(BBuf[bindex],2);
write(' but read: ');
HexPrint(rdata,2);
writeln;
dump(bindex+index);
halt(2);
end;
bindex := bindex + 1;
end;
index := index + FileBufferSize;
write('V ');
end;
end
else
begin
writeln('Can''t open configuration file');
halt(2);
end;
end;
procedure WriteBoot;
var index : word;
begin
writeln('Erasing sector 0 for boot block');
EraseSector25(BootSA);
for index := 0 to BBSize -1 do BBuf[index] := BootBlock[index];
for index := BBsize to PageSize-1 do BBuf[index] := 0;
WriteBlock(0,0);
writeln('BootBlock installed');
end;
function CheckBoot : boolean;
var
index : longint;
bootok: boolean;
begin
bootok := true;
for index := 0 to BBSize -1 do
begin
if ReadByte25(index) <> BootBlock[index] then bootok := false;
end;
CheckBoot := bootok;
end;
procedure WriteIt;
var
cbyte : byte;
bytesread,index : word;
bytecount : longint;
eepromadd : longint;
begin
if OpenForRead(CFile,FileName) then
begin
IdentifyEEPROM;
MakeBootBlock;
if not CheckBoot then WriteBoot else writeln('BootSector OK');
if not CheckBoot then BarfOut('Failed to write valid boot sector');
reset(CFile,1);
CFileSize := FileSize(CFile);
PrintBitfileHeader;
if Fallback then
begin
StartAddress := FallbackSA;
writeln('Writing fallback configuration');
end
else
begin
StartAddress := NormalSA;
writeln('Writing user configuration');
end;
StartProgramming(StartAddress);
writeln(':');
eepromadd:= StartAddress;
while not EOF(CFile) do
begin
bytesread := 0;
blockread(CFile,BBuf,FileBufferSize,bytesread);
index := 0;
write('W ');
while index < bytesread do
begin
WriteBlock(eepromadd,index);
index := index + PageSize;
eepromadd := eepromadd + Pagesize;
end;
end;
end
else
begin
writeln('Can''t open configuration file');
halt(2);
end;
writeln;
DoneProgramming;
end;
begin
GetParms;
GetOurEnv;
if not InitializeInterface(message) then bumout(message);
if VerifyOnly then VerifyIt else WriteIt;
writeln('Done');
CloseInterface;
halt(0);
end.