This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Cannot get button/gpio interrupt on NET CPU using nRF5340DK

Using just the nRF Connect SDK, I cannot get a push button to interrupt the NET CPU on the nRF5340DK.

I have the following code on the APP CPU:

  nrf_gpio_pin_mcu_select(23, NRF_GPIO_PIN_MCUSEL_NETWORK);

The following code runs on the NET CPU:

  nrfx_gpiote_init(NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);
  nrfx_gpiote_in_config_t cfg = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
  cfg.pull = NRF_GPIO_PIN_PULLUP;
  nrfx_gpiote_in_init(NRF_GPIO_PIN_MAP(0, 23), &cfg, MyEventHandler);
  nrfx_gpiote_in_event_enable(NRF_GPIO_PIN_MAP(0, 23), true);

Please help identify what I'm missing. Thank you in advance!

Parents
  • Sigurd,

    Thanks for the response. However, I believe my code is already doing what you suggested. Unless I'm missing something, can you please elaborate?

    John

  • Hi,

    Did you connect GPIOTE_0 IRQ to nrfx_gpiote_irq_handler ?

    You could take a look at how it's done in the Zephyr nrfx sample. See this link. To test this sample, build the nrfx sample for the nrf5340pdk_nrf5340_cpunet. And for the app core, you could e.g. use the NCS empty_app_core sample, and build that for nrf5340pdk_nrf5340_cpuapp. See this link.

  • Ahh...I missed this. I have this connected now but still do not get an interrupt.

    I verified pin configuration is correct by using nrf_gpio_pin_read(23). I can see the return value is the correct button state. This confirms the NET CPU is in control of the pin.

    Now it is just a matter of getting a NET CPU interrupt on button toggle. These are the registers I verified after button push (looks correct):

    INTENSET (0x4100A304) = 0x8000000f
    EVENTS_IN[0] (0x4100A100) = 0x1
    EVENTS_IN[1] (0x4100A104) = 0x1
    EVENTS_IN[2] (0x4100A108) = 0x1
    EVENTS_IN[3] (0x4100A10C) = 0x1

    As for connecting ISR handlers, I confirmed the vector table is setup in this manner:

    SCB->VTOR = IrqVectors[]
    IrqVectors[26] =nrfx_gpiote_irq_handler  // 26: GPIOTE_IRQn
    NVIC_EnableIRQ(GPIOTE_IRQn);

    Global interrupts are enabled. Any thing else I should check?

  • The following works fine here, testing on NCS v1.3.0 on a PCA10095 version 0.7.0

    For nrf5340pdk_nrf5340_cpuapp, I'm running the empty_app_core sample.

    On nrf5340pdk_nrf5340_cpunet, I'm running this:

    main.c

    /*
     * Copyright (c) 2019 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    
    #include <nrfx_gpiote.h>
    
    #include <logging/log.h>
    LOG_MODULE_REGISTER(nrfx_sample, LOG_LEVEL_INF);
    
    static void button_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
    	LOG_INF("GPIO input event callback");
    }
    
    void main(void)
    {
    	LOG_INF("nrfx_gpiote sample on %s", CONFIG_BOARD);
    
    	/* Connect GPIOTE_0 IRQ to nrfx_gpiote_irq_handler */
    	IRQ_CONNECT(DT_IRQN(DT_NODELABEL(gpiote)),
    		    DT_IRQ(DT_NODELABEL(gpiote), priority),
    		    nrfx_isr, nrfx_gpiote_irq_handler, 0);
    
    
        nrfx_gpiote_init(NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);
        nrfx_gpiote_in_config_t cfg = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
        cfg.pull = NRF_GPIO_PIN_PULLUP;
        nrfx_gpiote_in_init(NRF_GPIO_PIN_MAP(0, 23), &cfg, button_handler);
        nrfx_gpiote_in_event_enable(NRF_GPIO_PIN_MAP(0, 23), true);
      
    }
    

    prj.conf

    CONFIG_GPIO=n
    CONFIG_NRFX_GPIOTE=y
    CONFIG_LOG=y
    CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=100
    

    Then when I press button 1 (pin 23) on the kit, I get "GPIO input event callback" printed in the terminal (see this link on how to get log-output).

  • Sigurd,

    Thank you for trying this and confirming the code works. The difference in my setup is that I'm not using zephyr. 

    I did try using the empty_app_core on the APP CPU. And I tried using your NET CPU example code (removing the zephyr code) and I'm still not getting interrupts.

    My issue must have something to do with the code prior to main(). I will keep trying to see if I can resolve. But if you can point me to the zephyr startup code (e.g. Reset Handler) and/or if the ncs has a non-zephyr startup example, that would help.

    Appreciate your effort to help me on this issue.

    Thanks.

    John

