AnalogComparator Interrupts

Post here all questions related to STM32 core if you can't find a relevant section!
Post Reply
venousekb
Posts: 4
Joined: Thu Sep 01, 2022 6:50 am

AnalogComparator Interrupts

Post by venousekb »

Hi All,

I'm trying to utilize built-in comparator to resume from deepslep, but I'm currently failing on make comparator working. I Assume, that I'm doing something wrong, but I can't identify what.

Board is Generic STM32L051C8
Core is STM Core 2.6 ( but same issue was also in 2.5 )
Ide : Arduino IDE 1.18.16 or 2.1.1

I enabled HAL Comparator module by hal_conf_extra.h , but I can't assign interrupt handler.

Compilation is failing on lines with

Code: Select all

 if(HAL_COMP_RegisterCallback(&hcomp1, HAL_COMP_TRIGGER_CB_ID, HAL_COMP_TriggerCallback)!=HAL_OK)
In general, I found USE_HAL_COMP_REGISTER_CALLBACKS in STMicroelectronics\hardware\stm32\2.6.0\system\Drivers\STM32L0xx_HAL_Driver\Inc\stm32l0xx_hal_comp.h

I have made this sketch working only with modification of HAL Driver header file with removal of #if definitions, which is not ideal approach ( e.g. core upgrade will replace it) and this type of sketch was working on Nucleo L432

Any idea, where I'm doing something wrong ?

Vaclav
Test sketch is ( lot of serial debug messages :-) )

Code: Select all

#include "stm32l0xx_hal_comp.h"


COMP_HandleTypeDef  hcomp1;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  hcomp1.Instance = COMP1;
  hcomp1.Init.NonInvertingInput=COMP_INPUT_PLUS_IO3;   // plus to PA1 (nucleo A1)
  hcomp1.Init.InvertingInput=COMP_INPUT_MINUS_IO1;     // minus to PA0  (nucleo A0 )
//   hcomp1.Init.Output          = COMP_OUTPUT_NONE;
  hcomp1.Init.Mode=COMP_POWERMODE_MEDIUMSPEED;
  // hcomp1.Init.Hysteresis=COMP_HYSTERESIS_NONE;

   hcomp1.Init.OutputPol=COMP_OUTPUTPOL_NONINVERTED;          /*!< Set comparator output polarity.
                                    This parameter can be a value of @ref COMP_OutputPolarity */

   // hcomp1.Init.BlankingSrce=COMP_BLANKINGSRC_NONE;       /*!< Set comparator blanking source.
//                                    This parameter can be a value of @ref COMP_BlankingSrce */

  hcomp1.Init.TriggerMode=COMP_TRIGGERMODE_IT_RISING_FALLING;;        /*!< Set the comparator output triggering External Interrupt Line (EXTI) */
      // COMP_TRIGGERMODE_EVENT_RISING_FALLING
 //   hcomp1.Init.TriggerMode=COMP_TRIGGERMODE_EVENT_RISING_FALLING;;        /*!< Set the comparator output triggering External Interrupt Line (EXTI) */                                
  
  // HAL_COMP_MspInit(&hcomp1);
  HAL_NVIC_SetPriority(ADC1_COMP_IRQn, 0, 3);
   HAL_NVIC_EnableIRQ(ADC1_COMP_IRQn);
  
  if(HAL_COMP_Init(&hcomp1) != HAL_OK)
  {
    /* Initialization Error */
     Serial.println("COMP INIT Failed");
  }
  if(HAL_COMP_RegisterCallback(&hcomp1, HAL_COMP_TRIGGER_CB_ID, HAL_COMP_TriggerCallback)!=HAL_OK)
  {
     Serial.println("Callback Start failed");
  }
   /*##-2- Start teh COMP1 and enable the interrupt ###########################*/  
  if(HAL_COMP_Start_IT(&hcomp1) != HAL_OK)
  {
    /* Initialization Error */
     Serial.println("COMP Start failed");
  }


  
  
 
  Serial.println("Full Init OK");
  HAL_COMP_IRQHandler(&hcomp1);
    Serial.println("Full Init OK2");

}


extern "C" void COMP_IRQHandler(void) {
  HAL_COMP_IRQHandler(&hcomp1);
   /* if(HAL_COMP_GetOutputLevel(&hcomp1)==1)
    {
      digitalWrite(LED_BUILTIN,HIGH);
    }
    else
      digitalWrite(LED_BUILTIN,LOW);
  */
  }

extern "C" void HAL_COMP_TriggerCallback(COMP_HandleTypeDef *hcomp)
{
   
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
   //  Serial.println("T"); 
    if(HAL_COMP_GetOutputLevel(&hcomp1)==1)
    {
      digitalWrite(LED_BUILTIN,HIGH);
    }
    else
      digitalWrite(LED_BUILTIN,LOW);
      
}

void loop() {
  // put your main code here, to run repeatedly:

}
build_opt.h

Code: Select all

-DUSE_HAL_COMP_REGISTER_CALLBACKS=1
hal_conf_extra.h

Code: Select all

