cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with SPI3 on STM32H725ZGT6 device

SMali.3
Associate III

Hello

I would like to make SPI3 on my board with STM32H725ZGT6 micro-controller work.

Here is my initialization:

void MX_SPI3_Init(void) {
	GPIO_InitTypeDef GPIO_InitStruct;

	/* SPI3 parameter configuration*/
	hspi3.Instance = SPI3;
	hspi3.Init.Mode = SPI_MODE_MASTER;
	hspi3.Init.Direction = SPI_DIRECTION_2LINES;
	hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
	hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
	hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
	hspi3.Init.NSS = SPI_NSS_SOFT;
	hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
	hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
	hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
	hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
	hspi3.Init.CRCPolynomial = 0x0;
	hspi3.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
	hspi3.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
	hspi3.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
	hspi3.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
	hspi3.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
	hspi3.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
	hspi3.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
	hspi3.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
	hspi3.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
	hspi3.Init.IOSwap = SPI_IO_SWAP_DISABLE;
	if (HAL_SPI_Init(&hspi3) != HAL_OK) {
		Error_Handler();
	}
	//Now lets make our initialization

	__HAL_RCC_SPI3_CLK_ENABLE();
	__HAL_RCC_GPIOC_CLK_ENABLE();

	spi3UInttmp=(RCC->APB1LENR);
	sprintf(print_string,"SPI3 Device: APB1LENR register = 0x%x\n",spi3UInttmp);
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));

	/**SPI1 GPIO Configuration
  	PC10     ------> SPI1_SCK
	PC11     ------> SPI1_MISO
  	PC12     ------> SPI1_MOSI
	 */
	GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
	HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);


	(SPI3->CR1)|=0x00000001; //enable SPI
	(SPI3->CR1)&=0xfffffffe; //disable SPI

	/* SPI3 interrupt Init */
//    HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
//    HAL_NVIC_EnableIRQ(SPI3_IRQn);
//    writeSPI3Index=0;
//    readSPI3Index=0;



	(RCC->CFGR)&=0x0000ffff;
	(RCC->CFGR)|=0x60000000; //uC clock output 2 -> pll1_p_ck
	(RCC->CFGR)|=0x14000000; //division by 10
	(RCC->CFGR)|=0x00c00000; //uC clock output 1 -> pll1_q_ck
	(RCC->CFGR)|=0x00280000; //division by 10

	/**Clock Output 2
  	PC9     ------> MCO2
	 */
	GPIO_InitStruct.Pin = GPIO_PIN_9;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
	HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

	/**Clock Output 1
  	PA8     ------> MCO1
	 */
	GPIO_InitStruct.Pin = GPIO_PIN_8;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

void spiGeneral_Init(void) {
	GPIO_InitTypeDef GPIO_InitStruct;

	MX_SPI3_Init();
	/* PD11, PD12, PD13, - SPI address Decoder pins - Output */
	GPIO_InitStruct.Pin =  GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

	DEC_DISABLE_RESET

#if 0
	GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Alternate = 0x0;
	HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,1);
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_11,1);
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_12,1);
#endif

	sprintf(print_string,"SPI3 Device -> RCC source control register: RCC_CR = 0x%x\n",(unsigned int)(RCC->CR));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
	sprintf(print_string,"SPI3 Device -> RCC clock configuration register: RCC_CFGR = 0x%x\n",(unsigned int)(RCC->CFGR));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
	sprintf(print_string,"SPI3 Device -> RCC PLL configuration register: RCC_PLLCFGR = 0x%x\n",(unsigned int)(RCC->PLLCFGR));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
	sprintf(print_string,"SPI3 Device -> RCC domain 2 kernel clock configuration register: RCC_D2CCIP1R = 0x%x\n",(unsigned int)(RCC->D2CCIP1R));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
	sprintf(print_string,"SPI3 Device -> RCC APB1 clock enable register: RCC_APB1LENR = 0x%x\n",(unsigned int)(RCC->APB1LENR));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
	sprintf(print_string,"SPI3 Device -> RCC APB1 clock LP enable register: RCC_APB1LLPENR = 0x%x\n",(unsigned int)(RCC->APB1LLPENR));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));


}

 

After calling this initialization I get this printout:

