Checksum & Eprom Programmers

 

 

https://sourceforge.net/projects/srecord/files/srecord/1.63/ The SRecord package is a collection of powerful tools for manipulating
EPROM load files

 

chksumwin32.zip courtesy Gonzalo Fernandez Val from Spain - works on WIn32 and Win64

the dll´s, hdpmi32.exe and dpmild32.exe in chksum.zip are from https://www.japheth.de/HX.html
these files are a DOS extender that allows console win32 app to run under DOS, hence chksum.exe can run under DOS up to
Windows 10 (and Windows 11?) If we want to run under Windows (Windows 98 up to Windows 11) a binary can be build using

gcc -O2 chksum.c -o chksum.exe
strip chksum.exe

/*

chksum.c

(c) 2012 - Version 1.0

chksum - Programa que calcula el valor Checksum, Checksum 32, CRC-CCITT,
CRC-16, CRC-32 y Fluke signature (usado en el Fluke 9010a) de un fichero
dado como argumento al programa.

Para compilarlo por l¡nea de comandos:


bcc -1- -G -O2 -c -mt -v- chksum.c
tlink /Tdc lib\c0t chksum, chksum,, lib\cs

Genera un fichero COM, optimizado para m xima rapidez, y sin informaci¢n
de depuraci¢n compatible con el procesador 8088 y superiores.


bcc -1- -G -O2 -c -ms -v- chksum.c
tlink /Tde lib\c0s chksum, chksum,, lib\cs

Genera un fichero EXE, optimizado para m xima rapidez, y sin informaci¢n
de depuraci¢n compatible con el procesador 8088 y superiores.


d:\msys32new>new-vars
d:\msys32new>gcc -O2 chksum.c -o chksum.exe
d:\msys32new>strip chksum.exe
d:\msys32new>copy chksum.exe c:\hxbeta\bin
c:\hxbeta\bin>pestub chksum.exe (ahora chksum.exe necesita dkrnl32.dll,
msvcrt.dll, dpmild32.exe y hdpmi32.exe
para su funcionamiento)

Genera un fichero EXE, optimizado para m xima rapidez, sin informaci¢n
de depuraci¢n y compatible con DOS, Windows 98, Windows XP, Windows 7 y
Windows 10

Para compilarlo desde el entorno integrado:

Abrimos un proyecto, seleccionando las opciones de optimizaci¢n y de
depuraci¢n que nos interesen, generando un fichero tipo EXE.
Despu‚s, en la l¡nea de comandos del DOS:

exe2bin chksum.exe chksum.com

*/

#include <stdio.h>
#include <stdlib.h>

#define CRCCCITT 0x1021 /* polinomio CCITT */
#define CRCCCITT_REV 0x8408 /* polinomio CCITT inverso */
#define CRC16 0x8005 /* polinomio CRC16 */
#define CRC16_REV 0xA001 /* polinomio CRC16 inverso */

#define crcupdate(d, a, t) *(a) = (*(a) << 8) ^ (t)[(*(a) >> 8) ^ (d)]
#define crcrevupdate(d, a, t) *(a) = (*(a) >> 8) ^ (t)[(*(a) ^ (d)) \
& 0x00FF]
unsigned long crc_table[256];

unsigned short crchware(unsigned short data, unsigned short genpoly,
unsigned short accum)
{
int i;

data <<= 8; /* datos al byte alto */
for (i = 8; i > 0; i--)
{
if ((data ^ accum) & 0x8000)
/* si b+s de (data XOR accum) es TRUE */
accum = (accum << 1) ^ genpoly;
/* desplaza y resta polinomio */
else
accum <<= 1; /* si no, desplazamiento transparente */
data <<= 1; /* sube bit siguiente para XOR */
}
return accum;
}


unsigned short crcrevhware(unsigned short data, unsigned short genpoly,
unsigned short accum)
{
int i;

for (i = 8; i > 0; i--)
{
if ((data ^ accum) & 0x0001)/* si b-s de (data XOR accum) TRUE */
accum = (accum >> 1) ^ genpoly; /* desplaza y resta */
else
accum >>= 1; /* si no, desplazamiento transparente */
data >>= 1; /* baja bit siguiente para XOR */
}
return accum;
}


