Hi All,
I was using the Automatic Checksum Generation and realized that there could be a bug with this functionality.
My objective was to generate a checksum, CCITT method, for the whole program flash memory.
Interestingly, it seems that the linker is not generating the correcting checksum value for a section of memory if the addressing scheme is other than Local addressing.
So long as the range of memory the checksum is calculated is the same why is the calculation differing.
Please find below part of the linker command file entries with different addressing modes for the same block of memory.
The same block of memory is used as an input and the results differ.
The following two entries generated different checksum values:
---------------------------------------------------------------------------
// The local addressing generates a correct checksum value - THIS CALCULATES CORRECT VALUE
CHECKSUM
CHECKSUM_ENTRY
METHOD_CRC_CCITT
OF READ_ONLY 0xC000 TO 0xFEF7
INTO READ_ONLY 0xFEFC SIZE 2
UNDEFINED 0xff
END
END
---------------------------------------------------------------------------
The following Global Addressing generates a different checksum value that is identical to a Local addressing input address.
// Input - Global Addressing - THIS DOES NOT GENEATE CORRECT VALUE
CHECKSUM
CHECKSUM_ENTRY
METHOD_CRC_CCITT
OF READ_ONLY 0x7FC000'G TO 0x7FFEF7'G
INTO READ_ONLY 0xFEFC SIZE 2
UNDEFINED 0xff
END
END
// Input - Logical Addressing - THIS DOES NOT GENERATE CORRECT VALUE
CHECKSUM
CHECKSUM_ENTRY
METHOD_CRC_CCITT
OF READ_ONLY 0xFF8000 TO 0xFFBEF7
INTO READ_ONLY 0xFEFC SIZE 2
UNDEFINED 0xff
END
END
---------------------------------------------------------------------------
Thank you in advance for your help.
Best regards,
Ziggy
Solved! Go to Solution.
Hi Zegeye,
The described generating method works fine on my side.
However you have to take into account that linker do not know anything about page mirroring inside MCU.
So, if you place data at address 0xC000, the linker do not know that the same data will be also at address 0xFF8000.
So, the first range works fine because page FF is defined as
ROM_C000 = READ_ONLY DATA_NEAR IBCC_NEAR 0xC000 TO 0xFEFF;
The paged address range 0xFF8000 TO 0xFFBFFF is not defined in linker file (is commented out). The linker do not place any data into this area and linker will calculate “correct” checksum as it is empty space (all bytes 0xFF).
The same is valid for range 0x7FC000'G TO 0x7FFEF7'G. The linker calculates checksum from fully erased area because you/linker didn’t place any data into this range.
In fact, It has no sense define page FF as anything else than 0xC000~0xFFFF.
I tested this principle on page FD (0x4000~0x7FFF, 0xFD8000~0xFDBFFF, 0x7F4000'G~0x7F7FFF'G)
For example: I defined PAGE_FD segments in prm file as
SEGMENTS
PAGE_FD = READ_ONLY DATA_FAR IBCC_FAR 0x7F4000'G TO 0x7F7FFF'G;
END
I created my user segment and place it into this page:
PLACEMENT
MY_DATA DISTRIBUTE_INTO PAGE_FD;
END
I placed data into this area in main code:
#pragma CONST_SEG MY_DATA
const unsigned char flash_array[] = {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBD};
#pragma CONST_SEG DEFAULT
With that, the linker calculated correct checksum value:
CHECKSUM
CHECKSUM_ENTRY
METHOD_CRC_CCITT
OF READ_ONLY 0x7F4000'G TO 0x7F7EF7'G
INTO READ_ONLY 0xFEFC SIZE 2
UNDEFINED 0xff
END
END
When I place this array at address 0x4000 (const unsigned char flash_array[] @0x4000) and calculate checksum at 0x4000 TO 0x7EF7, I will get the same checksum value.
The same is valid also for paged addresses (const unsigned char flash_array[] @0xFD8000, 0xFD8000 TO 0xFDBEF7).
So, the checksum calculation works fine, but you have to manage that mirrored address spaces will be defined only one way and checksum will be defined at appropriate address ranges.
I hope it helps you.
Have a great day,
Radek
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Zegeye,
The described generating method works fine on my side.
However you have to take into account that linker do not know anything about page mirroring inside MCU.
So, if you place data at address 0xC000, the linker do not know that the same data will be also at address 0xFF8000.
So, the first range works fine because page FF is defined as
ROM_C000 = READ_ONLY DATA_NEAR IBCC_NEAR 0xC000 TO 0xFEFF;
The paged address range 0xFF8000 TO 0xFFBFFF is not defined in linker file (is commented out). The linker do not place any data into this area and linker will calculate “correct” checksum as it is empty space (all bytes 0xFF).
The same is valid for range 0x7FC000'G TO 0x7FFEF7'G. The linker calculates checksum from fully erased area because you/linker didn’t place any data into this range.
In fact, It has no sense define page FF as anything else than 0xC000~0xFFFF.
I tested this principle on page FD (0x4000~0x7FFF, 0xFD8000~0xFDBFFF, 0x7F4000'G~0x7F7FFF'G)
For example: I defined PAGE_FD segments in prm file as
SEGMENTS
PAGE_FD = READ_ONLY DATA_FAR IBCC_FAR 0x7F4000'G TO 0x7F7FFF'G;
END
I created my user segment and place it into this page:
PLACEMENT
MY_DATA DISTRIBUTE_INTO PAGE_FD;
END
I placed data into this area in main code:
#pragma CONST_SEG MY_DATA
const unsigned char flash_array[] = {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBD};
#pragma CONST_SEG DEFAULT
With that, the linker calculated correct checksum value:
CHECKSUM
CHECKSUM_ENTRY
METHOD_CRC_CCITT
OF READ_ONLY 0x7F4000'G TO 0x7F7EF7'G
INTO READ_ONLY 0xFEFC SIZE 2
UNDEFINED 0xff
END
END
When I place this array at address 0x4000 (const unsigned char flash_array[] @0x4000) and calculate checksum at 0x4000 TO 0x7EF7, I will get the same checksum value.
The same is valid also for paged addresses (const unsigned char flash_array[] @0xFD8000, 0xFD8000 TO 0xFDBEF7).
So, the checksum calculation works fine, but you have to manage that mirrored address spaces will be defined only one way and checksum will be defined at appropriate address ranges.
I hope it helps you.
Have a great day,
Radek
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------