SPI3 Device: APB1LENR register = 0xa28000
SPI3 Device -> RCC source control register: RCC_CR = 0x303f025
SPI3 Device -> RCC clock configuration register: RCC_CFGR = 0x74e8001b
SPI3 Device -> RCC PLL configuration register: RCC_PLLCFGR = 0x1ff000d
SPI3 Device -> RCC domain 2 kernel clock configuration register: RCC_D2CCIP1R = 0x0
SPI3 Device -> RCC APB1 clock enable register: RCC_APB1LENR = 0xa28000
SPI3 Device -> RCC APB1 clock LP enable register: RCC_APB1LLPENR = 0xeaffc3ff

I assume that the 3 clocks are present on SPI3 block. I can measure both pll1_q_ck (on pin MCO1 -> PA8 - 97 is 55MHz with divider 10) and pll1_p_ck (on pin MCO2 -> PC9 - 96 is 11MHz with divider 10) with an oscilloscope on the pins of the micro-controller.

Then I am periodically sending 6 bytes of information to the transmit buffer to this function:

unsigned int i_spi, i_spiTimeout;
//for now limited to 16 bytes in one frame
unsigned char SPI3_TxRx(unsigned char device, unsigned char *dataRx, unsigned char *dataTx, unsigned int datalength) { //sending and receiving 8 bit data stream
	(SPI3->CR1)&=0xfffffffe; //disable SPI

	(SPI3->CFG1)&=0x8fffffff; //Master baud rate to 000
	(SPI3->CFG1)|=0x70000000; //Master baud rate to SPI master clock/256

	(SPI3->CFG1)&=0xffbfffff; //disable CRC calculation
//	(SPI3->CFG1)|=0x00400000; //enable CRC calculation
//	(SPI3->CFG1)&=0xffe0ffff; //reset CRCSIZE value
//	(SPI3->CFG1)|=0x00070000; //set CRCSIZE to 8bit
	(SPI3->CFG1)&=0xfffffe1f; //reset FIFO Threshold
//	(SPI3->CFG1)|=0x000001e0; //set FIFO Threshold level to 16 data
	(SPI3->CFG1)&=0xfffffff0; //reset DSIZE number of bits in the data frame
	(SPI3->CFG1)|=0x00000007; //set DSIZE to 8 bit data frame

	(SPI3->CFG2)|=0x10000000; //SPI is always in the control of associated GPIOs
	(SPI3->CFG2)&=0xbfffffff; //SSOE is disabled
//	(SPI3->CFG2)&=0xfdffffff; //CPOL is 0 -> sck is 0 when idle
	(SPI3->CFG2)|=0x02000000; //CPOL is 1 -> sck is 1 when idle
	(SPI3->CFG2)&=0xfeffffff; //CPHA is 0 -> first clock transition is the first data capture edge
//	(SPI3->CFG2)|=0x01000000; //CPHA is 1 -> the second clock transition is the first data capture edge
	(SPI3->CFG2)&=0xff7fffff; //LSBFIRST is 0 -> MSB is transmitted first
//	(SPI3->CFG2)|=0x00800000; //LSBFIRST is 1 -> LSB is transmitted first
//	(SPI3->CFG2)&=0xffbfffff; //MASTER is 0 -> device configured as slave
	(SPI3->CFG2)|=0x00400000; //MASTER is 1 -> device configured as master
	(SPI3->CFG2)&=0xffc7ffff; //SPI Motorola
//	(SPI3->CFG2)|=0x00080000; //SPI TI
	(SPI3->CFG2)&=0xfff9ffff; //COMM is full duplex
//	(SPI3->CFG2)|=0x00020000; //COMM is simplex transmitter
	(SPI3->CFG2)&=0xffffff0f; //MIDI - master inter data idleness -> no delay
	(SPI3->CFG2)|=0x00000050; //MIDI - master inter data idleness -> 5 SPI clock cycles

	(SPI3->IER)&=0x00000000; //disable all interrupts

	sprintf(print_string,"SPI3 Device: Status register 1 = 0x%x\n",(unsigned int)(SPI3->SR));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));

	(SPI3->IFCR)|=0x0ff8; //clear all flags
	(SPI3->CR1)|=0x00000001; //enable SPI

	(SPI3->CR2)=datalength; //TSIZE number of data for current transfer
