cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 SPI Slave problems (wrong transmission)

KR51K
Associate III

Hello,

I'm struggling to get the SPI Slave on my STM32F4 running. I send 9 Byte from the master every 1ms with soft NSS:

	HAL_GPIO_WritePin( MCU_CS_GPIO_Port, MCU_CS_Pin, GPIO_PIN_RESET );
	SPISlaveTXdata[0] = frameCounter++;
	SPISlaveTXdata[1] = sys_getStatus();
	SPISlaveTXdata[COMM_PACKET_CS_POSITION] = chk_calculateChecksum16(SPISlaveTXdata, PACKET_SIZE-1 );
 
	status = HAL_SPI_TransmitReceive_DMA(&hspi1, (uint8_t *)SPISlaveTXdata, (uint8_t *)SPISlaveRXdata, PACKET_SIZE);
	if ( status != HAL_OK )
	{
		HAL_SPI_DMAStop(&hspi1);
		HAL_GPIO_WritePin( MCU_CS_GPIO_Port, MCU_CS_Pin, GPIO_PIN_SET );
	}

And later in the ISR:

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
	if ( hspi == &hspi1 )
	{
		uint16_t CS = chk_calculateChecksum16(SPISlaveRXdata, PACKET_SIZE-1);
		if (CS == SPISlaveRXdata[COMM_PACKET_CS_POSITION]) 
		{
			slavePacket.isPacketValid = true;
			rec++;
		}
		else
		{
			slavePacket.isPacketValid = false;
		}
		HAL_GPIO_WritePin( MCU_CS_GPIO_Port, MCU_CS_Pin, GPIO_PIN_SET );
	}
}

On the slave side I use an ext pin to detect the falling edge of the CS signal and call the receive function:

	status = HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)SPISlaveTXdata, (uint8_t*)SPISlaveRXdata, MASTER_SLAVE_COMM_FRAME_SIZE, 1);
	if ( status != HAL_OK )
	{
		HAL_SPI_Abort(&hspi1);
	}
	else
	{
		rec++;
	}

My problem is, that i often run into the HAL_SPI_Abort case. I used a further pin to see what happens: in blue you can see the CS signal. Before the TransmitReveive function I set the red pin to high, and afterwards to low. Here you can see that the TransmitReceive function runs into a timeout.

0693W000001cYd2QAE.png

So I tried to modify the TransmitReceive function to stop if CS is high again:

while ( ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U)) && ( HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_RESET ) )
{
...
}

Now, I have no more receive errors on the slave, and receive the complete packet of the Master (incl. checksum in the last word, so transmission is really completed).

But my problem is, that I don't get any complete packages on the master from the slave, because the last word (containing the checksum is missing/empty), although the time between the last clock and CS going high is (extremely) long:

0693W000001cYeAQAU.png

Maybe I don't see it, but what am I missing here? Why is the last word not transmitted??? Any ideas?

2 REPLIES 2
TDK
Guru

Looks like you're giving the slave about 25us to respond to the CS low and put data into the SPI buffer. Maybe this isn't enough time. Are all bytes except the last one correct?

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

Hi,

I tried it once again and some more (slightly) modifications, and now it is working - I don’t see any failures on the slave side.

But now I have the problem (maybe also before) that I have sometimes receive problems on the master side, where the MISO signal seems to be false. But running a scope in parallel, I see that the slave transmits the correct data. It isn’t only a bitflip or byteshift, but sometimes complete nonsense. Any idea how this could happen? The master code did not change...