Skip to main content
Graduate II
February 4, 2025
Solved

While(1) Not Executing

  • February 4, 2025
  • 4 replies
  • 1825 views

I am using STM32 with the following peripherals:

  • TIM7 for frequency generation
  • ADC with DMA
  • DAC with DMA
  • TIM Interrupt (TIM_IT)

My setup:

  • Clock: 150 MHz
  • Prescaler (PSC:( 3-1
  • Auto-reload register (ARR:( 13-1
  • 128 samples for DAC to generate a 30 kHz signal

When using these settings, the ADC half-complete and complete callbacks are triggered correctly, meaning ADC DMA is working. However, nothing seems to happen in the while(1) loop in main().

What do you think could be causing this?

Could it be related to TIM7 interrupt priority, DMA behavior, or CPU being blocked?
Is the DMA transfer taking over completely, preventing execution in while(1)?
Any insights or suggestions would be greatly appreciated!

    This topic has been closed for replies.
    Best answer by mƎALLEm

    @BitCurious wrote:

    do you mean in stm32g4xx_it.c ?


    Yes. To convince you that even you comment the callbacks the interrupt still fired and the IRQ handler is executed.

    But I recommend to disable the ADC NVIC config and check if you reach the while loop.

     

    4 replies

    Technical Moderator
    February 4, 2025

    Hello,

    May be due to the CPU load due to the interrupt timing rate and the CPU was not able to get a time slot to reach the while loop. As soon as it exits the interrupt it returns in it again. If you disable the interrupt do you reach the while(1)?

    Graduate II
    February 5, 2025

    It seems the issue is related to the timer settings. Even after commenting out the ADC half and complete callbacks, the program still doesn’t reach while(1). However, when I increase ARR or PSC, the issue is resolved.

    Initially, with PSC: 3-1 & ARR: 13-1, the timer frequency was 3.85 MHz, and while(1) was unresponsive. Now, with PSC: 13-1 & ARR: 5-1, the frequency is 2.31 MHz, and the program runs normally.

    Is there a specific limit or best practice when configuring timers? My goal is to generate a 30 kHz signal using DAC with 128 samples, with a 150 MHz clock and PSC: 13-1, ARR: 3-1. Should I reduce the number of points or adjust the frequency further?

    Technical Moderator
    February 5, 2025

    @BitCurious wrote:

    It seems the issue is related to the timer settings. Even after commenting out the ADC half and complete callbacks


    Commenting the callbacks doesn't mean the interrupt handler is not executed. Bear in mind that the callback is called from the interrupt handler and it's declared as __weak.

    Put breakpoint in the ADC interrupt handler then you can confirm or disable the ADC NVIC interrupt.

    Super User
    February 4, 2025

    30 kHz *  half-complete and complete callbacks = 60k interrupts/s ?

    That's alot, especially when using HAL. Try lowering the freq. generously by increasing PSC until "something happens" in the main loop. You may use the DWT cycle counter to estimate the length your code spends in the interrupts or use some logic analyzer for that.

     Solved: How do you measure the execution CPU cycles for a ... - STMicroelectronics Community

    hth

    KnarfB

    Graduate
    February 5, 2025

    You could toggle different IO pins in each of the interrupt handlers. Set the IO at the start of the interrupt handler and reset it at the end of the handler - that way you can check how often the handler is called and how efficient/inefficient the code is. The BSRR is the easiest and most efficient and safest way to toggle the bits - eg.

    #define RED_LED_ON GPIOB->BSRR = GPIO_BSRR_BS_14
    #define RED_LED_OFF GPIOB->BSRR = GPIO_BSRR_BR_14

    Explorer
    February 5, 2025

    > However, nothing seems to happen in the while(1) loop in main().

    What exactly you mean, i.e. what is supposed to happen there ?
    You would need to share this specific code.
    Many (example) applications just have a "while (1) {} " at the end of main, and all the work happens in the interrupt chain.

    > Is the DMA transfer taking over completely, preventing execution in while(1)?

    No, DMA cannot do that.
    Once started it operates independant of the core, and can at most co-opt some bus cycles.

    > Could it be related to TIM7 interrupt priority, ...

    Again, I suggest to share the related interrupt code.
    Careless interrupt callbacks can consume 100+% of core cycles.

    Graduate II
    February 5, 2025
     

    You can reply as follows:


    In while(1), I need to process ADC values (a sampled sine wave) to compute amplitude and phase shift with respect to the DAC output or input signal. This involves mathematical computations like averaging, square root calculations, etc.

    The DMA is handling ADC sampling, and the ADC complete callback stores the processed values. However, when PSC: 3-1 & ARR: 13-1, the program doesn't reach while(1). If I increase ARR/PSC, it starts working.

    and the callbacks I have is given below:

     

    void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
    {
    	Real_Sum = 0;
    	Imag_Sum = 0;
    	for(i = 0; i< HALF_NUM_OF_SAMPLES;i++)
    	{
    		Real_Sum += (int32_t)adc_buffer[i] * Reference_Sinus[i];
    		Imag_Sum += (int32_t)adc_buffer[i] * Reference_Cosinus[i];
    	}
     counter_half++;
    }
    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
    {
     for(i = HALF_NUM_OF_SAMPLES ; i< NUM_OF_SAMPLES;i++)
    	{
     Real_Sum += (int32_t)adc_buffer[i] * Reference_Sinus[i];
     Imag_Sum += (int32_t)adc_buffer[i] * Reference_Cosinus[i];
    	}
     Out_Real = Real_Sum;
     Out_Imag = Imag_Sum;
     counter_full++;
    }

     

    Explorer
    February 5, 2025

    > The DMA is handling ADC sampling, and the ADC complete callback stores the processed values. 

    I don't understand what you are doing here.
    If you have more than one ADC channel, you would want to use DMA to move a complete sequence, and get a DMA_TC interrupt when finished.
    In this case, you don't need or want an ADC interrupt, as you want to work on a consistent ADC data set.

    And for a single-channel ADC conversion, using DMA is overkill.

    > Real_Sum += (int32_t)adc_buffer[i] * Reference_Sinus[i];

    I suppose the "Reference_Sinus" and "Reference_Cosinus" arrays are scaled sin/cos value tables.
    This code should take very few instruction and processing time, and not be a problem.

    As a side note, you would only need one table for sin/cos, as sin(x) = cos(x + PI/2).