Skip to main content

IAR Embedded Workbench for RH850 3.20.x

Calculating and verifying a checksum

In this section:

In this example procedure, a checksum is calculated for ROM memory from 0x8002 up to 0x8FFF and the 2-byte calculated checksum is placed at 0x8000.

  1. If you are using ielftool from the command line, you must first allocate a memory location for the calculated checksum.

    Note

    If you instead are using the IDE (and not the command line), the __checksum, __checksum_begin, and __checksum_end symbols, and the .checksum section are automatically allocated when you calculate the checksum, which means that you can skip this step.

    You can allocate the memory location in two ways:

    • By creating a global C/C++ or assembler constant symbol with a proper size, residing in a specific section—in this example, .checksum

    • By using the linker option ‑‑place_holder.

      For example, to allocate a 2-byte space for the symbol __checksum in the section .checksum, with alignment 4, specify:

      ‑‑place_holder _ _checksum,2,.checksum,4
  2. The .checksum section will only be included in your application if the section appears to be needed. If the checksum is not needed by the application itself, use the linker option ‑‑keep=_  _checksum (or the linker directive keep) to force the section to be included.

    Alternatively, choose Project>Options>Linker>Input and specify __checksum:

    KeepingChecksumSymbol_1.png
  3. To control the placement of the .checksum section, you must modify the linker configuration file. For example, it can look like this (note the handling of the block CHECKSUM):

    define block CHECKSUM    { ro section .checksum };
    place in ROM_region  { ro, first block CHECKSUM }; 

    Note

    It is possible to skip this step, but in that case the .checksum section will automatically be placed with other read-only data.

  4. When configuring ielftool to calculate a checksum, there are some basic choices to make:

    • Checksum algorithm

      Choose which checksum algorithm you want to use. In this example, the CRC16 algorithm is used.

    • Memory range

      Using the IDE, you can specify one memory range for which the checksum should be calculated. From the command line, you can specify any ranges.

    • Fill pattern

      Specify a fill pattern—typically 0xFF or 0x00—for bytes with unknown values. The fill pattern will be used in all checksum ranges.

    • Specify an alignment that matches the alignment requirement.

    For more information, see Briefly about checksum calculation.

    Caution

    To run ielftool from the IDE, choose Project>Options>Linker>Checksum and make your settings, for example:

    CreatingChecksum.png

    In the simplest case, you can ignore (or leave with default settings) these options: Alignment, Complement, Bit order,Reverse byte order within word, and Checksum unit size.

    Danger

    To run ielftool from the command line, specify the command, for example, like this:

    ielftool ‑‑fill=0x00;0x8002–0x8FFF
    ‑‑checksum=__checksum:2,crc16;0x8002–0x8FFF sourceFile.out destinationFile.out

    Note

    ielftool needs an unstripped input ELF image. If you use the linker option ‑‑strip, remove it and use the ielftool option ‑‑strip instead.

    The checksum will be created later on when you build your project and will be automatically placed in the specified symbol __checksum in the section .checksum.

  5. You can specify several ranges instead of only one range.

    Caution

    If you are using the IDE, perform these steps:

    • Choose Project>Options>Linker>Checksum and make sure to deselect Fill unused code memory.

    • Choose Project>Options>Build Actions and specify the ranges together with the rest of the required commands in the Post-build command line text field, for example like this:

      $TOOLKIT_DIR$\bin\ielftool "$TARGET_PATH$" "$TARGET_PATH$"
      ‑‑fill 0x00;0x0-0x3FF;0x8002-0x8FFF
      ‑‑checksum=__checksum:2,crc16;0x0-0x3FF;0x8002-0x8FFF

      In your example, replace output.out with the name of your output file.

      SpecifyingChecksumRanges_ILINK_02.png

    Danger

    If you are using the command line, specify the ranges, for example like this:

    ielftool output.out output.out
    ‑‑fill 0x00;0x0-0x3FF;0x8002-0x8FFF
    ‑‑checksum=__checksum:2,crc16;0x0-0x3FF;0x8002-0x8FFF

    In your example, replace output.out with the name of your output file.

  6. Add a function for checksum calculation to your source code. Make sure that the function uses the same algorithm and settings as for the checksum calculated by ielftool. For example, a variant of the crc16 algorithm with small memory footprint (in contrast to the fast variant that uses more memory):

    unsigned short SmallCrc16(uint16_t sum, 
                             unsigned char *p,
                             unsigned int len)
    {
      while (len‑‑)
      {
        int i;
        unsigned char byte = *(p++);
    
        for (i = 0; i < 8; ++i)
        {
          unsigned long oSum = sum;
          sum <<= 1;
          if (byte & 0x80)
            sum |= 1;
          if (oSum & 0x8000)
            sum ^= 0x1021;
          byte <<= 1;
        }
      }
      return sum;
    }

    You can find the source code for this checksum algorithm in the rh850\src\linker directory of your product installation.

  7. Make sure that your application also contains a call to the function that calculates the checksum, compares the two checksums, and takes appropriate action if the checksum values do not match.

    This code gives an example of how the checksum can be calculated for your application and to be compared with the ielftool generated checksum:

    /* The calculated checksum */
    
    /* Linker generated symbols */
    extern unsigned short const __checksum;
    extern int __checksum_begin;
    extern int __checksum_end;
    
    
    void TestChecksum()
    {
      unsigned short calc = 0;
      unsigned char  zeros[2] = {0, 0};
    
      /* Run the checksum algorithm */
      calc = SmallCrc16(0,
                      (unsigned char *) &__checksum_begin,
                      ((unsigned char *) &__checksum_end -
                      ((unsigned char *) &__checksum_begin)+1));
    
      /* Fill the end of the byte sequence with zeros. */
      calc = SmallCrc16(calc, zeros, 2);
    
      /* Test the checksum */
      if (calc != __checksum)
      {
        printf("Incorrect checksum!\n");
        abort();   /* Failure */
      }
    
      /* Checksum is correct */
    }
  8. Build your application project and download it.

    During the build, ielftool creates a checksum and places it in the specified symbol __checksum in the section.checksum.

  9. Choose Download and Debug to start the C-SPY Debugger.

    During execution, the checksum calculated by ielftool and the checksum calculated by your application should be identical.

    If the two checksums prove to be different to each other, there can be several possible causes for that, see Troubleshooting checksum calculation.