4

I am working on a firmware project in which i have to do a crc16 check for flash integrity.

The crc is calculated using IAR Xlink linker and kept at the end of the flash. Again crc is calculated at run time from the code and compared with the stored value in the flash to check integrity. However, we can only calculate crc on the code segment of the flash memory. It's size may change whenever we make some changes in the code. Can i automate this process which i am manually doing right now?

from the .xcl linker file:

// ---------------------------------------------------------
// CRC16 Essentials: -H for fill,-J for checksum calculation
// ---------------------------------------------------------

-HFF         

-J2,crc16,,,CHECKSUM2,2=(CODE)5C00-FF7F;(CODE)10000-0x20A13

Here i need to change the end value of second code segment which is 0x20A13 right now. I get this value from the .map file, i.e on how much memory range my code is residing inside the flash. This is the 1st change i make.

Here i need to make 2nd change from code:

  sum = fast_crc16(sum, 0x5C00, 0xFF7F-0x5C00+1);

  sum = fast_crc16(sum, 0x10000,0x20A13-0x10000+1); 

  //Check the crc16 values 
   if(sum != __checksum)
   {
    // Action to be taken if checksum doesn't match
   }

Please help automating this process!!

OnkarK
  • 127
  • 2
  • 9

2 Answers2

2

You can try to use the __segment_begin and __segment_size or __segment_end intrinsics in IAR which are explained in the "C/C++ Compiler Reference Guide", which you can get to from your Help menu in IAR EW430. The manual says they work with segments defined in the linker file, and plenty of the people around the internet seem to be using it like that, but I tried and got compiler errors (IAR EW430 5.40.7). If that is somehow broken you might want to report it to IAR and get a fix (assuming you have a support contract).

You can use them like this:

sum = fast_crc16(sum, __segment_begin("CODE"), __segment_size("CODE"));

I don't know what happens with split segments. But why would you exclude your reset vectors from your checksum calculation? You could just go from the start of CODE to the end and include the reset vectors.

I guess you could structure your code like this:

sum = fast_crc16(sum, __segment_begin("CODE"), (char *)__segment_begin("INTVEC") - (char *)__segment_begin("CODE") + 1);

sum = fast_crc16(sum, 0x10000, (char *)__segment_end("CODE") - 0x10000);

Also, you may or may not have noticed that the __checksum variable is put into memory wherever it fits. I found it lurking after my DATA16_ID segment, which put it right in the middle of the range of my checksum code, and I did not know of a way to automate skipping sections of memory for the checksum calculation. What I did was forced __checksum to the first two bytes in flash by defining a segment for those first two bytes and putting it in there.

Edit: Missed the first change. If you are manually adjusting the range of the IAR linker checksum routine then to be able to use the segment intrinsics from the compiler your would need to define a custom segment that uses the end of your code in your linker.

I don't know if there's any way to automate that. You might need to compile your code twice (ugh) once with the segment unlimited to get the end of the code, then use a script to extract the end of code and then update a linker script. You could probably run the initial build on a pre-build command line event and just build the IAR project with an unrestricted linker file. But that seems pretty ugly.

tinman
  • 6,348
  • 1
  • 30
  • 43
  • Thanks Tinman for your suggestion about using intrinsics in function call. I didn't know about those ones. My actual concern is that i only want to calculate checksum on what seems like: 1 and 2 in the map file. I want to exclude any other segments in the code memory because they have some global data which is meant to change and i am calculating checksum at runtime every hour(Project requirement). – OnkarK Aug 23 '12 at 12:57
  • that is why i have to manually change the address ranges in linker and in the source for every download. This is what i want to automate. Even if you can suggest me some way to push these DATA20_C and DATA20_ID before 2 is okay for me. I just want to exclude the from crc calculation at all! (FYI)__checksum in my image is at the end. You can place it anywhere you want – OnkarK Aug 23 '12 at 13:37
2

Perhaps you can also change your solution to build the crc over the complete flash reserved for the application, not only for the used part.

Then you never need to change your linker file nor your c-code, and even a bootloader could calculating the crc without knowledge about the actual size of the application.

jeb
  • 78,592
  • 17
  • 171
  • 225
  • Will it affect the runtime calculation and checking of crc? i need to check it every hour. The map file shows some global data in the DATA20_C and DATA20_ID segments. – OnkarK Aug 24 '12 at 11:22
  • It will affect the runtime calculation time, but if you only need it every hour, I suppose it's not a problem, but to be sure you could measure the duration – jeb Aug 24 '12 at 11:25
  • for entire 256K memory on 922KHz clock, calculation takes almost a second to calculate. That much is still okay for the app. Anyways, Thanks for the inputs! – OnkarK Aug 24 '12 at 11:29