HCS12x Linker Command Automatic Checksum Generation

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

HCS12x Linker Command Automatic Checksum Generation

Jump to solution
555 Views
zegeyealemu
Contributor III

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

Labels (1)
1 Solution
430 Views
RadekS
NXP Employee
NXP Employee

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!
-----------------------------------------------------------------------------------------------------------------------

View solution in original post

0 Kudos
1 Reply
431 Views
RadekS
NXP Employee
NXP Employee

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!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos