cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to enable DMA for multiple ADC within a TouchGFX project on a F429-DISCO

NCo
Associate
/******************************************************************************
 *
 * @brief     This file is part of the TouchGFX 4.8.0 evaluation distribution.
 *
 * @author    Draupner Graphics A/S <http://www.touchgfx.com>
 *
 ******************************************************************************
 *
 * @section Copyright
 *
 * This file is free software and is provided for example purposes. You may
 * use, copy, and modify within the terms and conditions of the license
 * agreement.
 *
 * This is licensed software for evaluation use, any use must strictly comply
 * with the evaluation license agreement provided with delivery of the
 * TouchGFX software.
 *
 * The evaluation license agreement can be seen on www.touchgfx.com
 *
 * @section Disclaimer
 *
 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Draupner Graphics A/S has
 * no obligation to support this software. Draupner Graphics A/S is providing
 * the software "AS IS", with no express or implied warranties of any kind,
 * including, but not limited to, any implied warranties of merchantability
 * or fitness for any particular purpose or warranties against infringement
 * of any proprietary rights of a third party.
 *
 * Draupner Graphics A/S can not be held liable for any consequential,
 * incidental, or special damages, or any other relief, or for any claim by
 * any third party, arising from your use of this software.
 *
 *****************************************************************************/
 
#include <touchgfx/hal/HAL.hpp>
#include <touchgfx/hal/BoardConfiguration.hpp>
 
using namespace touchgfx;
 
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "stm32f4xx_hal.h"
 
/**
 * Functions prototypes
 */
static void gpio_init(void);
static void adc_init(void);
static void dma_init(DMA_HandleTypeDef *hdma, DMA_Stream_TypeDef *stream, uint32_t channel, ADC_HandleTypeDef *hadc, uint32_t nadc, uint32_t *data, IRQn_Type irq);
static void serial_init(void);
//static void timer_init(void);
 
/**
 * Global variables
 */
UART_HandleTypeDef huart[3];
TIM_HandleTypeDef htim[2];
ADC_HandleTypeDef hadc[3];
DMA_HandleTypeDef hdma[3];
uint32_t adcValues[4];
 
/**
 * Define the FreeRTOS task priorities and stack sizes
 */
#define configGUI_TASK_PRIORITY                 ( tskIDLE_PRIORITY + 3 )
#define configGUI_TASK_STK_SIZE                 ( 1024 )
 
static void GUITask(void* params)
{
    touchgfx::HAL::getInstance()->taskEntry();
}
 
int main(void)
{
    hw_init();
	  gpio_init();
	  adc_init();
	  dma_init(&hdma[0], DMA2_Stream4, DMA_CHANNEL_0, &hadc[0], 2, &adcValues[0], DMA2_Stream4_IRQn);
	  dma_init(&hdma[1], DMA2_Stream2, DMA_CHANNEL_1, &hadc[1], 1, &adcValues[2], DMA2_Stream2_IRQn);
	  dma_init(&hdma[2], DMA2_Stream0, DMA_CHANNEL_2, &hadc[2], 1, &adcValues[3], DMA2_Stream0_IRQn);
	  serial_init();
	  //timer_init();
	  touchgfx_init();
	
    xTaskCreate(GUITask, "GUITask",
                configGUI_TASK_STK_SIZE,
                NULL,
                configGUI_TASK_PRIORITY,
                NULL);
	
    vTaskStartScheduler();
 
    for (;;);
}
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
 
  /* USER CODE END Error_Handler_Debug */
}
 
void gpio_init(void)
{
	GPIO_InitTypeDef pinInit;
	pinInit.Pull = GPIO_NOPULL;
	
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
	
	pinInit.Mode = GPIO_MODE_OUTPUT_PP;
	pinInit.Speed = GPIO_SPEED_FREQ_LOW;
	pinInit.Pin = GPIO_PIN_13;
	HAL_GPIO_Init(GPIOC, &pinInit);
 
	pinInit.Mode = GPIO_MODE_ANALOG;
	pinInit.Pin = GPIO_PIN_3;
	HAL_GPIO_Init(GPIOC, &pinInit);
 
	pinInit.Pin = GPIO_PIN_5;
	HAL_GPIO_Init(GPIOA, &pinInit);
 
	pinInit.Pin = GPIO_PIN_6;
	HAL_GPIO_Init(GPIOF, &pinInit);
}
 
/**
  * @brief USART Initialization Function
  * @param None
  * @retval None
  */
void uart_init(UART_HandleTypeDef *huart, USART_TypeDef *uart, uint32_t baud, uint32_t mode)
{
  huart->Instance = uart;
  huart->Init.BaudRate = baud;
  huart->Init.WordLength = UART_WORDLENGTH_8B;
  huart->Init.StopBits = UART_STOPBITS_1;
  huart->Init.Parity = UART_PARITY_NONE;
  huart->Init.Mode = mode;
  huart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart->Init.OverSampling = UART_OVERSAMPLING_16;
	if (mode == UART_MODE_TX_RX)
	{
		if (HAL_UART_Init(huart) != HAL_OK)
		{
			Error_Handler();
		}
	} else {
		if (HAL_HalfDuplex_Init(huart) != HAL_OK)
		{
			Error_Handler();
		}
	}
}
 
