2019-09-29 03: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 :
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 ?
2019-09-29 04: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).
2019-09-29 04: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.