One of the things missing for Embedded in the GNU linker is that it cannot generate a CRC checksum. Luckily, there is the solution of using SRecord:
Outline
Because the GNU (e.g. GNU ARM Embedded/launchpad) toolchain does not include a CRC checksum calculation function, I’m showing how the SRecord utility can be used for this. The SRecord tool is an open source project on SourceForge (http://srecord.sourceforge.net/). It is a command line utility which runs on many platforms. I’m using it in this post with Eclipse (e.g. Freescale Kinetis Design Studio, or any other Eclipse based toolchain using the GNU ARM Embedded (Liviu) with GNU for ARM (GNU for ARM Embedded (Launchpad): https://launchpad.net/gcc-arm-embedded). It goes through the steps to create a checksum, add it to the binary image and checking that checksum in the application.
💡 As the name ‘SRecord’ suggests it deals with S-Records (or S19) files. This is just the default format. SRecord can read and generate pretty much any file format which is used for programming memory devices or microcontroller.
Installation
Go to http://srecord.sourceforge.net/ and download the binaries of your choice from http://srecord.sourceforge.net/download.html. Of course you can as well download the sources and build it yourself. That site hosts as well a lot of good documentation, but if you are a (mostly) Windows user as I am, then be prepared for some Windows user bashing ;-).
SRecord comes with three utilities:
- srec_info: used to retrieve basic information about the file. It reports things like start address.
- srec_cmp: used to compare two files. This utility only tells you if two files are (memory-wise) different or not, but not more.
- srec_cat: This tool is used to extract/add/create/merge/etc files.
All the three tools are command line tools and have extensive support for options. So they easily can be used with make files, scripts or from IDEs as Eclipse. See http://srecord.sourceforge.net/man/index.html for the online manual.
💡 The cool part is that they support ‘input generators’ and ‘filters’, see http://srecord.sourceforge.net/man/man1/srec_input.html
Generating S-Record Files
Usually the linker main output file is an ELF/Dwarf file which has both code and debug information. The ELF/Dwarf file is used for debugging. All toolchains I’m aware of are able to generate more output files beside of the ELF/Dwarf: S-Record (S19), Intel Hex, etc files. For example in Kinetis Design Studio use the ‘Create flash image’ option in the project settings and press ‘Apply’:
Then you can select the ‘Motorola S-record’ option in the project settings:
The generated S19 file can be found in the Debug output folder:
srec_info
srec_info gives basic information about the file:
srec_info Debug\FRDM-KL25Z_CRC.srec
gives
Format: Motorola S-Record Header: "FRDM-KL25Z_CRC.srec" Execution Start Address: 000007CD Data:Â Â 0000 - 00BF Â Â Â Â Â Â Â 0400 - 0C3B
See http://srecord.sourceforge.net/man/man1/srec_info.html for further information
srec_cmp
srec_cmp is a program which can compare two files. Unlike a normal diff, it compares two ‘memory’ files. For example
srec_cmp app1.srec app2.srec
gives
srec_cmp: files "app1.srec" and "app2.srec" differ
See http://srecord.sourceforge.net/man/man1/srec_cmp.html for further information.
srec_cat
srec_cat is the ‘main’ program of the suite. As the name indicates it can concatenate multiples files. But it can do much more:
- Converting files
- Inserting or removing data
- Joining/splitting files
- Moving data
- Fill in patterns or fill the blanks
- Creating data
- Changing data
- and of course creating multiple kinds of checksums 🙂
There are many good examples how to use it here: http://srecord.sourceforge.net/man/man1/srec_examples.html
Crop and Generating a Hex Dump
One thing I’m using often is to do a memory dump of my s-record. I can do this with the -hex-dump option:
srec_cat -crop -Output - -hex-dump
💡 After the -Output option there is usually a file name. Using ‘-‘ as file name will write the output to the console.
For example
srec_cat FRDM-KL25Z_CRC.srec -crop 0x500 0x530 -Output - -hex-dump
produces
00000500: BD 46 80 BD B0 B5 82 B0 00 AF 78 60 39 60 10 4CÂ #=F.=05.0./x`9`.L 00000510: 00 25 15 E0 23 1C 1B 02 9A B2 23 0A 9B B2 19 1CÂ #.%.`#....2#..2.. 00000520: 7B 68 58 1C 78 60 1B 78 5B B2 59 40 FF 23 19 40Â #{hX.x`.x[2Y@.#.@
I use that approach to quickly inspect or dump content of my image (.elf/.s19) file. Additionally, this allows me to inspect the memory of the target and compare it with what I have in my file.
💡 The -crop command crops (or cuts) everything out of the data except the range specified (the end address not included).
Filling Memory
Typically a data file as the Motorola S19/SRecord only describes the bytes to be programmed, but not the ‘holes’ or gaps in the memory map. If building a CRC over a memory area with gaps, I need to define it first. For this I can use the -fill command:
-fill [ ]
To fill multiple areas, e.g. to fill 0x100-0x1FF and 0x300-0x3FF with 0xFF, I could use
-fill 0xFF 0x100 0x200 -fill 0xFF 0x300 0x400
Or I could use a list of <start>…<end> addresses:
-fill 0xFF 0x100 0x200 0x300 0x400
For the microcontroller on the FRDM-KL25Z board (a KL25Z128) I have the following memory map:
MEMORY {  m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x000000C0  m_text     (RX) : ORIGIN = 0x00000410, LENGTH = 0x0001FBF0  m_data     (RW) : ORIGIN = 0x1FFFF000, LENGTH = 0x00004000  m_cfmprotrom (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010 }
To fill the interrupt table (m_interrupts) and the code (m_text) with 0xFF and dump it, I can use
-fill 0xFF 0x0000 0x00C0 0x0410 0x20000
Generating CRC
srec_cat supports many checksums. The challenge for me was to match the srec_cat way of generating the checksum with the right algorithm and polynom. An online CRC calculation utility on http://www.lammertbies.nl/comm/info/crc-calculation.html helped me to identify the matching CRC polynom and algorithm. In my applications I’m using the Big Endian CCITT CRC16. To generate it, use the following command:
-CRC16_Big_Endian 0x1FFFE -CCITT
-CRC16_Big_Endian or -crc16-b-e is used to store the CRC is stored in Big Endian format.
CRC16 Source Files
http://www.menie.org/georges/embedded/crc16.html is a great source for a CRC16 calculation function. Another even better one is on http://www.sunshine2k.de/coding/javascript/crc/crc_js.html. I have updated the source to match the 0x1D0F starting point which is used for -CRC16_Big_Endian. I changed the implementation to use a defined starting point: The interface file:
/* * Copyright 2001-2010 Georges Menie (www.menie.org) * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CRC16_H_ #define _CRC16_H_ #define CRC16_START_VAL 0x1D0F /* start value which is used by SRecord tool for -CRC16_Big_Endian */ unsigned short crc16_ccitt(const void *buf, int len, unsigned short start); #endif /* _CRC16_H_ */The implementation file:
/* * Copyright 2001-2010 Georges Menie (www.menie.org) * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "crc16.h" /* CRC16 implementation according to CCITT standards */ static const unsigned short crc16tab[256]= { 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6, 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de, 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485, 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d, 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4, 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc, 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823, 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b, 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12, 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a, 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41, 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49, 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70, 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78, 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f, 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067, 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e, 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256, 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d, 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405, 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c, 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634, 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab, 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3, 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a, 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92, 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9, 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1, 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8, 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0 }; unsigned short crc16_ccitt(const void *buf, int len, unsigned short start) { register int counter; register unsigned short crc = start; for( counter = 0; counter < len; counter++) { crc = (crc<<8) ^ crc16tab[((crc>>8) ^ *(char *)buf++)&0x00FF]; } return crc; }Checking CRC in the Application
Below is a piece of code in the application which checks the CRC:
/* * Application.c * * Created on: 16.04.2015 * Author: Erich Styger */ #include "Application.h" #include "crc16.h" #define CRC_RANGE_START_ADDR 0x00410 /* start addr */ #define CRC_RANGE_END_ADDR 0x1FFFE /* end addr, this one will not be counted */ #define CRC_VALUE_ADDR 0x1FFFE /* address of CRC (16bits) */ void APP_CheckCRC(void) { unsigned short crc; crc = crc16_ccitt((void*)CRC_RANGE_START_ADDR, CRC_RANGE_END_ADDR-CRC_RANGE_START_ADDR, CRC16_START_VAL); if (crc!=*((unsigned short*)CRC_VALUE_ADDR)) { for(;;) {} /* error! CRC does not match! */ } }The above code assumes that the 16bit CRC is stored at address 0x1FFFE. The application checks the CRC for the code space from address 0x410 up to 0x1FFFD (which does *not* include the CRC itself which is at 0x1FFFE-0x1FFFF).
Using Command Files
Instead passing everything on the command line, I can call the SRecord tool suite programs with the options in an external file. The syntax is
<SrecordProgram> @filenameFor example
srec_cat @crc_cmd.txtDumping the CRC for a memory range
Using the ‘@’ syntax, I can execute a script which calculates the CRC and dumps it for me so I can manually check it. For this I use the following content of a command file:
# srec_cat command file to dump the CRC for a code area # Usage: srec_cat @filename FRDM-KL25Z_CRC.srec         # input file -fill 0xFF 0x0410 0x20000         # fill code area with 0xff -crop 0x0410 0x1FFFE              # just keep code area for CRC calculation below (CRC will be at 0x1FFFE..0x1FFFF) -CRC16_Big_Endian 0x1FFFE -CCITT  # calculate big endian CCITT CRC16 at given address. -crop 0x1FFFE 0x20000             # keep the CRC itself -Output                           # produce output -                                 # '-' is special 'file': use console output -hex-dump                         # dump in hex formatThat way I can have things commented (comments start with ‘#’) and keep things readable. The above program calculates the CRC over a given range, stores the value at the artificial address 0x20000 (outside of the code area) and dumps the 16bit value on the console:
Incorporating the CRC Value into the Application
Knowing the CRC, I need to incorporate the CRC value itself into my application. One way would be to do this in the GNU linker script itself (see “FILLing unused Memory with the GNU Linker“). However, that would be a manual process:
- Determine the CRC value with SRecord and dump it
- Enter the CRC value into the linker script
Another approach would be:
- Generate the CRC with SRecord and produce the S19 file which only has the CRC in it (CRC S19 file)
- Merge the application S19 file with the CRC S19 file
This approach works very well, as srec_cat (as the name indicates) is excellent to concatenate files :-). To produce the CRC S19 file I can use the following command file:
FRDM-KL25Z_CRC.srec         # input file -fill 0xFF 0x0410 0x20000         # fill code area with 0xff -crop 0x0410 0x1FFFE              # just keep code area for CRC calculation below (CRC will be at 0x1FFFE..0x1FFFF) -CRC16_Big_Endian 0x1FFFE -CCITT  # calculate big endian CCITT CRC16 at given address. -crop 0x1FFFE 0x20000             # keep the CRC itself -Output                           # produce output FRDM-KL25Z_CRC.srec # S19 with CRC onlyWith this, I have only the CRC in FRDM-KL25Z_CRC.srec.
Then I need to fill the unused areas in the application file. Here again, I can generate a ‘filled’ file:
srec_cat FRDM-KL25Z_CRC.srec -fill 0xFF 0x0410 0x1FFFE -Output FRDM-KL25Z_CRC_Filled.srecFinally, concatenate the two files with
srec_cat FRDM-KL25Z_CRC_Filled.srec FRDM-KL25Z_CRC.srec -Output Debug\FRDM-KL25Z_CRC_Added.srecHowever, this involves using temporary files which is not ideal. A better approach is to do everything in one step, with a single command file like this:
# srec_cat command file to add the CRC and produce application file to be flashed # Usage: srec_cat @filename #first: create CRC checksum FRDM-KL25Z_CRC.srec         # input file -fill 0xFF 0x0410 0x20000         # fill code area with 0xff -crop 0x0410 0x1FFFE              # just keep code area for CRC calculation below (CRC will be at 0x1FFFE..0x1FFFF) -CRC16_Big_Endian 0x1FFFE -CCITT  # calculate big endian CCITT CRC16 at given address. -crop 0x1FFFE 0x20000             # keep the CRC itself #second: add application file FRDM-KL25Z_CRC.srec         # input file -fill 0xFF 0x0410 0x1FFFE         # fill code area with 0xff #finally, produce the output file -Output                           # produce output FRDM-KL25Z_CRC_Added.srecTo me, this is really a cool thing of the SRecord tool: the ability to line up files and content and then merge it 🙂
And as expected: the application image file has the CRC added:
Adding CRC as Post-Build Step
Now I have the ability to add the CRC to my application file. It would be great if this could be part of my build process? Using normal make files, I simply would call srec_cat after linking. The same thing can be done with Eclipse as ‘Post-Build-Step’. For example to dump the CRC value, I can have this in the project settings:
💡 Keep in mind that the ‘current directory’ for the build process is the output folder, usually the ‘Debug’ folder.
And it will dump the CRC at the end of the build process:
The same way I can add the CRC to the application:
However, this will fail for a clean build:
The reason is that the post build step is executed *before* the S19 file is generated. The solution is to add the generation of the S19 file to the post build step too. It is possible to execute multiple post-build steps (see “Executing Multiple Commands as Post-Build Steps in Eclipse“), just be aware that the separator on Windows is ‘@’ and it is ‘;’ on Linux:
💡 One strange thing I noticed: as soon as I had multiple commands, I had to use ‘/’ instead of ‘\’ on Windows.
With this, everything works as expected:
Summary
Generating a CRC is not possible directly with the GNU linker. But this is not a problem, as there is an even more powerful way with the ‘SRecord’ utilities: with the SRecord utilities I can almost any manipulation of the output files I need, plus best of all: it is open source too 🙂
I have put my project used in this post on GitHub here:Â https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/KDS/FRDM-KL25Z/FRDM-KL25Z_CRC
Links
- ‘SRecord’ home page: http://srecord.sourceforge.net/
- ‘SRecord’ examples: http://srecord.sourceforge.net/man/man1/srec_examples.html
- Online CRC calculation: http://www.lammertbies.nl/comm/info/crc-calculation.html
- GNU ARM Eclipse Plugins
- GNU for ARM Embedded (Launchpad): https://launchpad.net/gcc-arm-embedded
- Generating S19 Files with CodeWarrior: https://mcuoneclipse.com/2012/09/13/s-record-generation-with-gcc-for-armkinetis/
- Generating S19 Files with Kinetis Design Studio: https://mcuoneclipse.com/2014/04/20/binary-files-for-the-mbed-bootloader-with-eclipse-and-gnu-arm-eclipse-plugins/
- CRC16 CCITT Example source code: http://www.menie.org/georges/embedded/crc16.html
- Post-Build-Steps in Eclipse: Executing Multiple Commands as Post-Build Steps in Eclipse
Nice writeup.
I’ve used this in the past but never spent the time to integrate it with Eclipse.
Another tool I’ve found quite handy is Srecordizer (srecordizer.com/). It allows you to browse and edit Srecord files. Worth a look.
LikeLike
Hi Tom,
thanks for that link to SRecordizer, that’s indeed a cool tool 🙂
LikeLike
This is an excellent post. Thank you!
LikeLike
Great Post Erich,
S-record is going to become one of my best programming tools !
Many thanks also for having found an excellent crc16 source code.
About this code : i’ ve seen that the parameter len for the function crc16_ccitt is ‘int’ type .
This limit the checksum range to 32767 bytes. Since in my implementation, i needed to calculate the crc16 on a larger memory size ( 80 KB ) I’ve modified this parameter in ‘unsigned long’ type.
It is obvious that more the range is increased and more possibilities exist for the crc16 to not detect an error ..
Does exist some figures about this matter ? (i.e. : for a 32 KB of datas the probability to not detect an error is of xx % ) ..
LikeLike
Hi Luca,
the size of int dependends on the target machine, and is usually 32bit on 32bit microcontrollers.
LikeLike
Touche Erich !
On my DSC800E where i’ve implemented ‘int’ is 16.bit..
( Another case where it is better to use typedef defined types like uint_32 , etc .. ) .
LikeLike
Pingback: Aligning S19 Records to 64-bit Boundaries | MCU on Eclipse
What I haven’t solved yet is getting the checksum into the debugger; I think the debugger does not use the SREC file, so this would not work?
LikeLike
You can load S19 files with the debugger, in multiple way. A simple way is to specify the .s19 in the debugger launch configuration instead of the .elf file.
LikeLike
Thanks! Couldn’t replace the “application” with srec instead of elf because then no debugging – but found I could specify an additional ELF file, and specify it as an srec file containing the checksum.
LikeLike
Pingback: Merging S19 Files | MCU on Eclipse
CRC’s checking properties only apply over a given block size. While my math skills are a bit fuzzy as reading the many papers and books about CRCs tend to make my eyes glaze over from things like Syndrome Lengths of Galois fields. It is my understanding that a 16 bit CRC’s properties only hold over a block size of 4096 bytes minus one bit.
Therefor a 32 bit CRC is needed for anything larger than 4K -1 bit.
Perhaps you can find a math wiz in one of your students to turn all of this Galois crap into a real world paper that us in the Embedded world would actually understand. We don’t care about the polynomials, I accept the Math Gurus figured those out, etc. We want to known the formula for CRC5/8/16/32/64 is good for X number of bits, real world kind of stuff we need to know.
LikeLike
Hi Bob,
https://users.ece.cmu.edu/~koopman/roses/dsn04/koopman04_crc_poly_embedded.pdf is a good source on that topic.
Basically, the number of CRC bits are the number of bits for the ‘hash’ value. So if using a 16bit CRC, it can have 65k differnt hash values. Now the question is how big are the chances that your given block size can have the same hash value? This basically drives the number of CRC bits needed. https://en.wikipedia.org/wiki/Cyclic_redundancy_check gives a good number: a the number of bits are effective for less than 2^(n-1)-1 data bits. So for 8 bits, it would be 2^(8-1)-1 == 127 bits or 15 bytes. For a 16bit CRC it would be 2^(16-1)-1 or for 4095 bytes. So indeed, if your block is >4K, you need e.g. a CRC-32bit one.
Erich
LikeLike
Hi Eric,
i try to use your program, bu the result of crc from s record and from the application it’is dfferent and i dont’ understand why. Do you have any suggest? Thank you, Anna
P.S. : I use a STM8.
LikeLike
Hi Anna,
if the result is not the same, the issue is most likely
a) you are not calculating the same bytes/memory areas
b) you are not using the same polynom and start value
Are you using the CRC method I have presented with the same settings?
I hope this helps,
Erich
LikeLike
Thank you for the faster answer,
i need to calculate the crc in the flash area memory.
I use the some polynom and start value, even if i read in the s record manual that the start point id 0xFFFF. Itry change it but the value is different.
thabks,
Anna
LikeLike
Hi Anna,
to verify the polynom, start value and memory area is correct, I recommend that you calculate the CRC over a small memory area (e.g. from 0x1000 to 0x100F). Verify that what you have in memory matches what you have in the S-Record.
It could be that your debugger is writing values differently e.g. to special configuration data, e.g. to prevent you permanently locking your device.
I hope this helps,
Erich
LikeLike
Hi Eric,
for the small area falsh it worksss!!! Why if i extend my area there is a problem? It’s necesessary for me to calculate the crc for a lenght of 8k.
LikeLike
Hi Anna,
I recommend that you compare (with the debugger?) your 8K memory area if it really matches what you have in the S19 file.
LikeLike
Hi Erich,
How can i debug the project using the .srec file (preferebly the one with CRC) instead of .elf file in KDS ?
LikeLike
Hi Ankur,
see https://mcuoneclipse.com/2016/04/19/programming-s-records-with-gnu-arm-eclipse-debugger-plugins/
Erich
LikeLike
thanks for the reply…but i tried this already and failed.
When debug was using .elf everything goes fine and the session starts with a breakpoint at main().
But if I specify .srec in the debug configuration, although the debug session starts it doesn’t hits the main() breakpoint. Plus I am not able to debug the code or put any other breakpoints. [It is only visible in disassembly view]. I am using KDS 3.2 with PE.
LikeLike
S19 files do not contain any debug information. It is raw code (see https://mcuoneclipse.com/2012/09/27/s-record-intel-hex-and-binary-files/). So without any other symbol or debug information, the debugger only can see assembly code. If you want to debug it with source and variable information, you have to provide that information the to the debugger, e.g. in the form of the ELF/Dwarf file.
LikeLike
Although i found that if I specify the .srec in debug configuration ( as in https://mcuoneclipse.com/2016/04/19/programming-s-records-with-gnu-arm-eclipse-debugger-plugins/ ) and in the “Debug->startup tab” change the only “Load symbol” file to “.elf” from “.srec” (Debug->Startup->Load Executable is .srec only) everything works fine.
is this because although .srec is an executable it does not contain debug information for which I have to use .elf ? Or am I doing something wrong.
Hope i explained myself clearly. its confusing
LikeLike
Hi Ankur,
yes, if you want to debug it, it you need to provide debug information. That is the ‘Dwarf’ part in the ELF/Dwarf (.elf) file. See https://mcuoneclipse.com/2012/06/01/debug-vs-release/ for mor details (you can strip off the debug information from an ELF/Dwarf file). So yes, the S19/.srec only contains code, but no debug information. You can download the code (elf, s19, bin, hex, etc), but if you want to debug it beyond assembly code, you have to provide the symbols (you can do this separately).
LikeLike
Pingback: MCUXpresso IDE: S-Record, Intel Hex and Binary Files | MCU on Eclipse
Pingback: Using Eclipse to Program Binary Files to an Embedded Target | MCU on Eclipse
Thanks for the informative writeup.
I have created a script to…
1. Fill 0xFF at unused spaces in Bootloader (format S31)
2. Fill 0xFF at unused spaces in Application (format S31)
3. Merge Bootloader and Application into 1 hex file (s19) (format S31)
Here is the script…
#PART 1
D:\Debug\Bootloader1KSeries.srec
-fill 0xFF 0x00 0x7800
-address-length=4
-line-length=46
-o D:\Hex\BootLong.hex
#PART 2
D:\FLASH\App.hex
-fill 0xFF 0x7800 0x40000
-address-length=4
-line-length=46
-o D:\Hex\AppLong.hex
#PART 3
D:\Hex\BootLong.hex
D:\Hex\LT500Long.hex
-o D:\Hex\Final.hex
-address-length=4
-line-length=46
If any one of these parts is executed (with other two parts commented) then the script runs nicely. I run it using “srec_cat @script.txt”
However, if I try to run all the above parts (1, 2 and 3) then I get following message…
Usage: srec_cat […] filename…
srec_cat Help
srec_cat VERSion
srec_cat LICense
And no output file is generated in the Hex folder (destination folder)
Please tell me, how to resolve this issue.
LikeLike
See http://srecord.sourceforge.net/man/man1/srec_cat.html for a description of the command line interface. You cannot use it like you did, you have to do it in three steps, and then you can combine the files as needed, see https://mcuoneclipse.com/2016/02/26/merging-s19-files/
LikeLike
Thank you for the reply, Erich.
I am new to the cmd line scripting. I have been through the links you have shared. (sorry, but I really could not find anything there that would solve my problem).
Please make a note, all the above steps that I mentioned in my first post work ok when run alone (i.e. by commenting the other two). However clubbing them together has a problem.
Do you mean to say that I have to create three different script.txt file, for three steps and call them in post build steps in the Eclipse settings?
Or is there any command available that closes the generated/opened output file?
LikeLike
Yes, I meant that there shall be three different calls/scripts to the srecord utility. This is how I would do it. You can combine the three steps into a single command/batch file.
LikeLike
Hello Erich,
I created three commands separately in a batch file. This is how my batch file look like…
D:\Tools\srecord-1.63-win32\srec_cat D:\Hex\Boot.srec -fill 0xFF 0x00 0x7800 -address-length=4 -line-length=46 -o D:\Hex\BootLong.hex
D:\Tools\srecord-1.63-win32\srec_cat D:\Hex\App.hex -fill 0xFF 0x7800 0x40000 -address-length=4 -line-length=46 -o D:\Hex\AppLong.hex
D:\Tools\srecord-1.63-win32\srec_cat D:\Hex\BootLong.hex D:\Hex\AppLong.hex -o D:\Hex\Final.hex -address-length=4 -line-length=46
I ran it by double clicking on .bat file and it was generating the expected output. Thanks for suggesting this method. 🙂
Now, to automate the process I added it into Postbuild commands of ECLIPSE based Codewarrior like this…
In Post-Build Steps -> Command->
D:\Tools\srecord-1.63-win32\script_Trial2.bat
When I try to compile, the Codewarrior generates .hex, .elf and displays the code and data size and then nothing happens. no message is displayed in console window of Codewarrior and expected files are also not generated.
Please tell me where am I failing.
LikeLike
The post build step is only executed if there is previously a link phase (calling the linker). Otherwise, I suggest that you try to call the batch file in the post build step from a new/clean project, as some custom file options might prevent executing a post build step. If it works for you on a clean project, than the batch file is working fine and it must be a problem of your actual project.
LikeLike
Very helpful as always! FWIW, there’s a small formatting issue near the first mention of “CRC16_Big_Endian” — it appears that some pointy-bracket enclosed text got swallowed as HTML directives. But easy enough to figure out by context and subsequent examples…
LikeLike
Hi Robert,
many thanks for reporting this! Not sure what happened with WordPress, but I have it fixed now.
LikeLike
I was having a devil of a time figuring out what CRC32 algorithm the KL27 hardware uses for the KL Bootloader 2.0 protocol. Although the site you cite (https://www.lammertbies.nl/comm/info/crc-calculation.html) was useful, it only had one CRC32 algorithm.
I found a more comprehensive online CRC calculator at http://www.sunshine2k.de/coding/javascript/crc/crc_js.html that helped me identify the KL27 CRC32 used by the bootloader as CRC32_MPEG2.
As an aside, I have referred to this blog entry more times than I can count. Many thanks (again!).
LikeLike
Hi Robert,
thank you so much for sharing that link for this CRC calculator, very useful! I have added that one to the article too. And thanks for identifying the CRC the Kinetis Bootloader is using, I was wondering about this too. I have not seen that documented anywhere 😦
LikeLike
Hmm – do you have any suggestions how to generate CRC variants that are not natively supported by SRecord? (For example, see https://stackoverflow.com/questions/46799907/extending-srecord-to-handle-crc32-mpeg2)
LikeLike
Thanks for asking that question in that forum. But I have no advise here as well, except maybe this:
a) export the data of the range using SRecord to a file
b) call a program to calcualate the CRC with the desired method and put it into another file
c) combine/merge the data using SRecord
Above could be done in a script/batch file, but requires to implement the CRC somehow.
LikeLike
Solved!! It’s possible to do it with just srec_cat and filters. See https://stackoverflow.com/a/46947352/558639
After that, it’s simply cropping and merging the srec files along the lines that you’ve outlined here. Many thanks!
LikeLike
Great! Thanks for posting the solution and closing the loop, appreciated!
LikeLike
To elaborate on this, the SRecord tool uses a *reversed* polynomial of 0xedb88320. Furthermore, when it calculates the CRC, it uses the following function:
table[(crc ^ octet) & 0xFF] ^ (crc >> 8);
Which is apparently a little backwards from the “standard” way – as explained in the comment above the polynomial. Thus, even if you change your polynomial to match, the checksum still won’t be the same.
To fix this, you can either use Robert’s posted solution to get back to the standard computation and polynomial, or edit the SRecord code and re-compile it on your system
LikeLike
Pingback: Adding a Delay to the ARM DAPLink Bootloader | MCU on Eclipse
Hey Erich/ all, it looks like the the sourceforge site for srecord is down while they migrate, and has been for at least the past two days. Does anyone have a comparable tool?
LikeLike
Hi Andrew,
in my view, there is really other alternative (at least not with all the functionalites).
I have emailed the SRecord to your gmail email address, so hopefully this gets you started.
Erich
LikeLike
typo: produdes -> produces
LikeLike
Thank you! Fixed now.
LikeLike
Pingback: Tutorial: CRC32 Checksum with the KBOOT Bootloader | MCU on Eclipse
‘srec_cat’ can’t not find this file[..\..\Debug\s32k118_GCC_base.srec]
srec_cat: ..\..\Debug\s32k118_GCC_base.srec: open: No such file or directory
LikeLike
if you are using a relative path, it depends what you have used as current directory of srec_cat: this might depend on how you call the executable.
LikeLike