DFU Protocol how is the CRC-32C of the flash row calculated?

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

cross mob
wistc_299286
Level 3
Level 3
10 replies posted 10 sign-ins First solution authored

Hi Everyone,

I am writing a program that opens a .cycad2 file and sends the data over UART. In the program I format the flash rows using the Infineon-AN213924_PSoC_6_MCU_Device_Firmware_Update_Software_Development_Kit_Guide-ApplicationNotes-v09_00-EN user guide and from a record of a successful DFU programming over UART which shows the DFU protocol and formatting.

I have successfully programed a device using the boot loader app from PSOC creator. I am using the AN213924 example project with App0, and App1 as a working model to test my code. 

My question is how is the CRC-32C calculated on page 54 of the guide for the 0x49 DFU command (Program Data)? I have a function to calculate CRC-32C, but I'm unsure how the row of data in the .cycad2 is broken down to generate the CRC-32C bytes? Are all the bytes in the row added together, then a CRC-32C is performed on the result? Is the flash row broken into 4 byte 32 bit number, then added together for the CRC-32C? I don't see how it is specified in the document. All the other data packets with the DFU 0x37 command use a checksum which I have been able encode and matches the UART data I have observed.

I see these 4 bytes while watching the a successful DFU programming with App1 on the UART bus with the 0x49 command: 0x15, 0x61, 0x56, and 0x48 which I think is 0x48566115 to match the byte order of the other byte fields. 

The row that generated this CRC-32C is below from the app1 .cyacd2 file: 

:0000041000200008230104100D00000085010410000000000000000000000000000000000000000000000000000000008101041000000000000000008101041081010410810104108101041081010410810104108101041081010410810104108101041081010410810104108101041081010410810104108101041081010410810104108101041081010410810104108101041081010410810104108101041081010410810104108101041081010410810104108101041081010410810104108101041010B5064C2378002B07D1054B002B02D0044800E000BF0123237010BD3C07000800000000B8240410084B10B5002B03D00749084800E000BF07480368002B00D110BD064B002BFBD09847F9E70000000040070008B8240410E8010008000000007047FFF7FDFF72B60F4C104DAC4209DA21686268A368043B02DBC858D050FAE70C34F3E70A490B4A0020521A02DD043A8850FCDC084809490860BFF34F8F00F005F900F01DF8FEE7BC240410D42404103C070008140900080001000808ED00E0FEE7FEE700B504207146084202D0EFF3098001E0EFF30880043001F04BFBFEE710B562B6014800F067F9FEE70000051010B5002001F0BAF810BDC04670B56249E0239B00CB580F2213401A00D0329200525807210A40032A05D0042A06D0002A12D15A4814E05A4A106811E01A00C0329200554952581F210A40112A06D0132A

How is this CRC-32C evaluated? This is the last part I need to figure out to get my remote DFU updated program working.

0 Likes
1 Solution
wistc_299286
Level 3
Level 3
10 replies posted 10 sign-ins First solution authored

Hello Ninad,

I wanted to report that I was able to perform the CRC-32C  on the .cyacd2 rows of data! The issue I found was with the ~ operator in python. In C this operator inverts the bits of a variable, but in python it performs a -(x+1) operation which is not the same. So in above code snippet I need to replace:

    crc  =  ~crc

With:

     crc = ~crc  & 0xFFFFFFFF

When I do this the CRC-32C result matches what is sent for the first row from the DFU host program in creator. 

I was able to find this out by debugging App0 and setting a breakpoint at the Cy_DFU_DataChecksum() and doing a set by step debug along with my python code when I initiate a data transfer from app1. I now have a DFU host programmer class in python that will open a .cyacd2 file and format each row to pass app data to a DFU on a psoc6. Thank you very much for you help. 

View solution in original post

0 Likes
5 Replies
nin
Moderator
Moderator
Moderator
50 solutions authored 100 replies posted First like given

Hi @wistc_299286 ,

 

Q1: My question is how is the CRC-32C calculated on page 54 of the guide for the 0x49 DFU command (Program Data)?

Ans: Cy_DFU_DataChecksum() is a function that computes a CRC-32C for the provided number of bytes contained in the provided buffer. This function is used to validate the Program Data and Verify Data DFU commands and a metadata row.

Please refer to DFU Middleware Library API Reference or refer to https://github.com/Infineon/dfu/blob/master/cy_dfu.c. The file cy_dfu.c provides the implementation of DFU Middleware which contains an implementation of the Cy_DFU_DataChecksum() function.

----

Q2: I have a function to calculate CRC-32C, but I'm unsure how the row of data in the .cycad2 is broken down to generate the CRC-32C bytes?

Ans: Row Checksum is not available in .cyacd2, it is generated by DFU Host Tool and will be added to the Packet.

Please follow the section:  Generating a Flash patch (.cyacd2) File for use with the Bootloader SDK  ofCyMCUElfTool 1.0 User Guide.

---

Q3: Are all the bytes in the row added together, then a CRC-32C is performed on the result? Is the flash row broken into 4 byte 32 bit number, then added together for the CRC-32C?

