cancel
Showing results for 
Search instead for 
Did you mean: 

Impossible to check data for checksums using SPI

Dreamer3D
Associate III

Hello,

I’m using two STM32 F4 boards to continuously send and receive data over SPI communication.

The first board is configured as the Master and only transfers data, while the second board is configured as the Slave and only receives data.

I have already manually checked my data using an oscilloscope and debug tools, and I receive exactly the data I transmit.

Now, I use a checksum to verify the integrity of my data. I have two problems:

  1. On Master Side: The sprintf() function alters my data. When I use sprintf() on the Master side, I get different checksum values even if I transfer the same data. I resolved this problem by using memcpy(), but this complicates things when adding several parameter values into the buffer. Do you know a better solution if I want to do something like sprintf((char *)data_tx.msg, "IdFrame%d", IdFrame) where I can easily load the buffer with several parameters without altering it?

  2. On Slave Side: I compute the checksums directly from the data buffer received from SPI without any manipulation, but I get different checksum values even I send the same data from the Master.

This is my code

 

 

/*
	MASTER BOARD
*/
#define MSG_SIZE 300
struct Struct_Formatted_Data {
	uint8_t msg[MSG_SIZE];
	uint8_t checksum;
} __attribute__((packed));

struct Struct_Formatted_Data data_tx;
int size_of_struct_formatted_data = sizeof(struct Struct_Formatted_Data);

uint8_t calculate_checksum(uint8_t *data, size_t length) {
    uint8_t checksum = 0;
    for (size_t i = 0; i < length; i++) {
        checksum += data[i];
    }
    return checksum;
}

int main(){

	while(1){
		sprintf((char *)data_tx.msg, "{\"DATA:{\"IdFrame\":5,\"AccVert\":5,\"Pression1\":5,\"Pression2\":5}}"); //This does not give the same checksums every iteration
		
		memcpy(data_tx.msg, "{\"DATA:{\"IdFrame\":5,\"AccVert\":5,\"Pression1\":5,\"Pression2\":5}}", size_of_struct_formatted_data); //This does not give the same checksums every iteration

		data_tx.checksum = calculate_checksum((uint8_t *)data_tx.msg, size_of_struct_formatted_data);
		
		HAL_SPI_Transmit(&hspi1, (uint8_t *)&data_tx, size_of_struct_formatted_data, HAL_MAX_DELAY);

		HAL_Delay(100);
	}
}

/*
	SLAVE BOARD
*/
volatile int msgFromSPI = 0;

#define MSG_SIZE 300
struct Struct_Formatted_Data {
	uint8_t msg[MSG_SIZE];
	uint8_t checksum;
} __attribute__((packed));

struct Struct_Formatted_Data data_tx;
int size_of_struct_formatted_data = sizeof(struct Struct_Formatted_Data);

uint8_t calculate_checksum(uint8_t *data, size_t length) {
    uint8_t checksum = 0;
    for (size_t i = 0; i < length; i++) {
        checksum += data[i];
    }
    return checksum;
}

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) {
	if(hspi->Instance == hspi1.Instance && -1 == msgFromSPI) {
		 msgFromSPI = 1;
	}
}

int main(){
	while (1){
		if (1 == msgFromSPI){ //Process the message
			msgFromSPI = 0;

			HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
			checksum_computed = calculate_checksum((uint8_t *)data_tx.msg, size_of_struct_formatted_data);

		} else if (0 == msgFromSPI){
			msgFromSPI = -1;

			HAL_SPI_Receive_DMA(&hspi1, (uint8_t *)&data_tx, size_of_struct_formatted_data);
		}
	}
}

 

Thanks in advance for your help

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

You should zero-initialize the entire structure. sprintf will only modify the start of it, up until the null terminating character. Characters after that will not be modified, but are being used by your checksum calculation.

> I compute the checksums directly from the data buffer received from SPI without any manipulation, but I get different checksum values even I send the same data from the Master.

Logically, then either the data is different or the checksum function is invalid, right?

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

2 REPLIES 2
TDK
Guru

You should zero-initialize the entire structure. sprintf will only modify the start of it, up until the null terminating character. Characters after that will not be modified, but are being used by your checksum calculation.

> I compute the checksums directly from the data buffer received from SPI without any manipulation, but I get different checksum values even I send the same data from the Master.

Logically, then either the data is different or the checksum function is invalid, right?

If you feel a post has answered your question, please click "Accept as Solution".
Dreamer3D
Associate III

Thank you for your response,

My code works partialy.

If I transmit the same data in a loop from the Master using this code: snprintf((char *)data_tx.msg, MSG_SIZE, "IdFrame=0"); then I the same checksum on the Slave.

However, if I add a parameter, so the data change every iteration: snprintf((char *)data_tx.msg, MSG_SIZE, "IdFrame=%d", IdFrame); then I get different checksum on the Slave.

I still think the problem is related to the snprintf().

I do not understand what you said about sprintf() will only the start of it.