AnsweredAssumed Answered

SPI slave receives only last byte

Question asked by woolston.jared on Aug 6, 2014
Latest reply on Aug 13, 2014 by woolston.jared
 - I have a system with two STM32F407 processors communicating via SPI. 
 - I am using the HAL drivers generated by STMCube
 - They use the same firmware and adjust their behavior into master or slave mode depending on the state of a pin at startup.
 - On startup they attempt to synchronize by performing a full duplex SPI exchange via DMA transfer and comparing the results.
 - After the SYNC the slave calls HAL_SPI_ReceiveDMA() to prepare to receive a command from the master
 - On a user input, the master sends a a command to the slave via HAL_SPI_TransmitDMA(). 
 - The command should be a 3 byte transfer, in this case 0x42 0x00 0x03. A logic analyzer confirms the master transmits this correctly. 

 - The slave 'receives' 0x03 0x00 0x00. This is the contents of the register when accessed from the SPI RX Complete callback.

Some Relevant Code:

- SPI Initialization
/* SPI1 init function */
void MX_SPI_Init(void) {
    hspi.Instance = SPI_NUM;
    if (isDevice == true) {
        hspi.Init.Mode = SPI_MODE_MASTER;
        hspi.Init.NSS = SPI_NSS_HARD_OUTPUT;
    else {
        hspi.Init.Mode = SPI_MODE_SLAVE;
        hspi.Init.NSS = SPI_NSS_SOFT;
    hspi.Init.Direction = SPI_DIRECTION_2LINES;
    hspi.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
    hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi.Init.TIMode = SPI_TIMODE_DISABLED;
    hspi.Init.CRCPolynomial = 469;

- SPI DMA Init
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) {
     /* GPIO Init code */
     /* Peripheral DMA init*/
    hdma_spi_rx.Instance = SPI_DMA_RX_STREAM;
    hdma_spi_rx.Init.Channel = SPI_DMA_RX_CHANNEL;
    hdma_spi_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi_rx.Init.Mode = DMA_NORMAL;
    hdma_spi_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
    hdma_spi_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    __HAL_LINKDMA(hspi, hdmarx, hdma_spi_rx);
    hdma_spi_tx.Instance = SPI_DMA_TX_STREAM;
    hdma_spi_tx.Init.Channel = SPI_DMA_TX_CHANNEL;
    hdma_spi_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi_tx.Init.Mode = DMA_NORMAL;
    hdma_spi_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
    hdma_spi_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    __HAL_LINKDMA(hspi, hdmatx, hdma_spi_tx);
    /* Peripheral interrupt init*/
    /* Sets the priority grouping field */

- Setup for slave to receive a command:
static void WaitForCommand(void) {
    printf("Waiting for command...\n\r");
    spiEngine.state = WAITING_FOR_CMD;
    HAL_StatusTypeDef status = HAL_SPI_Receive_DMA(spiEngine.handle, rxCmdBuffer, SPI_CMD_LEN);
    if (status != HAL_OK) {
    if (isDevice) {

- Command receive buffer definition:
static uint8_t rxCmdBuffer[3];

Since the synchronization at the beginning functions properly, I do not believe there is a problem with the configuration of the SPI on either end, especially since the master transmits correctly. Perhaps there is something happening where the slave is in some faulty state? Is there a register I should clear or access to get things moving properly? Insights and suggestions are most welcome. Thankyou.

I noticed that if I set the receive transfer size to 1, the value in the buffer is the expected first byte.