//	(SPI3->CR2)=0; //TSIZE number of data for current transfer
//	(SPI3->CR2)&=0x0000ffff; //TSER is 0, only one buffer to transmit
//	(SPI3->CR2)|=0xffff0000; //TSER is 0, only one buffer to transmit





	for(i_spi=0;i_spi<datalength;i_spi++) {
		*((__IO uint8_t *)SPI3->TXDR) = *((unsigned char *)dataTx);
//		*((__IO unsigned short int *)SPI3->TXDR) = *((unsigned char *)dataTx);
//		*((__IO unsigned int *)SPI3->TXDR) = *((unsigned char *)dataTx);
	}

	(SPI3->CR1)|=0x00000100; //master transfer start


	sprintf(print_string,"SPI3 Device: Status register 2 = 0x%x\n",(unsigned int)(SPI3->SR));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
	sprintf(print_string,"SPI3 Device: CR2 register = 0x%x\n",(unsigned int)(SPI3->CR2));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));


	//wait till all bytes are transmitted and all received
	i_spiTimeout=0;
	while(((SPI3->SR)|0x00000008)!=0x00000008) { //check EOT bit for end of transfer
		i_spiTimeout++;
		if(i_spiTimeout>100000) {
			sprintf(print_string,"Error: SPI3 Device: EOT bit not set. Status register = 0x%x\n",(unsigned int)(SPI3->SR));
			writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
			break;
//			return 1;
		}
	}
	for(i_spi=0;i_spi<datalength;i_spi++) {
		*((unsigned char *)dataRx) = *((__IO uint8_t *)SPI3->RXDR);
	}
	return 0;
}

 

The output to my console for the first 3 messages which I would like to send:

SPI3 Device: Status register 1 = 0x1202
SPI3 Device: Status register 2 = 0x202
SPI3 Device: CR2 register = 0x6
Error: SPI3 Device: EOT bit not set. Status register = 0x202

SPI3 Device: Status register 1 = 0x202
SPI3 Device: Status register 2 = 0x202
SPI3 Device: CR2 register = 0x6
Error: SPI3 Device: EOT bit not set. Status register = 0x202

SPI3 Device: Status register 1 = 0x202
SPI3 Device: Status register 2 = 0x202
SPI3 Device: CR2 register = 0x6
Error: SPI3 Device: EOT bit not set. Status register = 0x202

I see no activity on the SPI3 IO pins, no clock, no output. If I am controlling this pins PC10, PC11, P12 as a GPIO I can do that without problems. But no working SPI3. What I am doing wrong?

 

1 ACCEPTED SOLUTION

Accepted Solutions

Code is a bit of a mess. Not many people want to sort through register fields by value to figure it out. Using the standard CMSIS header defines will make it infinitely more readable.

> for(i_spi=0;i_spi<datalength;i_spi++) {
>   *((__IO uint8_t *)SPI3->TXDR) = *((unsigned char *)dataTx);
> }

You're sending the first character datalength times. No incrementation is done. Not the main problem.

Also, this code reads the value at TXDR, then dereferences it and writes to that location. Not what you want. Could be causing a crash, but otherwise not the main problem. You should be doing:

for(i_spi=0;i_spi<datalength; i_spi++) {
    *((__IO uint8_t *)&SPI3->TXDR) = dataTx[i_spi];
}

 

> *((unsigned char *)dataRx) = *((__IO uint8_t *)SPI3->RXDR);

Same issue with this code. Missing & and not incrementing. Not the main problem.

 

> (SPI3->CR1)|=0x00000100; //master transfer start

Looks like you want to set the CSTART bit, but you're off by one. CSTART is bit 9, so it should be either of these. Preferably the one with the CMSIS define.

SPI3->CR1 |= 0x00000200;
SPI3->CR1 |= SPI_CR1_CSTART;

 

Note that your scheme where you send all characters before you receive any characters will only work if all characters fit within the FIFO which is something like 4 or 8 words long.

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

View solution in original post

4 REPLIES 4
TDK
Guru

Does HAL_SPI_TransmitReceive() produce the correct output?

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

Yes, using HAL_SPI_TransmitReceive() I get the expected output MOSI with CLK signal. I will go deeper into my code to see why it is not working. Thank you very much for the hint.

Code is a bit of a mess. Not many people want to sort through register fields by value to figure it out. Using the standard CMSIS header defines will make it infinitely more readable.

> for(i_spi=0;i_spi<datalength;i_spi++) {
>   *((__IO uint8_t *)SPI3->TXDR) = *((unsigned char *)dataTx);
> }

You're sending the first character datalength times. No incrementation is done. Not the main problem.

