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!

  • 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

Related