Checksum Description

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

I'm working on creating a custom bootloader host program. I need to compute the checksums of the .cyacd file and to verify against the checksum calculated by the PSoC. I've seen some mixed descriptions and implementations in calculating this checksum and wonder if anyone could help.

To help guide the answers here is a list of what I'm confused about and what I understand.

   

1. The .cyacd is in ASCII and has to be parsed into hex values. I've done this in my code using help from btldrutils.

   

2. Format of the header in the .cyacd file is [4-byte silicon ID][1-byte Silicon Rev][1-byte checksum type]

   

Format of row in the .cyacd file is [1-byte array ID][2-byte row number][2-byte data length][64 data bytes][1 byte checksum]

   

3. The start of the program row is marked by a ':' and the end of the row is marked by '..'.

   

4. I'm using the basic summation (type 00 in header) from the data sheet this adds up every byte sent (besides the checksum) and takes the 2's complement of this value. Note- App note AN86526 attaches example code to run a bootloader host on a PSoC kit board and in the code the checksum for each row is calculated without taking the 2's complement.

   

 

   

My questions revolve around 4.

   

1. Is the header included in the checksum calculation?

   

2. Are the semi colons and periods part of this calculation?

   

3. Is the checksum calculated for each row or is it a running checksum for the entire file?

   

4. If its a running checksum do you take the 2's complement each row and then add it to the continuous checksum or do you take the 2's complement to verify that row and then add the number before you took the 2's complement to the continuous checksum?

   

5. Do you just add everything up and check the data after each row?

   

 

   

Any help or directions toward a file that would help me out would be great.

0 Likes
1 Solution
Anonymous
Not applicable

Hi Brendan,

   

The header and semicolon is not included as part of the checksum computation. The header is only used for validating the properties of the device (whether we are trying to bootload to the correct device, done using Silicon ID match) and is done using CyBtldr_ParseHeader.

   

Now, in the header itself - we specify the checksum type which indicates the type of checksum used in the packets sent between the bootloader and the bootloader host during the bootloading operation. If this byte is 0, the checksum is a basic summation. If it is 1, the checksum is CRC-16.

   

Please refer to the implementation of CyBtldr_ComputeChecksum in cybtldr_commad.c file. Simple SUM checksum is implemented in two's complement form: (you can find "return (1 + ~sum);").

   

Also, we validate if each row is correctly programmed. Hence we have a row checksum and check if the checksum received from bootloader matches the expected row checksum stored in cyacd file. If TRUE, then we conclude that the row is correctly programmed.

View solution in original post

0 Likes
15 Replies
Anonymous
Not applicable

Hi Brendan,

   

The header and semicolon is not included as part of the checksum computation. The header is only used for validating the properties of the device (whether we are trying to bootload to the correct device, done using Silicon ID match) and is done using CyBtldr_ParseHeader.

   

Now, in the header itself - we specify the checksum type which indicates the type of checksum used in the packets sent between the bootloader and the bootloader host during the bootloading operation. If this byte is 0, the checksum is a basic summation. If it is 1, the checksum is CRC-16.

   

Please refer to the implementation of CyBtldr_ComputeChecksum in cybtldr_commad.c file. Simple SUM checksum is implemented in two's complement form: (you can find "return (1 + ~sum);").

   

Also, we validate if each row is correctly programmed. Hence we have a row checksum and check if the checksum received from bootloader matches the expected row checksum stored in cyacd file. If TRUE, then we conclude that the row is correctly programmed.

0 Likes
Anonymous
Not applicable

Is the the row checksum just the checksum for the data in that row? Or is it a combination of the rows before?

0 Likes
Anonymous
Not applicable

It is only for that row.

0 Likes
Anonymous
Not applicable
        One more small clarification on this: If you check the Host project, there is a variable called "checksum2". This is the final checksum of a particular row. This checksum2 is used for ensuring the validity of the row when CyBtldr_VerifyRow API is used (Device sends the flash row checksum). The checksum2 value will not have the headers (arrayId and Row Number) as part of the checksum. But, there is another variable called "checksum". This is the checksum which is obtained from the cyacd row and this includes the header as well (header means arrayId and Row Number). Now, to this checksum - we again add arrayId and rowNum to get checksum2. checksum2 will not have the arrayId and rowNum as part of it.   
0 Likes
Anonymous
Not applicable

