cancel
Showing results for 
Search instead for 
Did you mean: 

[STM32F469] Using HAL_SPI_TransmitReceive not writing on the receive buffer.

Riccardo Franceschetto
Associate III

Hello,

I implemented a simple spi transmission on a STM32F469 based board.

The problem i'm facing is that the spi function I'm not getting any value in the receive buffer.

Trough the oscilloscope i can see the byte being send and the one transmitted back from slave device, i'm using a gpio as chip select because notoriusly the hardware NSS by hal does not work properly.

What could be the problem?

Here's my code., the function names might differ because of internal implementation, but are HAL based.

Init Function:

void SIN_SPI6_Init(SPI_HandleTypeDef* spiP)
{
 
 
  spiP ->Instance = SPI6;
  spiP ->Init.Mode = SPI_MODE_MASTER;
  spiP ->Init.Direction = SPI_DIRECTION_2LINES;
  spiP ->Init.DataSize = SPI_DATASIZE_8BIT;
  spiP ->Init.CLKPolarity = SPI_POLARITY_LOW;
  spiP ->Init.CLKPhase = SPI_PHASE_1EDGE;
  spiP ->Init.NSS = SPI_NSS_SOFT;
  spiP ->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  spiP ->Init.FirstBit = SPI_FIRSTBIT_MSB;
  spiP ->Init.TIMode = SPI_TIMODE_DISABLE;
  spiP ->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  spiP ->Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(spiP) != HAL_OK)
  {
        Error_Handler(2);
  }
 
}

MSP function:

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
   if(hspi->Instance==SPI2)
  {
    /* Peripheral clock enable */
    __HAL_RCC_SPI2_CLK_ENABLE();
 
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**SPI2 GPIO Configuration
    PB13     ------> SPI2_SCK
    PC3     ------> SPI2_MOSI
    PC2     ------> SPI2_MISO
    */
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
  }
 
   else if(hspi->Instance==SPI6)
  {
  /* USER CODE BEGIN SPI6_MspInit 0 */
 
  /* USER CODE END SPI6_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI6_CLK_ENABLE();
 
    __HAL_RCC_GPIOG_CLK_ENABLE();
    /**SPI6 GPIO Configuration
    PG14     ------> SPI6_MOSI
    PG13     ------> SPI6_SCK
    PG12     ------> SPI6_MISO
    */
    GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_13|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI6;
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
 
    }
}

The code to the transmission:

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);  //SPI6_NSS  low
  
            uint8_t readStatusRegister = 0b00000101;
            uint8_t  readback = 0;
            
                
            if (HAL_SPI_TransmitReceive (&hspi6, &readStatusRegister,&readback,2, 10) != HAL_OK)
            {
                  Error_Handler(6);    
            }
 
            HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);    //SPI6_NSS  high

14 REPLIES 14

> I'm not getting any value in the receive buffer.

If you initialize the receive buffer to some particular (non-zero, non-FF) value, does it change?

> Trough the oscilloscope i can see the byte being send and the one transmitted back from slave device,

Did you check directly on the mcu pin? Think bad solder joints or shorts.

JW

gbm
Lead II

You are writing 2 bytes from a 1-byte buffer, then reading 2 bytes into another 1-byte buffer. There might be more errors like these in the rest of your code.

Sorry, but isn't the total number of bytes that needs to be specified? The number of bytes to transmit+receive.

I cant check on the mcu pins because its a bga package.

But i checked on the nearest contact i can put a probe.

No, and that would be ridiculous even for ST's broken bloatware. It took me few seconds to find it out by looking at the code... Less than writing this short post!

On user manual referring to the function TransmitReceive is written "total amount of data to be sent and received".

I thought after sending known amount of data from bufferr SPI "listens" the respond from slave the total-sent amount of bytes.

So you meaning that The function transmits and receive the same amount of data everytime from transmit and also for receive?@gbm​ 

You can probably probe the 4 SPI signals with a multimeter/oscilloscope, go in debug mode, stop the code, view and modify the GPIO registers to confirm the copper lanes are the right ones.

S.Ma
Principal

Local variables are sometime optimized to be only core registers which don't have memory address location. They are also not volatile, DMA for example can't access them. At least make them volatile to be sure.

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);  //SPI6_NSS  low
  
            uint8_t readStatusRegister = 0b00000101; ==> Make them global to exist as memory address and not a register. Make them volatile type
            uint8_t  readback = 0; ==> Same thing.
            
                
            if (HAL_SPI_TransmitReceive (&hspi6, &readStatusRegister,&readback,2, 10) != HAL_OK)
            {
                  Error_Handler(6);    
            }
 
            HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);    //SPI6_NSS  high

Wrong. No need for volatile specifier at all. If the data address is referenced, the compiler must implement the data in memory.