#define HAL_COMP_MODULE_ENABLED
#define USE_HAL_COMP_REGISTER_CALLBACKS 1
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: AnalogComparator Interrupts

Post by fpiSTM »

Hi @venousekb

Issue comes from the fact the USE_HAL_COMP_REGISTER_CALLBACKS cannot be redefined.
It should be protected here to allow redefinition:
https://github.com/stm32duino/Arduino_C ... 16-L182C16

simply do this:

Code: Select all

#ifndef USE_HAL_COMP_REGISTER_CALLBACKS
#define USE_HAL_COMP_REGISTER_CALLBACKS       0U
#endif
I will make a PR to allow REGISTER callback redefinition.
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: AnalogComparator Interrupts

Post by fpiSTM »

venousekb
Posts: 4
Joined: Thu Sep 01, 2022 6:50 am

Re: AnalogComparator Interrupts

Post by venousekb »

Hi @fpiSTM ,

Thanks, first, sorry for late response, I was focused on my daily business.

I updated my core and uploaded updated stm32l0xx_hal_conf_default.h from github, and compilation issue was resolved.

But my code still doesn't works, based on serial dump I'm getting issue with call back registration, method doesn't return HAL_OK :-(

And then code is freezing on HAL_COMP_Start_IT

My current code follows ...

Any idea, what I'm doing wrong ?

Regards, V.

Code: Select all

#include "stm32l0xx_hal_comp.h"

#define LED_PIN PB4


// put function declarations here:
COMP_HandleTypeDef  hcomp1;
volatile uint32_t pulseCounter=0;


void setup() {
  // put your setup code here, to run once:
  pinMode(LED_PIN,OUTPUT);
  digitalWrite(LED_PIN,LOW);
  delay(5000);
  digitalWrite(LED_PIN,HIGH);
  Serial.begin(115200);
  Serial.println("Service starting");
  Serial.flush();
  hcomp1.Instance = COMP1;
  hcomp1.Init.WindowMode=COMP_WINDOWMODE_DISABLE; 
  // hcomp1.Init.NonInvertingInput=COMP_INPUT_PLUS_IO1;   // plus to PA1 (nucleo A1)
  // hcomp1.Init.InvertingInput=COMP_INPUT_MINUS_IO1;     // minus to PA0  (nucleo A0 )
  hcomp1.Init.NonInvertingInput=COMP_INPUT_MINUS_1_2VREFINT;
  hcomp1.Init.OutputPol          = COMP_OUTPUTPOL_NONINVERTED;
  hcomp1.Init.Mode=COMP_POWERMODE_MEDIUMSPEED;
  // hcomp1.Init.Hysteresis=COMP_HYSTERESIS_MEDIUM;


  hcomp1.Init.TriggerMode=COMP_TRIGGERMODE_IT_RISING;;        /*!< Set the comparator output triggering External Interrupt Line (EXTI) */
 //    hcomp1.Init.TriggerMode=COMP_TRIGGERMODE_EVENT_RISING;
  Serial.println("NVIC1");
  Serial.flush();

  HAL_NVIC_SetPriority(ADC1_COMP_IRQn, 1, 3);
  Serial.println("NVIC2");
  Serial.flush();

   HAL_NVIC_EnableIRQ(ADC1_COMP_IRQn);
     Serial.println("NVIC3");
  Serial.flush();
  int retVal=HAL_COMP_RegisterCallback(&hcomp1, HAL_COMP_TRIGGER_CB_ID, vHAL_COMP_TriggerCallback);
  Serial.println(retVal);
  if(HAL_COMP_RegisterCallback(&hcomp1, HAL_COMP_TRIGGER_CB_ID, vHAL_COMP_TriggerCallback)!=HAL_OK)
  {
     Serial.println("Callback register failed");
     Serial.flush();
  }
  else
  {
    Serial.println("Callback  OK");
     Serial.flush();
  }
  if(HAL_COMP_Init(&hcomp1) != HAL_OK)
  {
    /* Initialization Error */
     Serial.println("COMP INIT Failed");
     Serial.flush();
  }
  else
  {
    Serial.println("COMP INIT OK");
     Serial.flush();
  }


   /*##-2- Start teh COMP1 and enable the interrupt ###########################*/  
  if(HAL_COMP_Start_IT(&hcomp1) != HAL_OK)
  {
    /* Initialization Error */
     Serial.println("COMP Start failed");
     Serial.flush();
  }
    else
  {
    Serial.println("Comp Start OK");
     Serial.flush();
  }
  

    Serial.println("Setup Done");

}

// ADC1_COMP_IRQHandler
// extern "C" void ADC1_COMP_IRQHandler(void) {
extern "C" void COMP_IRQHandler(void) {
 
   HAL_COMP_IRQHandler(&hcomp1);

   }

extern "C" void vHAL_COMP_TriggerCallback(COMP_HandleTypeDef *hcomp)
{
   
       pulseCounter++;
      
}




void loop() {
  // put your main code here, to run repeatedly:
  delay(500);
  Serial.print("Pulse count ");
  Serial.println(pulseCounter);
}
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: AnalogComparator Interrupts

Post by fpiSTM »