unsigned short * mk_crctbl(unsigned short poly,
unsigned short (* crcfn) (unsigned short,
unsigned short,
unsigned short))
/* el segundo par metro es un puntero a funci¢n CRC */
{
unsigned short * crctp; /* puntero a la tabla */
int i;

if ((crctp = (unsigned short *) malloc(256 * sizeof(unsigned short))) ==
NULL)
return NULL;
for (i = 0; i < 256; i++) /* rellena la tabla con CRC de valores... */
crctp[i] = (*crcfn) (i, poly, 0); /* ... 0 - 255 */
return crctp; /* devuelve un puntero a la tabla */
}


void gen_table(void) /* build the crc table */
{
unsigned long crc, poly;
int i, j;

poly = 0xEDB88320L;
for (i = 0; i < 256; i++)
{
crc = i;
for (j = 8; j > 0; j--)
{
if (crc & 1)
crc = (crc >> 1) ^ poly;
else
crc >>= 1;
}
crc_table[i] = crc;
}
}


unsigned short int ShiftBits(unsigned long sig)
{
return ((sig >> 6) ^ (sig >> 8) ^ (sig >> 11) ^ (sig >> 15));
}

int main(int argc, char *argv[])
{
FILE * handle;
unsigned short * tablep;
unsigned short * tablep2;
int c;
int i, b, tmp, p, n, bits;
int crcData[16];
int pointers[5];
unsigned short chksum = 0;
unsigned long chksum32 = 0;
unsigned short crcccitt = 0;
unsigned short crc16 = 0;
unsigned long crc32 = 0xFFFFFFFF;
unsigned long flukesig = 0;


if (argc < 2)
exit(puts("\nUsage:\nchksum filename.ext"));
if ((handle = fopen(argv[1], "rb")) == NULL)
exit(printf("\nCannot open input file %s\n", argv[1]));
if ((tablep2 = mk_crctbl(CRCCCITT, crchware)) == NULL)
exit(puts("\nNot enough memory for CRC-CCITT table."));
if ((tablep = mk_crctbl(CRC16_REV, crcrevhware)) == NULL)
exit(puts("\nNot enough memory for CRC-16 table."));

gen_table(); /* Used in CRC-32 calculation */

for (i = 0; i < 16; i++) /* Used */
crcData[i] = 0; /* in */
pointers[0] = 6; /* calculation */
pointers[1] = 8; /* of */
pointers[2] = 11; /* Fluke */
pointers[3] = 15; /* signature */
pointers[4] = 0;

while ((c = fgetc(handle)) != EOF)
{
tmp = c;

chksum += c; /* Calculates Checksum */

chksum32 += c; /* Calculates Checksum 32 */

crcupdate(c, &crcccitt, tablep2);/* Used in CRC-CCITT calculation */

crcrevupdate(c, &crc16, tablep); /* Used in CRC-16 calculation */

crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ c) & 0xFF];
/* Used in CRC-32 calculation */

for (i = 0; i < 5; i++) /* Used */
{
p = pointers[i]; /* in */
if (i < 4)
tmp = tmp ^ crcData[p]; /* calculation */
else
crcData[p] = tmp; /* of */
--p;
if (p < 0) /* Fluke */
p = 15;
pointers[i] = p; /* signature */
}
}

crc32 ^= 0xFFFFFFFF; /* Used in CRC-32 calculation */

for (n = 0; n < 16; n++) /* Used */
{
tmp = crcData[n]; /* in */
for (i = 0; i < 8; ++i)
{ /* calculation */
bits = tmp ^ (ShiftBits(flukesig));
flukesig <<= 1; /* of */
flukesig |= (bits & 0x01);
tmp >>= 1; /* Fluke signature */
}
}
flukesig &= 0xFFFF; /* Used in calculation of Fluke signature */

printf("\nChecksum = %04X\n", chksum);
printf("Checksum 32 = %08lX\n", chksum32);
printf("CRC - CCITT = %04X\n", crcccitt);
printf("CRC - 16 = %04X\n", crc16);
printf("CRC - 32 = %08lX\n", crc32);
printf("Fluke signature = %04X\n", flukesig);
free(tablep2);
free(tablep);
fclose(handle);
return 0;
}

