cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_SPI_Transmit on F0, F1, F4, F7

VLev
Associate II

Hi!

I have module for transmit dates to SPI Interface.

Data is - pointer to data buffer uint8_t.

In F1 & F4 all will be ok.

But in F0 & F7 modules will send *((uint16_t *)pData) (see modules below)

Program for F1 or F4 will not work on F0 & F7.

Where error?

STM32Cube_FW_F7_V1.14.0:

HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)

 /* Transmit data in 8 Bit mode */

 else

 {

   while (hspi->TxXferCount > 0U)

   {

     /* Wait until TXE flag is set to send data */

     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))

     {

       if (hspi->TxXferCount > 1U)

       {

         /* write on the data register in packing mode */

         hspi->Instance->DR = *((uint16_t *)pData);

         pData += sizeof(uint16_t);

         hspi->TxXferCount -= 2U;

       }

       else…..

STM32Cube_FW_F4_V1.18.0:

 /* Transmit data in 8 Bit mode */

 else

 {

   if((hspi->Init.Mode == SPI_MODE_SLAVE)|| (hspi->TxXferCount == 0x01))

   {

     *((__IO uint8_t*)&hspi->Instance->DR) = (*pData);

     pData += sizeof(uint8_t);

     hspi->TxXferCount--;

   }

   while (hspi->TxXferCount > 0U)

   {

     /* Wait until TXE flag is set to send data */

     if(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))

     {

       *((__IO uint8_t*)&hspi->Instance->DR) = (*pData);

       pData += sizeof(uint8_t);

       hspi->TxXferCount--;

     }

     else…

STM32Cube_FW_F1_V1.7.0:

 /* Transmit data in 8 Bit mode */

 else

 {

   if((hspi->Init.Mode == SPI_MODE_SLAVE)|| (hspi->TxXferCount == 0x01))

   {

     *((__IO uint8_t*)&hspi->Instance->DR) = (*pData);

     pData += sizeof(uint8_t);

     hspi->TxXferCount--;

   }

   while (hspi->TxXferCount > 0U)

   {

     /* Wait until TXE flag is set to send data */

     if(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))

     {

       *((__IO uint8_t*)&hspi->Instance->DR) = (*pData);

       pData += sizeof(uint8_t);

       hspi->TxXferCount--;

     }

     else…

STM32Cube_FW_F0_V1.9.0:

/* Transmit data in 8 Bit mode */

 else

 {

   if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U))

   {

     if (hspi->TxXferCount > 1U)

     {

       /* write on the data register in packing mode */

       hspi->Instance->DR = *((uint16_t *)pData);

       pData += sizeof(uint16_t);

       hspi->TxXferCount -= 2U;

     }

     else

     {

       *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++);

       hspi->TxXferCount--;

     }

   }

   while (hspi->TxXferCount > 0U)

   {

     /* Wait until TXE flag is set to send data */

     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))

     {

       if (hspi->TxXferCount > 1U)

       {

         /* write on the data register in packing mode */

         hspi->Instance->DR = *((uint16_t *)pData);

         pData += sizeof(uint16_t);

         hspi->TxXferCount -= 2U;

       }

       else

       {

         *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++);

         hspi->TxXferCount--;

       }

17 REPLIES 17
Bob S
Principal

Have you tried this on an F7 of F0? If it fails, what happens? What do you see on the SPI port?

The HAL library tries to optimize transfers by writing 2 bytes at a time as long as there are at least 2 bytes left to be sent (when the SPI is in 8-bit mode). Apparently this optimization is in the F0 and F7 HAL code but not in the F1 & F4 HAL code, even though the F4 has a 16-bit SPI DR just like the F0 & F7.

Are you wanting to run the same BINARY code on an F0, F1, F4 and F7? Or just compile the same source code, using the appropriate HAL libraries, for the different processor families?

VLev
Associate II

Hi Bob!

thanks for answer.

I have program, that work with f1.

Program, example, have array uint8_t. And I send this array use hal_spi_transmit.

f1 - work correctly.

but this program will not work at f0. because in hal_spi driver:

hspi->Instance->DR = *((uint16_t *)pData);

         pData += sizeof(uint16_t);

         hspi->TxXferCount -= 2U;

I think this is not rigth code. where in documentation write, that I need use uint16_t in array for use hal_spi_transmit?

program at f0 not work. hardware fault!!!

