Need help with nRF5340 IRQ conflict errors when adding GPIOTE drivers to Nordic Bluetooth Peripheral UART project

We are using the Nordic Bluetooth "Peripheral UART" project as a base for our project and I am attempting to add the GPIOTE drivers to the project but getting the following error:

gen_isr_tables.py: error: multiple registrations at table_index 47 for irq 47 (0x2f)
Existing handler 0x39aa5, new handler 0x39aa5
Has IRQ_CONNECT or IRQ_DIRECT_CONNECT accidentally been invoked on the same irq multiple times?

It looks like there is an IRQ conflict with adding the GPIOTE drivers and the DK drivers.

The reason I need the GPIOTE driver is in order to add multiple QDEC rotary encoders (which is not supported by the current QDEC driver).  I have attached a sample app that demonstrates the error.  We are using NCS v2.3.0 targeting nrf5340dk_nrf5340_cpuapp_ns.  We need to deconflict the IRQ but also keep the as much of the DK drivers as possible to expedite this project.

See attached application below:
peripheral_uart_GPIOTE.zip

Thanks for the help!

Parents
  • I understand.

    You cannot use nrfx_gpiote driver separately when you are using gpio_nrfx.c.

    You need to do what nrf\lib\dk_buttons_and_leds\dk_buttons_and_leds.c did. You need to get the device pointer of gpiote zephyr driver like below

    const struct device *const gpiote = DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiote));

    And use this instead of direct nrfx API for GPIOTE. 

    You can register another callback for your application just like nrf\lib\dk_buttons_and_leds\dk_buttons_and_leds.c did.

  • The file dk_buttons_and_leds.c is using loads of macros to abstract away the code to support multiple DKs so referencing the DK code doesn't help me much because I am very unfamiliar with Zephyr and Nordic.

    When you say one CANNOT use GPIO and GPIOTE I assume you mean that it is forbidden to have the following in the prj.conf:
    CONFIG_GPIO=y
    CONFIG_NRFX_GPIOTE=y

    Can you modify my posted application to trigger an event on the rising edge of GPIO pin 37?  I understand you may not be able to test but I would like to see what the code would look like to do this.

    As a side note I have been able to get the generic nrfx GPIOTE sample application working on the nRF5340 even though the 5340 is not listed as supported by the sample application.  However, this application is using no GPIO.

     

  • Peter,

    Thanks for the information. I will wait for your update. Susheel will be back this week so either he or I will continue supporting you.

    Regards,

    Hieu

  • Hello,

    I was able to scope my pins and they do appear to have the proper voltage.  We are using a CR 2032 button cell battery at 3V and I am seeing the A and B signals swing between 0V and 3V as expected.

    What I discovered is that I was missing a call that would enable the trigger for my sensor pins.

    	// Enable encoder sensor trigger events
    	nrfx_gpiote_trigger_enable(GPIO_ENC_RIGHT_A, true);
    	nrfx_gpiote_trigger_enable(GPIO_ENC_RIGHT_B, true);

    After adding the above code I finally started to get the trigger events for "GPIO_ENC_RIGHT_A" but now I have a new problem.  I am not getting trigger events for "GPIO_ENC_RIGHT_B" pin.  When it is all said and done I have two rotary encoders each with an A and B sensor pin so I need a total of four triggers to fire.

    Is there some limitation of GPIOTE to lmiit only to one trigger or how do I enable up to four triggers at once?

    Thanks,
    Peter

  • Hi,

    GPIOTE is limited, but, on the nRF5340, the limit is eight event or task total. So, you should be able to get four triggers.

    I just tested the following code. In writing it, I realize that maybe you are reusing GPIOTE channel for all inputs? Here is my code, tested to be working with nRF DK buttons.

    #define PRINTK_CASE(_CASE) case _CASE: printk(#_CASE); break
    
    void gpiote_interrupt_handler_230504(nrfx_gpiote_pin_t     pin,
    										nrfx_gpiote_trigger_t trigger,
    										void *                p_context)
    {
    	printk("gpiote_interrupt_handler_230504 Pin %d ", pin);
    	switch (trigger)
    	{
    		PRINTK_CASE(NRFX_GPIOTE_TRIGGER_NONE);
    		PRINTK_CASE(NRFX_GPIOTE_TRIGGER_LOTOHI);
    		PRINTK_CASE(NRFX_GPIOTE_TRIGGER_HITOLO);
    		PRINTK_CASE(NRFX_GPIOTE_TRIGGER_TOGGLE);
    		PRINTK_CASE(NRFX_GPIOTE_TRIGGER_LOW);
    		PRINTK_CASE(NRFX_GPIOTE_TRIGGER_HIGH);
    		PRINTK_CASE(NRFX_GPIOTE_TRIGGER_MAX);
    		default: printk("OH NO");
    	}
    	printk("\n");
    }
    
    // Interrupt enabled on 
    void config_input_via_nrfx_230504(const uint8_t port, const uint8_t pin)
    {
    	nrfx_err_t err;
    
    	nrfx_gpiote_input_config_t t_input_config = {.pull = NRF_GPIO_PIN_PULLUP};
    	
    	uint8_t t_gpiote_channel;
    	err = nrfx_gpiote_channel_alloc(&t_gpiote_channel);
    	printk("nrfx_gpiote_channel_alloc ");
    	switch (err)
    	{
    		PRINTK_CASE(NRFX_SUCCESS);
    		PRINTK_CASE(NRFX_ERROR_INTERNAL);
    		PRINTK_CASE(NRFX_ERROR_NO_MEM);
    		PRINTK_CASE(NRFX_ERROR_NOT_SUPPORTED);
    		PRINTK_CASE(NRFX_ERROR_INVALID_PARAM);
    		PRINTK_CASE(NRFX_ERROR_INVALID_STATE);
    		PRINTK_CASE(NRFX_ERROR_INVALID_LENGTH);
    		PRINTK_CASE(NRFX_ERROR_TIMEOUT);
    		PRINTK_CASE(NRFX_ERROR_FORBIDDEN);
    		PRINTK_CASE(NRFX_ERROR_NULL);
    		PRINTK_CASE(NRFX_ERROR_INVALID_ADDR);
    		PRINTK_CASE(NRFX_ERROR_BUSY);
    		PRINTK_CASE(NRFX_ERROR_ALREADY_INITIALIZED);
    		PRINTK_CASE(NRFX_ERROR_DRV_TWI_ERR_OVERRUN);
    		PRINTK_CASE(NRFX_ERROR_DRV_TWI_ERR_ANACK);
    		PRINTK_CASE(NRFX_ERROR_DRV_TWI_ERR_DNACK);
    		default: printk("OH NO");
    	}
    	printk("\n");
    
    	nrfx_gpiote_trigger_config_t t_trigger_config = {
    		.trigger 		= NRFX_GPIOTE_TRIGGER_TOGGLE, 
    		.p_in_channel 	= &t_gpiote_channel
    	};
    
    	nrfx_gpiote_handler_config_t t_handle_config = {
    		.handler 	= &gpiote_interrupt_handler_230504,
    		.p_context 	= NULL
    	};
    	
    	err = nrfx_gpiote_input_configure(pin, &t_input_config, &t_trigger_config, &t_handle_config);
    	printk("nrfx_gpiote_input_configure ");
    	switch (err)
    	{
    		PRINTK_CASE(NRFX_SUCCESS);
    		PRINTK_CASE(NRFX_ERROR_INTERNAL);
    		PRINTK_CASE(NRFX_ERROR_NO_MEM);
    		PRINTK_CASE(NRFX_ERROR_NOT_SUPPORTED);
    		PRINTK_CASE(NRFX_ERROR_INVALID_PARAM);
    		PRINTK_CASE(NRFX_ERROR_INVALID_STATE);
    		PRINTK_CASE(NRFX_ERROR_INVALID_LENGTH);
    		PRINTK_CASE(NRFX_ERROR_TIMEOUT);
    		PRINTK_CASE(NRFX_ERROR_FORBIDDEN);
    		PRINTK_CASE(NRFX_ERROR_NULL);
    		PRINTK_CASE(NRFX_ERROR_INVALID_ADDR);
    		PRINTK_CASE(NRFX_ERROR_BUSY);
    		PRINTK_CASE(NRFX_ERROR_ALREADY_INITIALIZED);
    		PRINTK_CASE(NRFX_ERROR_DRV_TWI_ERR_OVERRUN);
    		PRINTK_CASE(NRFX_ERROR_DRV_TWI_ERR_ANACK);
    		PRINTK_CASE(NRFX_ERROR_DRV_TWI_ERR_DNACK);
    		default: printk("OH NO");
    	}
    	printk("\n");
    
    	nrfx_gpiote_trigger_enable(pin, true);
    }

    Regards,

    Hieu

  • Hieu,

    I am able to get the GPIOTE triggering on all four of my "pins" now.  I am using four "channels" and that is working fine.  I have all four triggers calling the same event handler.  We still have some work to do in order to de-glitch the rotary encoder signals but that is outside of the GPIOTE driver layer.

    Right now I am triggering on edge toggle, but I might have a need to trigger on both rising and falling edge in a way that I can decode if the trigger was a rising or falling edge in the event handler.  Toggle always returns toggle trigger regardless of the edge direction.  I assume I cannot just OR together the LOTOHI and HITOLO trigger events because it is an enum and not a bitmask?

    Thanks for the help,
    Peter

  • Peter,

    For detecting what edge it is, I think you can use the GPIO (not GPIOTE) HAL APIs to read the pin state.

    Please also be informed that I am out of office from today, for three working days.

    Regards,

    Hieu

Reply Children
No Data
Related