cancel
Showing results for 
Search instead for 
Did you mean: 

srec_cat CRC calculated over hex file doens't match one calculated with CRC peripheral

CiuppaPT
Associate III

Hello,

  

I know this has been discussed before, but following your procedure i am still unable to generate with srec_cat the same CRC of one generated by STM32 CRC hw peripheral.

did you make some other tricks in order to have match between the two CRC calculation over the whole STM32F746G 1MB of flash?

I post my chesum.bat file launched in post compliation

..\srec_cat.exe %1 -Intel -fill 0xFF 0x08000000 0x080FFFFC -STM32 0x080FFFFC -o 06_F746-DISCO-CRC_SRECORD.hex -Intel

8 REPLIES 8

How do you configure the CRC module in STM32, and then how do you feed it?

Try this on some shorter portion of the file, post that portion and results of both calcutions.

JW

Dfarr.1
Senior

I am no expert at this. But I got my CRC system working after lots of guides followed and a couple of questions on here. I'll try and pay it forward.

Here's my post from when I was trying to figure all this out. Its a bit scattered, but there are a couple of links there that were helpful to me:

https://community.st.com/s/question/0D53W00000jo7VhSAI/flash-integrity-crc

So here's my working solution. Hold onto your hat.

I've split my SREC script into 3 post-build steps. The 3 steps are called by a post build batch file:

0_postbuild.bat

Call this from your IDE as a post-build step. You'll have to define a path variable in your IDE to srec_cat.exe to use this batch file as-written.

..\0_postBuild.bat ${SREC_PATH} ${ProjName}
@echo off
set Srec_Path=%1
set ProjName=%2
set unfill=%3
 
%Srec_Path%\srec_cat.exe %ProjName%.hex @..\1_fillgaps.srec
 
if not "%unfill%"=="" (
	%Srec_Path%\srec_cat.exe @..\2_sign.srec -o 2_signed.hex -Intel -line-length=44
	%Srec_Path%\srec_cat.exe @..\3_unfillgaps.srec -o %ProjName%_CRC.hex -Intel -line-length=44
	echo "WARNING %ProjName%_CRC.hex has had all 0xFF data stripped out for a smaller hex file size and faster programming time.  Entire flash must be erased to 0xFF before uploading this hex file."
) else (
	%Srec_Path%\srec_cat.exe @..\2_sign.srec -o %ProjName%_CRC.hex -Intel -line-length=44
)

1_fillgaps.srec

-Intel                              # type Intel Hex
-fill 0xFF 0x08000000 0x08200000    # Memory from 0x08000000 to 0x08200000 (stm32f777 2Mbyte)
-o 1_filled.hex             		# Output file
-Intel                              # Output type Intel Hex
-line-length=44						# Set fixed line width to match original output from CUBEIDE for easy comparison

Fill all empty space in the hex file with known data (0xFF in my case) out to the full size of the device memory. Watch out! SREC uses inclusive addressing for the end address for padding.

So the 2MB on-chip flash memory of my device is addressed as:

0x08000000 0x08200000

This padding is necessary to ensure every bit used to calculate the CRC during post build matches every bit used to compute CRC in the hardware. We can't trust memory that isn't explicitly programmed.

I also did some formatting on line-length of the file for easier comparison with the STMCubeIDE hex file output. Helped me with debugging.

2_sign.srec

									# Replace the last word with calculated CRC to match what hardware will produce
1_filled.hex                		# Source hex file
-Intel                              # input Intel Hex
-crop 0x08000000 0x081FFFFC         # CRC from 0x08000000 to 0x081FFFFF-4bytes (stm32f777 2Mbyte)
-STM32 0x081FFFFC                   # Put CRC32 here (calculate identical as STM32)
									#Optional, move the following lines to the IDE post build command to use ${ProjName} parameter to create file name dynamically
#-o 2_signed.hex       			# output file name
#-Intel                             # type Intel Hex
#-line-length=44					# adjust line length to match original output from CUBEIDE for easy comparison

