AnsweredAssumed Answered

HAL_SPI_TransmitReceive_IT() never completes

Question asked by hodgson.andrew.001 on Oct 20, 2014
Latest reply on Oct 22, 2014 by Amel N
I am having an issue with the STM32Cube HAL function, HAL_SPI_TransmitReceive_IT(). I am using the STM32CubeF2 library with STM32CubeMX tool to generage most of the initialisation code.

I have an STM3220G evalutation board (STM32F207) modified to connect to a single SPI FRAM device via the SPI2 peripheral (full duplex master, 2 line, ~1.8MHz, software controlled chip select). There are no other SPI slaves present.

When using HAL_SPI_TransmitReceive_IT() to communicate with said device using a data length > 1, I never see the HAL_SPI_TxRxCpltCallback() function called.

Here is the SPI2 init (Cube auto-generated):

/* SPI2 init function */
void MX_SPI2_Init(void)
{
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
  HAL_SPI_Init(&hspi2);
}


And the msp function (also auto-generated):

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  if(hspi->Instance==SPI2)
  {
    /* Peripheral clock enable */
    __SPI2_CLK_ENABLE();
  
    /**SPI2 GPIO Configuration    
    PC2     ------> SPI2_MISO
    PC3     ------> SPI2_MOSI
    PB10     ------> SPI2_SCK 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);


    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


    /* Peripheral interrupt init*/
    /* Sets the priority grouping field */
    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
    HAL_NVIC_SetPriority(SPI2_IRQn, 3, 0);
    HAL_NVIC_EnableIRQ(SPI2_IRQn);
  }
}


The board was modifed as specified in the STM3220G user manual to disconnect the various active components on SPI2. I have also used a 'scope to verify all signals. There doesn't appear to be anything wrong with the data being transmitted, or the correct number of clocks being generated so that the receive data can be shifted out of the FRAM device.

I instrumented the interrupt handling inside the HAL driver and this is what I see for a single byte full duplex transfer (TXE = SPI_TxISR() & RXNE = SPI_2LinesRxISR()):

TXE (SPI_TxCloseIRQHandler), RXNE (SPI_RxCloseIRQHandler()

Now I do the same for a four-byte full duplex transmission:

TXE, TXE, RXNE, TXE, RXNE, TXE (SPI_TxCloseIRQHandler)

I would have expected another two RXNE interrupts after the closing of Tx. However, they never happen, which means SPI_RxCloseIRQHandler() is never called, which means HAL_SPI_TxRxCpltCallback() isn't called either.

If I go and stick breakpoints in both the interrupt handling routines (I'm using IAR EW 7.2), slowing them down markedly, the transfer is successful!

TXE, RXNE, TXE, RXNE, TXE, RXNE, TXE (SPI_TxCloseIRQHandler), RXNE, (SPI_RxCloseIRQHandler)

There seems to be a weird race condition working, but I am having difficulty pinpointing the cause. Has anyone else seen anything like this? If further information is required I will do my best to supply it.

EDIT: I should add that the polled-mode function HAL_SPI_TransmitReceive() works fine.

Outcomes