Before I duplicate work someone else has done...

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Everyone,

 

It seems the ELF is much more used than the HEX file and I believe (I actually remembered before asking!) I've had the discussion before about trying to embed a crc16 into the elf and the answer was that there is no tool to do this.  Something else I like about the elf is that you can embed the fuses and lock bits into it and have a single file to configure/flash a chip.

 

So, if there is a way to do this already (crc16 in elf), please let me know before I do the work.

 

What I am planning is this:

 

1. Embed a string in the program code using PROGMEM like this "cRcLxxxx".  The "cRcL" must be unique and not appear anywhere else in the flash code.

2. Write a tool that opens the elf, reads the headers, and determines where the flash area is.

3. Once it knows where the flash area is, it looks for the cRcL signature to verify that it is found only once.

4. In case the 4 bytes following cRcL have been changed, they are rewritten with "xxxx".

5. Calculate a crc16 on the flash area.

6. Write the size into the first two bytes of the "xxxx" and write the crc into the last two bytes of the "xxxx"

 

You can then flash the ELF.

 

In the beginning of program code, it will scan the flash looking for the cRcL signature.

It will read the size and crc16.

It will then read the flash to calculate the crc16.

When it gets to the cRcL signature, it must use "xxxx" for the crc16 calculation so it will be correct.

Finally it compares the crc16 from the cRcL entry against what it calculated to see if all is well.

 

I can make a single utility called elfcrc16 that does this.

 

The advantages I can think of for this method are:

 

Advantages of the elf file including all things (flash, eeprom, fuse bits, lock bits) together.

You don't have to put the crc16 at the end making the flash section larger than the actual code length.

I think it would be compatible with debugging.

 

Any thoughts about how it could be done better?  Why it might or might not work?  If there are other tools that can do this already?

 

Thanks,

 

Alan

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It seems the ELF is much more used than the HEX file - See more at: https://www.avrfreaks.net/forum/i...

Not if you use Atmel assembler, no choice but hex.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John - I can make the tool update the hex file too, then we are covered.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Will the flash always be the .text + .data ?  There are quite a number of sections in the ELF!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does anyone have any example ELF or HEX that are not traditional such as they have a bootloader embedded, etc?  If so can you post them so I can see how I might be able to support them?

 

I am pretty sure I can write a tool that deals with a single application in flash (which is what I always do), but I wouldn't mind it supporting other situations too.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It always strikes me as a pointless exercise.     In practice,   your Flash memory is good for the lifetime of the product.

 

If you do want to keep someone happy,   you treat the complete flash memory as CRC-able.   e.g. 0x0000-0x7ffe for a mega32. with a 16-bit CRC at 0x7ffe-0x7fff.

Perhaps you have a bootloader at 0x7800.   In which case you would have the CRC-app @ 0x77fe and the CRC-boot @ 0x7ffe.

 

Most ISP software will erase the whole memory.    e.g.  0x0000-0x7fff

Your bootloader should just erase the application memory.   e.g. 0x0000-0x77ff.

 

Note that not all bootloaders behave like this.

 

A 16-bit CRC seems a bit wimpy.    You can always use a 32-bit CRC or 128-bit if you are really paranoid.

 

Obviously,   you could just have a CRC for the actual app size.    But then you would need to store the app size somewhere.    And what happens if this location is corrupted?

In other words,   you should CRC the complete memory.   And have a fixed location to hold the CRC value.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi David,

 

I know what you are saying - and there is a point to saying why not let a device do what it can?  For example, if a part of the flash is corrupted and it only affects one function, why not let it work otherwise...

 

I've always tried to add a crc to code I make.  It is always better than to try to troubleshooting something for hours only to find out it was corrupted the whole time.

 

I don't want to move to crc32 because of the overhead on the avr side of things.  Maybe I can think of a way to crc16 the entire flash range instead of just the program size, I don't want to make the code and flash time longer though like the put it at the end method does.

 

Thanks,

 

Alan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well,   if you CRC a fixed area,   it does not take long to calculate or verify.

 

I assume that you will verify the CRC at startup.     Then every 24 hours or even every second if you are really paranoid.

I have not timed a CRC-32 or CRC-16.    I guess that it will take a few milliseconds for 32kB.

 

You might find it more convenient if the CRC is directly following your app.   i.e. app + CRC are in contiguous memory.

Or even arrange for just the app area to end up with a magic CRC value.

 

This is easy with arithmetic check sums.   You just add the complement to get a magic zero checksum.   A CRC is easier to have as a real value.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think I'm going to change my MsgCRC PROGMEM string to "cRcL032xx<0>" where the 032 is the flash size in kB.  The xx characters will have the crc16 written in their place.  This method will validate the entire flash without having to expand the hex/elf file to the full size of the flash.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You do know srec_cat does pretty much all the CRCing and embedding you could possibly ever hope for? I don't see much point in reinventing that wheel!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think the wall we hit before was that it does not work with ELF files, isn't that right?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So,  what is the problem?

 

You can create any SREC or HEX or BIN from an ELF file.

 

You can add any extra steps as Post-Build commands.

Or simply add extra targets to a custom Makefile.

 

They can be simple or complex.

