Arduino Due ADC compare mode

I am working with Due ADC in compare mode to get an interrupt when signal is above certain threshold. I got some examples from the Forum and tried to understand the Atmel data sheet and have a working example program, that reacts to signal above the threshold in an expected way, i.e. I get, say 100 interrupts in a time necessary for 100 conversions. The ADC A0 is connected to 3.3 V.
But this happens only when the filtering option is off. When I set ADC_EMR_CMPFILTER to a value between 1 and 3 there is apparently no interrupts at all.

Does someone know what the cause is?
What is the correct way to set CMPFILTER field to more than zero and have an interrupt?

Below is the code (credits go to ard_newbie and to Atmel):

#include <Arduino.h>
#include "c:\Users\Andrzej\.platformio\packages\framework-arduino-sam\system\libsam\include\adc.h"

bool flag, flagCOMP, flagDRDY, flagEOC;
uint32_t cntHand, cntCOMP, cntDRDY, cntEOC, uTime, count, shift;
uint32_t regOVER, regISR, adcDatum;

void adc_check(Adc *p_adc, const uint32_t ul_mck);
void adc_interrupt_check(Adc *p_adc);
void adc_interrupt_event(uint32_t intSR);
void adc_overrun_event(uint32_t ovrSR);
void adc_setup();
String regToHex(uint32_t reg);

void setup() {
  delay(500);
  shift = 10;
  count = 10000 + shift;
  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_LED2, OUTPUT);
  pinMode(PIN_LED3, OUTPUT);
  digitalWrite(PIN_LED, LOW);
  digitalWrite(PIN_LED2, HIGH);
  digitalWrite(PIN_LED3, HIGH);
  Serial.begin(115200);
  while (!Serial) ;
  Serial.println("  new run: ");
  delay(100);
  
  adc_setup();
  adc_check(ADC, 84000000);
  delay(100);
  ADC->ADC_MR |= ADC_MR_FREERUN_ON;
  uTime = micros();
}

void loop() {
  if (flag) {
    flag = false;
    cntHand++;
  }
  // if (flagCOMP) {
  //   flagCOMP = false;
  //   // digitalWrite(PIN_LED, digitalRead(PIN_LED) == HIGH ? LOW : HIGH);
  //   cntCOMP++;
  // }
  // if (flagDRDY) {
  //   flagDRDY = false;
  //   // digitalWrite(PIN_LED2, digitalRead(PIN_LED2) == HIGH ? LOW : HIGH);
  //   cntDRDY++;
  // }
  // if (flagEOC) {
  //   flagEOC = false;
  //   // digitalWrite(PIN_LED3, digitalRead(PIN_LED3) == HIGH ? LOW : HIGH);
  //   cntEOC++;
  // }
  if (cntHand == shift) {
    uTime = micros();
  }
  if (cntHand == count) {
    // stop freerun and interrupts
    ADC->ADC_MR &= ~ADC_MR_FREERUN;
    adc_disable_interrupt(ADC, 0xFFFFFFFF);
    uTime = micros() - uTime;
    adc_interrupt_event(regISR);
    adc_overrun_event(ADC->ADC_OVER);
    Serial.println("counters: ");
    Serial.println("HANDLER " + String(cntHand));
    // Serial.println("COMPE  " + String(cntCOMP));
    // Serial.println("DRDY   " + String(cntDRDY));
    // Serial.println("EOC7   " + String(cntEOC));
    Serial.println("conversion time, us " + String((float)uTime/(int)(count - shift), 4));
    Serial.println();
    cntHand = 0;
    // cntCOMP = 0;
    // cntDRDY = 0;
    // cntEOC = 0;
    // regISR = adc_get_status(ADC);
    // adc_interrupt_event(regISR);
    // regOVER = ADC->ADC_OVER;
    // adc_overrun_event(regOVER);
  }
}

