LC60: CRC Control of Program Content

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LC60: CRC Control of Program Content

3,463 Views
BasePointer
Contributor II
Hi to all,
 
We are living corrupted program memory problem in mass production.
I want to add CRC algorithm to verify program content in run-time.
Two methods are suggested in the CW6.1 Help for that:
   * PRM file controlled checksum computation
   * Automatic linker controlled checksum computation
 
I choosed Automatic Linker Controlled checksum computation for my project and added <start08.h> and <checksum.h> to my project.
 
 
Code:
#include <hidef.h>#include <start08.h>#include <checksum.h>#include "derivative.h"_CHECKSUM_STARTUP_ENTRY......void main(void){  __RESET_WATCHDOG();  while(__CHECKSUM_IS_OK != 1) __RESET_WATCHDOG();  ...  ... }

But it gives error "C1085: checkSum is not a member"
I looked to _startupData and it doesn't really have member such as checkSum.
What am I doing wrong?
 
Thanks,
BP.
 
Labels (1)
0 Kudos
Reply
12 Replies

1,193 Views
CompilerGuru
NXP Employee
NXP Employee
The standard start08.h does not support that checksum feature, it does need a small extension from checksum.h. The checksum header contains a macro to provide the added fields, by placing those into a local copy of start08.h it should just work :smileyhappy:.
There have been 3 checksum samples with previous versions, but they did not ship with the recent versions.
Anyway, out of my memory, the following should do it:
- copy start08.h into your local project (in order not to change other projects)
- include checksum.h in start08.h
- search for the macro defining the checkSum field in checksum.h and add it in the struct in start08.h where the compiler expects the checkSum field.

There is no need to recompile the ANSI lib, you may have to add checksum.c to your project though.

Daniel
0 Kudos
Reply

1,193 Views
CompilerGuru
NXP Employee
NXP Employee
Just rereading the OP.
_CHECKSUM_STARTUP_ENTRY has to be added in (a copy of) start08.h, not in main.c.


0 Kudos
Reply

1,193 Views
BasePointer
Contributor II
Dear Daniel,
 
1. I copied checksum.h, checksum.c and Start08.h to my project source location.
2. In Local Start08.h file, I added #include "checksum.h" immediatel after #include <hidef.h>.
3. In Local Start08.h file, I added _CHECKSUM_STARTUP_ENTRY to the end of both struct _tagStartup definition.
4. I added local checksum.c file to my project to build.
5. In my mail.c file, I added #include "checksum.h", #include "Start08.h" lines.
 
The project is now linked successfully with a warning:
Is this problem? I also want to use at least 16bit CRC. How can I define this?
 
Code:
#include <hidef.h> /* for EnableInterrupts macro */#include <string.h>#include "checksum.h"#include "Start08.h"#include "derivative.h"

 
Thanks,
BP.
 
 
0 Kudos
Reply

1,193 Views
BasePointer
Contributor II
Hi,
 
These two flags in Start08.c cause the warning.
 
Code:
#define __NO_FLAGS_OFFSET   /* we do not need the flags field in the startup data descriptor */#define __NO_MAIN_OFFSET    /* we do not need the main field in the startup data descriptor */#include "Start08.h"

 
I don't know the meaning of them. Included start08.h in main.c doesn't define these two flags (__NO_FLAGS_OFFSET and __NO_MAIN_OFFSET) and so size of _startupData in main.c and _startupData in start08.c be different.
Should I remove these flags in start08.c? Or Should I add these flags to also main.c before including start08.h? 
 
Regards,
BP.
0 Kudos
Reply

1,193 Views
BasePointer
Contributor II
Hi,
 
I solved the problem above by moving flag definitions to Start08.h.
I have an other problem:
When I debug the code below
   _Checksum_Check(_startupData.checkSum, _startupData.nofCheckSums)
 
I saw that _startupData.nofCheckSums equals to 6 for my project. It iterates _Checksum_CheckAreaCRC16(check->start, check->len...) function six times.
 
