1

I have an STM32F411VET and I want to have interrupt triggered after ADC conversion is finished. Documentation says following:

In Single conversion mode the ADC does one conversion. This mode is started with the CONT bit at 0 by either:

  • setting the SWSTART bit in the ADC_CR2 register (for a regular channel only) Once the conversion of the selected channel is complete:

If a regular channel was converted:

  • The converted data are stored into the 16-bit ADC_DR register
  • The EOC (end of conversion) flag is set
  • An interrupt is generated if the EOCIE bit is set

Then the ADC stops.

Thus, I have following code:

Enabling interrupts

SET_BIT(ADC1->CR1, ADC_CR1_EOCIE);      // enable interrupt generation
NVIC_EnableIRQ(ADC_IRQn);       // allow interrupt in NVIC
__enable_irq();     // change cpu flags to enable interrupts

Configuring ADC

void ConfigureADC()
{
    // PA1 - ADC_IN1
    SET_BIT(GPIOA->MODER, GPIO_MODER_MODE1_0 | GPIO_MODER_MODE1_1); 
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC1EN);      // enable ADC1 clock
    SET_BIT(ADC1->CR2, ADC_CR2_ADON);       // enable ADC1
    SET_BIT(ADC1->CR1, ADC_CR1_RES_1);      // 8-bit conversion
    SET_BIT(ADC->CCR, ADC_CCR_ADCPRE_0);    // prescaler - /4
    SET_BIT(ADC1->SQR3, 1);     // channel 1 (PA1)
    SET_BIT(ADC1->CR2, ADC_CR2_CONT);       // Continious mode
}

Interrupt handler

void ADC_IRQHandler()
{
    vConverted = true;
    CLEAR_BIT(ADC1->SR, ADC_SR_EOC);        // Software clears EOC flag
}

While in debug mode or reading directly from ADC1->DR register I get a fine result.

Thing that make me worry is that I cannot debug interrupt handler in uVision5 (IDE I'm using).

The problem is that interrupt handler is not being executed and I don't know how to debug it properly.


Thank everyone for help.

hrust
  • 734
  • 1
  • 11
  • 34
  • You should be able to debug the interrupt handler in uVision 5 without problem if it is occuring so I would be very concerned about that. – Realtime Rik Apr 28 '17 at 09:51
  • @RealtimeRik I can't put a breakpoint on any line of the interrupt handler – hrust Apr 28 '17 at 11:02
  • You should be able to. Are you sure the handler you are trying to put the breakpoint in is actually included in the final build?. Normally when you can't do this the function is not actually in the the build. Try looking in the map file, you might find you only have the default handler. – Realtime Rik Apr 28 '17 at 11:05
  • @RealtimeRik All three block of code presented in the question are part on `main.c` file, which is the only one file I've created. Thus, handler is right next to `main` function. – hrust Apr 28 '17 at 11:07
  • Just a thought, but try declaring the function void ADC_IRQHandler( void ). – Realtime Rik Apr 28 '17 at 11:10
  • @RealtimeRik I was trying to move function itself before and after the main function (currently it's at the very end of the file) and also have a function prototype at the very beginning, right after includes. I've also tried making declaration `extern` because I was down to everything I could think of. May there be other interrupt handlers (how can I check that within debug mode) or chip having a fault (kernel exception) of some kind? – hrust Apr 28 '17 at 11:15
  • If you can't set a breakpoint it is likely for some reason that it is not breaking the weak binding of the default handler in the vector table and therefore not being included in the build. Possibly the void parameter is important for this. – Realtime Rik Apr 28 '17 at 11:21
  • @RealtimeRik Problem was trivial, C++ compiler was used, but not C. Thus, binding was not rewritten. Should I delete question this now? – hrust Apr 28 '17 at 17:03
  • Maybe you should post an answer instead of deleting the question. – linuxfan says Reinstate Monica Apr 28 '17 at 17:06
  • You should be able to mark you own answer as answered in a day or two. – Realtime Rik Apr 28 '17 at 18:31

2 Answers2

3

I should note that C++ is used and, because of that, compiled function names do not match with ones in code, thus they are not binded/replaced. The IRQ handler was not referenced and hence not included in the compiled code.

To make functions 'C' linked extern "C" should be used.

extern "C"
{
    void ADC_IRQHandler();
    // Other handlers
}

To get more information on extern "C" refer to that answer.

Community
  • 1
  • 1
hrust
  • 734
  • 1
  • 11
  • 34
  • Yes, interrupt handlers need to be written in C, or at least the vector does. It is kind of what I getting at with declaring the void xxx () not having a void parameter. I should of noticed this was actually c++ – Realtime Rik Apr 28 '17 at 18:31
  • 1
    You should mention it in your initial question. Otherwise it is only waste of our time. – 0___________ Apr 29 '17 at 08:43
  • In my case, once the IRQ got triggered, the controller was hanging because I was using a uint32 type var as a counter inside the interrupt and it was NOT marked "volatile." – Umar Hassan Feb 11 '23 at 17:38
1

Just check if you call SET_BIT(ADC1->CR1, ADC_CR1_EOCIE); after the ADC_Configure

0___________
  • 60,014
  • 4
  • 34
  • 74
  • I'm setting interrupt flag and enable interrupts at the very last moment after all configurations are done. – hrust Apr 28 '17 at 09:38
  • 1. See what is the name of the vector handler in the vector table (some startup files do not define all vector routine names). The interrupt handler can be different depending on the toolchain you use – 0___________ Apr 28 '17 at 11:48