I take some code from hal f1 driver and set up one to f0 driver. But this is magia. not correct job!

---

Sincerely,

Vitaly.

Just to be clear - when you programmed your code into an F0, you had re-compiled the code with the F0 HAL library, correct?

And you got a hardware fault FROM THAT HAL CODE that attempts to write 16-bits to the SPI DR?

And hand-editing the F0 HAL SPI function to force the F0 code to do only 8-bit writes to the SPI DR then makes the F0 code work with no hardware faults, correct?

Then I would guess that your SPI buffer is not aligned on a 16-bit boundary and that the F0 doesn't allow non-aligned 16-bit access (see section 2.4 of the STM32 Cortex M0 Programming Manual (https://www.st.com/resource/en/programming_manual/dm00051352.pdf).

Seems strange that the F0 HAL library would attempt to do 16-bit transfers on a 8-bit buffer on a CPU that does not support unaligned access. This is perhaps a bug in the F0 HAL library?

S.Ma
Principal

Compare the reference manual. If the F0 SPI has FIFO and variable bit length from 4 to 16 bit, it's a Gen2 SPI IP with different behaviour when writing DR as 8 or 16 bit quantity.

The status register tells how filled are the FIFOs.

And just to make sure, are you in master mode?

VLev
Associate II

really I use master mode & 8 bit length.

VLev
Associate II

I work with st7735 spi display.

I use program from github.

https://github.com/afiskon/stm32-st7735

this program work without any problem at STM32F103C8T6.

And after, I take this program & compile one for F042T6Tx microcontroller.

And program not work.

Hardware error!

I noticed that the program works to the point where the function transmits more than one byte.

Next, I replace code in hal_spi_transmit function.

take some code from f1 hal driver & put one to f0 hal driver.

And program work!!!!

but this is not good idea, I think, change standart ST library driver.

0690X0000088C5GQAU.png

HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)

{

 uint32_t tickstart = 0U;

 HAL_StatusTypeDef errorcode = HAL_OK;

 if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (Size > 1U))

 {

  /* in this case, 16-bit access is performed on Data

    So, check Data is 16-bit aligned address */

  assert_param(IS_SPI_16BIT_ALIGNED_ADDRESS(pData));

 }

 /* Check Direction parameter */

 assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));

 /* Process Locked */

 __HAL_LOCK(hspi);

 /* Init tickstart for timeout management*/

 tickstart = HAL_GetTick();

 if (hspi->State != HAL_SPI_STATE_READY)

 {

  errorcode = HAL_BUSY;

  goto error;

 }

 if ((pData == NULL) || (Size == 0U))

 {

  errorcode = HAL_ERROR;

  goto error;

 }

 /* Set the transaction information */

 hspi->State    = HAL_SPI_STATE_BUSY_TX;

 hspi->ErrorCode  = HAL_SPI_ERROR_NONE;

 hspi->pTxBuffPtr = (uint8_t *)pData;

 hspi->TxXferSize = Size;

 hspi->TxXferCount = Size;

 /*Init field not used in handle to zero */

 hspi->pRxBuffPtr = (uint8_t *)NULL;

 hspi->RxXferSize = 0U;

 hspi->RxXferCount = 0U;

 hspi->TxISR    = NULL;

 hspi->RxISR    = NULL;

 /* Configure communication direction : 1Line */

 if (hspi->Init.Direction == SPI_DIRECTION_1LINE)

 {

  SPI_1LINE_TX(hspi);

 }

#if (USE_SPI_CRC != 0U)

 /* Reset CRC Calculation */

 if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)

 {

  SPI_RESET_CRC(hspi);

 }

#endif /* USE_SPI_CRC */

 /* Check if the SPI is already enabled */

 if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)

 {

  /* Enable SPI peripheral */

  __HAL_SPI_ENABLE(hspi);

 }

 /* Transmit data in 16 Bit mode */

 if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)

 {

  if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U))

  {

   hspi->Instance->DR = *((uint16_t *)pData);

   pData += sizeof(uint16_t);

   hspi->TxXferCount--;

  }

  /* Transmit data in 16 Bit mode */

  while (hspi->TxXferCount > 0U)

  {

   /* Wait until TXE flag is set to send data */

   if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))

   {

    hspi->Instance->DR = *((uint16_t *)pData);

    pData += sizeof(uint16_t);

    hspi->TxXferCount--;

   }

   else

   {

    /* Timeout management */

    if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout)))

    {

     errorcode = HAL_TIMEOUT;

     goto error;

    }

   }

  }

 }

 /* Transmit data in 8 Bit mode */

 else

 {

  if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U))

  {

   *((__IO uint8_t*)&hspi->Instance->DR) = (*pData);

   pData += sizeof(uint8_t);

   hspi->TxXferCount--;

  }

  while (hspi->TxXferCount > 0U)

  {

   /* Wait until TXE flag is set to send data */

   if(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))

   {

    *((__IO uint8_t*)&hspi->Instance->DR) = (*pData);

    pData += sizeof(uint8_t);

    hspi->TxXferCount--;

   }

