cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F413VG, I am not able to work SPI over DMA or Interrupt. I can do it in a polling way which is not an option for my case.

sarp daltaban
Associate II

I have followed many of tutorials on the web.

I have problems using SPI via DMA and IT. There is no data flow. But it works using polling.

In addition to this, UART also is not functional over DMA.

My CubeMX version is 5.4.0.

I have watched tutorials below:

https://www.youtube.com/watch?v=L_sEt8-Mj3w&t=385s

https://www.youtube.com/watch?v=0XMS86bdzEo

I did the same but no result, please let me know furher.

4 REPLIES 4
mckenney
Senior

Here's something I keep forgetting: If any of the DMA completion bits is set, the DMA won't start. I usually end up writing a little "clear all" macro for this.

Unsolicited: Don't reject polling a priori. My experience is that (1) For a fast SPI, interrupts are a net loss due to ISR overhead (2) For short transactions (say < 10 bytes or so) DMA is a net loss due to the cost of loading the registers. Just something to think about.

May I want you to give an example clearing DMA bits? In a generic way hopefully.​ Because, in examples nobody does it i.e dma usart tutorial I shared above, the tutorial owner does not clear anything and works for 3 bytes accurately like doing an interrupt callback context.

Do you have an example project done via cubemx?​

Bests​

Perhaps read the reference manuals and have understanding of the underlying hardware/architecture (micro-controllers). Watching videos is not how most of us learned to do stuff or got things done.

>>STM32F413VG, I am not able to work SPI over DMA or Interrupt.

What specifically is the issue? "Not Working" doesn't really identify an issue, use a scope and logic analyzer and try to explain what's actually happening, and what's wrong about what's happening vs what you've commanded the thing to do.

>>I can do it in a polling way which is not an option for my case.

Again, lacks any context of what your case is, or why it is not an option, or why you can't manage the status transitions in interrupts generated by those transitions.

Not going to what videos to determine what YOU have done. The guy in the video was presumably successful, need to figure out why your implementation wasn't.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Ok, here is what I have:

uint8_t recData, recBuf[100], recIndex = 0;
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* init code for FATFS */
  MX_FATFS_Init();
 
  /* init code for USB_DEVICE */
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN StartDefaultTask */
	HAL_UART_Receive_IT(&huart3, &recData, 1);
	
	HAL_GPIO_WritePin(WIFI_POWER_ENABLE_GPIO_Port, WIFI_POWER_ENABLE_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(WIFI_RESET_GPIO_Port, WIFI_RESET_Pin, GPIO_PIN_SET);
	HAL_Delay(100);
  /* Infinite loop */
  for(;;)
  {
		vIWDGReset();
		
		uint32_t res = HAL_UART_Transmit_DMA(&huart3, (uint8_t *)"AT\r\n", sizeof("AT\r\n"));
		HAL_Delay(1000);
		printf("res: %i \r\n", res);
  }
  /* USER CODE END StartDefaultTask */
}
 
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if (huart->Instance == USART3)
	{
		if (recIndex == sizeof(recBuf) - 1) recIndex = 0;
		recBuf[recIndex++] = recData;
		printf("%c", recData);
		HAL_UART_Receive_IT(&huart3, &recData, 1);
	}
}

There is only 1 DMA send part is above, which returns HAL_OK once and HAL_BUSY rest of the times.

I have activated DMA for this USART in CubeMX settings.

When I change _DMA -> _IT, everything works, which leds us thinking of DMA USART sending is buggy.

On the other hand, I have the reversed case below where I transmit using _IT but waiting reception via _DMA.

As you see, I do not clear anything and/but, callback is never called.

uint8_t recData, recBuf[100], recIndex = 0;
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* init code for FATFS */
  MX_FATFS_Init();
 
  /* init code for USB_DEVICE */
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN StartDefaultTask */	
	printf("%i", HAL_UART_Receive_DMA(&huart3, &recData, 1));
	
	HAL_GPIO_WritePin(WIFI_POWER_ENABLE_GPIO_Port, WIFI_POWER_ENABLE_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(WIFI_RESET_GPIO_Port, WIFI_RESET_Pin, GPIO_PIN_SET);
	HAL_Delay(100);
  /* Infinite loop */
  for(;;)
  {
		vIWDGReset();
		
		uint32_t res = HAL_UART_Transmit_IT(&huart3, (uint8_t *)"AT\r\n", sizeof("AT\r\n"));
		HAL_Delay(1000);
		printf("res: %i \r\n", res);
  }
  /* USER CODE END StartDefaultTask */
}
 
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if (huart->Instance == USART3)
	{
		if (recIndex == sizeof(recBuf) - 1) recIndex = 0;
		recBuf[recIndex++] = recData;
		printf("%c", recData);
		printf("%i", HAL_UART_Receive_DMA(&huart3, &recData, 1));
	}
}

Polling method is not an option for my case; it is because, I should be doing real time calculations at the same time.

Sorry for the indentation, I can't reindent on website's editor.