Reply
  • Sigurd,

    Thank you for trying this and confirming the code works. The difference in my setup is that I'm not using zephyr. 

    I did try using the empty_app_core on the APP CPU. And I tried using your NET CPU example code (removing the zephyr code) and I'm still not getting interrupts.

    My issue must have something to do with the code prior to main(). I will keep trying to see if I can resolve. But if you can point me to the zephyr startup code (e.g. Reset Handler) and/or if the ncs has a non-zephyr startup example, that would help.

    Appreciate your effort to help me on this issue.

    Thanks.

    John

Children
  • If you set a breakpoint in nrfx_gpiote_irq_handler(), and press the button, do you hit the breakpoint ?

    If not, make sure that you have something like this defined,

    // GPIOTE0_IRQn
    #define nrfx_gpiote_irq_handler     GPIOTE_IRQHandler

    Still not working, then you might need something like this,

    #define NRF_GPIOTE        NRF_GPIOTE0
    #define GPIOTE_IRQHandler GPIOTE0_IRQHandler

  • These are useful links. But did not solve my problem.

    I think the issue is even more fundamental. I tried a VTOR with every entry pointing to a default handler/trap, I never break on any ISR. I am setting the global interrupt __enable_irq(). I call NVIC_EnableIRQ(GPIOTE_IRQn). And I'm relying on the nrfx drivers to enable IRQs. Missing anything else?

  • I'm tried something extremely basic in the reset handler. I expected to trap in the SystemDefaultHandler() upon a button press but instead remains looping in the Reset_Handler(). I'm missing something basic.

    static void SystemDefaultHandler(void)
    {
      while(1);
    }
    
    SECTION(".isr_vector")
    void (* const systemVectors[256])(void) =
    {
      (void (*)(void))(&__stack_top__),
      Reset_Handler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
    
      /* External interrupts */
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler,
      SystemDefaultHandler
    
    };
    
    #include <nrfx_gpiote.h>
    
    static void button_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
      while(1);
    }
    
    void Reset_Handler(void)
    {
      /* Use linker defined location for ROM vector tables. */
      SCB->VTOR = (uint32_t)systemVectors;
    
      /* Core initialization. */
      SystemInit();
    
      nrfx_gpiote_init(NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);
      nrfx_gpiote_in_config_t cfg = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
      cfg.pull = NRF_GPIO_PIN_PULLUP;
      nrfx_gpiote_in_init(NRF_GPIO_PIN_MAP(0, 23), &cfg, button_handler);
      nrfx_gpiote_in_event_enable(NRF_GPIO_PIN_MAP(0, 23), true);
    
      NVIC_EnableIRQ(GPIOTE_IRQn);
      __enable_irq();
    
      while(1);
    }
    

  • Alright, I am able to get interrupts now. The above code is fine. The issue is the NET CPU startup is not always reliable. Using the empty_app_core project, I do not see my NET CPU startup. 

    When I reset the NET CPU using "nrfjprog -f NRF53 --coprocessor CP_NETWORK --reset", then I see the NET CPU execute my binary. And buttons presses reliably generate interrupt.

    Any idea how to make the empty_app_core reliably start my application?

  • I created a new public ticket with the FORCEOFF question. I suppose this ticket with button interrupts is now resolved. Thanks for your help!

Related