8.2.4.1.3 Fletcher Algorithms
Hexmate has several algorithms that implement Fletcher’s checksum. These algorithms are more complex, providing a robustness approaching that of a cyclic redundancy check, but with less computational effort. There are two forms of this algorithm which correspond to the selector values 7 and 8 in the algorithm suboption and which implement a 1-byte calculation and 2-byte result, with a 2-byte calculation and 4-byte result, respectively. Hexmate will automatically store the checksum in the HEX file at the address specified in the checksum option.
The function shown below performs a 1-byte-wide addition and produces a 2-byte result.
#include <stdint.h>
typedef uint16_t result_t; // size of fletcher result
result_t
fletcher8(const unsigned char * data, unsigned int n )
{
result_t sum = 0xff, sumB = 0xff;
unsigned char tlen;
while (n) {
tlen = n > 20 ? 20 : n;
n -= tlen;
do {
sumB += sum += *data++;
} while (--tlen);
sum = (sum & 0xff) + (sum >> 8);
sumB = (sumB & 0xff) + (sumB >> 8);
}
sum = (sum & 0xff) + (sum >> 8);
sumB = (sumB & 0xff) + (sumB >> 8);
return sumB << 8 | sum;
}
Here is how this function might be used when, for example, a 2-byte-wide Fletcher hash is to be calculated over the address range 0x100 to 0x7fb, starting with an offset of 0x20. The checksum is to be stored at 0x7fc thru 0x7ff in little endian format.
=
in the
Checksum field in the Additional
options Option category in the XC8
Linker category. Note that the width cannot be controlled with the
width
suboption, but the sign of this suboption's argument is used
to indicate the required endianism of the
result.-mchecksum=100-7fb@7fc,offset=20,algorithm=8,width=-4
w
suboption, but the sign of this
suboption's argument is used to indicate the required endianism of the
result.-ck=100-7bd@7fc+20g8w-4
This code can be called in a manner similar to that shown for the addition algorithms (see 8.2.4.1.1 Addition Algorithms).
The code for the 2-byte-addition Fletcher algorithm, producing a 4-byte result is shown below.
#include <stdint.h>
typedef uint32_t result_t; // size of fletcher result
result_t
fletcher16(const unsigned int * data, unsigned n)
{
result_t sum = 0xffff, sumB = 0xffff;
unsigned tlen;
while (n) {
tlen = n > 359 ? 359 : n;
n -= tlen;
do {
sumB += sum += *data++;
} while (--tlen);
sum = (sum & 0xffff) + (sum >> 16);
sumB = (sumB & 0xffff) + (sumB >> 16);
}
sum = (sum & 0xffff) + (sum >> 16);
sumB = (sumB & 0xffff) + (sumB >> 16);
return sumB << 16 | sum;
}