Also, this code reads the value at TXDR, then dereferences it and writes to that location. Not what you want. Could be causing a crash, but otherwise not the main problem. You should be doing:

for(i_spi=0;i_spi<datalength; i_spi++) {
    *((__IO uint8_t *)&SPI3->TXDR) = dataTx[i_spi];
}

 

> *((unsigned char *)dataRx) = *((__IO uint8_t *)SPI3->RXDR);

Same issue with this code. Missing & and not incrementing. Not the main problem.

 

> (SPI3->CR1)|=0x00000100; //master transfer start

Looks like you want to set the CSTART bit, but you're off by one. CSTART is bit 9, so it should be either of these. Preferably the one with the CMSIS define.

SPI3->CR1 |= 0x00000200;
SPI3->CR1 |= SPI_CR1_CSTART;

 

Note that your scheme where you send all characters before you receive any characters will only work if all characters fit within the FIFO which is something like 4 or 8 words long.

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

Ok. I have solved the problem with my code. After introducing the correction you proposed my code was still not working. Digging in I have found that this bit was not set correctly:

(SPI3->CFG2)|=0x10000000; //SPI is always in the control of associated GPIOs

it should be:

	(SPI3->CFG2)|=0x80000000; //SPI is always in the control of associated GPIOs

The writing set bit SSIOP to 1 which in consequence SSOE enabled -> disabled SPI. To set SSOE was also a mistake. It should be 0.

So the clean working code is now:

#if 1
unsigned int i_spi, i_spiTimeout;
//for now limited to 16 bytes in one frame
unsigned char SPI3_TxRx(unsigned char device, unsigned char *dataRx, unsigned char *dataTx, unsigned int datalength) { //sending and receiving 8 bit data stream
	(SPI3->CR1)&=0xfffffffe; //disable SPI

	(SPI3->CFG1)&=0x8fffffff; //Master baud rate to 000
	(SPI3->CFG1)|=0x70000000; //Master baud rate to SPI master clock/256

	(SPI3->CFG1)&=0xffbfffff; //disable CRC calculation
//	(SPI3->CFG1)|=0x00400000; //enable CRC calculation
//	(SPI3->CFG1)&=0xffe0ffff; //reset CRCSIZE value
//	(SPI3->CFG1)|=0x00070000; //set CRCSIZE to 8bit
	(SPI3->CFG1)&=0xfffffe1f; //reset FIFO Threshold
//	(SPI3->CFG1)|=0x000001e0; //set FIFO Threshold level to 16 data
	(SPI3->CFG1)&=0xfffffff0; //reset DSIZE number of bits in the data frame
	(SPI3->CFG1)|=0x00000007; //set DSIZE to 8 bit data frame

	(SPI3->CFG2)|=0x80000000; //SPI is always in the control of associated GPIOs
#if 1
	(SPI3->CFG2)&=0xdfffffff; //SSOE is disabled
#endif

//	(SPI3->CFG2)&=0xfdffffff; //CPOL is 0 -> sck is 0 when idle
	(SPI3->CFG2)|=0x02000000; //CPOL is 1 -> sck is 1 when idle
	(SPI3->CFG2)&=0xfeffffff; //CPHA is 0 -> first clock transition is the first data capture edge
//	(SPI3->CFG2)|=0x01000000; //CPHA is 1 -> the second clock transition is the first data capture edge

	(SPI3->CFG2)&=0xff7fffff; //LSBFIRST is 0 -> MSB is transmitted first
//	(SPI3->CFG2)|=0x00800000; //LSBFIRST is 1 -> LSB is transmitted first
//	(SPI3->CFG2)&=0xffbfffff; //MASTER is 0 -> device configured as slave
	(SPI3->CFG2)|=0x00400000; //MASTER is 1 -> device configured as master

	(SPI3->CFG2)&=0xffc7ffff; //SPI Motorola
//	(SPI3->CFG2)|=0x00080000; //SPI TI
	(SPI3->CFG2)&=0xfff9ffff; //COMM is full duplex
//	(SPI3->CFG2)|=0x00020000; //COMM is simplex transmitter
	(SPI3->CFG2)&=0xffffff0f; //MIDI - master inter data idleness -> no delay
	(SPI3->CFG2)|=0x00000050; //MIDI - master inter data idleness -> 5 SPI clock cycles
	(SPI3->IER)&=0x00000000; //disable all interrupts

	sprintf(print_string,"SPI3 Device: Status register 1 = 0x%x\n",(unsigned int)(SPI3->SR));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));

	(SPI3->IFCR)|=0x0ff8; //clear all flags
	(SPI3->CR1)|=0x00000001; //enable SPI

	(SPI3->CR2)=datalength; //TSIZE number of data for current transfer