Ans: Each byte of data in the .cyacd2 file followed by : is represented by two characters. For example, a byte 0x1E is represented by the characters 0x31 (ASCII ‘1’) followed by 0x45 (ASCII ‘E’). All multi-byte fields are little-endian.

Please follow appendix C .cyacd2 file format of PSoC™ 6 MCU Device Firmware Update (DFU) software development kit guide for more details. Table 12 cyacd2 Data Row Structure shows the structure of the row in the .cyacd2 file.

 

Let me know if you have any other doubts.

 

Best regards,

Ninad

 

 

0 Likes
wistc_299286
Level 3
Level 3
10 replies posted 10 sign-ins First solution authored

Hello Ninad,

Thank you for the links to all the resource documents and for answering my questions. I have opened the function Cy_DFU_DataChecksum() in cy_dfu.c to look at the how the CRC-32C is calculated in psoc6. Here is the code software function which is some very interesting code:

wistc_299286_0-1671479679055.png

I am trying to replicate the same functionality in Python that will be used as the host system for the boot loader to the Psoc6 but my results do not match the correct CRC-32C transmission that I observed. 

Are the bytes in the cyacd2 row file constructed into an array of 32 bit words before being passed into the Cy_DFU_DataChecksum()? For example in the first row we have: 0x00, 0x20, 0x00, 0x08 after the 4 address bytes at the beginning of the row in my first post. Does this mean that these bytes are part of a 32 bit word 0x00200008? Or 0x08002000? ( I know you mentioned that PSOC6 is little endian, but the byte order isn't clear from the text file and the UART transmission. )

If they are 32 bits words, does that mean that each .cyacd2 file row would have 128 32 bits words that a CRC-32C is performed on? (512 bytes/ 4 byte word = 128 32 bit words)

I've tried many ways to replicate the above code in python, but my final result doesn't equal 0x15, 0x61, 0x56, 0x48 in either big endian or little endian in the UART transmission. 

Here is the working UART transmission (example app1) for the last DFU command (program file) on the first row of data in the .cyacd2 file that I am trying to match the CRC-32C code for:

wistc_299286_1-1671481050148.png

 

 

0 Likes

Here is my python code if that helps to understand what I'm doing:

wistc_299286_2-1671482211785.png

The variable "conversion_list" contains the 32 bit word conversions  that has been performed on the .cyacd2 row data. The list contains the 128 elements.

 

0 Likes
nin
Moderator
Moderator
Moderator
50 solutions authored 100 replies posted First like given

Hi @wistc_299286 ,

 

Are the bytes in the cyacd2 row file constructed into an array of 32 bit words before being passed into the Cy_DFU_DataChecksum()?

The row in the .cyacd2 row file is generated by is generated by DFU Host Tool and will be added to the Packet. Cy_DFU_DataChecksum() function will calculate CRC-32C internally.

Cy_DFU_DataChecksum function computes a CRC-32C for the provided number of bytes contained in the provided buffer. Cy_DFU_DataChecksum function takes following inputs:

param address (uint8_t): The pointer to a buffer containing the data to compute the checksum for.

param length (uint32_t): The number of bytes in the buffer to compute the checksum for.

param params: The pointer to a DFU parameters structure.

Does this mean that these bytes are part of a 32 bit word 0x00200008? Or 0x08002000? 

As mentioned earlier, data row has a structure with 4 bytes of address followed by N bytes. Here N bytes are total amount of data to be sent followed by Program data byte (Command Byte: 0x49). 0x00, 0x20, 0x00, 0x08 is a part of address bytes. Little endian format is followed here (0x08002000).

---

If they are 32 bits words, does that mean that each .cyacd2 file row would have 128 32 bits words that a CRC-32C is performed on?

The .cyacd2 file contains data in the form of ASCII hex numbers, similar to Intel hex format. Each byte of data is represented by two characters.

Each byte of data is represented by two characters. For example, a byte 0x1E is represented by the characters 0x31 (ASCII ‘1’) followed 0x45 (ASCII ‘E’). That means for each byte of data representation, 32 bits (16 * 2 ) are required.

If they are 32-bit words, .cyacd2 file row would have 32-word bits.

---

Could you please share your complete python code? It would be easy for us to understand how exactly you are calculating the CRC if you share the code file. It will help to troubleshoot why there is CRC-32C mismatch during transmission.

---

Let me know if you have any other doubts.

 

Best regards,

Ninad

0 Likes
wistc_299286
Level 3
Level 3
10 replies posted 10 sign-ins First solution authored

Hello Ninad,

I wanted to report that I was able to perform the CRC-32C  on the .cyacd2 rows of data! The issue I found was with the ~ operator in python. In C this operator inverts the bits of a variable, but in python it performs a -(x+1) operation which is not the same. So in above code snippet I need to replace:

    crc  =  ~crc

With:

     crc = ~crc  & 0xFFFFFFFF

When I do this the CRC-32C result matches what is sent for the first row from the DFU host program in creator. 

I was able to find this out by debugging App0 and setting a breakpoint at the Cy_DFU_DataChecksum() and doing a set by step debug along with my python code when I initiate a data transfer from app1. I now have a DFU host programmer class in python that will open a .cyacd2 file and format each row to pass app data to a DFU on a psoc6. Thank you very much for you help. 

0 Likes