0: start->0x1870, len->57056 (decimal)
1: start->0xFEB0, len->210 (decimal)
2: start->0xFFBD, len->1 (decimal)
3: start->0xFFBF, len->1 (decimal)
4: start->0xFFD2, len->46 (decimal)
5: start->0xFFD2, len->44 (decimal) [again]
 
 
Code:
SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */        Z_RAM                    =  READ_WRITE   0x0060 TO 0x00FF;  // 160 byte    RAM                      =  READ_WRITE   0x0100 TO 0x085F;  // 1888 byte    NO_INIT_RAM_SEG          =  NO_INIT      0x0860 TO 0x0C5F;  // 1024 byte    MY_STK                   =  NO_INIT      0x0C60 TO 0x105F;  // 1024 byte    NV_SAVE_SEG              =  READ_ONLY    0x1060 TO 0x13FF FILL 0x8D;  // reserve 928 (512) byte for NV    ROM1                     =  READ_ONLY    0x1400 TO 0x17FF FILL 0x8D;    ROM                      =  READ_ONLY    0x1870 TO 0xFEAF FILL 0x8D;    FLASH_ROUTINE_SEG        =  READ_ONLY    0xFEB0 TO 0xFFAF FILL 0x8D;    ROM2                     =  READ_ONLY    0xFFC0 TO 0xFFD1 FILL 0x8D;    INTVECT                  =  READ_ONLY    0xFFD2 TO 0xFFFF FILL 0x8D;// Reserved for Int. Vectors*/ENDPLACEMENT /* Here all predefined and user segments are placed into the SEGMENTS defined above. */    _DATA_ZEROPAGE, MY_ZEROPAGE         INTO  Z_RAM;    DEFAULT_RAM                         INTO  RAM;    NO_INIT_RAM                         INTO  NO_INIT_RAM_SEG;    SSTACK                              INTO  MY_STK;    NV_SAVE_AREA                        INTO  NV_SAVE_SEG;    FLASH_ROUTINE_AREA                  INTO  FLASH_ROUTINE_SEG;    _PRESTART, STARTUP, DEFAULT_ROM,     ROM_VAR, STRINGS, COPY, .checksum   INTO  ROM, ROM1; /* ROM1,ROM2 In case you want to use ROM1,ROM2                                                            as well, be sure the option -OnB=b                                                             is passed to the compiler. */END

 I don't understant what the 2., 3., 4. and 5. iterations are. Especially, 4. and 5. seem as a problem.
 
Here is related section from map file:
Code:
*********************************************************************************************SECTION-ALLOCATION SECTIONSection Name                    Size  Type     From       To       Segment---------------------------------------------------------------------------------------------FLASH_ROUTINE_AREA               210     R     0xFEB0     0xFF81   FLASH_ROUTINE_SEG.init                            132     R     0x1870     0x18F3   ROM.startData                        18     R     0x18F4     0x1905   ROM.text                          54720     R     0x1906     0xEEC5   ROM.rodata                         1221     R     0xEEC6     0xF38A   ROM.rodata1                         930     R     0xF38B     0xF72C   ROM.copy                             35     R     0xF72D     0xF74F   ROM.checksum                         36     R     0xF750     0xF773   ROM.abs_section_ffbd                  1     R     0xFFBD     0xFFBD   .absSeg128.abs_section_ffbf                  1     R     0xFFBF     0xFFBF   .absSeg129.abs_section_ffd6                  2     R     0xFFD6     0xFFD7   .absSeg130.abs_section_ffd8                  2     R     0xFFD8     0xFFD9   .absSeg131.abs_section_ffda                  2     R     0xFFDA     0xFFDB   .absSeg132.abs_section_ffdc                  2     R     0xFFDC     0xFFDD   .absSeg133.abs_section_ffe8                  2     R     0xFFE8     0xFFE9   .absSeg134.abs_section_ffe6                  2     R     0xFFE6     0xFFE7   .absSeg135.abs_section_ffec                  2     R     0xFFEC     0xFFED   .absSeg136.abs_section_ffee                  2     R     0xFFEE     0xFFEF   .absSeg137.abs_section_fff2                  2     R     0xFFF2     0xFFF3   .absSeg138.abs_section_fff4                  2     R     0xFFF4     0xFFF5   .absSeg139.abs_section_fff8                  2     R     0xFFF8     0xFFF9   .absSeg140.abs_section_fffa                  2     R     0xFFFA     0xFFFB   .absSeg141.abs_section_fffc                  2     R     0xFFFC     0xFFFD   .absSeg142.abs_section_ffd2                  2     R     0xFFD2     0xFFD3   .absSeg143.abs_section_fff6                  2     R     0xFFF6     0xFFF7   .absSeg144.abs_section_ffd4                  2     R     0xFFD4     0xFFD5   .absSeg145.abs_section_fff0                  2     R     0xFFF0     0xFFF1   .absSeg146.abs_section_ffea                  2     R     0xFFEA     0xFFEB   .absSeg147.abs_section_ffe2                  2     R     0xFFE2     0xFFE3   .absSeg148.abs_section_ffe0                  2     R     0xFFE0     0xFFE1   .absSeg149.abs_section_ffe4                  2     R     0xFFE4     0xFFE5   .absSeg150.abs_section_ffde                  2     R     0xFFDE     0xFFDF   .absSeg151INTVECT_vect                      46     R     0xFFD2     0xFFFF   INTVECTNV_SAVE_SEG_152                  928     R     0x1060     0x13FF   NV_SAVE_SEGROM1_153                        1024     R     0x1400     0x17FF   ROM1ROM_154                         1852     R     0xF774     0xFEAF   ROMFLASH_ROUTINE_SEG_155             46     R     0xFF82     0xFFAF   FLASH_ROUTINE_SEGSummary of section sizes per section type:READ_ONLY (R):        EF3C (dec:    61244)

 
0 Kudos
Reply

