Unable to enable DMA for multiple ADC within a TouchGFX project on a F429-DISCO
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2019-09-29 3:09 AM
/******************************************************************************
*
* @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 ?
- Labels:
-
ADC
-
DMA
-
STM32F4 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2019-09-29 4:23 AM
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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2019-09-29 4:46 AM
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.
Up vote any posts that you find helpful, it shows what's working..