2 things here. We crop the file by snipping out the very last word to leave us space to graft in the computed CRC. Then compute the CRC using the STM32 algorithm (built into SREC) and place the result at the end of the file in the space we just made by cropping. Line length formatting again for easy visual comparison during debugging.

Watch out again! SREC uses non-inclusive addressing for the end address for cropping.

So the 2MB on-chip flash memory of my device is cropped as:

0x08000000 0x081FFFFC

And again! When setting a destination for the CRC output, SREC uses normal addressing. So the CRC will be placed at

0x081FFFFC

Very confusing but you can noodle around with the numbers by reading the hex file outputs manually.

3_unfillgaps.srec

									# optional, remove 0xFF to shrink hex file and reduce programming time
									#WARNING! strictly requires chip erasure to 0xFF before programming
2_signed.hex           				# Source hex file
-Intel                              # type Intel Hex
-unfill 0xFF                        # Remove >256 bytes blocks 0xFF
									#Optional, move the following lines to the IDE post build command to use ${ProjName} parameter to create file name dynamically
#-o YourProjectNameHere_CRC.hex     # output file name
#-Intel                             # type Intel Hex
#-line-length=44					# adjust line length to match original output from CUBEIDE for easy comparison

Strip out all the padding we inserted. This makes the hex file smaller to store (intel hex supports sparse file data) and faster to load into the device. BUT it absolutely requires that the device memory be erased to known values before programming. Line length formatting again for easy visual comparison during debugging.

This step is purely optional. I'm actually not using it right now because I can't guarantee that my team's devices are being erased properly at each program. You can just take the output hex file after step 2. Its valid, just more data than strictly necessary so device programming time is longer.

Then in code I'm doing the following:

static void MX_CRC_Init(void)
{
  hcrc.Instance = CRC;
  hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
  hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
  hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
  hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
  hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_WORDS;
  if (HAL_CRC_Init(&hcrc) != HAL_OK)
  {
    Error_Handler();
  }
}

This is generated code. I didn't type this. But mess with your MX configuration (Computing>CRC) to get these settings to come out.

Then to actually perform the CRC check in hardware assuming ALLLLL this other stuff is working properly:

#define BUFFER_SIZE (0x200000 - 4) / 4
void flashIntegrityCheck()
{
    uint32_t * myDataBuffer = (uint32_t*) 0x08000000;
 
    uwCRCValue = HAL_CRC_Calculate(&hcrc, myDataBuffer, BUFFER_SIZE);
 
    if (uwCRCValue == *flashCRC)
    {
        //CRC ok
    }
    else
    {
        //CRC fail
    }
}

Notice the size is computed in WORDS to match with the CRC hardware configuration. The size should exclude the last word where we grafted in the CRC computed by SREC. On the other hand, if you include it you'll always get zero as the result of a correct hardware CRC computation, so that might be useful to you.

I made 2 main mistakes when I was figuring it out:

  1. lots of address/memory size errors due to the different inclusive/non-inclusive/word/byte addressing. Visually looking at the hex file output really helped me struggle through those bugs. This is part of the reason I adopted the 3-step approach.
  2. STM hardware CRC wasn't configured in a way that matched the SREC.STM32 algorithm.
CiuppaPT
Associate III

FInally i found the solution. The CRC from SREC was correct. It was the internal FLASH corrupted by previous download that corrupt the internal calculation by the CRC peripheral.

Thanks anyway for the advice. I will keep them

Hi Dfarr.1, I can't build with your code, see picture:


_legacyfs_online_stmicro_images_0693W00000bkxwxQAA.pngimpossible to find path.


_legacyfs_online_stmicro_images_0693W00000bkxx2QAA.pngas you can see, this the place where the file are included, and the srec path.

can you help for this? thanks.

Solved, the problem was in a missed #. The code work perfectli flowless... very thanks for this help....

I'm glad you found it! I wasn't seeing the problem from your post.

Would you consider posting a few lines of your code where you found the error to help others in case they have the same problem?

hi Dfarr, was only "Replace the last word with calculated CRC to match what hardware will" without "#". Copyng from screen the file I made a mistake... really thanks for share your work! thanks.