关于STM32 hal库SPI的一个BUG

Posted Rogueman

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于STM32 hal库SPI的一个BUG相关的知识,希望对你有一定的参考价值。

具体bug点在HAL_SPI_TransmitReceive这个函数里面。具体表现是莫名其妙会进入hardfault,但是,也不排除直接debug跑死没反应的情况。

因为在最初的时候,程序调试异常都是直接调试卡死。这其中的具体原因还没搞清楚。

既然是bug,那肯定是满足了一定条件下的错误。但是很遗憾,具体条件我没找到。但是解决方法找到了。

代码中这一段改成:

while((hspi->TxXferCount > 0) || (hspi->RxXferCount > 0))
    {
      /* check TXE flag */
      if((hspi->TxXferCount > 0) && ((hspi->Instance->SR & SPI_FLAG_TXE) == SPI_FLAG_TXE))
      {
//        if(hspi->TxXferCount > 1)
//        {
//          hspi->Instance->DR = *((uint16_t*)hspi->pTxBuffPtr);
//          hspi->pTxBuffPtr += sizeof(uint16_t);
//          hspi->TxXferCount -= 2;
//        }
//        else
//        {
          *(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr++);
          hspi->TxXferCount--;
//        }

        /* Enable CRC Transmission */
        if((hspi->TxXferCount == 0) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
        {
          /* Set NSS Soft to received correctly the CRC on slave mode with NSS pulse activated */
          if(((hspi->Instance->CR1 & SPI_CR1_MSTR) == 0) && ((hspi->Instance->CR2 & SPI_CR2_NSSP) == SPI_CR2_NSSP))
          {
             SET_BIT(hspi->Instance->CR1, SPI_CR1_SSM);
          }
          hspi->Instance->CR1 |= SPI_CR1_CRCNEXT;
        }
      }

      /* Wait until RXNE flag is reset */
      if((hspi->RxXferCount > 0) && ((hspi->Instance->SR & SPI_FLAG_RXNE) == SPI_FLAG_RXNE))
      {
//        if(hspi->RxXferCount > 1)
//        {
//          *((uint16_t*)hspi->pRxBuffPtr) = hspi->Instance->DR;
//          hspi->pRxBuffPtr += sizeof(uint16_t);
//          hspi->RxXferCount -= 2;
//          if(hspi->RxXferCount <= 1)
//          {
//            /* set fiforxthresold before to switch on 8 bit data size */
//            SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
//          }
//        }
//        else
//        {
                    SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
          (*hspi->pRxBuffPtr++) =  *(__IO uint8_t *)&hspi->Instance->DR;
          hspi->RxXferCount--;
//        }
      }
      if((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >=  Timeout))
      {
        errorcode = HAL_TIMEOUT;
        goto error;
      }
    }while((hspi->TxXferCount > 0) || (hspi->RxXferCount > 0))
    {
      /* check TXE flag */
      if((hspi->TxXferCount > 0) && ((hspi->Instance->SR & SPI_FLAG_TXE) == SPI_FLAG_TXE))
      {
//        if(hspi->TxXferCount > 1)
//        {
//          hspi->Instance->DR = *((uint16_t*)hspi->pTxBuffPtr);
//          hspi->pTxBuffPtr += sizeof(uint16_t);
//          hspi->TxXferCount -= 2;
//        }
//        else
//        {
          *(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr++);
          hspi->TxXferCount--;
//        }

        /* Enable CRC Transmission */
        if((hspi->TxXferCount == 0) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
        {
          /* Set NSS Soft to received correctly the CRC on slave mode with NSS pulse activated */
          if(((hspi->Instance->CR1 & SPI_CR1_MSTR) == 0) && ((hspi->Instance->CR2 & SPI_CR2_NSSP) == SPI_CR2_NSSP))
          {
             SET_BIT(hspi->Instance->CR1, SPI_CR1_SSM);
          }
          hspi->Instance->CR1 |= SPI_CR1_CRCNEXT;
        }
      }

      /* Wait until RXNE flag is reset */
      if((hspi->RxXferCount > 0) && ((hspi->Instance->SR & SPI_FLAG_RXNE) == SPI_FLAG_RXNE))
      {
//        if(hspi->RxXferCount > 1)
//        {
//          *((uint16_t*)hspi->pRxBuffPtr) = hspi->Instance->DR;
//          hspi->pRxBuffPtr += sizeof(uint16_t);
//          hspi->RxXferCount -= 2;
//          if(hspi->RxXferCount <= 1)
//          {
//            /* set fiforxthresold before to switch on 8 bit data size */
//            SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
//          }
//        }
//        else
//        {
                    SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
          (*hspi->pRxBuffPtr++) =  *(__IO uint8_t *)&hspi->Instance->DR;
          hspi->RxXferCount--;
//        }
      }
      if((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >=  Timeout))
      {
        errorcode = HAL_TIMEOUT;
        goto error;
      }
    }

 

问题就解决了。具体原因似乎是因为

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

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

 

In 8-bit mode the address pTxBuffPtr (pRxBuffPtr) may be not word-aligned. The casting (uint16_t*)hspi->pTxBuffPtr is the cause of hard-fault.

以上是关于关于STM32 hal库SPI的一个BUG的主要内容,如果未能解决你的问题,请参考以下文章

笔记之STM32F0芯片SPI_DMA的使用(HAL库)

笔记之STM32F0芯片SPI_DMA的使用(HAL库)

STM32H7的SPI总线基础知识和HAL库API

STM32 HAL库怎么使用SPI的发送和接收函数

STM32F429开发板用户手册第31章 STM32F429的SPI总线基础知识和HAL库API

STM32F4 HAL库开发 -- SPI Flash