cancel
Showing results for 
Search instead for 
Did you mean: 

ADC+DMA : Problem with Memory Increment and Destination Width

marcel23
Associate II
Posted on May 01, 2017 at 23:05

Hi,

I'm currently trying to use ADC1 + DMA1 + TIM1 on STM32F091CC. I've run into two problems:

1 - DMA is not incrementing the memory buffer('Increment Address' is checked on CubeMX and hdma_adc.Init.MemInc = DMA_MINC_ENABLE). It overwrites every data read on the same address.

2 - Regardless of Data_Width value, DMA is only copying the first byte to the destination address.(overwriting previous values - see 1 and attached pictures).

Generated ADC code:

/**
 ******************************************************************************
 * File Name : ADC.c
 * Description : This file provides code for the configuration
 * of the ADC instances.
 ******************************************************************************
 *
 * Copyright (c) 2017 STMicroelectronics International N.V. 
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted, provided that the following conditions are met:
 *
 * 1. Redistribution of source code must retain the above copyright notice, 
 * this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * 3. Neither the name of STMicroelectronics nor the names of other 
 * contributors to this software may be used to endorse or promote products 
 * derived from this software without specific written permission.
 * 4. This software, including modifications and/or derivative works of this 
 * software, must execute solely and exclusively on microcontroller or
 * microprocessor devices manufactured by or for STMicroelectronics.
 * 5. Redistribution and use of this software other than as permitted under 
 * this license is void and will automatically terminate your rights under 
 * this license. 
 *
 * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS 'AS IS' 
 * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
 * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
 * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT 
 * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************
 */
/* Includes ------------------------------------------------------------------*/
#include 'adc.h'
#include 'gpio.h'
#include 'dma.h'
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
ADC_HandleTypeDef hadc;
DMA_HandleTypeDef hdma_adc;
/* ADC init function */
void MX_ADC_Init(void)
{
 ADC_ChannelConfTypeDef sConfig;
 /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
 */
 hadc.Instance = ADC1;
 hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
 hadc.Init.Resolution = ADC_RESOLUTION_12B;
 hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
 hadc.Init.EOCSelection = ADC_EOC_SINGLE_SEQ_CONV;
 hadc.Init.LowPowerAutoWait = DISABLE;
 hadc.Init.LowPowerAutoPowerOff = DISABLE;
 hadc.Init.ContinuousConvMode = DISABLE;
 hadc.Init.DiscontinuousConvMode = DISABLE;
 hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_TRGO;
 hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
 hadc.Init.DMAContinuousRequests = DISABLE;
 hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
 if (HAL_ADC_Init(&hadc) != HAL_OK)
 {
 Error_Handler();
 }
 /**Configure for the selected ADC regular channel to be converted. 
 */
 sConfig.Channel = ADC_CHANNEL_5;
 sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
 sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
 if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /**Configure for the selected ADC regular channel to be converted. 
 */
 sConfig.Channel = ADC_CHANNEL_6;
 if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /**Configure for the selected ADC regular channel to be converted. 
 */
 sConfig.Channel = ADC_CHANNEL_VBAT;
 if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
 GPIO_InitTypeDef GPIO_InitStruct;
 if(adcHandle->Instance==ADC1)
 {
 /* USER CODE BEGIN ADC1_MspInit 0 */
 /* USER CODE END ADC1_MspInit 0 */
 /* Peripheral clock enable */
 __HAL_RCC_ADC1_CLK_ENABLE();
 
 /**ADC GPIO Configuration 
 PA5 ------> ADC_IN5
 PA6 ------> ADC_IN6 
 */
 GPIO_InitStruct.Pin = AUDIO_ENVELOPE_IN_Pin|AUDIO_RAW_IN_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 /* Peripheral DMA init*/
 
 hdma_adc.Instance = DMA1_Channel1;
 hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
 hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
 hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
 hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
 hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
 hdma_adc.Init.Mode = DMA_NORMAL;
 hdma_adc.Init.Priority = DMA_PRIORITY_MEDIUM;
 if (HAL_DMA_Init(&hdma_adc) != HAL_OK)
 {
 Error_Handler();
 }
 __HAL_DMA1_REMAP(HAL_DMA1_CH1_ADC);
 __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc);
 /* USER CODE BEGIN ADC1_MspInit 1 */
 /* USER CODE END ADC1_MspInit 1 */
 }
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
 if(adcHandle->Instance==ADC1)
 {
 /* USER CODE BEGIN ADC1_MspDeInit 0 */
 /* USER CODE END ADC1_MspDeInit 0 */
 /* Peripheral clock disable */
 __HAL_RCC_ADC1_CLK_DISABLE();
 
 /**ADC GPIO Configuration 
 PA5 ------> ADC_IN5
 PA6 ------> ADC_IN6 
 */
 HAL_GPIO_DeInit(GPIOA, AUDIO_ENVELOPE_IN_Pin|AUDIO_RAW_IN_Pin);
 /* Peripheral DMA DeInit*/
 HAL_DMA_DeInit(adcHandle->DMA_Handle);
 }
 /* USER CODE BEGIN ADC1_MspDeInit 1 */
 /* USER CODE END ADC1_MspDeInit 1 */
} 
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/**
 * @}
 */
/**
 * @}
 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Calling function:

uint16_t dataBuffer[2000] =
{ 0 };
bool helperFlag = false;
int main()
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC_Init();
MX_USART1_UART_Init();
SB_PowerAudioEnable();
HAL_UART_Transmit(&huart1, 'TEST AUDIO - START\n', 19, 50);
MX_DMA_Init();
MX_TIM1_Init();
SB_Test_Audio_RawChannel_4khz();
while (1)
;
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
helperFlag = true;
}
uint8_t SB_Test_Audio_RawChannel_4khz()
{
uint8_t asd = 0;
HAL_ADC_Start_DMA(&hadc, (uint32_t *) dataBuffer, 30);
HAL_TIM_Base_Start(&htim1);
while (helperFlag == false)
{
asd++;
}
HAL_TIM_Base_Stop(&htim1);
HAL_ADC_Stop_DMA(&hadc);
return HAL_OK;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Has anyone dealt with something similar before?

Regards,

Marcel

#dma #adc
1 REPLY 1
BarryWhit
Senior III

This was fixed twice (because it came back once). It seems to have been resolved conclusively with CubeMX V6.6.0.

Note that old ioc file need to be fixed manually - it is not enough to upgrade CubeMX/CubeIDE.

 

Guru Jan made a comprehensive post collecting together the storm of threads opened by folks injured by this

CubeMX: ADC and DMA initialized in the wrong order 

The wiki also details how to manually update the call order:

MX_DMA_Init order in the main.c file generated by STM32CubeMX, How to fix? 

and another helpful post about this is

Stm32cubemx Tips & Tricks: How To Fix MX_DMA_Init Call Rank In Stm32cubemx Generated Projects 

 

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.