I'm implementing SPI communication between two Nucleo STM32H743 boards.
I've configured SPI in Full-Duplex mode, with CRC enabled, at the maximum SPI frequency (100MHz for SCK frequency).
It's working fine as long as I'm doing only transmission from Master side and Reception from Slave side.
Here is the code I'm using to transmit from master and receive from slave. Please note that I am aware it is quick and dirty code, it is only a proof of concept so please do not comment coding style (I know, hard coded values, pointers for registers, etc...). For the record I have also used STMicro HAL functions HAL_SPI_Transmit
and HAL_SPI_Receive
with the same behaviour.
volatile unsigned long *CR1 = (unsigned long *)0x40013000;
volatile unsigned long *CR2 = (unsigned long *)0x40013004;
volatile unsigned long *TXDR = (unsigned long *)0x40013020;
volatile unsigned long *RXDR = (unsigned long *)0x40013030;
volatile unsigned long *SR = (unsigned long *)0x40013014;
volatile unsigned long *IFCR = (unsigned long *)0x40013018;
volatile unsigned long *TXCRC = (unsigned long *)0x40013044;
volatile unsigned long *RXCRC = (unsigned long *)0x40013048;
volatile unsigned long *CFG2 = (unsigned long *)0x4001300C;
void HAL_SPI_TransmitRegister(uint32_t Data, uint32_t Dummy)
{
// size of transfer (TSIZE)
*CR2 = 2;
// Enable SPI peripheral
*CR1 |= 1;
// Master transfer start
*CR1 |= SPI_CR1_CSTART;
// Fill the FIFO
*TXDR = Data;
*TXDR = Dummy;
while ( ((*SR) & SPI_FLAG_EOT) == 0 );
// clear flags
*IFCR = 0xFFFFFFFF;
// disable SPI
*CR1 &= ~1;
}
void HAL_SPI_ReceiveRegister(uint32_t *pData)
{
// two 32 bits words to be received
*CR2 = 2;
// Enable SPI peripheral
*CR1 |= 1;
while ( ((*SR) & (SPI_FLAG_EOT | SPI_FLAG_RXWNE)) == 0 );
*(pData) = (*RXDR);
while ( ((*SR) & (SPI_FLAG_EOT | SPI_FLAG_RXWNE)) == 0 );
*(pData+1) = (*RXDR);
// clear flags
*IFCR = 0xFFFFFFFF;
// disable SPI
*CR1 &= ~1;
}
So the code above is working fine. Now this is where it starts to be interesting: I want to transmit something from the slave. I modified the code as follows (also tried the function HAL_SPI_TransmitReceive
with the same behaviour):
void HAL_SPI_ReceiveRegister(uint32_t *pData)
{
unsigned long response = 0xABCDEF99;
*CR2 = 2;
/* Enable SPI peripheral */
*CR1 |= 1;
// write response in advance
*TXDR = 0;
*TXDR = response;
// first 4 bytes are the command
while ( ((*SR) & (SPI_FLAG_EOT | SPI_FLAG_RXWNE)) == 0 );
*(pData) = (*RXDR);
// next 4 bytes are the dummy bytes used to send response
while ( ((*SR) & (SPI_FLAG_EOT | SPI_FLAG_RXWNE)) == 0 );
*(pData+1) = (*RXDR);
// clear flags
*IFCR = 0xFFFFFFFF;
// disable SPI
*CR1 &= ~1;
}
The Master receives crap but the Slave receives correct data.
Now, the datasheet of STM32H7x3 indeed mentions a limitation for SPI in Slave mode but I don't understand what "slave mode transmitter" means:
My questions are:
what does the datasheet "slave mode transmitter" means ?
I don't understand why the slave is able to receive at 100Mhz but not to transmit, since the communication is full-duplex.