2023-11-17 09:55 AM - edited 2023-11-17 10:32 AM
Hi,
I am using STM32U575VIT6Q in a BPSK receiver. The STM32U575 SPI1 is set to slave, receiver only. GPDMA channel 6 is linked to the SPI1 input and buffering input data to a data array. The SPI1 clock input (PA5) is connected to TIM1 channel 3 output (PE13) with clock at 1.6667MHz.
The SPI1 input is working well when the data size is set to 8 bits. To optimize the demodulator, I would like to use 20bits data size which will simplify the algorithm implementation. However once I changed the SPI1 data size other than 8, it will be always trapped to Error_Handler(). What is the reason and how to solve it?
Thanks.
Regards,
Hao
if(HAL_TIM_OC_Start_IT(&htim1, TIM_CHANNEL_3) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
MX_SPI1Queue_Config();
HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel6, &SPI1Queue);
__HAL_LINKDMA(&hspi1, hdmarx, handle_GPDMA1_Channel6);
cStatus = HAL_SPI_Receive_DMA(&hspi1, (uint8_t *)aSPI1_RXBuffer, SPI1_RX_BUFFER_SIZE);
if (cStatus != HAL_OK)
{
/* Transfer error in transmission process */
Error_Handler();
}
The aSPI1_RxBuffer is set as
ALIGN_32BYTES (uint32_t aSPI1_RXBuffer[SPI1_RX_BUFFER_SIZE]);
The SPI1 and DMA setup is listed below:
static void MX_SPI1_Init(void)
{
SPI_AutonomousModeConfTypeDef HAL_SPI_AutonomousMode_Cfg_Struct = {0};
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 0x7;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
hspi1.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
hspi1.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerState = SPI_AUTO_MODE_DISABLE;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerSelection = SPI_GRP1_GPDMA_CH0_TCF_TRG;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerPolarity = SPI_TRIG_POLARITY_RISING;
if (HAL_SPIEx_SetConfigAutonomousMode(&hspi1, &HAL_SPI_AutonomousMode_Cfg_Struct) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPDMA1 Initialization Function
* @PAram None
* @retval None
*/
static void MX_GPDMA1_Init(void)
{
/* Peripheral clock enable */
__HAL_RCC_GPDMA1_CLK_ENABLE();
/* GPDMA1 interrupt Init */
HAL_NVIC_SetPriority(GPDMA1_Channel6_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel6_IRQn);
handle_GPDMA1_Channel6.Instance = GPDMA1_Channel6;
handle_GPDMA1_Channel6.InitLinkedList.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT;
handle_GPDMA1_Channel6.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel6.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
handle_GPDMA1_Channel6.InitLinkedList.TransferEventMode = DMA_TCEM_LAST_LL_ITEM_TRANSFER;
handle_GPDMA1_Channel6.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel6) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel6, DMA_CHANNEL_NPRIV) != HAL_OK)
{
Error_Handler();
}
}
2023-11-17 10:12 AM
The SPI clock polarity and phase settings can affect data reception. Double-check that hspi1.Init.CLKPolarity and hspi1.Init.CLKPhase are configured correctly for your application.
2023-11-17 10:29 AM
What's the cStatus actually report? Look at the function source, it's all provided, to see what specifically it is objecting too.
Likely due to the DMA transfer width, buffer size or alignment.
Size passed is a transfer count, not a byte count, at 20 bits you'd be talking about 32-bit word transfers
The code pasting tool is </>, click the ... icon to see the full list of tools in the tool bar.
2023-11-17 10:43 AM
Thank you for your response.
The returned error is always HAL_ERROR.
I read the document (RM0456, page 2434), regarding of the SPI data size, there is an ambiguous description as:
Note: Maximum data size can be limited up to 16-bits at some instances. At instances with
limited set of features, DSIZE2:0] bits are reserved and must be kept at reset state.
DSIZE[4:3] bits then control next settings of data size:
00xxx: 8-bits
01xxx: 16-bits
10xxx: 24-bits
11xxx: 32-bits.
Is that indicating the the data size only valid as 8, 16, 24 or 32? I tried to use 16, not work either.
2023-11-17 11:54 AM
I think I found the issue.
Even I set the DMA destination data setting to WORD in .ioc linkedlist file, the actual DMA destination data setting is remaining as DMA_DEST_DATAWIDTH_BYTE, then the integrity checking in
HAL_SPI_Receive_DMA()
will be fail if the data size bit is over 8.
I manually added following code before the integrity checking:
hspi->hdmarx->Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
/* Packing mode management is enabled by the DMA settings */
if (((hspi->Init.DataSize > SPI_DATASIZE_16BIT) && (hspi->hdmarx->Init.DestDataWidth != DMA_DEST_DATAWIDTH_WORD) && \
(IS_SPI_FULL_INSTANCE(hspi->Instance))) || \
((hspi->Init.DataSize > SPI_DATASIZE_8BIT) && (hspi->hdmarx->Init.DestDataWidth == DMA_DEST_DATAWIDTH_BYTE)))
{
/* Restriction the DMA data received is not allowed in this mode */
errorcode = HAL_ERROR;
__HAL_UNLOCK(hspi);
return errorcode;
}
Then the codes are going through and the 20bit data size is working well.
I suspect there is a bug in the STM32CubeIDE which deals the linkedlist file incompletely but I am not sure.
Thanks all to help me out.
2024-05-06 02:51 AM
Do you think it's the same problem as me? Don't know if my solution is possible.