cancel
Showing results for 
Search instead for 
Did you mean: 

SPI RXNE IT: volatile buffer index effect on buffer type when reading DR register

Framet
Associate III

Hey guys, befor asking my question I want to give you a brief overview of the test case:

TestCase: SPI Full Duplex

Master send [0-3](4) bytes and Slave returns received bytes [0-2](3) immediatly. 

(no register preload in slave)

Example:

Master <-> Slave

0x01 <-> unkown

0x02 <-> 0x01

0x03 <-> 0x02

0x04 <-> 0x03

-------Variante 1 working-------------

Variables:

volatile uint32_t spiFrameCounter;
uint8_t spiRxTestData;
uint8_t spiRxBuffer[255];

On Chipselect:

spiFrameCounter = 0;

RXNE interrupt routine:

spiRxTestData = (uint8_t)(READ_REG(SPI3->DR)); //IMPORTANT: assembler contains uxtb command
 
if (spiFrameCounter < 2) {
	 *((__IO uint8_t *)&SPIx->DR) = spiRxTestData;
}
spiRxBuffer[spiFrameCounter] = spiRxTestData;
spiFrameCounter++;

-------Variante 2 not working---------

Variables:

volatile uint32_t spiFrameCounter;
uint8_t spiRxBuffer[255];

On Chipselect:

spiFrameCounter = 0;

RXNE interrupt routine:

spiRxBuffer[spiFrameCounter] = (uint8_t)(READ_REG(SPI3->DR)); //IMPORTANT: assembler contains NO uxtb command
 
if (spiFrameCounter < 2) {
	*((__IO uint8_t *)&SPIx->DR) = (uint8_t)spiRxBuffer[spiFrameCounter]);
}
spiFrameCounter++;

---- Variante 2 Solution to Fix Problem 1 -----

change: 

volatile uint32_t spiFrameCounter;

to:

uint32_t spiFrameCounter;

Result: uxtb is used again in assembler and therfor DR register is read with 1 byte

---- Variante 2 Solution to Fix Problem 2 -----

change:

spiRxBuffer[spiFrameCounter] = (uint8_t)(READ_REG(SPI3->DR));

to:

*((__IO uint8_t *)&spiRxBuffer[spiFrameCounter]) = (uint8_t)(READ_REG(SPI3->DR));

Result: uxtb is used again in assembler and therfor DR register is read with 1 byte

---- Variante 2 Solution to Fix Problem 3 -----

change:

spiRxBuffer[spiFrameCounter] = (uint8_t)(READ_REG(SPI3->DR));

to:

spiRxBuffer[(uint8_t)spiFrameCounter] = (uint8_t)(READ_REG(SPI3->DR));

Disadvantage: spiRxBuffer max size 255

Question:

Why does a volatile variable used as an array index have effect on the type of the actual array?

Or why is DR register read without uxtb command?

Note:

With "Not Working" i mean the SPI3->DR register is not read as 1 Byte but instead is ready as 4 Byte.

This can also be noticed in the response of the slave to the master. (Response is shifted by 4 Bytes)

Kind regards

Franco

5 REPLIES 5
S.Ma
Principal

What STM32 is it (master and slave) ? Does the SPI have FIFO and programmable word length from 4 to 16 bit?

More important is to know what you wish to have ultimately.

Framet
Associate III

Thank you for your response and sorry for my late reply.

STM32 is an F302R8 in Slave Mode

The SPI has 32 Bit RX/TX Fifo Buffer.

Word Length is set to 8 Bit (TX Fifo only 24 Bit when word length is smaller or equal to 😎

The RX Fifo Buffer Threshold is set to 8 bit.

My ultimate goal is to read the first byte and depending on its content send back certain bytes.

But for this test case I just send back the received bytes.

S.Ma
Principal

Flush the received fifo by reading 4 times DR, flush the TX fifo by sw reset the SPI, for SPI slave mode. Do this while NSS is high.

Framet
Associate III

I do that already when ever the NSS goes high, to keep Master and Slave synchronized

If you're filling the buffer in the interrupt, the buffer should be marked volatile also.

If the SPI unit of the STM32 has access width issues and a FIFO

volatile uint32_t spiFrameCounter;

volatile uint8_t spiRxBuffer[255];

spiRxBuffer[spiFrameCounter++] = *((volatile uint8_t *)&SPI3->DR); // Read with 8-bit width

You always want to read the DR to clear the RXNE bit else it will be stale

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..