2
\$\begingroup\$

I am working with a nucleo-F401RE - I am experimenting with the DMA and ADC. When I try to debug my code it is immediately going into Infinite_Loop

enter image description here

here is my code:

main.c

#include <stdio.h>
#include "stm32f4xx_hal.h"
#include "uart.h"
#include "adc.h"

ADC_HandleTypeDef hadc1;
uint32_t sensor_value[1];

int main()
{
    HAL_Init();
    uart_init();
    adc_pa0_DMA_init();

    // Start ADC
    HAL_ADC_Start_DMA(&hadc1,(uint32_t *)sensor_value,1);


    while(1)
    {
        printf("The sensor value : %d \n\r", (int)sensor_value);
    }
}

void SysTick_Handler(void)
{
    HAL_IncTick();
}

uart.c

#include "stm32f4xx_hal.h"


UART_HandleTypeDef huart2;


int __io_putchar(int ch)
{
    HAL_UART_Transmit(&huart2,(uint8_t*)&ch,1,10);
    return ch;
}



void uart_init(void)
{

     GPIO_InitTypeDef GPIO_InitStruct = {0};

    //Enable UART pins clock access
    __HAL_RCC_GPIOA_CLK_ENABLE();

    //Enable UART module clock access
    __HAL_RCC_USART2_CLK_ENABLE();


    //Configure pins to act as alternate func pins(UART)

     GPIO_InitStruct.Pin  = GPIO_PIN_2|GPIO_PIN_3;
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
     GPIO_InitStruct.Pull =  GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

     HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);

     //Configure UART module
     huart2.Instance = USART2;
     huart2.Init.BaudRate = 115200;
     huart2.Init.WordLength = UART_WORDLENGTH_8B;
     huart2.Init.StopBits = UART_STOPBITS_1;
     huart2.Init.Parity = UART_PARITY_NONE;
     huart2.Init.Mode = UART_MODE_TX;
     huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
     huart2.Init.OverSampling = UART_OVERSAMPLING_16;

     HAL_UART_Init(&huart2);


}

and adc.c

#include "stm32f4xx_hal.h"

extern ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

void adc_pa0_DMA_init(void)
{
    // Configure pa0 as analog pin

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    ADC_ChannelConfTypeDef sConfig = {0};

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


    // Configure adc module for continuous conversion

    __HAL_RCC_ADC1_CLK_ENABLE();

    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    hadc1.Init.ContinuousConvMode = ENABLE;
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.NbrOfConversion = 1;
    hadc1.Init.DMAContinuousRequests = ENABLE;
    hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

    HAL_ADC_Init(&hadc1);

    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);

    // enable clock for the DMA2
    __HAL_RCC_DMA2_CLK_ENABLE();

    // enable DMA interrupt
    HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);


    hdma_adc1.Instance  = DMA2_Stream0;
    hdma_adc1.Init.Channel = DMA_CHANNEL_0;
    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_adc1.Init.Mode = DMA_CIRCULAR;
    hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
    hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

    HAL_DMA_Init(&hdma_adc1);

    // link ADC to DMA
    //__HAL_LINKDMA(hadc1, DMA_Handle, hdma_adc1);
    hadc1.DMA_Handle = &hdma_adc1;
}

void DMA2_Stream0_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma_adc1);
}

void ADC_IRQHandler(void) // interrupt handler for ADC
{
    HAL_ADC_IRQHandler(&hadc1);
}

When the exception is raised and I continue to execute the code, I can see my ADC value (sensor value) being changed in the inspector but the value is NOT broadcasted to the UART channel.

When I analyze the call stack I see the code entering in the infinite loop while executing the printf

enter image description here

\$\endgroup\$
4
  • \$\begingroup\$ Print some debugging messages in the middle of adc_pa0_DMA_init() and see where exactly it falls into infinite loop. Or put some breakpoints in it. Find where exactly it goes into infinite loop. \$\endgroup\$
    – Ilya
    Commented Dec 2, 2021 at 9:34
  • \$\begingroup\$ I did try but it doesn't help, in fact the issue is happening before the call of adc_pa0_DMA_init() \$\endgroup\$
    – Michael
    Commented Dec 2, 2021 at 12:04
  • \$\begingroup\$ So find where exactly it happens. Put delays between your initializations too. Just in case. Find the exact line where it fails. \$\endgroup\$
    – Ilya
    Commented Dec 2, 2021 at 12:05
  • \$\begingroup\$ Look at your call stack which you've just posted. It's telling you that your code has caused a "Usage Fault". \$\endgroup\$
    – brhans
    Commented Dec 2, 2021 at 17:09

1 Answer 1

3
\$\begingroup\$

It's written right in the comment what is the problem:

This code gets called when the processor receives an unexpected interrupt.

enter image description here

What happens, is that an interrupt is called that isn't defined in your code. Probably you are using the wrong interrupt handler for the DMA or ADC, using the wrong name, or are missing an interrupt handler.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks I saw that message and I was thinking it is the problem but how should I incorrect or missing handler ? \$\endgroup\$
    – Michael
    Commented Dec 2, 2021 at 10:41
  • 1
    \$\begingroup\$ @Michael when your code gets stuck in the loop, pause it in your debugger and look at the micro's IPRS register. the lower 9 bits tell you exactly which interrupt it's trying to execute. The lower 16 values indicate interrupt sources internal to the code, like HardFault, SysTick, etc, and anything over that is a peripheral. \$\endgroup\$
    – brhans
    Commented Dec 2, 2021 at 13:47
  • \$\begingroup\$ @brhans thanks for this info - where should I find this register ?it seems that in my case the program stop at the printf statement (looking at the call stack) - I added a screenshot of the stack trace in the question \$\endgroup\$
    – Michael
    Commented Dec 2, 2021 at 15:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.