//	(SPI3->CR2)=0; //TSIZE number of data for current transfer
//	(SPI3->CR2)&=0x0000ffff; //TSER is 0, only one buffer to transmit
//	(SPI3->CR2)|=0xffff0000; //TSER is 0, only one buffer to transmit


	(SPI3->CR1)|=SPI_CR1_CSTART; //master transfer start


	for(i_spi=0;i_spi<datalength;i_spi++) {
		*((__IO uint8_t *)&SPI3->TXDR) = dataTx[i_spi];
//		*((__IO unsigned short int *)SPI3->TXDR) = *((unsigned char *)dataTx);
//		*((__IO unsigned int *)SPI3->TXDR) = *((unsigned char *)dataTx);
	}



	sprintf(print_string,"SPI3 Device: Status register 2 = 0x%x\n",(unsigned int)(SPI3->SR));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
	sprintf(print_string,"SPI3 Device: CR2 register = 0x%x\n",(unsigned int)(SPI3->CR2));
	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));


	//wait till all bytes are transmitted and all received
	i_spiTimeout=0;
	while(((SPI3->SR)&0x00000008)!=0x00000008) { //check EOT bit for end of transfer
		i_spiTimeout++;
		if(i_spiTimeout>100000) {
			sprintf(print_string,"Error: SPI3 Device: EOT bit not set. Status register = 0x%x\n",(unsigned int)(SPI3->SR));
			writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
			break;
//			return 1;
		}
	}
	for(i_spi=0;i_spi<datalength;i_spi++) {
		dataRx[i_spi] = *((__IO uint8_t *)&SPI3->RXDR);
	}

	  __HAL_SPI_CLEAR_EOTFLAG(&hspi3);
	  __HAL_SPI_CLEAR_TXTFFLAG(&hspi3);

	  /* Disable SPI peripheral */
	  __HAL_SPI_DISABLE(&hspi3);

	return 0;
}

#endif

 

In the mean time while analyzing upper code of mine I have reworked original routine to suit my purpose better:

#if 1
/**
  * @brief  Transmit and Receive an amount of data in blocking mode.
  * @PAram  hspi   : pointer to a SPI_HandleTypeDef structure that contains
  *                  the configuration information for SPI module.
  * @PAram  pTxData: pointer to transmission data buffer
  * @PAram  pRxData: pointer to reception data buffer
  * @PAram  Size   : amount of data to be sent and received
  *
  */

uint32_t   tickstart;
uint32_t   fifo_length;
uint32_t   temp_sr_reg;
uint16_t   initial_TxXferCount;
uint16_t   initial_RxXferCount;
uint16_t   init_max_data_in_fifo;
unsigned int i_spi, i_spiTimeout;

