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.

C6747 CRC Differences Between ROM Codes

Other Parts Discussed in Thread: OMAP-L137, OMAP-L138

I'm extremely confused about how we've implemented CRCs for the C6747.  My primary confusion stems over a couple things:

  1. Handling of padding to the end of sections
  2. Algorithm (lookup vs computation)

My customer has C6747 with d800k001 ROM.  He has been using an older version of our AIS-generation tools which were made specifically for d800k001.  PROBLEM: A bug in that version of the tools will take a section that's MOSTLY zero (but not completely!) and simply use a "fill" command to load the memory with all zeros!

To further add to the confusion, I see slightly different implementations of the CRC in different places:

  • Appendix of the bootloader app note
  • OMAP-L137 boot ROM
  • OMAP-L138 boot ROM (is this what's in PG2.0 of OMAP-L137/C6747?)
  • d800k001 ais generation scripts

Can someone please clarify?  This has wasted days of the customer's time and most of my day today.

Thanks,
Brad

  • I've been working with Daniel Allred and others to get clarification.  Here's a summary:

    • The "old" utility for C6747 d800k001 ROM has a critical bug (as I reported above) where it incorrectly will turn sections into "fills" that should not be, i.e. a "mostly zero" section can be turned into a "fill zero" section!
    • The new utility for C6747 d800k003 ROM does not have the above issue as it does not try to turn sections into "fills" regardless of the content.
    • There is an issue related to the CRC generation in the version of the program that's online right now (10 June 2010) along side the bootloader app note (sprabb1).  It does not work correctly!  This is corrected in 0.7.0.0.
    • The tools can also be downloaded from http://sourceforge.net/projects/dvflashutils/files/OMAP-L137/.  The CRC issue in the tool shipped along side sprabb1 has been corrected in these dvflashutils.  That is, if someone needs properly functioning tools now they can download these tools.  Additionally, these tools are callable from the command line which can be much easier to integrate into a build flow.
    • CRC calculation is the same between C6747 d800k001 and d800k003.  However, the d800k003 ROM supports features not available in d800k001:
      • PINMUX
      • LPSC
      • 16-bit NAND boot
    • The CRC algorithm must first be applied to an array containing the address (32-bit) and size (32-bit) of the data to be CRC'd.  (See later posts with Gaston for more info.)
    • The CRC algorithm currently listed in sprabb1 is not correct.  I will list the algorithm below.

    CRC code for C6747 said:
    static Uint32 LOCAL_updateCRC (Uint32 *data_ptr, Uint32 section_size, Uint32 crc)
    {
      Uint32 n, crc_poly = 0x04C11DB7;          /* CRC - 32 */
      Uint32 msb_bit;
      Uint32 residue_value;
      int bits;
     
      for (n = 0; n < (section_size >> 2); n++)
      {
        bits = 32;
        while (--bits >= 0)
        {
          msb_bit = crc & 0x80000000;
          crc = (crc << 1) ^ ((*data_ptr >> bits) & 1);
          if (msb_bit)
            crc = crc ^ crc_poly;
        }
        data_ptr++;
      }
     
      switch (section_size & 3)
      {
        case 0:
          break;
        case 1:
          residue_value = (*data_ptr & 0xFF);
          bits = 8;
          break;
        case 2:
          residue_value = (*data_ptr & 0xFFFF);
          bits = 16;
          break;
        case 3:
          residue_value = (*data_ptr & 0xFFFFFF);
          bits = 24;
          break;
      }
     
      if (section_size & 3)
      {
     
        while (--bits >= 0)
        {
          msb_bit = crc & 0x80000000;
          crc = (crc << 1) ^ ((residue_value >> bits) & 1);
          if (msb_bit)
            crc = crc ^ crc_poly;
        }
      }
      return (crc);
    }

  • Brad, I have used the CRC algorithm you have posted for data integrity checking during C6747 HPI boot. The point is that computed CRC by AISgen D800K003 does not match with expected CRC calculated by the algorithm. To be more accurate, for the _boot section of my application I expected CRC=0xF8CF534A that is the value computed by AIS. On the contrary, I obtain CRC=0xC2B3ACD9 after calling the function.

    The algorithm is called this way:

    crcGuess = updateCRC ((U32 *)_boot, 0xc0, 0);

     

    and I paste the _boot section data here below.

    const unsigned char _boot[0xc0] = {

    0x5a, 0xa3, 0x00, 0x00, 0xa2, 0x03, 0x00, 0x02, 0x2a, 0x3c, 0xb8, 0x07, 0x6a, 

    0xc0, 0x88, 0x07, 0x2a, 0xfe, 0x01, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x42, 0xe8, 

    0x81, 0x07, 0xf2, 0x09, 0xbf, 0x07, 0x2a, 0xe0, 0x34, 0x07, 0x6a, 0xc0, 0x08, 

    0x07, 0x5a, 0xa3, 0x80, 0x01, 0xa2, 0x03, 0x0c, 0x09, 0xa2, 0x03, 0x0c, 0x0a, 

    0x5a, 0xa3, 0x80, 0x01, 0xa2, 0x03, 0x0c, 0x00, 0xa2, 0x03, 0x8c, 0x00, 0x28, 

    0xf0, 0xa7, 0x01, 0x68, 0xc0, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x62, 0x13, 

    0x0c, 0x00, 0x62, 0x81, 0x85, 0x01, 0x28, 0x30, 0x28, 0x02, 0x68, 0xc0, 0x08, 

    0x02, 0xf2, 0x08, 0x38, 0x02, 0x2a, 0x00, 0x26, 0x00, 0x6a, 0xc0, 0x08, 0x00, 

    0x2a, 0x3a, 0xa0, 0x01, 0x6a, 0xc0, 0x88, 0x01, 0x6f, 0x00, 0x6e, 0x8c, 0x28, 

    0x3a, 0x38, 0x00, 0x68, 0xc0, 0x08, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x64, 0x42, 

    0x00, 0x03, 0x66, 0x22, 0x00, 0x02, 0x64, 0x02, 0x00, 0x02, 0x2a, 0xe0, 0x2e, 

    0x00, 0x6a, 0xc0, 0x08, 0x00, 0x2a, 0x52, 0xa0, 0x01, 0x6a, 0xc0, 0x88, 0x01, 

    0x62, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x92, 0xa5, 0x06, 0x10, 0x12, 

    0xf0, 0x01, 0x10, 0xe2, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };


     

    I have also debugged the routine to check the pointer increment (data_ptr++) and this is correct, the loop gets the right 0xc0/4 values from the _boot array. In this case: 0x0000A35A, 0x020003A2 and so on. Please, could you test this chunk of bytes to confirm there is nothing wrong with my implementation?

     

    Thanks in advance,

    Gaston

  • Are you using the GUI or the command line tools?  What version?

  • Brad Griffis said:
    Are you using the GUI or the command line tools?  What version?

    Only the GUI and the version is 0.7.0.0

  • Gaston,

    Looks like you've got the latest version of the GUI.  I tried out your data array that you posted previously and I computed the same number as you.  I noticed, however, that you were passing 0 as the 3rd argument.  Is this the very first CRC of the entire image?  If so, then 0 is the correct value to pass.  Generally speaking though, the ROM computes a "running CRC" so you would need to pass the previous CRC value.

    I created my own test case and tried passing in a previous value though I was still not getting the right value.  I have sent my test case to the author of the utility for his opinion.  Hopefully we'll get some answers soon.

    Best regards,
    Brad

  • Brad Griffis said:
    Is this the very first CRC of the entire image?

    Yes it is.

    Brad Griffis said:
    I created my own test case and tried passing in a previous value though I was still not getting the right value.  I have sent my test case to the author of the utility for his opinion.  Hopefully we'll get some answers soon.

    All right Brad, I'll be waiting for your news.

    Regards,

    Gaston

  • Gaston,

    Ok, I finally got the answers you need with some help from the author of the utility/ROM.  An earlier statement I made related to passing the previous CRC was not correct.  I struck that out in my earlier post.

    Here's the key piece of missing info.  When performing the CRC you need to also do a CRC of the address (32-bit) and the size (32-bit).  This info was not present in the document so there's no way you could have known!  I'm told it will be updated and that the code will be corrected as well in the document.

    So to summarize, for every section load command the CRC value gets reset to 0.  The easiest way to perform the CRC is to create a separate array to store address and size.  Then you can perform 2 CRCs, one on the address/size and then another on the actual data.

    Specifically I would re-write your earlier code as follows:

    U32 temp = { (U32)_boot, (U32)sizeof(_boot) };

    crcGuess = updateCRC((U32 *)temp, sizeof(temp), 0);

    crcGuess = updateCRC ((U32 *)_boot, sizeof(_boot), crcGuess);

    I'll go back and add another bullet to my original verified answer to try and reflect some of this info.

    Best regards,
    Brad

     

  • Brad, I've gone back to my code to add the address and size to the CRC computation as you suggested. Now I'm glad to see that the result does match with calculated by AIS! and I'm also happy to have collaborated on improving documentation. After all I have few points left to reach the expert level :) Again, thank you for your help.

    Regards,
    Gaston 

  • Gaston said:
    Brad, I've gone back to my code to add the address and size to the CRC computation as you suggested. Now I'm glad to see that the result does match with calculated by AIS!

    Great!  Thank you for letting us know that the issue is fully resolved.

    Gaston said:
    I'm also happy to have collaborated on improving documentation.

    Thank you for helping us find a gap in the documentation and also for your patience while we worked toward resolution!

    Gaston said:
    After all I have few points left to reach the expert level :) Again, thank you for your help.

    Keep up the contributions!  :)   It was a great question and I'm happy I could help you resolve it.