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

2017/7/22 更新

对于这个问题,有更为方便的方法。不需要修改库文件。

在使用的buff数组前,使用__align(4)进行4字节对齐。

完美解决问题~

posted on 2017-07-14 20:23  Rogueman  阅读(11526)  评论(0编辑  收藏  举报

导航