I have a similar question.  I would like to verify the checksum of the programmed flash memory as part of a BIT test upon startup.  So, at run time, I would like to checksum the flash memory and verify it with a known good value.  I was hoping that I could manually retrieve the checksum from the programmed *.hex file, and then use that value in a #define and check it...but upon further consideration, I realize this would not work because the checksum would change every time I edit the #define.  Now I am thinking that I could select a few flash memory locations, say 0x0003fffc through 0x0003ffff, and check their value...if they have not been written before, than I know that it is my first time running, so calculate checksum (but leave those locations out), then write the calculated value there.  Then, each startup, retrieve that memory and use that value to check against the run-time calculation.

I know this sounds sloppy, but I am unaware of another way...note also I am not terribly experienced in doing embedded software design.  The actual hardware design is not mine and cannot be changed, and the flash memory will be programmed once here, and then delivered to the customer.  I don't believe that the flash checksum is stored anywhere for me to use as my known good value, so...am I crazy?  Is there better way?

0 Likes

This is exactly what the bootloader component uses to verify (when requested) the bootloadable.

You may use the upmost flash row to store information, this will not get programmed when there is some flash left.

Bob

Anonymous
Not applicable

Thanks Bob!  So, I tried to write the flash, but the debugger shows all zeros at the location I am attempting to write.. Can you help me figure out where what my issue is?  Seems pretty straight forward.  This is my write flash call:

CyWriteRowData((CY_FLASH_NUMBER_ARRAYS-1),(CY_FLASH_NUMBER_ROWS-1),rowdata);

where "rowdata" properly initialized and is defined as:

uint8 rowdata[CY_FLASH_SIZEOF_ROW];

0 Likes

What value is returned by the CyWriteRowData() call? Check with .h file for meaning when != zero (0)

Did you made provisions for ECC? What are the ECC settings?

Bob

0 Likes
Anonymous
Not applicable

For reference, my target processor part number CY8C5888LTQ-LP097

My ECC settings under Configuration section in the system tab of the .cydwr file is:

     No checkmark for "Enable Error Correcting Code"

     Checkmark for "Store Configuration Data in ECC Memory"

The call to CyWriteRowData() call is returning a "1".  (I should have checked this before).  But, I am having trouble determining what that is.  I don't see where cystatus returns are defined, and my development environment seems unhappy with the CyFlash.h file, even though everything compiles and runs...:

pastedImage_1.png

Thanks...

0 Likes
Anonymous
Not applicable

I do not have BootLoader project, or a Bootloadable Project.  I am making the flash write call directly from my main project and testing using the debugger....is this an issue?

0 Likes

Can you please post your complete project or a shortened version that shows the error so that we all can have a look at all of your settings. To do so, use

Creator->File->Create Workspace Bundle (minimal)

and attach the resulting file.

Bob

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

I sure can.  I stripped out everything except the checksum stuff.  Thanks for your continued interest.  Note that I am running this on the CY8CKIT-050.

0 Likes
Anonymous
Not applicable

By the way, I may have accidentally had "Store Configuration Data in ECC Memory" set in the version posted above because I had moved from our actual hardware back to the Development kit hardware.  I continue to try on my end without the ECC options selected in the system page. 

0 Likes
Anonymous
Not applicable

I thought that I might have discovered the issue.  I read that I need to call CySetTemp() prior to trying to write row data.  This call returned zero, but I still get a return of 1 when calling CyWriteRowData();.  I also verified that the memory is not locked on the Flash Security page. Next, I figured I would try to call CyFlash_Start(), even though the documentation states that this is optional.  Interestingly, when making this call, the program hangs in CyFlash.c at this point:

while(0u == (CY_FLASH_SPC_FM_EE_CR_REG & CY_FLASH_EE_EE_AWAKE))

{

     ​/* Non-zero status denotes that the EEPROM/Flash is awake & powered. */

}

The comment suggests that the Flash is not awake/powered.  Is there something I need to do along these lines? 

0 Likes
Anonymous
Not applicable

Well, I got it.  Two issues:

1.  You must make a call to CySetTemp() prior to writing flash memory.

2.  The CY_FLASH_NUMBER_ROWS is equal to the total number of rows of flash, not the number of rows per array.  To use this in the CyWriteRowData() call you must divide by the number of arrays.  The error code was telling me I had one or more bad arguments in my call.  This is the call now:

CyWriteRowData((CY_FLASH_NUMBER_ARRAYS-1), ((CY_FLASH_NUMBER_ROWS/CY_FLASH_NUMBER_ARRAYS)-1), rowdata);

I still don't know why the CyFlash_Start() hangs, but it is not an issue for me.

0 Likes