cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 SPI send/receive issue

MSavc
Associate II

Hi!

I have an issue with SPI communication on STM32F746 MCU.

I have two MCU connected via SPI on my board in 16 bit mode, both MCU`s are STM32F746. At start point it seems normal, but after some time it starts to drop packeges cause CRC32 check(CRC32 computes on CRC module by hardware) not solved.

When i debugging dropped packets, i`ve see a repetition of pervious byte in next cell of receive buffer(for debugging, all cellc in buffer are initialize with unique value).

It not deterministically, so most part of packets are normal, but i wanna solve this "bug".

Can somebody help me?

12 REPLIES 12
T J
Lead

how are you reading the receive packets ?

Reflection or some other signal quality problem on the SPI clock, maybe?

MSavc
Associate II

Both MCU`s placed on one PCB, trace between them is very short, so, i think it`s not a clock. Same problem i have with another projects with f746 MCU, where i`m using another PCB`s.

I`m send and receive packets with HAL_SPI_TransmitReceive_DMA function, here is the code:

//transmit buff by timer irq
void TIM8_TRG_COM_TIM14_IRQHandler(void)
{
  /* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 0 */
 
  /* USER CODE END TIM8_TRG_COM_TIM14_IRQn 0 */
  HAL_TIM_IRQHandler(&htim14);
  /* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 1 */
	extern uint16_t recv_data_buff[BUFF_SIZE], transmit_data_buff[BUFF_SIZE];
	extern uint16_t pack_cnt;
	extern CRC_HandleTypeDef hcrc;
	extern SPI_HandleTypeDef hspi5;
	extern uint8_t received;
	if(received)
	{
		received = 0;
		//uint32_t 
	HAL_GPIO_WritePin(CPU_SPI_RXTXLEVEL_GPIO_Port, CPU_SPI_RXTXLEVEL_Pin, SET);
	HAL_GPIO_WritePin(CPU_SPI_RXTXLEVEL_GPIO_Port, CPU_SPI_RXTXLEVEL_Pin, RESET);
	for(uint8_t i = 0; i < 100; i++)
	{
		if(HAL_GPIO_ReadPin(CPU_RXTXCONTROL_GPIO_Port, CPU_RXTXCONTROL_Pin) == RESET)
		{
			transmit_data_buff[start_marker] = START_MARKER_VALUE;
			transmit_data_buff[packet_cnt] = pack_cnt++;
			transmit_data_buff[service_word] = SERVICE_WORD_VALUE;
			uint16_t p = 0x0000;
			for(uint16_t i = data; i < checksum; i++)
				transmit_data_buff[i] = p++;
			uint16_t * pbuff = &transmit_data_buff[1];
			uint32_t chksum_buff[30];
			for(uint8_t i = 0; i < 30; i++)
		{
			chksum_buff[i] = 0;
				for(uint8_t j = 0; j < 2; j ++)
				{
					chksum_buff[i] |= (uint32_t) (*pbuff << (16U *(1 - j)));
					pbuff++;
				}
		}
		uint32_t crc32 = HAL_CRC_Calculate(&hcrc, (uint32_t *)chksum_buff, 30);
		transmit_data_buff[checksum] = (uint16_t)(crc32 >> 16U);
		transmit_data_buff[checksum + 1] = (uint16_t) crc32;
		transmit_data_buff[finish_marker] = FINISH_MARKER_VALUE;
		for(uint8_t i = 0; i < 64; i++)
		transmit_data_buff[i + 64] = transmit_data_buff[i];
		//HAL_SPI_Transmit_DMA(&hspi5, (uint8_t *) transmit_data_buff, BUFF_SIZE);
		HAL_GPIO_WritePin(CPU_SPI_CS_GPIO_Port, CPU_SPI_CS_Pin, RESET);
		HAL_SPI_TransmitReceive_DMA(&hspi5, (uint8_t *) transmit_data_buff, (uint8_t *) recv_data_buff, BUFF_SIZE);
		//HAL_SPI_TransmitReceive_IT(&hspi5, (uint8_t *) transmit_data_buff, (uint8_t *) recv_data_buff, BUFF_SIZE);
		break;
		}
	}
}
  /* USER CODE END TIM8_TRG_COM_TIM14_IRQn 1 */
}
 
//check crc and markers on DMA callback
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
  /* Prevent unused argument(s) compilation warning */
  //UNUSED(hspi);
	if (hspi->Instance == SPIx){
		uint32_t chksum_buff[30];
		uint16_t * pbuff = &recv_data_buff[1];
		//if(recv_data_buff[0] != (uint16_t)0x6801)
			//start_bit_check++;
		packs_summary++;
		if((recv_data_buff[64] != (uint16_t)0x6801) && (recv_data_buff[0] != (uint16_t)0x6801))
			start_bit_check++;
		for(uint8_t i = 0; i < 30; i++)
		{
			chksum_buff[i] = 0;
				for(uint8_t j = 0; j < 2; j ++)
				{
					chksum_buff[i] |= (uint32_t) (*pbuff << (16U *(1 - j)));
					pbuff++;
				}
		}
		uint32_t chksum;
		chksum = ((uint32_t)recv_data_buff[checksum] << 16U) | (uint32_t)recv_data_buff[checksum + 1];
		uint32_t crc32;
		crc32 = HAL_CRC_Calculate(&hcrc, (uint32_t *)chksum_buff, 30);
		if (chksum == crc32)
			received_packet_cnt++;
		else
		{
			pbuff = &recv_data_buff[65];
		//packs_summary++;
		for(uint8_t i = 0; i < 30; i++)
		{
			chksum_buff[i] = 0;
				for(uint8_t j = 0; j < 2; j ++)
				{
					chksum_buff[i] |= (uint32_t) (*pbuff << (16U *(1 - j)));
					pbuff++;
				}
		}
		uint32_t chksum = ((uint32_t)recv_data_buff[checksum + 64] << 16U) | (uint32_t) recv_data_buff[checksum + 65];
		uint32_t crc32 = HAL_CRC_Calculate(&hcrc, (uint32_t *)chksum_buff, 30);
		if (chksum == crc32)
			received_packet_cnt++;
		else
			packs_dropped++;
		}
		HAL_GPIO_WritePin(CPU_SPI_CS_GPIO_Port, CPU_SPI_CS_Pin, SET);
		HAL_GPIO_WritePin(CPU_SPI_RXTXLEVEL_GPIO_Port, CPU_SPI_RXTXLEVEL_Pin, SET);
		//HAL_GPIO_TogglePin(CPU_LED1_GPIO_Port, CPU_LED1_Pin);
		//HAL_SPI_DeInit(&hspi5);
		//HAL_SPI_Init(&hspi5);
		//HAL_Delay(1);
		received = 1;
	}

Hopefully this will help: When the CRC module is configured to produce a 32-bit CRC it expects to run over an integral number of 32-bit words. So I had to ensure the byte count passed to HAL_CRC_Calculate() was increased to an evenly divisible-by-4 boundary and the memory in the buffer beyond the "real" data was cleared.

One other thing I did was use __HAL_CRC_INITIALCRCVALUE_CONFIG() before calling HAL_CRC_Calculate().

MSavc
Associate II

Problem not with CRC: when i debugging corrupted received packet, i see corrupted data in buffer before HAL_CRC_Calculate(), CRC working fine for me. It`s trouble with SPI module or with DMA.

OK, are you flushing/invalidating the data cache as needed (or are the buffers in non-cached memory)?

MSavc
Associate II

I`m not flushing or invalidating data in buffers, but every packet have same data (i`m use it for debugging), so they are doesn`t needed to flush or invalidate because data is the same in each packet.

OK, next guess! :grinning_face:

Is BUFF_SIZE evenly divisible by 4? If not, try making it so.

MSavc
Associate II
#define BUFF_SIZE 128

Yes, it`s divisible by 4.