STM32F4 data length assert failed for HAL_SPI_TransmitReceive_DMA
Hello,
I think I have interesting case, but from the beginning
I use STM32F446ZEJx and HAL Drivers from STM32Cube_FW_F4_V1.28.3.
When I use
HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)with Size=5 it internally checks the argument
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
return HAL_ERROR;and passes the Size to
/* Set the transaction information */
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
hspi->pTxBuffPtr = (const uint8_t *)pTxData;
hspi->TxXferSize = Size;
hspi->TxXferCount = Size;
hspi->pRxBuffPtr = (uint8_t *)pRxData;
hspi->RxXferSize = Size;
hspi->RxXferCount = Size;later it configures the DMA channels,
Rx
/* Enable the Rx DMA Stream/Channel */
HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr, hspi->RxXferCount)Tx
/* Enable the Tx DMA Stream/Channel */
HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR, hspi->TxXferCount)where is another control of DataLength parameter
HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
/* Check the parameters */
assert_param(IS_DMA_BUFFER_SIZE(DataLength));
// #define IS_DMA_BUFFER_SIZE(SIZE) (((SIZE) >= 0x01U) && ((SIZE) < 0x10000U))which triggers the assertion
Assert failed in file ../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c on line 459And here is the problem, what could happen in the mean time?
Quite obvious answer is interrupt that changed the structure fields
hspi->TxXferCount = 0;
hspi->RxXferCount = 0;but the SPI and DMA interrupts are enabled at the end, after the configuration that failed.
The stack and heap is big enough, no nested interrupts, assert failed stops the execution and waits for watchdog reset.
The way I use HAL library is summarized below, the same callback for success and for error, when error I clean up using HAL_SPI_Abort, is it enough?
HAL_SPI_RegisterCallback(self->Spi,HAL_SPI_TX_RX_COMPLETE_CB_ID,SpiCallback);
HAL_SPI_RegisterCallback(self->Spi,HAL_SPI_ERROR_CB_ID ,SpiCallback);
// SpiCallback uses osSemaphoreRelease to resume the SpiTransaction
static U8 SpiTransaction(tTmc* const self, U8* const data, U16 size)
{
assert_param(self);
if(HAL_SPI_TransmitReceive_DMA(self->Spi,data,data,size)!=HAL_OK)
return 2;
__HAL_DMA_DISABLE_IT(self->Spi->hdmarx,DMA_IT_HT); // mask half transfer interrupt
if(osSemaphoreAcquire(self->SpiSync,5)!=osOK)
{
HAL_SPI_Abort(self->Spi);
osSemaphoreAcquire(self->SpiSync,0);
return 3;
}
return HAL_SPI_GetError(self->Spi);
};The problem happens once a few days, normally it works and transmission is executed every 200 ms.
Did someone have similar issue?
Best Regards
JH
