Starting ADC with DMA Mode causes chip to freeze

Post here all questions related to STM32 core if you can't find a relevant section!
Post Reply
Eldi4
Posts: 22
Joined: Fri Dec 20, 2019 8:10 am
Answers: 1
Location: Kediri, Indonesia

Starting ADC with DMA Mode causes chip to freeze

Post by Eldi4 »

As explained by the thread title, my stm32f103c8t6 (blue pill) freezes when i call HAL_ADC_Start_DMA() function, i use STM32Core 1.8.0.
here is my whole code :

Code: Select all

#include <hd44780.h>
#include <hd44780ioClass/hd44780_pinIO.h> // Arduino pin i/o class header
#include "stm32f1xx_hal.h"
#include <HardwareTimer.h>

#define CH2_PWM PB7

#define LCD_RS       PB12
#define LCD_EN       PB13
#define LCD_D4       PB14
#define LCD_D5       PB15
#define LCD_D6       PC14
#define LCD_D7       PC15

hd44780_pinIO lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);

  /*Configure GPIO pin : PB10 */
  GPIO_InitStruct.Pin = GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

ADC_HandleTypeDef hadc1;
static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 2;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_6;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_CONVERSIONCLOCKCYCLES_SAMPLETIME_7CYCLES5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
    Error_Handler();
  }
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  sConfig.SamplingTime = ADC_CONVERSIONCLOCKCYCLES_SAMPLETIME_7CYCLES5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
    Error_Handler();
  }
  
  if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK){
    Error_Handler();
  }
}

static void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

}

void ErrorHandler(void){
  while(1){
    HAL_GPIO_TogglePin (GPIOB, GPIO_PIN_10);
    HAL_Delay(100);
  }
}


uint32_t adc[2048];
void setup() {
  HAL_Init();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  HAL_ADC_Start(&hadc1);
  HAL_ADC_Start_DMA(&hadc1, adc, 2048);
  lcd.begin(20,4);
  lcd.clear();
  TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(digitalPinToPinName(CH2_PWM), PinMap_PWM);
  uint32_t channel = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(CH2_PWM), PinMap_PWM));


  // Instantiate HardwareTimer object. Thanks to 'new' instantiation, HardwareTimer is not destructed when setup function is finished.
  HardwareTimer *MyTim = new HardwareTimer(Instance);
  MyTim->setMode(channel, TIMER_OUTPUT_COMPARE_PWM1, CH2_PWM);
  // MyTim->setPrescaleFactor(8); // Due to setOverflow with MICROSEC_FORMAT, prescaler will be computed automatically based on timer input clock
  MyTim->setOverflow(20, MICROSEC_FORMAT); // 100000 microseconds = 100 milliseconds
  MyTim->setCaptureCompare(channel, 30, PERCENT_COMPARE_FORMAT); // 50%
  MyTim->resume();
}

void loop() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("ADC PA6 : ");
  lcd.print(adc[0]);
  
  lcd.setCursor(0,1);
  lcd.print("ADC PB1 : ");
  lcd.print(adc[1]);
  lcd.setCursor(0,2);
  lcd.print(adc[2]);
  lcd.print(", ");
  lcd.print(adc[3]);
  lcd.print(", ");
  lcd.print(adc[4]);
  lcd.print(", ");
  lcd.print(adc[5]);
  lcd.print(", ");
  
  HAL_Delay(200);
}
I also had USB problem with my blue pill, cant recognized by any pc even after changing usb pull up resistor, but i guess this is risk of using china conterfeit.
did this DMA problem could actually because of counterfeit defect too?
Eldi4
Posts: 22
Joined: Fri Dec 20, 2019 8:10 am
Answers: 1
Location: Kediri, Indonesia

Re: Starting ADC with DMA Mode causes chip to freeze

Post by Eldi4 »

using adc with Interrupt freezes my stm32 too, i guess i do something wrong.

Code: Select all

#include <hd44780.h>
#include <hd44780ioClass/hd44780_pinIO.h> // Arduino pin i/o class header
#include "stm32f1xx_hal.h"
#include <HardwareTimer.h>

#define CH2_PWM PB7

#define LCD_RS       PB12
#define LCD_EN       PB13
#define LCD_D4       PB14
#define LCD_D5       PB15
#define LCD_D6       PC14
#define LCD_D7       PC15

hd44780_pinIO lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);

  /*Configure GPIO pin : PB10 */
  GPIO_InitStruct.Pin = GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

ADC_HandleTypeDef hadc1;
static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_6;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_CONVERSIONCLOCKCYCLES_SAMPLETIME_239CYCLES5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
    Error_Handler();
  }
  /*
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  sConfig.SamplingTime = ADC_CONVERSIONCLOCKCYCLES_SAMPLETIME_239CYCLES5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){
    Error_Handler();
  }
  
  if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK){
    Error_Handler();
  }*/
}

void ErrorHandler(void){
  while(1){
    HAL_GPIO_TogglePin (GPIOB, GPIO_PIN_10);
    HAL_Delay(100);
  }
}