unsigned char SPI_TransmitReceive_8B(SPI_HandleTypeDef *hspi, unsigned char spiDevice, unsigned char *pTxData, unsigned char *pRxData,
                                          unsigned short int Size) {

	init_max_data_in_fifo = (((uint16_t)(hspi->Init.FifoThreshold >> 5U) + 1U));
//	sprintf(print_string,"init_max_data_in_fifo: %d\n",init_max_data_in_fifo);
//	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));

	/* Check Direction parameter */
	assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));


	initial_TxXferCount = Size;
	initial_RxXferCount = Size;



	/* Set the transaction information */
	hspi->pRxBuffPtr  = (uint8_t *)pRxData;
	hspi->RxXferCount = Size;
	hspi->RxXferSize  = Size;
	hspi->pTxBuffPtr  = (const uint8_t *)pTxData;
	hspi->TxXferCount = Size;
	hspi->TxXferSize  = Size;


	/* Set Full-Duplex mode */
	SPI_2LINES(hspi);
	fifo_length = SPI_HIGHEND_FIFO_SIZE;
	/* Set the number of data at current transfer */
	(hspi->Instance->CR2)=Size; //TSIZE number of data for current transfer
	(hspi->Instance->CR1)|=0x00000001; //enable SPI
	(hspi->Instance->CR1)|=SPI_CR1_CSTART; //master transfer start


	i_spiTimeout=0;
	/* Transmit and Receive data in 8 Bit mode */
    while ((initial_TxXferCount > 0UL) || (initial_RxXferCount > 0UL)) {
    	/* Check the TXP flag */
    	if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP)) && (initial_TxXferCount > 0UL) &&
    		(initial_RxXferCount  < (initial_TxXferCount + fifo_length))) {

    		*((__IO uint8_t *)&hspi->Instance->TXDR) = *((const uint8_t *)hspi->pTxBuffPtr);
    		hspi->pTxBuffPtr += sizeof(uint8_t);
    		hspi->TxXferCount--;
    		initial_TxXferCount = hspi->TxXferCount;
//			sprintf(print_string,"write to buffer.\n");
//			writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
    	}

    	/* Evaluate state of SR register */
    	temp_sr_reg = hspi->Instance->SR;

    	if (initial_RxXferCount > 0UL) {
    		/* Check the RXP flag */
    		if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXP)) {
    			*((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
    			hspi->pRxBuffPtr += sizeof(uint8_t);
    			hspi->RxXferCount--;
    			initial_RxXferCount = hspi->RxXferCount;
//    			sprintf(print_string,"read from buffer.\n");
//    			writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));

    		}
    		/* Check RXWNE flag if RXP cannot be reached */
    		else if ((initial_RxXferCount < init_max_data_in_fifo) && ((temp_sr_reg & SPI_SR_RXWNE_Msk) != 0UL)) {
    			*((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
    			hspi->pRxBuffPtr += sizeof(uint8_t);
    			*((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
    			hspi->pRxBuffPtr += sizeof(uint8_t);
    			*((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
    			hspi->pRxBuffPtr += sizeof(uint8_t);
    			*((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
    			hspi->pRxBuffPtr += sizeof(uint8_t);
    			hspi->RxXferCount -= (uint16_t)4UL;
    			initial_RxXferCount = hspi->RxXferCount;
    		}
    		/* Check RXPLVL flags when RXWNE cannot be reached */
    		else if ((initial_RxXferCount < 4UL) && ((temp_sr_reg & SPI_SR_RXPLVL_Msk) != 0UL)) {
    			*((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
    			hspi->pRxBuffPtr += sizeof(uint8_t);
    			hspi->RxXferCount--;
    			initial_RxXferCount = hspi->RxXferCount;
    		}
    		else {


    		}
    	}
		i_spiTimeout++;
		if(i_spiTimeout>100000) {
			sprintf(print_string,"Error: SPI%d Device: No Tx/Rx actions. Timeout.\n", (unsigned int)hspi->Instance);
			writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
			break;
//			return 1;
		}
    }
	i_spiTimeout=0;
	while(((hspi->Instance->SR)&0x00000008)!=0x00000008) { //check EOT bit for end of transfer
		i_spiTimeout++;
		if(i_spiTimeout>100000) {
			sprintf(print_string,"Error: SPI%d Device: EOT bit not set. Timeout. Status register = 0x%x\n",(unsigned int)hspi->Instance , (unsigned int)(hspi->Instance->SR));
			writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));
			break;
//			return 2;
		}
	}
//	sprintf(print_string,"i_spiTimeout: %d\n",i_spiTimeout);
//	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));

#if 0
    /* Wait for Tx/Rx (and CRC) data to be sent/received */
    if (SPI_WaitOnFlagUntilTimeout_My(hspi, SPI_FLAG_EOT, RESET, Timeout, tickstart) != HAL_OK)  {
    	SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
    }
#endif
    /* Call standard close procedure with error check */
//    SPI_CloseTransfer_My(hspi);
    __HAL_SPI_CLEAR_EOTFLAG(hspi);
    __HAL_SPI_CLEAR_TXTFFLAG(hspi);
    __HAL_SPI_DISABLE(hspi);

//   sprintf(print_string,"HAL_SPI_TransmitReceive_8B: end\n");
//	writeMessageRS232(PRIMARY_COM_PORT, (uint8_t *)print_string, strlen(print_string));


   	return HAL_OK;
}
#endif

This also works as expected. Can you recheck if I have deleted something which could be important in some strange situations? Or is there more to delete? I only need 8 byte, master mode.

I guess I can fill up the FIFO with up to 16 bytes and SPI_FLAG_TXP tells when the FIFO is full? Actually after a byte written I always read a byte from the receive buffer but I assume you can write much faster than sending information out on the SPI.