1,193 Views
CompilerGuru
NXP Employee
NXP Employee
Are you getting any warnings from the linker? Check that none are disabled in the linker preference panel.
It looks to me as if the area used by the INTVECT segment, is used concurrently by some absolutely allocated vectors too.

Code:
INTVECT_vect                      46     R     0xFFD2     0xFFFF   INTVECT.abs_section_ffd2                  2     R     0xFFD2     0xFFD3   .absSeg143


Daniel
0 Kudos
Reply

1,193 Views
BasePointer
Contributor II
Hi Daniel,
 
I removed INTVEC segment from the prm file. Now it iterates five times:
 
0. start: 0x1870, len: 57056 -> ROM segment
1. start: 0xFEB0, len: 210 -> FLASH_ROUTINE_SEG segment
2. start: 0xFFBD, len: 1 -> NVPROT
3. start: 0xFFBF, len: 1 -> NVOPT
4. start: 0xFFD2, len: 46 -> Absolutely allocated interrupt vectors
 
Empty program memory but filled with 0x8D by linker via the PRM file isn't included for CRC calculation. This is not so much problem for me.
 
Code:
/* Block Protection Disabled */const unsigned char NVPROT_INIT @0x0000FFBD = 0b11111111;/* NVOPT: KEYEN=0,FNORED=1,??=1,??=1,??=1,??=1,SEC01=0,SEC00=1 *//* Backdoor Key disabled, no vector redirection, MCU is unsecure */const unsigned char NVOPT_INIT @0x0000FFBF = 0b01000010; // CyclonePro makes it secure after programming!
 
For the NVOPT, I leave that MCU is in unsecure mode. But CyclonePro make it secure after programming. Because, if I make it secure in the code, CyclonePro can't program it. So the CRC of the content would be different. Is it possible to mark linker not to include NVOPT register for CRC calculation? Or any other method?
 
Thanks,
BP.
0 Kudos
Reply

1,193 Views
BasePointer
Contributor II
Hi Daniel,
 
I also removed NVPROT and NVOPT definition in my code. CRC routine doesn't scan these registers and it iterates three times.
 
0. start: 0x1870, len: 57056 -> ROM segment
1. start: 0xFEB0, len: 210 -> FLASH_ROUTINE_SEG segment
3. start: 0xFFD2, len: 46 -> Absolutely allocated interrupt vectors
 
Cyclone Pro configures these registers after programming.
 
Benchmark for CRC Routines: (ENABLE_PRECOMPUTE uses table)
CRC_8 -> 294msec
CRC_16 -> 700msec
CRC_CCITT -> 1.2sec
CRC_32 -> 4.94sec
CRC_ADD_BYTE -> 392msec
CRC_ADD_WORD -> 280msec ****
CRC_ADD_LONG -> 4.95sec
CRC_XOR_BYTE -> 393msec
CRC_XOR_WORD -> 278msec ****
CRC_XOR_LONG -> 4.93sec
------------------------------------------------
 