unsigned long thisone,elapsed,lastone;
int idx;
uint32_t adc[2];
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc1)
{
  /* time between interrupts
   *  
   */
  thisone = micros();
  elapsed = thisone - lastone;
  lastone = thisone;  
  
  /* Get the converted value of regular channel */ 
  adc[0] = HAL_ADC_GetValue(hadc1);
}

void setup() {
  HAL_Init();
  MX_GPIO_Init();
  MX_ADC1_Init();
  HAL_NVIC_EnableIRQ(ADC1_IRQn);
  HAL_ADC_Start(&hadc1);
  if(HAL_ADC_Start_IT(&hadc1) != HAL_OK)
  {
    /***** HAL_ADC_Start_IT() always returns HAL_OK ******/
    Error_Handler();
  }  
  lcd.begin(20,4);
  lcd.clear();
  TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(digitalPinToPinName(CH2_PWM), PinMap_PWM);
  uint32_t channel = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(CH2_PWM), PinMap_PWM));


  // Instantiate HardwareTimer object. Thanks to 'new' instantiation, HardwareTimer is not destructed when setup function is finished.
  HardwareTimer *MyTim = new HardwareTimer(Instance);
  MyTim->setMode(channel, TIMER_OUTPUT_COMPARE_PWM1, CH2_PWM);
  // MyTim->setPrescaleFactor(8); // Due to setOverflow with MICROSEC_FORMAT, prescaler will be computed automatically based on timer input clock
  MyTim->setOverflow(20, MICROSEC_FORMAT); // 100000 microseconds = 100 milliseconds
  MyTim->setCaptureCompare(channel, 30, PERCENT_COMPARE_FORMAT); // 50%
  MyTim->resume();
}

void loop() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("ADC PA6 : ");
  lcd.print(adc[0]);
  
  lcd.setCursor(0,1);
  lcd.print("ADC PB1 : ");
  lcd.print(adc[1]);
  lcd.setCursor(0,2);
  lcd.print(elapsed);
  lcd.print("uS");
  lcd.setCursor(0,3);
  lcd.print(millis()/1000);
  HAL_Delay(200);
}
User avatar
fpiSTM
Posts: 1745
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Starting ADC with DMA Mode causes chip to freeze

Post by fpiSTM »

You have to disable HAL ADC module usage by Arduino API because the MSP init is defined and I guess this is the reason why it freeze.

See this example:
viewtopic.php?f=41&t=110
To achieve this I simply disable the HAL ADC usage by the arduino API by defining -DHAL_ADC_MODULE_ONLY in build_opt.h file.
Eldi4
Posts: 22
Joined: Fri Dec 20, 2019 8:10 am
Answers: 1
Location: Kediri, Indonesia

Re: Starting ADC with DMA Mode causes chip to freeze

Post by Eldi4 »

fpiSTM wrote: Sat May 02, 2020 4:59 am You have to disable HAL ADC module usage by Arduino API because the MSP init is defined and I guess this is the reason why it freeze.

See this example:
viewtopic.php?f=41&t=110
To achieve this I simply disable the HAL ADC usage by the arduino API by defining -DHAL_ADC_MODULE_ONLY in build_opt.h file.
creating build_opt.h right beside my .ino file and fill it with "-DHAL_ADC_MODULE_ONLY" doesnt work.
I've managed to get multichannel with polling working before, then about to step it up to DMA but no luck.
stas2z
Posts: 131
Joined: Mon Feb 24, 2020 8:17 pm
Answers: 8

Re: Starting ADC with DMA Mode causes chip to freeze

Post by stas2z »

i can't see important parts in your code
at least i can't find init of analog pins, dma init and linking dma with adc
Eldi4
Posts: 22
Joined: Fri Dec 20, 2019 8:10 am
Answers: 1
Location: Kediri, Indonesia

Re: Starting ADC with DMA Mode causes chip to freeze

Post by Eldi4 »

stas2z wrote: Sat May 02, 2020 8:19 am i can't see important parts in your code
at least i can't find init of analog pins, dma init and linking dma with adc
Im sorry this is my first time dealing with DMA, but i see a lot of cubeide tutorial and examples just using those functions to set up DMA and ADC.
or even stm32duino examples, but in F4 series like this https://github.com/palmerr23/Black-F407 ... on_DMA.ino
stas2z
Posts: 131
Joined: Mon Feb 24, 2020 8:17 pm
Answers: 8

Re: Starting ADC with DMA Mode causes chip to freeze

Post by stas2z »

that ino you posted have separate .c/.h files with init code

check it
https://github.com/palmerr23/Black-F407 ... c#L81-L108
that's the main part you missing imho
Eldi4
Posts: 22
Joined: Fri Dec 20, 2019 8:10 am
Answers: 1
Location: Kediri, Indonesia

Re: Starting ADC with DMA Mode causes chip to freeze

Post by Eldi4 »

Ahhh, just realized it!, thanks for pointing it out!,
Will try it and see if it's going to work.
Eldi4
Posts: 22
Joined: Fri Dec 20, 2019 8:10 am
Answers: 1
Location: Kediri, Indonesia

Re: Starting ADC with DMA Mode causes chip to freeze

Post by Eldi4 »

It's working!, thanks a lot for the helps!
Post Reply

Return to “General discussion”