nRF52832 and NCS - using COMP to monitor incoming voltage signal

This is my environment

  • IDE: VSC
  • SDK: NCS v2.2.0
  • nRF52832 on custom hardware

This is what I am trying to do:

  1. Monitor the analog signal on one of my AIN pins using the COMP functionality
  2. Trigger an interrupt when that signal either goes above a reference level or below a reference level

The signal itself will normally sit at 1.0V, but when it gets a stimulus (its basically a Hall Effect sensor, so reacts to changing B-fields) I want to be able to capture that and see how far off set point it has gone (will do some fast ADC at this point).

This is how I have set up my COMP

#define COMP_LPCOMP_IRQn 19

nrfx_comp_config_t comp_config = {
	
	.reference = COMP_REFSEL_REFSEL_Int2V4,     /* Internal 2.4V reference */
    //.ext_ref = NRF_COMP_EXT_REF_3,            /* Analog reference connected to AIN3 */
    .main_mode = NRF_COMP_MAIN_MODE_SE,         /* Single ended mode. */
    .threshold = {
            .th_down = NRFX_VOLTAGE_THRESHOLD_TO_INT(1.5, 2.4),
            .th_up = NRFX_VOLTAGE_THRESHOLD_TO_INT(2.0, 2.4),
        },          							/* THDOWN and THUP values needed by the COMP_TH register. */
    .speed_mode = NRF_COMP_SP_MODE_High,        /* Speed mode set to high. */
    .hyst = NRF_COMP_HYST_50mV,               	/* Comparator hysteresis. */
	.isource = NRF_COMP_ISOURCE_Off,            /* Current source selected on analog input. */
	.input = NRF_COMP_INPUT_2,              	/* AIN2 to be monitored. */
    .interrupt_priority = NRFX_COMP_DEFAULT_CONFIG_IRQ_PRIORITY, /* Interrupt priority. */
};

void comparator_handler(nrf_comp_event_t event)
{
    switch (event)
    {
    case NRF_COMP_EVENT_READY:
        printk("NRF_COMP_EVENT_READY\n");
        break;
    case NRF_COMP_EVENT_DOWN:
        printk("NRF_COMP_EVENT_DOWN\n");
        break;
    case NRF_COMP_EVENT_UP:
        printk("NRF_COMP_EVENT_UP\n");
        break;
    case NRF_COMP_EVENT_CROSS:
        printk("NRF_COMP_EVENT_CROSS\n");
        break;

    default:
        break;
    }
}

This is my proj.conf:

CONFIG_ADC=y

CONFIG_COUNTER=y
CONFIG_COUNTER_TIMER0=y
CONFIG_COUNTER_TIMER1=y

CONFIG_NRFX_COMP=y

And in my main.c, this is how I set things up:

nrfx_comp_event_handler_t comp_event_config = comparator_handler;
	nrfx_err = nrfx_comp_init(&comp_config, comp_event_config);
	if (nrfx_err != NRFX_SUCCESS)
	{
		printk("ERR comp init (err %d)\n", nrfx_err);
		return ;
	}

	/* Connect COMP_IRQ to nrfx_comp_irq_handler */
	IRQ_CONNECT(COMP_LPCOMP_IRQn,
		    comp_config.interrupt_priority,
		    nrfx_isr,
			nrfx_comp_irq_handler,
			0);

	nrfx_comp_start(NRFX_COMP_EVT_EN_CROSS_MASK |
                        NRFX_COMP_EVT_EN_UP_MASK |
                        NRFX_COMP_EVT_EN_DOWN_MASK |
                        NRFX_COMP_EVT_EN_READY_MASK, 0);

I've been using this ticket as a guide as to how to get things working.

Problem I am having, is I am getting a bunch of build errors associated with the code that attempts to call IRQ_CONNECT():

C:\Nordic\v2.2.0\zephyr\include\zephyr\arch\arm\aarch32\irq.h:107:61: error: expression in static assertion is not constant
  105 |         BUILD_ASSERT(((flags_p & IRQ_ZERO_LATENCY) && \
      |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      
  106 |                       ((ZERO_LATENCY_LEVELS == 1) || \
      |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       
  107 |                        (priority_p < ZERO_LATENCY_LEVELS))) || \
      |                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
  108 |                      (priority_p <= IRQ_PRIO_LOWEST), \
      |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~         
C:\Nordic\v2.2.0\zephyr\include\zephyr\toolchain\gcc.h:77:51: note: in definition of macro 'BUILD_ASSERT'
   77 | #define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG)
      |                                                   ^~~~
C:\Nordic\v2.2.0\zephyr\include\zephyr\arch\arm\aarch32\irq.h:128:9: note: in expansion of macro '_CHECK_PRIO'
  128 |         _CHECK_PRIO(priority_p, flags_p) \
      |         ^~~~~~~~~~~
C:\Nordic\v2.2.0\zephyr\include\zephyr\irq.h:49:9: note: in expansion of macro 'ARCH_IRQ_CONNECT'
   49 |         ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p)
      |         ^~~~~~~~~~~~~~~~
c:\Nordic\Development\adc\src\main.c:233:9: note: in expansion of macro 'IRQ_CONNECT'
  233 |         IRQ_CONNECT(COMP_LPCOMP_IRQn,
      |         ^~~~~~~~~~~

If I dive into the irq.h header, it looks like there is an issue with the check on ZERO_LATENCY_LEVELS.  So, I basically added this to my proj.conf

CONFIG_ZERO_LATENCY_IRQS=y
CONFIG_ZERO_LATENCY_LEVELS=7

This seems to overcome the build errors.  Interestingly, if I set CONFIG_ZERO_LATENCY_LEVELS < 7, the build errors remain.

However, with those settings, my code isn't actually running!

So, clearly I've no idea what I'm doing, and could do with a bit of assistance in getting what, on the surface, seems like a pretty simple function working

Thanks and regards,

Mike

Parents
  • Hello,

    The problem is that 'comp_config.interrupt_priority' value is not a compile-time constant. I'm unsure if it is a change in the IRQ_CONNECT() macro or the compiler that caused this to not work anymore. The priority level is normally supposed to be retrieved from the Devicetree, but as there is no DT node for COMP, we need to hardcode the priority in this case. 

    e.g.,

    /* Connect COMP_IRQ to nrfx_comp_irq_handler */
    IRQ_CONNECT(COMP_LPCOMP_IRQn,
    5,
    nrfx_isr,
    nrfx_comp_irq_handler,
    0);

    Usage of Zero latency interrupts should be limited. By setting CONFIG_ZERO_LATENCY_LEVELS to '7', you essentially allocate all interrupt priorities to zero-latency interrupts since the HW only provides 7 priority levels.

    Best regards,

    Vidar

Reply
  • Hello,

    The problem is that 'comp_config.interrupt_priority' value is not a compile-time constant. I'm unsure if it is a change in the IRQ_CONNECT() macro or the compiler that caused this to not work anymore. The priority level is normally supposed to be retrieved from the Devicetree, but as there is no DT node for COMP, we need to hardcode the priority in this case. 

    e.g.,

    /* Connect COMP_IRQ to nrfx_comp_irq_handler */
    IRQ_CONNECT(COMP_LPCOMP_IRQn,
    5,
    nrfx_isr,
    nrfx_comp_irq_handler,
    0);

    Usage of Zero latency interrupts should be limited. By setting CONFIG_ZERO_LATENCY_LEVELS to '7', you essentially allocate all interrupt priorities to zero-latency interrupts since the HW only provides 7 priority levels.

    Best regards,

    Vidar

Children
Related