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!