void adc_setup () {
  PMC->PMC_PCER1 |= PMC_PCER1_PID37;                    // ADC power ON
  ADC->ADC_CR = ADC_CR_SWRST;                           // Reset ADC
  // ADC->ADC_MR = ADC_MR_FREERUN_ON                       // ADC in free running mode
  //                 | ADC_MR_LOWRES_BITS_12               // 12 bits resolution
  //                 // | ADC_MR_PRESCAL(255)                 // one conversion (+ loop) takes ca. 128 us
  //                 | ADC_MR_PRESCAL(2)                  // ADC clock is 14 MHz
  //                 | ADC_MR_SETTLING_AST3
  //                 | ADC_MR_STARTUP_SUT512
  //                 | ADC_MR_TRACKTIM(10)
  //                 | ADC_MR_TRANSFER(2);
  ADC->ADC_MR = ADC_MR_LOWRES_BITS_12               // 12 bits resolution
                  | ADC_MR_PRESCAL(20)                  // ADC clock 
                  | ADC_MR_SETTLING_AST3
                  | ADC_MR_STARTUP_SUT112
                  | ADC_MR_TRACKTIM(10)
                  | ADC_MR_TRANSFER(2);
  ADC->ADC_ACR = ADC_ACR_IBCTL(1);
  ADC->ADC_EMR = ADC_EMR_CMPMODE_HIGH                   // Compare with high threshold
                 | ADC_EMR_CMPSEL(7)                    // Compare channel 7 = A0
                 | ADC_EMR_CMPFILTER(0)                 // Number of consecutive compare events necessary
                                                        // to raise the flag = CMPFILTER+1
                 | ADC_EMR_TAG;
  ADC->ADC_CWR = ADC_CWR_HIGHTHRES(300);                // Compare with a high threshold of conversion

  ADC->ADC_CHER = ADC_CHER_CH7;                         // Enable Channel 7 = A0

  ADC->ADC_IER = ADC_IER_COMPE;                         // Interrupt on Compare match enable
  // ADC->ADC_IER |= ADC_IER_DRDY;                         // Interrupt on Data ready enable
  // ADC->ADC_IER = ADC_IER_DRDY;                         // Interrupt on Data ready enable
  // ADC->ADC_IER |= ADC_IER_EOC7;                         // Interrupt on End of conversion for channel 7 enable
  NVIC_EnableIRQ(ADC_IRQn);                             // Enable ADC interrupt
}

void ADC_Handler(void) {
  // Do some stuff (keep this as short as possible, e.g. set a flag to be processed in loop())
  // it is necessary to to read ISRegister, LCDRegister, and CDRegister(s)
  regISR = adc_get_status(ADC);
  adcDatum = adc_get_channel_value(ADC, ADC_CHANNEL_7);
  uint32_t lastDatum = adc_get_latest_value(ADC);
  
  flag = true;
  // flagCOMP = (regISR & ADC_ISR_COMPE) > 0;
  // flagDRDY = (regISR & ADC_ISR_DRDY) > 0;
  // flagEOC = (regISR & ADC_ISR_EOC7) > 0;
  // regOVER = ADC->ADC_OVER;
}

String regToHex(uint32_t reg) {
  String hexStr = String(reg, HEX);
  while (hexStr.length() < 8) hexStr = "0" + hexStr;
  return(hexStr);
}

static uint32_t calcul_startup(const uint32_t ul_startup) {
	uint32_t ul_startup_value = 0;

	if (ul_startup == 0)
		ul_startup_value = 0;
	else if (ul_startup == 1)
		ul_startup_value = 8;
	else if (ul_startup == 2)
		ul_startup_value = 16;
	else if (ul_startup == 3)
		ul_startup_value = 24;
	else if (ul_startup == 4)
		ul_startup_value = 64;
	else if (ul_startup == 5)
		ul_startup_value = 80;
	else if (ul_startup == 6)
		ul_startup_value = 96;
	else if (ul_startup == 7)
		ul_startup_value = 112;
	else if (ul_startup == 8)
		ul_startup_value = 512;
	else if (ul_startup == 9)
		ul_startup_value = 576;
	else if (ul_startup == 10)
		ul_startup_value = 640;
	else if (ul_startup == 11)
		ul_startup_value = 704;
	else if (ul_startup == 12)
		ul_startup_value = 768;
	else if (ul_startup == 13)
		ul_startup_value = 832;
	else if (ul_startup == 14)
		ul_startup_value = 896;
	else if (ul_startup == 15)
		ul_startup_value = 960;

	return ul_startup_value;
}

