cancel
Showing results for 
Search instead for 
Did you mean: 

SPI slave receives only last byte

jwoolston
Associate II
Posted on August 06, 2014 at 20:23

Background:

- 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.

Problem:

- 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.CRCCalculation = SPI_CRCCALCULATION_DISABLED;

//SPI_CRCCALCULATION_ENABLED;

hspi.Init.CRCPolynomial = 469;

HAL_SPI_Init(&hspi);

SPI_Initialize(&hspi);

- 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_DMA_DeInit(&hdma_spi_rx);

HAL_DMA_Init(&hdma_spi_rx);

__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_DMA_DeInit(&hdma_spi_rx);

HAL_DMA_Init(&hdma_spi_tx);

__HAL_LINKDMA(hspi, hdmatx, hdma_spi_tx);

/* Peripheral interrupt init*/

/* Sets the priority grouping field */

HAL_NVIC_SetPriorityGrouping(GLOBAL_IRQ_PRI_GROUP);

HAL_NVIC_SetPriority(SPI_IRQn, SPI_IRQ_PREEMPT_PRI, SPI_IRQ_SUB_PRI);

HAL_NVIC_EnableIRQ(SPI_IRQn);

}

- 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) {

Error_Handler();

}

if

(isDevice) {

SPI_SendHostReadySignal();

}

}

- 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.

EDIT 1:

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

#dma #stm32f4 #spi #error

1 REPLY 1
jwoolston
Associate II
Posted on August 13, 2014 at 02:08

I traced the problem down to the call I have for

HAL_DMA_DeInit()

prior to the initialization call. Apparently the DeInit function puts the DMA into some state the Init isn't able to properly recover from.