/*

 

 

 

 

it is a simple
addition of the bytes in a 16 Bit Variable (or 32 Bit in the case of
conitec, dataio chiplab, advantech labtool-48). That's no CRC at all.. it is a checksum only.

~/src/checksum $ ./ctest 2716.bin
File 2716.bin: 2048 Bytes!
Memory allocated
file read
cksum=23054 5A0E

 

The simple C program, it's more filesystem operations then actual
work...
-----------------------------------------------------------------

#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include <malloc_np.h>
#include <sys/stat.h>


int main(int argc,char* argv[])
{

uint8_t ebyte;
int epaddr;
uint16_t cksum;
uint8_t * bufp;
struct stat infstat;
int fno;

FILE * fp;

if(argc < 2)
{
fprintf(stderr,"Error Filename required!\n");
fprintf(stderr,"usage: %s <infile>\n", argv[0]);
exit (-1);
}


if((fp=fopen(argv[1],"r"))==NULL)
{
fprintf(stderr,"Error, can't open infile!\n");
fprintf(stderr,"usage: %s <infile>\n", argv[0]);
exit (-1);
}
fno=fileno(fp);

if(fstat(fno,&infstat)!=0)
{
fprintf(stderr,"fstat on %s failed!\n", argv[1]);
fclose(fp);
exit (-1);
}

printf("File %s: %ld Bytes!\n",argv[1],infstat.st_size);


if((bufp=(uint8_t *)calloc((size_t)infstat.st_size,sizeof(char)))==NULL)
{
fprintf(stderr,"Error, can't allocate %ld memory!\n",infstat.st_size);
fclose(fp);
exit (-1);
}
printf("Memory allocated\n");

if(fread(bufp,sizeof(uint8_t),infstat.st_size,fp)!=infstat.st_size)
{
fprintf(stderr,"Error, can't read from file %s!\n",argv[1]);
fclose(fp);
exit (-1);
}
printf("file read\n");


for(epaddr=0; epaddr<infstat.st_size;epaddr++)
{
cksum+=*bufp++;
}
printf("cksum=%d %04X\n",cksum,cksum);

fclose(fp);
free(bufp);

return 0;
}

 


In the unlikely event you need a simple CRC for something else, I have seen this used. It's taken from a Chinese user manual for a barcode scanner. I needed to implement this crc on my end to match theirs. It takes a pointer to a buffer and the number of bytes to process.

 

/*
.------------------------------------------------------------------------------
| uint16_t crc_cal_by_bit(uint8_t *ptr, uint16_t len);
`------------------------------------------------------------------------------
*/
uint16_t crc_cal_by_bit(uint8_t *ptr, uint16_t len)
{
uint32_t crc;
uint8_t i;
uint8_t dat;

crc = 0;
while(len-- != 0)
{
dat = *ptr;

for(i=0x80; i!=0; i>>=1)
{
crc <<= 1;
if((crc & 0x10000) != 0) // Last CRC * 2 ,if the first one is 1,so divide 0x11021
crc ^= 0x11021;
if((dat & i) != 0) // If the standard is 1,so CRC = last CRC + standard CRC_CCITT
crc ^= 0x1021;
}

ptr++;
}

return (uint16_t)crc;
}

 

 


The only checksum algorithm I've ever found specific to EPROMs is the "Kontron CRC". most of them use an additive checksum, which is almost worthless really. The Kontron CRC was used in the prestigious Kontron line of programmers.

For that alogorithm, you will need to find Appendix "E.2 KONTRON CRC CHECKSUM ALGORITHM" of the MPP-80S/EPP-80/GPP-80. I have several of the PDFs, but none of them have that appendix. I do have notes from when I taught this back in the late 1980's and early 1990's though.

Kontron_MPP-80_EPP-80_programmer_resources.htm

 

 

 

If you look forward for other information about this topic, do not hesitate to contact me by e-mail at: matthieu.benoit@free.fr .
Important Notice: Also if you have any data about this topic, do not hesitate to contribute to this page.

Si vous recherchez des informations pour ce sujet, vous pouvez me contacter par e-mail : matthieu.benoit@free.fr . De même si vous avez des informations sur ce sujet, n'hésitez pas à contribuer à cette page.

Retour au sommaire

Retour à la Page d'accueil

M-à-j: 9 novembre, 2025 .

matthieu.benoit@free.fr