void serial_init(void)
{
	uart_init(&huart[0], UART5,   74880, UART_MODE_TX_RX);
	uart_init(&huart[1], USART1, 115200, UART_MODE_TX_RX);
	uart_init(&huart[2], USART2,   1200, UART_MODE_RX);
}
 
/**
  * @brief ADC1 Initialization Function
  * @param None
  * @retval None
  */
static void adc_start(ADC_HandleTypeDef *hadc, ADC_TypeDef *adc, uint32_t nConv, ADC_ChannelConfTypeDef chCfg[])
{
  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
  */
  hadc->Instance = adc;
  hadc->Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
  hadc->Init.Resolution = ADC_RESOLUTION_12B;
  hadc->Init.ScanConvMode = ENABLE;
  hadc->Init.ContinuousConvMode = ENABLE;
  hadc->Init.DiscontinuousConvMode = DISABLE;
  hadc->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc->Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc->Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc->Init.NbrOfConversion = nConv;
  hadc->Init.DMAContinuousRequests = ENABLE;
  hadc->Init.EOCSelection = ADC_EOC_SEQ_CONV;
  if (HAL_ADC_Init(hadc) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
  */
	for (uint32_t n = 0; n < nConv; n++) {
	  chCfg[n].Rank = n + 1;
    chCfg[n].SamplingTime = ADC_SAMPLETIME_480CYCLES;
 
		if (HAL_ADC_ConfigChannel(hadc, &chCfg[n]) != HAL_OK)
		{
			Error_Handler();
		}
	}
	HAL_ADC_Start(hadc);
}
 
void adc_init(void)
{
	__HAL_RCC_ADC1_CLK_ENABLE();
	__HAL_RCC_ADC2_CLK_ENABLE();
	__HAL_RCC_ADC3_CLK_ENABLE();
 
  ADC_ChannelConfTypeDef sConfig[2] = {0};
 
	sConfig[0].Channel = ADC_CHANNEL_13;
  sConfig[1].Channel = ADC_CHANNEL_TEMPSENSOR;
	adc_start(&hadc[0], ADC1, 2, sConfig);
 
  sConfig[0].Channel = ADC_CHANNEL_5;
	adc_start(&hadc[1], ADC2, 1, sConfig);
 
  sConfig[0].Channel = ADC_CHANNEL_4;
	adc_start(&hadc[2], ADC3, 1, sConfig);
}
 
void dma_init(DMA_HandleTypeDef *hdma, DMA_Stream_TypeDef *stream, uint32_t channel, ADC_HandleTypeDef *hadc, uint32_t nadc, uint32_t *data, IRQn_Type irq)
{
	hdma->Instance = stream;
	hdma->Init.Channel = channel;
	hdma->Init.Direction = DMA_PERIPH_TO_MEMORY;
	hdma->Init.PeriphInc = DMA_PINC_DISABLE;
	hdma->Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
	hdma->Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
	if (nadc > 1) {
		hdma->Init.MemInc = DMA_MINC_ENABLE;
  	hdma->Init.Mode = DMA_CIRCULAR;
	} else {
		hdma->Init.MemInc = DMA_MINC_DISABLE;
  	hdma->Init.Mode = DMA_NORMAL;
  }
	hdma->Init.Priority = DMA_PRIORITY_LOW;
	hdma->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
	
	HAL_DMA_Init(hdma);
	
	__HAL_LINKDMA(hadc, DMA_Handle, *hdma);
	
	HAL_NVIC_SetPriority(irq, 0, 0);
	HAL_NVIC_EnableIRQ(irq);
	
	HAL_ADC_Start_DMA(hadc, data, nadc);
}

I'm trying to enable DMA for multiple ADC within a TouchGFX project on a F429-DISCO as follow :

  • ADC1 IN13 (PC3) on DMA2 Stream 4 (Channel 0)
  • ADC2 IN5 (PA5) on DMA2 Stream 2 (Channel 1)
  • ADC3 IN4 (PF6) on DMA2 Stream 0 (Channel 2)

I followed and adapt tutorial from https://www.youtube.com/watch?v=23tILSLmQLw, build is successfull but the board hangs on second call to dma_init.

I tried to change dma_init call order without success, the second call hang on HAL_GetTick call of HAL_DMA_Init.

I can go some step further when I step into each function.

I don't know where to search or what I've missed, if anyone has an idea ?

2 REPLIES 2
NCo
Associate

Also tried to put HAL_ADC_Start_DMA outside dma_init, all 3 dma_init call suceeded but second HAL_ADC_Start_DMA always hang.

Apparently hanging when starting the DMA channel (HAL_DMA_Start_IT).

If you stop execution in the debugger where is it stuck?

Instrument HardFault_Handler and Error_Handler properly so you know if you are there.

Make sure you have all the IRQ Handlers written, with the right naming. Check linkage.​

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