I'm trying to say that linker doesn't read your device to calculate checksums. Linker calculates checksum based on the knowledge of what it is putting into binary file. On device what you see say at nonbanked 0xC000-0xFEFF reads equally the same like what is read from banked addresses 0x3F8000-0x3FBEFF. But linker is not aware about this. It doesn't know that what you allocate to 0xC000 is readable from 0x3F8000! You say to checksum 0x3F8000 and linker ignores what is allocated to 0xC000. So your approach certainly won't work. I just verified it. The same code first checksums 0xC000-0xFeFF, then checksums 0x3F8000-0x3FBeFF. Checksums are the same and match linker calculated checksum, but only in case linker calculates checksum of nonbanked code at 0xC000.
- My checksum definition is not concerned about what segments, banked, unbanked etc are used or defined.
And this is your problem.
Another problem is related to area fill byte. For example vectors area is not included ROM_C000 FILL 0x3F segment, so it is not filled with 0x3F. You should try first to not fill areas and use UNDEFINED 0xFF, which matches erased flash state. Also you should take into account flash security byte. In case your code doesn't define its value, you should skip byte at 0xFF0F from checksum computation.
- I believe that it should blindly calculate the checksum on the defined regions of flash, as defined, providing those
You believe wrong. Support for those linker checksums aware of nonbanked-banked memory shortcuts could be added to the linker, but I fear that it would make linker much less device independant, which is not good, IMO.
- It should also assume that the user has properly filled unused flash bytes to a known value.
This works. But it seems that linker fills only areas, where at least one byte is placed to. Empty unused areas seem to be not filled with byte you specify. This is not hard to workaround, allocating some dummy byte to each area you are going to checksum.
- I have also assumed that the calculation order will be in the order the regions have been defined.
I think this is true
- Unfortunately the documentation is not clear on some of this stuff leaving things very open ended and difficult to get a consistent result.
Yes, I also spent too much time finding init and poly values for CRC32. INIT is 0xffffffff and POLY is 0x04C11DB7.
You may find checksum.c and checksum.h in lib\include and lib\src folders of your CW installation. There's tiny topic in the help files how to use these sources. What I found that to calculate checksums of far data areas, you should either edit checksum.* or use large memory model. I guess you don't want to use large memory model. So these steps are recommended
1) add -CpPPAGE=0x30 option to compiler command line string
2) add checksum.* to your project.
3) Add
#undef LIBDEF_FAR_VOID_PTR
#define LIBDEF_FAR_VOID_PTR 1
lines at the top of your copy of checksum.h
4) in the source code
#include <checksum.h> // because of step 3, this include should be last include
// , else you may get some message about redefinitions
// list of memory sections to check
const struct __ChecksumArea areas[] =
{
// start of area, size of area
{(const void * __far)(0xc000), 0x4000-0x100} ,
{(const void * __far)(0x3f8000), 0x4000-0x100} ,
};
unsigned long crc;
{
crc = _Checksum_CheckAreasCRC32(areas,
sizeof(areas)/sizeof(struct __ChecksumArea) ,
/*poly*/0x04C11DB7 , /*init*/0xFFFFFFFF );
}