Your best bet is to debug to see why and where it fails to init.
venousekb
Posts: 4
Joined: Thu Sep 01, 2022 6:50 am

Re: AnalogComparator Interrupts

Post by venousekb »

Hi @fpiSTM ,

your suggestion was too complex, main part of my issue was solved by reading source code of some methods and again MCU Specs.

Just for curiosity, my issues from previously posted code :

1) Callback registration HAL_COMP_RegisterCallback needs to be called after HAL_COMP_Init. Explicitly explained in stm32l0xx_hal_comp.c
2) Improper configuration of Comp inputs, comp1 supports only PA1 as Plus input, PA0 as minus input (of full vref) . Explained in same file as issue 1

But freezing of HAL_COMP_Start was issue related to proper naming of methods, which I don't know, where to properly find. During migration of my code from Nucleo 432KC I needed to change interrupt vector from COMP_IRQn to ADC1_COMP_IRQn and same rename was needed to rename external C function from

Code: Select all

extern "C" void COMP_IRQHandler(void)
to

Code: Select all

extern "C" void ADC1_COMP_IRQHandler(void)
After renaming, my code started to work.

Final demo code ( I have left lot of Serial dumps )

Thank for support.

Code: Select all

#include "stm32l0xx_hal_comp.h"

#define LED_PIN PB4


// put function declarations here:
COMP_HandleTypeDef  hcomp1;
volatile uint32_t pulseCounter=0;


void setup() {
  // put your setup code here, to run once:
  pinMode(LED_PIN,OUTPUT);
  digitalWrite(LED_PIN,LOW);
  delay(5000);
  digitalWrite(LED_PIN,HIGH);
  Serial.begin(115200);
  Serial.println("Service starting");
  Serial.flush();
  
  hcomp1.Instance = COMP1;
  hcomp1.Init.WindowMode=COMP_WINDOWMODE_DISABLE; 
  hcomp1.Init.NonInvertingInput=COMP_INPUT_PLUS_IO1;   // plus to PA1 (nucleo A1)
  hcomp1.Init.InvertingInput=COMP_INPUT_MINUS_IO1;     // minus to PA0  (nucleo A0 )
  hcomp1.Init.OutputPol          = COMP_OUTPUTPOL_NONINVERTED;
  hcomp1.Init.LPTIMConnection  = COMP_LPTIMCONNECTION_DISABLED;
  hcomp1.Init.Mode=COMP_POWERMODE_MEDIUMSPEED;
  // hcomp1.Init.Hysteresis=COMP_HYSTERESIS_MEDIUM;


   hcomp1.Init.TriggerMode=COMP_TRIGGERMODE_IT_RISING;;        /*!< Set the comparator output triggering External Interrupt Line (EXTI) */
   // hcomp1.Init.TriggerMode=COMP_TRIGGERMODE_EVENT_RISING;
  Serial.println("NVIC1");
  Serial.flush();
  HAL_NVIC_SetPriority(ADC1_COMP_IRQn, 0, 3);
  Serial.println("NVIC2");
  Serial.flush();

   HAL_NVIC_EnableIRQ(ADC1_COMP_IRQn);
     Serial.println("NVIC3");
  Serial.flush();
  // int retVal=HAL_COMP_RegisterCallback(&hcomp1, HAL_COMP_TRIGGER_CB_ID, vHAL_COMP_TriggerCallback);
  if(HAL_COMP_Init(&hcomp1) != HAL_OK)
  {
    /* Initialization Error */
     Serial.println("COMP INIT Failed");
     Serial.flush();
  }
  else
  {
    Serial.println("COMP INIT OK");
     Serial.flush();
  }
   /*##-2- Start teh COMP1 and enable the interrupt ###########################*/  
  if(HAL_COMP_RegisterCallback(&hcomp1, HAL_COMP_TRIGGER_CB_ID, HAL_COMP_TriggerCallback)!=HAL_OK)
  {
     Serial.println("Callback register failed");
     Serial.flush();
  }
  else
  {
    Serial.println("Callback  OK");
     Serial.flush();
  }
 
  
  // if(HAL_COMP_Start_IT(&hcomp1) != HAL_OK)
  if(HAL_COMP_Start(&hcomp1) != HAL_OK)
  {
    /* Initialization Error */
     Serial.println("COMP Start failed");
     Serial.flush();
  }
    else
  {
    Serial.println("Comp Start OK");
     Serial.flush();
  }
  
    Serial.println("Setup Done");

}

// ADC1_COMP_IRQHandler
extern "C" void ADC1_COMP_IRQHandler(void) {
// extern "C" void COMP_IRQHandler(void) {
 
   HAL_COMP_IRQHandler(&hcomp1);

   }

extern "C" void HAL_COMP_TriggerCallback(COMP_HandleTypeDef *hcomp)
{
   
       pulseCounter++;
      
}




void loop() {
  // put your main code here, to run repeatedly:
  delay(500);
  Serial.print("Pulse count ");
  Serial.println(pulseCounter);
 }
 
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: AnalogComparator Interrupts

Post by fpiSTM »

Great!
Post Reply

Return to “General discussion”