2

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;
}
fearless_fool
  • 33,645
  • 23
  • 135
  • 217
  • Are you sure? The ARM V8 Architecture Reference Manual says that the CRCs are reflected. By the way, there are two different families of CRC instructions on the ARM, where the other CRC uses the polynomial `0x1edc6f41`. – Mark Adler Oct 18 '17 at 05:04
  • @MarkAdler: I agree to what the ARM manual says. But the parameters are based on results I got at the http://www.sunshine2k.de/coding/javascript/crc/crc_js.html site. Let me know if I mis-interpreted anything. – fearless_fool Oct 18 '17 at 11:21
  • Yes, those bytes produce that MPEG2 CRC. But how did you verify that those bytes produce that CRC using the ARM processor CRC instruction? Which instruction? – Mark Adler Oct 18 '17 at 13:39
  • @MarkAdler: Added relevant CRC computation code (see above). I can also furnish `CRC_Init()` and `CRC_WriteData()` if needed (but it's pretty thin). – fearless_fool Oct 18 '17 at 14:59
  • Looks like you are using some sort of CRC "peripheral" that is configurable to any CRC, as opposed to the ARM V8 instructions which are rigged for two particular CRCs. – Mark Adler Oct 18 '17 at 17:45
  • @MarkAdler: You are correct: I'm using the CRC hardware in a Kinetis L series (ARM Cortex M0+). I should have made that clear from the start. I'll update the question. – fearless_fool Oct 18 '17 at 19:43

1 Answers1

1

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.

fearless_fool
  • 33,645
  • 23
  • 135
  • 217