After all,  modern PCs can process shell scripts,  Batch file,   EXE files,   ... faster than you can rotate a cat.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The problem is that it looks like the ELF file is what is used as the source file, for debugging, etc.  If I can come up with a crc validation solution compatible with ELF, then I can debug with it, and use the ELF file is my source for programming which can include fuses, lock bits, etc. as well.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Everyone,

 

I'm attaching the tool I made (crc16tool.exe) as well as its source code in C.  Also attached is an example which shows the AVR side code for flash 64K and less (easily modified to support >64K).  The tool was written to handle up to 1M of flash, but not tested above 8k so far.  Multiple filenames can be put on the command line and it will process all of them.  It can process ELF and HEX files.  It is finished, but I wouldn't say optimized or polished.

 

Upsides over the "srec_cat put the crc at the end method" are that this does not expand the programming size to the full size of the device, but yet does check the full size of the flash.  It also works with ELF files as well as HEX files.

 

 

One of the reason I did this was so I could produce a single ELF with fuse bits, lock bits, and the crc16 embedded correctly in it, so I could have a single file to flash in one operation.  I can also now keep my fuse/lockbit settings in my main.c and out of a batch file.

 

I will eventually add it as a project here, once I get some documentation made for it.

 

>crc16tool test.elf test.hex
CRC16TOOL 1.00

Processing test.elf
  File is ELF.
  Size is 7824 bytes.
  Scanning for cRcL signature.
  Found at 0x000000E6, Flash Size 32768 bytes.
  Calculating CRC16.
  CRC16 is 0x9B87
  Updating file.

 

Processing test.hex
  File is HEX.
  Loading file into memory.
  Size is 7824 bytes.
  Scanning for cRcL signature.
  Found at 0x000000E6, Flash Size 32768 bytes.
  Calculating CRC16.
  CRC16 is 0x9B87
  Updating file.

 

example.c

 

//sets the flash size 032=32Kb (must be 9 chars long with xx on end, do not remove xx)
//must be outside of function for PROGMEM to work properly
const char MsgCRC[] PROGMEM = "cRcL032xx";

 

int main()
  {

 

    //code to check crc16 (<64kb)
    {
      uint16_t crc_ui1,crc_ui2,crc_ui3;

      crc_ui2=((pgm_read_byte(MsgCRC+5)-'0')*10+(pgm_read_byte(MsgCRC+6)-'0'))*1024;
      crc_ui3=0xffff;
      for (crc_ui1=0;crc_ui1<crc_ui2;crc_ui1++)
        if (crc_ui1==MsgCRC+7 || crc_ui1==MsgCRC+8)
          crc_ui3=_crc16_update(crc_ui3,'x');
        else crc_ui3=_crc16_update(crc_ui3,pgm_read_byte(crc_ui1));
      crc_ui3=~crc_ui3;
      if (crc_ui3!=pgm_read_word(MsgCRC+7))
        {
          //crc failure

          //debug indicate failure here

          for(;;);
        }
    }

 

  }

 

You can easily put a post build command to call it from AS6:

 

c:\path\crc16tool "$(MSBuildProjectDirectory)\$(Configuration)\$(OutputFileName).hex" "$(MSBuildProjectDirectory)\$(Configuration)\$(OutputFileName).elf"

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So elf->hex->srec->hex->elf perhaps?

 

If really serious I'd be tempted to wrap a BFD (libbfd) wrapped around srec_cat.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Tool updated to 1.01, it could not handle a 0 byte .text or .data segment, but now it can.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There was a contribution: https://www.avrfreaks.net/forum/tutgccadding-crc-and-app-length-hex-files?skey=srec_cat on inserting a crc16 checksum using srec_cat

A utility would be very helpful, the procedure described works, but is laborious

Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Jerry,

 

I see what you mean.  I hope my tool/method is easier as you just pass it the ELF or HEX and it calculates the crc16 and updates it.  Beyond that you just have the AVR side code which checks it. 

 

Does anyone have an ELF with a bootloader and application present?  I am just loading the .text followed by the .data sections starting at 0x0000 right now in the ELF processor.

 

Thanks,

 

Alan

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The tool runs correctly if I start it from the command line, but if I include the command as a post-build event in the project properties the following message appears. A Google search didn't help in finding a fix. Can anyone suggest a solution?

Thanks for a very useful tool, Jerry

 

Error    1    The command ""C:\Program Files\WinAVR\bin\crc16tool" "C:\Users\Jerry\Dropbox\YAVTI\RCVSFTGPRtest\DebugELWMS.hex" "C:\Users\Jerry\Dropbox\YAVTI\RCVSFTGPRtest\Debug\ELWMS.elf" exited with code 3.    

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Jerry,

 

It should return 0 for ok.

 

It will return 1 for any of these conditions:

 

unable to allocate memory

unable to open file

unable to read from file

signature not found

too many signatures found

unable to seek file

file is corrupt

extended address to large

unknown record type in hex file

unable to write

unknown file type

 

It will print this error to the console and you should see it in the compiler messages.  Do you see an error surrounding the call?

 

I use this in the studio post build area:

 

"c:\crc16 tool\crc16tool" "$(MSBuildProjectDirectory)\$(Configuration)\$(OutputFileName).hex" "$(MSBuildProjectDirectory)\$(Configuration)\$(OutputFileName).elf"

 

Thanks,

 

Alan

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

exited with code 3.    

Most curious. I just pulled the source above and simply don't see the code path out of main() where it could return 3 ?!?