void adc_check(Adc *p_adc, const uint32_t ul_mck) {
	uint32_t ul_adcfreq;
	uint32_t ul_prescal;
	uint32_t ul_startup;

  printf("                            %s\r\n", " ");
  printf("Now doing %s...\r\n", "adc_check");
  //     "      "
	/* ADCClock = MCK / ( (PRESCAL+1) * 2 ) */
	ul_prescal = ((p_adc->ADC_MR & ADC_MR_PRESCAL_Msk) >>
			ADC_MR_PRESCAL_Pos);
	ul_adcfreq = ul_mck / ((ul_prescal + 1) * 2);
	printf("ADC clock prescaler = %d\r\n", (int)ul_prescal);
	printf("ADC clock frequency = %0.2f MHz\r\n", (float)ul_adcfreq/1e6);

	if (ul_adcfreq < ADC_FREQ_MIN) {
		printf("adc frequency too low (out of specification: %d Hz)\r\n",
			(int)ADC_FREQ_MIN);
	}
	if (ul_adcfreq > ADC_FREQ_MAX) {
		printf("adc frequency too high (out of specification: %d Hz)\r\n",
			(int)ADC_FREQ_MAX);
	}

	ul_startup = ((p_adc->ADC_MR & ADC_MR_STARTUP_Msk) >> ADC_MR_STARTUP_Pos);
  printf("Startup time: %d clock ticks\r\n", (int)calcul_startup(ul_startup));
  printf("Free run: %s\r\n", (p_adc->ADC_MR & ADC_MR_FREERUN_ON) ? "yes" : "no");
  if (!(p_adc->ADC_MR & ADC_MR_SLEEP_SLEEP)) {
		/* 40ms */
		if (ADC_STARTUP_NORM * ul_adcfreq / 1000000 >
				calcul_startup(ul_startup)) {
			printf("Startup time too small: %d, programmed: %d\r\n",
					(int)(ADC_STARTUP_NORM * ul_adcfreq /
							1000000),
					(int)calcul_startup(ul_startup));
		}
	} else {
		if (p_adc->ADC_MR & ADC_MR_FREERUN_ON) {
			puts("FreeRun forbidden in sleep mode\r");
		}
		if (!(p_adc->ADC_MR & ADC_MR_FWUP_ON)) {
			/* Sleep 40ms */
			if (ADC_STARTUP_NORM * ul_adcfreq / 1000000 >
					calcul_startup(ul_startup)) {
				printf("Startup time too small: %d, programmed: %d\r\n",
					(int)(ADC_STARTUP_NORM * ul_adcfreq / 1000000),
					(int)(calcul_startup(ul_startup)));
			}
		} else {
			if (p_adc->ADC_MR & ADC_MR_FWUP_ON) {
				/* Fast Wake Up Sleep Mode: 12ms */
				if (ADC_STARTUP_FAST * ul_adcfreq / 1000000 >
						calcul_startup(ul_startup)) {
					printf("Startup time too small: %d, programmed: %d\r\n",
						(int)(ADC_STARTUP_NORM * ul_adcfreq / 1000000),
						(int)(calcul_startup(ul_startup)));
				}
			}
		}
	}
  adc_interrupt_check(p_adc);
  delay(100);
  printf("temperature sensor is %s\r\n", ((p_adc->ADC_ACR & (ADC_ACR_TSON)) > 0) ? "on" : "off");
  printf("bias current control is %d\r\n", (int)((p_adc->ADC_ACR & ADC_ACR_IBCTL_Msk) >> ADC_ACR_IBCTL_Pos));
}

void adc_interrupt_check(Adc *p_adc) {
  if ((p_adc->ADC_IMR & ADC_IMR_RXBUFF) == ADC_IMR_RXBUFF) Serial.println("RXBUFF interrupt enabled");
  if ((p_adc->ADC_IMR & ADC_IMR_ENDRX) == ADC_IMR_ENDRX) Serial.println("ENDRX  interrupt enabled");
  if ((p_adc->ADC_IMR & ADC_IMR_COMPE) == ADC_IMR_COMPE) Serial.println("COMPE  interrupt enabled");
  if ((p_adc->ADC_IMR & ADC_IMR_GOVRE) == ADC_IMR_GOVRE) Serial.println("GOVRE  interrupt enabled");
  if ((p_adc->ADC_IMR & ADC_IMR_DRDY) == ADC_IMR_DRDY) Serial.println("DRDY   interrupt enabled");
  for (size_t i = 0; i < 16; i++) {
    if ((p_adc->ADC_IMR & (1 << i)) > 0) Serial.println("EOC" + String(i) + " interrupt enabled");
  }
}

void adc_interrupt_event(uint32_t intSR) {
  Serial.println("interrupt events:");
  if ((intSR & ADC_ISR_RXBUFF) > 0) Serial.println("RXBUFF event fired");
  if ((intSR & ADC_ISR_ENDRX) > 0) Serial.println("ENDRX  event fired");
  if ((intSR & ADC_ISR_COMPE) > 0) Serial.println("COMPE  event fired");
  if ((intSR & ADC_ISR_GOVRE) > 0) Serial.println("GOVRE  event fired");
  if ((intSR & ADC_ISR_DRDY) > 0) Serial.println("DRDY   event fired");
  for (size_t i = 0; i < 16; i++) {
    if ((intSR & (1 << i)) > 0) Serial.println("EOC" + String(i) + "   event fired");
  }
}

void adc_overrun_event(uint32_t ovrSR) {
  Serial.println("overrun events:");
  for (size_t i = 0; i < 16; i++) {
    if ((ovrSR & (1 << i)) > 0) Serial.println("OVRE" + String(i) + "  event fired");
  }
}

And the output:

  new run: 
 
Now doing adc_check...
ADC clock prescaler = 20
ADC clock frequency = 2.00 MHz
Startup time: 112 clock ticks
Free run: no
COMPE  interrupt enabled
temperature sensor is off
bias current control is 1
interrupt events:
RXBUFF event fired
ENDRX  event fired
COMPE  event fired
DRDY   event fired
EOC7   event fired
overrun events:
counters: 
HANDLER 10010
conversion time, us 10.4995

When the line #105 is changed to:

                 | ADC_EMR_CMPFILTER(1)                 // Number of consecutive compare events necessary

the output stops after printing

...
bias current control is 1

that is, there is no response from the code in loop().

Hi, I'm quite late with my reply. Hopefully you solved the problem. If not, a hint may help:
All variables used inside and outside an interrupt handler have to be declared volatile, e.g. volatile bool flag.