2017-01-04 03:53 AM
I have a Nucleo-F446RE Eval Board with a STM32F446 RET6U. I use the SPI2 peripheral. When I switched from baudrate prescaler 4 to 2 I get problems with the SPI status flag 'Rx buffer not empty': The last flag does not trigger at certain conditions. When a additional delay is generated in the write/read process of a SPI Byte, the flag triggers. Is it possible, that the 'Tx buffer empty' and 'Rx buffer not empty' flags can cause an access conflict at the flag register?
I added pictures to describe the situation more clearly:
The yellow line corresponds to the SPI CLK. The blue line corresponds to a 'Rx buffer not empty' flag trigger action.
Picture 1:
Baudrate prescaler 4 is used. Bytes are written after 'Tx buffer empty' flag triggers. All three 'Rx buffer not empty' flags trigger.
Picture 2:
Baudrate prescaler 2 is used. Bytes are written after 'Rx buffer not empty' flag triggers and data register has been read out. All three 'Rx buffer not empty' flags trigger.
Picture 3:
Baudrate prescaler 2 is used. Bytes are written after 'Tx buffer empty' flag triggers. Only the first and second 'Rx buffer not empty' flags trigger.
Picture 4:
Baudrate prescaler 2 is used. Bytes are written after 'Tx buffer empty' flag triggers. Now additional delays have been added. All three 'Rx buffer not empty' flags trigger.
2017-01-04 04:35 AM
> The blue line corresponds to a 'Rx buffer not empty' flag trigger action.
How?
JW
2017-01-04 05:19 AM
I change the status of a µC output pin, if the 'if statement' checks the 'Rx buffer not empty' flag with positive result. The external pin is observed together with the SPI CLK on the oscilloscope. If one 'Rx buffer not empty' flag does not trigger, the SPI read out does not happen. Because the 'Rx buffer not empty' flag clears only with a readout, the Overrun flag triggers then and signalizes an error. Subsequent data will be lost.
2017-01-04 06:35 AM
Post a minimal but complete compilable code exhibiting the problem.
JW
2017-01-05 04:46 AM
2017-01-05 06:39 AM
I don't see the 'I change the status of a µC output pin, if the 'if statement' checks the 'Rx buffer not empty' flag with positive result.' in the above code.
JW
2017-01-05 07:53 AM
I forgot unintentionally to add the pin set code. I edited the code above in the section /* Wait until RXNE flag is reset */in the function 'SPI_WriteRead'.
2017-01-05 10:20 AM
Well, I am convinced that code used to produce the given waveforms differed in more than just this.
Nevertheless, the mechanism of failure will be similar to this - I am unrolling the loop as it executes:
while((TxCount > 0U) || (RxCount > 0U)) { /* check TXE flag */ if((TxCount > 0U) && (SPI_GET_FLAG(SPI_FLAG_TXE)))TxCount==3, TXE==1
{ *(__IO uint8_t *)&SPI_INSTANCE->DR = (*pTxData++);start Tx 1st byte
TxCount--; } /* Wait until RXNE flag is reset */ if((RxCount > 0U) && (SPI_GET_FLAG(SPI_FLAG_RXNE)))RXNE==0, so skipped
{
(*(uint8_t *)pRxData++) = SPI_INSTANCE->DR; RxCount--; GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET); GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); } /* Check if timeout is reached */at around this time 1st byte Tx/Rx finished; RXNE gets set
if((CLOCK_GetTime()-tickstart) >= SPI_TIMEOUT){
error_code = HAL_TIMEOUT; goto error; // stop transmit and receive immediately }loop
/* check TXE flag */ if((TxCount > 0U) && (SPI_GET_FLAG(SPI_FLAG_TXE)))TxCount==2, TXE==1
{ *(__IO uint8_t *)&SPI_INSTANCE->DR = (*pTxData++);start Tx 2nd byte
TxCount--; } /* Wait until RXNE flag is reset */ if((RxCount > 0U) && (SPI_GET_FLAG(SPI_FLAG_RXNE)))RXNE==1
{at around this time 2nd byte Tx/Rx finished; Rx overflow
(*(uint8_t *)pRxData++) = SPI_INSTANCE->DR; RxCount--; GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);first pulse
GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);[...]