Search code examples
crc32mpeg-2srecord

Extending SRecord to handle crc32_mpeg2?


statement of problem:

I'm working with a Kinetis L series (ARM Cortex M0+) that has a dedicated CRC hardware module. Through trial and error and using this excellent online CRC calculator, I determined that the CRC hardware is configured to compute CRC32_MPEG2.

I'd like to use srec_input (a part of SRecord 1.64) to generate a CRC for a .srec file whose results must match the CRC_MPEG2 computed by the hardware. However, srec's built-in CRC algos (CRC32 and STM32) don't generate the same results as the CRC_MPEG2.

the question:

Is there a straightforward way to extend srec to handle CRC32_MPEG2? My current thought is to fork the srec source tree and extend it, but it seems likely that someone's already been down this path.

Alternatively, is there a way for srec to call an external program? (I didn't see one after a quick scan.) That might do the trick as well.

some details

The parameters of the hardware CRC32 algorithm are:

  • Input Reflected: No
  • Output Reflected: No
  • Polynomial: 0x4C11DB7
  • Initial Seed: 0xFFFFFFFF
  • Final XOR: 0x0

To test it, an input string of:

0x10 0xB5 0x06 0x4C 0x23 0x78 0x00 0x2B 
0x07 0xD1 0x05 0x4B 0x00 0x2B 0x02 0xD0

should result in a CRC32 value of:

0x938F979A

what generated the CRC value in the first place?

In response to Mark Adler's well-posed question, the firmware uses the Freescale fsl_crc library to compute the CRC. The relevant code and parameters (mildly edited) follows:

void crc32_update(crc32_data_t *crc32Config, const uint8_t *src, uint32_t lengthInBytes)
{
    crc_config_t crcUserConfigPtr;
    CRC_GetDefaultConfig(&crcUserConfigPtr);
    crcUserConfigPtr.crcBits = kCrcBits32;
    crcUserConfigPtr.seed = 0xffffffff;
    crcUserConfigPtr.polynomial = 0x04c11db7U;
    crcUserConfigPtr.complementChecksum = false;
    crcUserConfigPtr.reflectIn = false;
    crcUserConfigPtr.reflectOut = false;

    CRC_Init(g_crcBase[0], &crcUserConfigPtr);
    CRC_WriteData(g_crcBase[0], src, lengthInBytes);
    crcUserConfigPtr.seed = CRC_Get32bitResult(g_crcBase[0]);

    crc32Config->currentCrc = crcUserConfigPtr.seed;
    crc32Config->byteCountCrc += lengthInBytes;
}

Solution

  • Peter Miller be praised...

    It turns out that if you supply enough filters to srec_cat, you can make it do anything! :) In fact, the following arguments the correct checksum:

    $ srec_cat test.srec -Bit_Reverse -CRC32LE 0x1000 -Bit_Reverse -XOR 0xff -crop 0x1000 0x1004 -Output -HEX_DUMP
    00001000: 93 8F 97 9A                                      #....
    

    In other words, bit reverse the bits going to the CRC32 algorithm, bit reverse them on the way out, and 1's compliment them.