Skip to main content
Deadbeef
Associate
January 25, 2022
Question

SPI6 Slave + BDMA + STM32H743 + CubeIDE/MX

  • January 25, 2022
  • 3 replies
  • 1351 views

Hello,

My design does not produce interrupts and I'm not sure why.

Goal:

SPI6 gets a 2MHz clock (external). For each clock the BDMA should take one 1 byte from a buffer (SRAM4, D3) and put it to the MISO. The BDMA runs double buffered => it should cycle M0/M1.

void MX_SPI6_Init(void)
{
 
 /* USER CODE BEGIN SPI6_Init 0 */
 
 /* USER CODE END SPI6_Init 0 */
 
 /* USER CODE BEGIN SPI6_Init 1 */
 
 /* USER CODE END SPI6_Init 1 */
 hspi6.Instance = SPI6;
 hspi6.Init.Mode = SPI_MODE_SLAVE;
 hspi6.Init.Direction = SPI_DIRECTION_2LINES;
 hspi6.Init.DataSize = SPI_DATASIZE_8BIT;
 hspi6.Init.CLKPolarity = SPI_POLARITY_LOW;
 hspi6.Init.CLKPhase = SPI_PHASE_1EDGE;
 hspi6.Init.NSS = SPI_NSS_SOFT;
 hspi6.Init.FirstBit = SPI_FIRSTBIT_MSB;
 hspi6.Init.TIMode = SPI_TIMODE_DISABLE;
 hspi6.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 hspi6.Init.CRCPolynomial = 0x0;
 hspi6.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
 hspi6.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
 hspi6.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
 hspi6.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
 hspi6.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
 hspi6.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
 hspi6.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
 hspi6.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
 hspi6.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
 hspi6.Init.IOSwap = SPI_IO_SWAP_DISABLE;
 if (HAL_SPI_Init(&hspi6) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN SPI6_Init 2 */
 
 /* USER CODE END SPI6_Init 2 */
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
 
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
 
if(spiHandle->Instance==SPI6)
 {
 /* USER CODE BEGIN SPI6_MspInit 0 */
 
 /* USER CODE END SPI6_MspInit 0 */
 
 /* SPI6 clock enable */
 __HAL_RCC_SPI6_CLK_ENABLE();
 
 __HAL_RCC_GPIOG_CLK_ENABLE();
 /**SPI6 GPIO Configuration
 PG14 ------> SPI6_MOSI
 PG13 ------> SPI6_SCK
 PG12 ------> SPI6_MISO
 */
 GPIO_InitStruct.Pin = SPI6_MOSI_Pin|SPI6_SCLK_Pin|SPI6_MISO_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF5_SPI6;
 HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
 
 /* SPI6 DMA Init */
 /* SPI6_TX Init */
 hdma_spi6_tx.Instance = BDMA_Channel0;
 hdma_spi6_tx.Init.Request = BDMA_REQUEST_SPI6_TX;
 hdma_spi6_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
 hdma_spi6_tx.Init.PeriphInc = DMA_PINC_DISABLE;
 hdma_spi6_tx.Init.MemInc = DMA_MINC_ENABLE;
 hdma_spi6_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
 hdma_spi6_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
 hdma_spi6_tx.Init.Mode = DMA_CIRCULAR;
 hdma_spi6_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
 if (HAL_DMA_Init(&hdma_spi6_tx) != HAL_OK)
 {
 Error_Handler();
 }
 
 __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi6_tx);
 
 /* SPI6 interrupt Init */
 HAL_NVIC_SetPriority(SPI6_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(SPI6_IRQn);
 
 /* USER CODE BEGIN SPI6_MspInit 1 */
 
 hdma_spi6_tx.XferCpltCallback 	= Dma_Trx_Spi_Transfer_Complete_M0;
 hdma_spi6_tx.XferM1CpltCallback 	= Dma_Trx_Spi_Transfer_Complete_M1;
 hdma_spi6_tx.XferErrorCallback	= Dma_Trx_Spi_Transfer_ERROR;
 
 /* USER CODE END SPI6_MspInit 1 */
}
void MX_BDMA_Init(void)
{
 
 /* DMA controller clock enable */
 __HAL_RCC_BDMA_CLK_ENABLE();
 
 /* DMA interrupt init */
 /* BDMA_Channel0_IRQn interrupt configuration */
 HAL_NVIC_SetPriority(BDMA_Channel0_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(BDMA_Channel0_IRQn);
 
}

Main.c

int main(void)
{
 /* USER CODE BEGIN 1 */
 
 /* USER CODE END 1 */
 
 /* MCU Configuration--------------------------------------------------------*/
 
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 
 /* USER CODE BEGIN Init */
 
 /* USER CODE END Init */
 
 /* Configure the system clock */
 SystemClock_Config();
 
/* Configure the peripherals common clocks */
 PeriphCommonClock_Config();
 MX_GPIO_Init();
 MX_BDMA_Init();
 MX_SPI6_Init();
 
/* USER CODE BEGIN 2 */
 start_SPI_BDMA_MULTIBUFFERED();
/* USER CODE END 2 */
 
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* USER CODE END WHILE */
 
 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
volatile TrxTxFrameBuffer	_gTxTrxCircBuffer[TRX_FRAME_COUNT] __attribute__((section(".sram4_d3"))); // circular TX buffer
 
void start_SPI_BDMA_MULTIBUFFERED(void)
{
 /* start the dma */
 if(HAL_DMAEx_MultiBufferStart_IT(&hdma_spi_tx, \
				 (uint32_t)&_gTxTrxCircBuffer[1].buf[0], \
				 (uint32_t)&hspi6->TXDR, \
				 (uint32_t)&_gTxTrxCircBuffer[1].buf[1], \
				 (uint32_t)TRX_FRAME_SIZE) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* enable spi instance */
 __HAL_SPI_ENABLE(&hspi6);
}

void BDMA_Channel0_IRQHandler(void)
{
 /* USER CODE BEGIN BDMA_Channel0_IRQn 0 */
 
 /* USER CODE END BDMA_Channel0_IRQn 0 */
 HAL_DMA_IRQHandler(&hdma_spi6_tx);
 /* USER CODE BEGIN BDMA_Channel0_IRQn 1 */
 
 /* USER CODE END BDMA_Channel0_IRQn 1 */
}

There are no interrupts generated. If I change the code and manually start HAL_TransmitReceive_SPI it works.

Maybe I need to create a DMAMUX event interrupt? But as far as I understand this should be routed directly to the BDMA. And since I used and configured everything in CubeMX it should run without a problem, right?

This topic has been closed for replies.

3 replies

Deadbeef
DeadbeefAuthor
Associate
January 27, 2022

Hi again,

I played around with different HAL_API to figure out its not generating anything.

SPI6 as slave.

HAL_SPI_Transmit_IT() is working

HAL_SPI_Transmit_DMA() is partially working.

HAL_DMAEx_MultiBufferStart_IT() not working at all.

Deadbeef
DeadbeefAuthor
Associate
January 27, 2022

Hi,

so. I fixed it.

The SPI (slave) was permanently feed with a running SCLK. The internal driver simply flagged UDR. This was the problem which caused it to directly stall.

The HAL_SPI_Transmit_IT was not affected. I assume it evaluates a little later and the buffer is send.

The HAL_SPI_Transmit_DMA just wont start, since the UDR is directly active.

Workaround is to clear the UDR bit before the HAL_DMA_IRQHandler() evaluates the interrupt.

void SPI6_IRQHandler(void)
{
	/* USER CODE BEGIN SPI6_IRQn 0 */
	__HAL_SPI_CLEAR_UDRFLAG(&hspi6);
	/* USER CODE END SPI6_IRQn 0 */
	HAL_SPI_IRQHandler(&hspi6);
}

GCava.2
Visitor II
June 22, 2022

Hello Deadbeef,

I'm working to an SPI communication between two STM32H743 boards, in particular, for the first ST I use SPI3 (slave) with DMA and for the second ST I use SPI6 (slave) with BDMA. Both the boards are clocked with an external fixed clock.

Now, for SPI3 I haven't any problems in fact, with oscilloscope, I see go out from the MISO data that I set, while with SPI6 I have only poblems in fact i don't see anything on MISO pin.

Could u share your .ioc and completed project in order to get ideas?

Thanks and regards.