2019-03-22 06:12 AM
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
2019-03-22 10:35 AM
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.
2019-03-25 01:40 AM
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.
2019-03-25 05:56 AM
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.
2019-03-25 07:31 AM
I do that already when ever the NSS goes high, to keep Master and Slave synchronized
2019-03-25 08:03 AM
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