This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430FR2476: Trying to use linker-generated CRC tables with CRC Module

Part Number: MSP430FR2476
Other Parts Discussed in Thread: MSP430F2132

Hello,
I was able to validate the TLV CRC on the MSP430FR2476 using its CRC module.  Here is a link to the code when I had a question about it earlier:
https://e2e.ti.com/support/microcontrollers/msp430/f/msp-low-power-microcontroller-forum/972585/ccs-msp430fr2476-another-tlv-structure-checksum

Now I'm trying to generate CRC tables with the linker and use the CRC module to verify them.  The code was originally for an MSP430F2132 without a CRC module so it used a C function to check the linker CRC.  I'm hoping I can use the CRC module instead like I did for the TLV.  Unfortunately, the CRC results from the linker and the module don't match.

Here are the pertinent parts of the linker:

...
    GROUP(ALL_FRAM)
    {
        GROUP(READ_WRITE_MEMORY)
        {
            .TI.persistent : {}              /* For #pragma persistent            */
            .cio           : {}              /* C I/O Buffer                      */
            .sysmem        : {}              /* Dynamic memory allocation area    */
        } PALIGN(0x0400), RUN_START(fram_rw_start) RUN_END(fram_rx_start)

        GROUP(READ_ONLY_MEMORY)
        {
            .cinit      : {}                   /* Initialization tables             */
            .pinit      : {}                   /* C++ constructor tables            */
            .binit      : {}                   /* Boot-time Initialization tables   */
            .init_array : {}                   /* C++ constructor tables            */
            .mspabi.exidx : {}                 /* C++ constructor tables            */
            .mspabi.extab : {}                 /* C++ constructor tables            */
            .const      : {}, crc_table(linkerCrcTable, algorithm=CRC16_802_15_4) /* Constant data */
        }

        GROUP(EXECUTABLE_MEMORY)
        {
            .text       : {}, crc_table(linkerCrcTable, algorithm=CRC16_802_15_4) /* Code */
            .text:_isr  : {}                   /* Code ISRs                         */
        }
    } > FRAM_APPL
    
...

    UNMI         : { * ( .int44 ) } > INT44 type = VECT_INIT
    SYSNMI       : { * ( .int45 ) } > INT45 type = VECT_INIT
    .reset       : {}               > RESET  /* MSP430 reset vector         */

    // CRC Table.  Don't put this in FRAM2, it will get warnings
    // because the memory addresses there are over 16 bits.
    .TI.crctab   : > FRAM_APPL
...

Here is the CRC code:

...
#define BYTES_PER_WORD  2       /**< Number of bytes in a word. */

// CRC16-CCITT parameters
#define CRC_INIT 0xFFFF

extern CRC_TABLE linkerCrcTable;        /**< Provides access to linker-generated CRC table. */
...

static bool POST_CRC_Code(void) {
  volatile CRC_TABLE  * linkerTable = &linkerCrcTable;
  volatile CRC_RECORD   codeCRCRecord;
  volatile uint16_t     crcResult   = 0x0000;
  uint8_t   loopCtrl1   = 0;
  uint16_t  loopCtrl2   = 0;
  uint16_t  numRecords  = linkerTable->num_recs;
  bool      retVal      = true;

  // Process each record of linker CRC table
  for (loopCtrl1 = 0; loopCtrl1 < numRecords; loopCtrl1++) {
    // Get the current CRC table record
    codeCRCRecord = linkerTable->recs[loopCtrl1];

    // Calculate the CRC
    // (example at https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/803317)
    CRC_setSeed(CRC_BASE, CRC_INIT);

    for ( loopCtrl2 = codeCRCRecord.addr;
          loopCtrl2 < codeCRCRecord.addr + codeCRCRecord.size;
          loopCtrl2 += BYTES_PER_WORD)
    {
        CRC_set16BitDataReversed(CRC_BASE, *(uint16_t*) loopCtrl2);
    };

    // Check if calculated CRC value matches linker record
    crcResult = CRC_getResult(CRC_BASE);
    if (crcResult != codeCRCRecord.crc_value) {
      // CRC check failed, return false and break
      retVal = false;
      break;
    }
  }


  #if 1 == POST_forceCrcPass
  // Debug flag set so force return to true
  retVal = true;
  #endif

  return retVal;
}

Using the debugger, it looks like the first loop of POST_CRC_Code is checking the following memory right before main:

GPIO_PORT_TO_BASE
0000	0200	0200	0220	0220	0240	0240	0260
0260	0280	0280	FFFF	FFFF	0320
$P$T0$1
0000	0000	0000	0000	0000	0000	0000	0000
$P$T0$1
0000	0000	0000	0000	0000	0000	0000
$P$T0$1
0000	0000	0000	0000	0000

When it compares crcResult to codeCRCRecord.crc_value, it fails with crcResult = 64786 (0xFD12) and crc_value = 53469 (0xD0DD).

I'm using the same seed that I used for the TLV and the same CRC function, CRC_set16BitDataReversed.  I tried using the regular CRC_set16BitData but that also failed.

If anyone can see any issues right away please let me know.  Otherwise I'd appreciate any debugging advice...

Thanks!

**Attention** This is a public forum