There are some notes for ADD_WORD/LONG and XOR_WORD/LONG
"For WORD: /* careful: this one only works when all the addresses/sizes are  a multiple of 2 */"
"For LONG: /* careful: this one only works when all the addresses/sizes are  a multiple of 4 */"
How can I be sure if addresses/sizes are really a multiple of 2 or 4?
 
I will choose one of CRC_ADD_WORD or CRC_XOR_WORD method due to execution time.
Which method do you thing safer?
 
Thanks,
BP.
0 Kudos
Reply

1,193 Views
bigmac
Specialist III
Hello BP,
 
All of the error checking schemes will detect a single bit error within the data block.  However, if more than one bit error is probable, the effectiveness of some of the methods will be significantly reduced.
 
The following would be more properly called "checksum" methods, rather than CRC:
CRC_ADD_BYTE, CRC_ADD_WORD, CRC_ADD_LONG
CRC_XOR_BYTE, CRC_XOR_WORD, CRC_XOR_LONG
 
These are particularly prone to non-detection of multiple bit errors, compared with the true CRC methods that utilize a "polynomial" for the error checking.
 
However, for each of the true CRC methods CRC_8, CRC_16, CRC_CCITT and CRC_32, the detection of multiple bit errors is good, but will start to deteriorate, when the data block size exceeds certain limits -
8-bit CRC:   32 bytes
16-bit CRC: 8192 bytes
32-bit CRC: More than 500Mb
 
You will therefore need to use a method that suits the size of the data block you are checking.
 
Regards,
Mac
 
0 Kudos
Reply

1,193 Views
BasePointer
Contributor II
Hi Jim, Mac,
 
My bus frequency is about 6Mhz and the program size is around 60K. CCITT takes time about 1.2sec for my application. So Jim's estimation is approximately equal to my result. I choosed CHECKSUM_ADD_WORD method due to short execution time. But there is a limitation for it: /* careful: this one only works when all the addresses/sizes are  a multiple of 2 */
 
The algorithm is really not working when the size are not a multiple of 2. Everytime I don't want to check address/size if they really are a multiple of 2.
 
Can I control this at linking stage automatically?
 
I know safest method is CRC32 or more bits.. But if you had to use a method between CHECKSUM_ADD_WORD and CHECKSUM_XOR_WORD, which of them would you choose?
 
10x,
BP.


Message Edited by BasePointer on 2008-03-17 05:00 PM
0 Kudos
Reply

1,193 Views
JimDon
Senior Contributor III
CRC32 is the most safe, by quite a wide margin.

CRC_CCITT is safe, and probably the best comprise between time and results.. This is a carefully designed algorithm that minimizes the chances of hashing collisions.  This means the chances that it gets the same CRC for incorrect date is minimized. It is very well researched.

If that is too slow, my next choice would be CRC16.

I would use CRC_8 before any of the other faster ones. At least is a CRC computation, and has known characteristics.

Personally, unless the time is a killer, I would not waste my time with the others.
There is much data available, so check it out for yourself.

0 Kudos
Reply

1,193 Views
JimDon
Senior Contributor III
Just for a check I did some timings for CCITT16
Using an 8 Mhz bus clock (16 Mhz CPU Clock) on a QG8 I got about 16.5 ms/K.
(not running in the debugger).
Don't know how much you are checking or your clock speed, but things should scale linearly.

I also discovered if you don't set _CHECKSUM_CRC_8 to 0, it will include that one as well by default, so you might check into that. It will end up doing both

You also do not need to copy checksum.c or h to you project directory, you can just add them from the src directory. The advantage to that is if they ever get bug fixes, you will get the fixes - the disadvantage is you may not care for the bug fixes.

If you choose the leave them there in the src folder, you will need to add this to cimplier command line args dialog:
-D_CHECKSUM_CRC_CCITT=1 -D_CHECKSUM_CRC_8=0
Also if you do things like this either way, you will not have change #define s in your code.

As you mentioned, it will only include generated code - not filled areas even though it seems you told it to.
If these are important to verify flash integrity, you could just loop on a compare for those areas, but if you use them later the code would have to be adjusted.



0 Kudos
Reply