...compute a CRC and embed it in the binary image? [arm]
To calculate a CRC32 checksum of the FLASH segment and modify the global variable crc32 with the result:
- Add a crc32 variable to your program and place it in a different section so that it will be outside of the memory range included in the CRC32 calculation:
unsigned int crc32 __attribute__ ((section(".crc32"))) = 0; - Modify the memory map so that it reduces the size of the FLASH segment and locates the section containing the crc32 variable after it, for example:
... <MemorySegment access="ReadOnly" start="0x00000000" size="0x7FFC" name="FLASH"/> <MemorySegment access="ReadOnly" start="0x00007FFC" size="0x4" name="CRC32"> <ProgramSection alignment="4" size="0x4" load="Yes" name=".crc32"/> </MemorySegment> ...
- Add a JavaScript file to your project called calc_crc32.js containing the following code:
function calc_crc32(filename) { backupFilename = filename + ".bak"; CWSys.removeFile(backupFilename); CWSys.renameFile(filename, backupFilename); ElfFile.load(backupFilename); var start= ElfFile.symbolValue("__FLASH_segment_start__"); var end = ElfFile.symbolValue("__FLASH_segment_end__"); var crc32Value = ElfFile.crc32(start, end - start, false, 0xFF); var crc32Address = ElfFile.symbolValue("crc32"); ElfFile.pokeUint32(crc32Address, crc32Value, false); ElfFile.save(filename); } - Set the User Build Step Options > Link Patch Command project property of your executable project to:
"$(StudioDir)/bin/crossscript" "load(\"$(ProjectDir)/calc_crc32.js\");calc_crc32(\"$(TargetPath)\");"
- Within your program, you can check the CRC32 with the following code:
#include <libmem.h> extern unsigned char __FLASH_segment_start__, __FLASH_segment_end__; int crc_ok() { return ~libmem_crc32_direct(&__FLASH_segment_start__, &__FLASH_segment_end__ - &__FLASH_segment_start__, 0xFFFFFFFF) == crc32; }Note that you will need to link in the libmem library in order to pick up the libmem_crc32_direct() function, to do this add the line $(StudioDir)/lib/libmem$(LibExt)$(LIB) to your Linker Options > Additional Input Files project property if you have not done so already.
-
There's something wrong here. In 2 separate projects on 2 different processors (Cortex M3's from different vendors), in both cases, when I link, it indicates that the entire RAM is being used (and then some). The memory map change does not appear to be correct or is having some unexpected impact on the linker.
-
@Michael:
The memory map example is not very good, you have to use the real physical addresses for the flash area, which is usually not starting at 0x00000000 for Cortex M3 processors. See the datasheet of your CPU for the memory addresses. Here is what i changed in my memory map file for an STM32F103RE processor:
<MemorySegment size="0x40000" access="ReadOnly" name="FLASH" start="0x08000000"/>
<MemorySegment size="0x4" access="ReadOnly" name="CRC32" start="0x08040000">
<ProgramSection alignment="4" size="0x4" load="Yes" name=".crc32"/>
</MemorySegment> -
Michael,
As I say, I can't reproduce the problem you are describing by following the instructions above - I've just tried it again here using an EFM32 Cortex-M3 target running the latest version of CrossWorks for ARM. If you can attach a project that I can compile here that demonstrates the problem, or tell me how I can generate one, I'll take a look. If you don't want your project to be available publicly I suggest you create a ticket and we'll take it from there.
Best regards,
Jon Elliott
-
Here is my Javascript file:
function calc_crc32(filename)
{
backupFilename = filename + ".bak";
CWSys.removeFile(backupFilename);
CWSys.renameFile(filename, backupFilename);
ElfFile.load(backupFilename);
var start= ElfFile.symbolValue("__FLASH_segment_start__");
var end = ElfFile.symbolValue("__FLASH_segment_used_end__");
var crc32Value = ElfFile.crc32(start, end - start, false, 0xFFFFFFFF);
var crc32Address = ElfFile.symbolValue("__CRC32_segment_start__");
WScript.Echo("Flash Start Address = 0x" + start.toString(16) + "\n");
WScript.Echo("Flash Used End Address = 0x" + end.toString(16) + "\n");
WScript.Echo("crc32Value = 0x" + crc32Value.toString(16) + "\n");
WScript.Echo("crc32Value NOT = 0x" + (~crc32Value).toString(16) + "\n");
WScript.Echo("crc32Address = 0x" + crc32Address.toString(16) + "\n");
ElfFile.pokeUint32(crc32Address, crc32Value, false);
ElfFile.save(filename);
} -
And here is my C module:
/*-----------------------------------------------------------*/
/* Library includes. */
#include <libmem.h>
/*-----------------------------------------------------------*/
/// external crc32 checksum placed in a different section so that it will be outside of the memory range included in the CRC32 calculation
const unsigned long int crc32 __attribute__ ((section(".crc32"))) = 0;
/// external address of the flash segment start
extern unsigned char __FLASH_segment_start__;
/// external address of the flash segment end
extern unsigned char __FLASH_segment_used_end__;
/// external address of the crc32 segment start
/*-----------------------------------------------------------*/
/**
* \fn int flashtest_crc_ok( void )
* \brief Calculates and compares the CRC32 over the used program flash area
* Calculates the crc over the \b used program flash area of the CPU and compares it with the value
* stored in the CRC32 section. Uses the libmem_crc32_direct() function from libmem.h to calculate
* the checksum over used flash area, the result is bitwise negated and then compared with the crc32 checksum
* stored in the flash section CRC32. Both checksums have to be equal to pass the flashtest.
*
* \return int result of the flashtest
* \retval 1 flashtest passed, both checksums are equal
* \retval 0 flashtest failed, checksums are NOT equal
* \attention \b Pitfall: Result of libmem_crc32_direct() have to be \b negated \b bitwise to get the crc32 checksum that can be compared
*
*/
int flashtest_crc_ok( void )
{
return ( ~libmem_crc32_direct(&__FLASH_segment_start__, &__FLASH_segment_used_end__ - &__FLASH_segment_start__, 0xFFFFFFFF) == crc32 );
} -
Pitfall:
The result of libmem_crc32_direct() have to be negated bitwise to get the same CRC32 checksum that was calculated by the ElfFile.crc32 method!
@Jon:
- Please make this clearer in your documentation for the libmem_crc32_direct() function.
- The fourth parameter (here 0xFF) of the Javascript ElfFile.crc32 method has no effect at all. No matter what start value is used, the result of ElfFile.crc32 will always be the same. The documentation and examples are inconsistent here, please correct this in the documentation and also mention, that the inherent start value for the ElfFile.crc32 method is 0xFFFFFFFF. Besides, the method ElfFile.crc mentioned in the Script Classes documentation does not exist.
-
I'm getting a feeling my js program is not running. Where do the WScript.Echo lines get echoed to?
Why is the User Build Step Options > Link Patch Command passing the TargetPath to the calc_crc32 function?
(StudioDir)/bin/crossscript" "load(\"$(ProjectDir)/calc_crc32.js\");calc_crc32(\"$(TargetPath)\");
Should I change that to the path of my elf file? Where is "TargetPath" defined?
Should I see the CRC value calculated in my elf file or hex file? I don't and this is why I don't think my .js file is running.
-
I appear to be confusing TargetPath with TargetsDir. Sorry. TargetPath seems to be right. But, I don't see where the .calc)crc32.js file running in my output window.
Rebuilding “36-1863 Application” in configuration “THUMB Flash Release”
Compiling bsp.c
Compiling eeprom.c
Compiling gpio.c
Compiling rs485.c
Compiling ssp.c
Compiling timer16.c
Compiling timer32.c
Compiling f_sin_x.c
Compiling main.c
Compiling modbus.c
Compiling coils.c
Compiling holdingregs.c
Compiling motordrive.c
Assembling thumb_crt0.s
Assembling LPC1100_Startup.s
Compiling system_LPC11xx.c
Generating linker script
Linking 36-1863 Application.elf
Build complete
Is this where the WScriptEcho lines should be viewed?I'm using Crossworks 2.1.1
-
If I move the command
(StudioDir)/bin/crossscript" "load(\"$(ProjectDir)/calc_crc32.js\");calc_crc32(\"$(TargetPath)\");
to a pre compile or other place, I get an error that says it can not start "C:\Program" Which means it can't parse the spaces in the generated path from the $StudioDir tag.
Please help me understand what is going on. I tried very hard to solve this on my own but have been unsuccessful.
-
I did the "Build Number" script right out of the help file and I get the following when I compile:
Rebuilding “36-1863 Application” in configuration “THUMB Flash Release” — 1 error
Compiling bsp.c
Compiling eeprom.c
Compiling gpio.c
Compiling rs485.c
Compiling ssp.c
Compiling timer16.c
Compiling timer32.c
Compiling f_sin_x.c
Pre-compile command — 1 error
Can't start process C:/Program
Build failedI tried replacing the $(StudioDir) with the full path and "%20" for all the spaces, and that was no help. It's chocking on "Program Files" Something is definitely wrong and I need help.
-
If I get this resolved, it would be prefered to place the CRC32 at the end of the last code byte rather than at the end of the code space. Then, at the end of the vectors I can reserve a place for a pointer to tell me where the CRC is, or the length of the code. This way all the blank space is not part of the calculation and it will go faster during the upgrading process.
-
> Something is definitely wrong and I need help.
I assume your StudioDir path has space characters, you have to put the whole path between " ".
> it would be prefered to place the CRC32 at the end of the last code byte
This is already the case by using the symbol __FLASH_segment_used_end__ and not the symbol __FLASH_segment_end__
But i faced problems with the crc calculation in this case, i assume there is something wrong with the byte alignment or the fill option - i haven't solved it yet... -
>I assume your StudioDir path has space characters, you have to put the whole path between " ".
It helped to include the quotes on each end of the command line.
The command still does not seem to execute from the Link Patch Command.
I put the same command in the Pre Compile Command and I get the new error message below:
error: cannot open $(TargetPath).bak
So, it looks like it found my .js now, but it's not resolving the $(TargetPath) symbol in the script to the actual elf output path. -
my calc_crc32 js file is simply this for debugging now:
function calc_crc32(filename)
{
WScript.Echo(filename);
}This generates the following output:
Rebuilding “36-1863 Application” in configuration “THUMB Flash Release”
Pre-compile command
$(TargetPath)I execute the same script from the Link patch command, and I get absolutely no sign of it running in the output window.
"$(StudioDir)/bin/crossscript" "load(\"$(ProjectDir)/calc_crc32.js\");calc_crc32(\"$(TargetPath)\");"
Thanks for the help.
-
Michael,
I agree with Christian, it looks like $(TargetPath) isn't being expanded - the only causes for this I can think of are that there is a typo in your command or you are using a very old version of CrossWorks.
If you are still stuck, attach your project and I'll take a look. If you don't want your project to be available publicly I suggest you create a ticket and we'll take it from there.
Regards,
Jon
-
Jon - I still can not make a script that will get run from the link patch command. How do I create a ticket? I guess I need to take you up on reviewing my solution. Do I have to do anything to install cross script? Is there a command line that will for sure generate some sort of "File Not Found" error so I can determine if the link patch command is executing?
Thanks,
-
Michael,
The pre-compile and link patch commands are executed in exactly the same way, I would imagine the problem is the link patch command hasn't been set up correctly, for example set in a different build configuration to the one you are using.
CrossScript is included in the main CrossWorks installation, as you are running a pre-compile command that is using it, I guess it is installed correctly.
You can create a ticket, by clicking the "Submit A Request" button at the top of this page.
Regards,
Jon
-
I found out that if I put iexplorer.exe in the command field for Pre-Compile commands, it throws an error and halts the build process. So, I added the command to the link-patch command in every configuration in the project and to the solution properties as well and I get no error and no iexplorer.exe.
Is the submit a request Private? I don't want to send my customer's code to anybody but you for the purposes of helping out. I believe I have had strangers reply to requests before. It is difficult for me to discern which page is private and which is public, so I may be confused.
-
Michael,
Tickets are private, only visible by Rowley Associates support staff.
If you don't want to send us your code, just send the .hzp file - it may be sufficient to diagnose the problem. Alternatively, try reproducing the problem with one of our example projects and send us that.
Regards,
Jon
-
Even though this is an old thread, I was trying to do the same task but got the same error as the poster. I didn't see a solution but figured out the problem. The user was entering
(StudioDir)/bin/crossscript" "load(\"$(ProjectDir)/calc_crc32.js\");calc_crc32(\"$(TargetPath)\");
Instead of
"(StudioDir)/bin/crossscript" "load(\"$(ProjectDir)/calc_crc32.js\");calc_crc32(\"$(TargetPath)\");"
Please sign in to leave a comment.
Comments
27 comments