//   if (hspi->TxXferCount > 1U)

//   {

//    /* write on the data register in packing mode */

//    hspi->Instance->DR = *((uint16_t *)pData);

//    pData += sizeof(uint16_t);

//    hspi->TxXferCount -= 2U;

//   }

//   else

//   {

//    *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++);

//    hspi->TxXferCount--;

//   }

//  }

//  while (hspi->TxXferCount > 0U)

//  {

//   /* Wait until TXE flag is set to send data */

//   if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))

//   {

//    if (hspi->TxXferCount > 1U)

//    {

//     /* write on the data register in packing mode */

//     hspi->Instance->DR = *((uint16_t *)pData);

//     pData += sizeof(uint16_t);

//     hspi->TxXferCount -= 2U;

//    }

//    else

//    {

//     *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++);

//     hspi->TxXferCount--;

//    }

//   }

   else

   {

    /* Timeout management */

    if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout)))

    {

     errorcode = HAL_TIMEOUT;

     goto error;

    }

   }

  }

 }

#if (USE_SPI_CRC != 0U)

 /* Enable CRC Transmission */

 if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)

 {

  SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);

 }

#endif /* USE_SPI_CRC */

 /* Check the end of the transaction */

 if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)

 {

  hspi->ErrorCode = HAL_SPI_ERROR_FLAG;

 }

 /* Clear overrun flag in 2 Lines communication mode because received is not read */

 if (hspi->Init.Direction == SPI_DIRECTION_2LINES)

 {

  __HAL_SPI_CLEAR_OVRFLAG(hspi);

 }

 if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)

 {

  errorcode = HAL_ERROR;

 }

error:

 hspi->State = HAL_SPI_STATE_READY;

 /* Process Unlocked */

 __HAL_UNLOCK(hspi);

 return errorcode;

}

VLev
Associate II

Just to be clear - when you programmed your code into an F0, you had re-compiled the code with the F0 HAL library, correct?

yes I programmed my code into f1, and re-compiled with F0.

And you got a hardware fault FROM THAT HAL CODE that attempts to write 16-bits to the SPI DR?

yes

And hand-editing the F0 HAL SPI function to force the F0 code to do only 8-bit writes to the SPI DR then makes the F0 code work with no hardware faults, correct?

yes

Then I would guess that your SPI buffer is not aligned on a 16-bit boundary and that the F0 doesn't allow non-aligned 16-bit access (see section 2.4 of the STM32 Cortex M0 Programming Manual (https://www.st.com/resource/en/programming_manual/dm00051352.pdf).

really, program use 8 bit data array.

Seems strange that the F0 HAL library would attempt to do 16-bit transfers on a 8-bit buffer on a CPU that does not support unaligned access. This is perhaps a bug in the F0 HAL library?

exactly! that's what I wanted to say.

I transfer the program from one controller to another. controllers with one company and built on the same architecture. And the drivers are different. and most importantly, the f0 driver does not work correctly.

but maybe I'm wrong in something?

Below, in comment, I give the code and also the program that I use.

VLev
Associate II

Hi Bob!

I think, I understood what the problem is and why the program goes to hardware error.

Is this code fair in 8bit mode?

hspi->Instance->DR = *((uint16_t *)pData);

I think not!

In this code program immediately go to hardware error!

I think, driver for f0 & f7 in that place have fatal error!

What do you think about?

---

Sincerely,

Vitaly.

VLev
Associate II

Hi!

who can answer for question.

Is this code fair in 8bit mode?

hspi->Instance->DR = *((uint16_t *)pData);

In this code program immediately go to hardware error!

I think, driver for f0 & f7 in that place have fatal error!

Or not?

---

Sincerely,

Vitaly.