cancel
Showing results for 
Search instead for 
Did you mean: 

SPI6 Slave + BDMA + STM32H743 + CubeIDE/MX

Deadbeef
Associate II

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?

3 REPLIES 3
Deadbeef
Associate II

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
Associate II

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
Associate II

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.