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

nRF52832 Custom Board Pin In Use By GPIOTE Fault in BSP

Hi, 

I am trying to build out a button pressing scheme for BSP on a custom device with 15 buttons operating on a BL652 Laird Module (underlying nRF52832). After modifying the BOARD_PCA10040.h file to a custom one with our buttons (15) and leds (2), I've been able to get the LED initialization working provided I have defined my BUTTONS_NUMBER to 11 or less (not sure why). The LED indications change based on connecting and disconnecting to the BLE device, so that part works. However, when I increase the 'GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS' to 15 in the sdk_config.h file for our 15 buttons I get a hard fault. 

// <e> GPIOTE_ENABLED - nrf_drv_gpiote - GPIOTE peripheral driver - legacy layer
//==========================================================
#ifndef GPIOTE_ENABLED
#define GPIOTE_ENABLED 1
#endif
// <o> GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - Number of lower power input pins 
#ifndef GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS
#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 15
#endif

I've traced the hard fault through the following areas of code and found that the fault is due to a pin (I think P0.14) being used twice (one for my button and one for something else 'maybe TRACE'). 

1. First - buttons_led_init  (found in main.c)

static void buttons_leds_init(bool * p_erase_bonds)
{
    ret_code_t err_code;
    bsp_event_t startup_event;

    err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
    APP_ERROR_CHECK(err_code);

    err_code = bsp_btn_ble_init(NULL, &startup_event);
    APP_ERROR_CHECK(err_code);

    *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
}

2. Second - bsp_init   (found in bsp.c)

uint32_t bsp_init(uint32_t type, bsp_event_callback_t callback)
{
    uint32_t err_code = NRF_SUCCESS;

#if LEDS_NUMBER > 0 && !(defined BSP_SIMPLE)
    m_indication_type     = type;
#endif // LEDS_NUMBER > 0 && !(defined BSP_SIMPLE)

#if (BUTTONS_NUMBER > 0) && !(defined BSP_SIMPLE)
    m_registered_callback = callback;

    // BSP will support buttons and generate events
    if (type & BSP_INIT_BUTTONS)
    {
        uint32_t num;

        for (num = 0; ((num < BUTTONS_NUMBER) && (err_code == NRF_SUCCESS)); num++)
        {
            err_code = bsp_event_to_button_action_assign(num, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_DEFAULT);
        }

        if (err_code == NRF_SUCCESS)
        {
            err_code = app_button_init((app_button_cfg_t *)app_buttons,
                                       BUTTONS_NUMBER,
                                       APP_TIMER_TICKS(50));
        }

        if (err_code == NRF_SUCCESS)
        {
            err_code = app_button_enable();
        }

        if (err_code == NRF_SUCCESS)
        {
            err_code = app_timer_create(&m_bsp_button_tmr,
                                        APP_TIMER_MODE_SINGLE_SHOT,
                                        button_timer_handler);
        }
    }
#elif (BUTTONS_NUMBER > 0) && (defined BSP_SIMPLE)
    bsp_board_init(type);
#endif // (BUTTONS_NUMBER > 0) && !(defined BSP_SIMPLE)

#if LEDS_NUMBER > 0 && !(defined BSP_SIMPLE)
    if (type & BSP_INIT_LEDS)
    {
      //handle LEDs only. Buttons are already handled.
      bsp_board_init(BSP_INIT_LEDS);

      // timers module must be already initialized!
      if (err_code == NRF_SUCCESS)
      {
          err_code =
              app_timer_create(&m_bsp_leds_tmr, APP_TIMER_MODE_SINGLE_SHOT, leds_timer_handler);
      }

      if (err_code == NRF_SUCCESS)
      {
          err_code =
              app_timer_create(&m_bsp_alert_tmr, APP_TIMER_MODE_REPEATED, alert_timer_handler);
      }
    }
#endif // LEDS_NUMBER > 0 && !(defined BSP_SIMPLE)

    return err_code;
}

3. Third - app_button_init   (found in app_button.c)

uint32_t app_button_init(app_button_cfg_t const *       p_buttons,
                         uint8_t                        button_count,
                         uint32_t                       detection_delay)
{
    uint32_t err_code;

    if (detection_delay < APP_TIMER_MIN_TIMEOUT_TICKS)
    {
        return NRF_ERROR_INVALID_PARAM;
    }

    if (!nrf_drv_gpiote_is_init())
    {
        err_code = nrf_drv_gpiote_init();
        VERIFY_SUCCESS(err_code);
    }

    // Save configuration.
    mp_buttons          = p_buttons;
    m_button_count      = button_count;
    m_detection_delay   = detection_delay;

    m_pin_state      = 0;
    m_pin_transition = 0;

    while (button_count--)
    {
        app_button_cfg_t const * p_btn = &p_buttons[button_count];

#if defined(BUTTON_HIGH_ACCURACY_ENABLED) && (BUTTON_HIGH_ACCURACY_ENABLED == 1)
        nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(p_btn->hi_accuracy);
#else
        nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
#endif
        config.pull = p_btn->pull_cfg;

        err_code = nrf_drv_gpiote_in_init(p_btn->pin_no, &config, gpiote_event_handler);
        VERIFY_SUCCESS(err_code);
    }

    // Create polling timer.
    return app_timer_create(&m_detection_delay_timer_id,
                            APP_TIMER_MODE_SINGLE_SHOT,
                            detection_delay_timeout_handler);
}

4. Finally (Fault Here) - nrfx_gpiote_in_init  (found in nrfx_gpiote.c)

nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t               pin,
                               nrfx_gpiote_in_config_t const * p_config,
                               nrfx_gpiote_evt_handler_t       evt_handler)
{
    NRFX_ASSERT(pin < NUMBER_OF_PINS);
    nrfx_err_t err_code = NRFX_SUCCESS;

    /* Only one GPIOTE channel can be assigned to one physical pin. */
    if (pin_in_use_by_gpiote(pin))
    {
        err_code = NRFX_ERROR_INVALID_STATE;
    }
    else
    {
        int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
        if (channel != NO_CHANNELS)
        {
            if (!p_config->skip_gpio_setup)
            {
                if (p_config->is_watcher)
                {
                    nrf_gpio_cfg_watcher(pin);
                }
                else
                {
                    nrf_gpio_cfg_input(pin, p_config->pull);
                }
                pin_configured_set(pin);
            }

            if (p_config->hi_accuracy)
            {
                nrf_gpiote_event_configure((uint32_t)channel, pin, p_config->sense);
            }
            else
            {
                m_cb.port_handlers_pins[channel -
                                        GPIOTE_CH_NUM] |= (p_config->sense) << SENSE_FIELD_POS;
            }
        }
        else
        {
            err_code = NRFX_ERROR_NO_MEM;
        }
    }

    NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
    return err_code;
}

Specifically the fault happens in the following with the following images showing the local variables, etc. information.

    /* Only one GPIOTE channel can be assigned to one physical pin. */
    if (pin_in_use_by_gpiote(pin))
    {
        err_code = NRFX_ERROR_INVALID_STATE;
    }

 

I've changed my clock configuration to the following for use in a BL652 and verified that I am not attempting to use high accuracy interrupts as described in the following link. 

// </h> 
//==========================================================

// <h> Clock - SoftDevice clock configuration

//==========================================================
// <o> NRF_SDH_CLOCK_LF_SRC  - SoftDevice clock source.
 
// <0=> NRF_CLOCK_LF_SRC_RC 
// <1=> NRF_CLOCK_LF_SRC_XTAL 
// <2=> NRF_CLOCK_LF_SRC_SYNTH 

#ifndef NRF_SDH_CLOCK_LF_SRC
#define NRF_SDH_CLOCK_LF_SRC 0
#endif

// <o> NRF_SDH_CLOCK_LF_RC_CTIV - SoftDevice calibration timer interval. 
#ifndef NRF_SDH_CLOCK_LF_RC_CTIV
#define NRF_SDH_CLOCK_LF_RC_CTIV 16
#endif

// <o> NRF_SDH_CLOCK_LF_RC_TEMP_CTIV - SoftDevice calibration timer interval under constant temperature. 
// <i> How often (in number of calibration intervals) the RC oscillator shall be calibrated
// <i>  if the temperature has not changed.

#ifndef NRF_SDH_CLOCK_LF_RC_TEMP_CTIV
#define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 2
#endif

// <o> NRF_SDH_CLOCK_LF_ACCURACY  - External clock accuracy used in the LL to compute timing.
 
// <0=> NRF_CLOCK_LF_ACCURACY_250_PPM 
// <1=> NRF_CLOCK_LF_ACCURACY_500_PPM 
// <2=> NRF_CLOCK_LF_ACCURACY_150_PPM 
// <3=> NRF_CLOCK_LF_ACCURACY_100_PPM 
// <4=> NRF_CLOCK_LF_ACCURACY_75_PPM 
// <5=> NRF_CLOCK_LF_ACCURACY_50_PPM 
// <6=> NRF_CLOCK_LF_ACCURACY_30_PPM 
// <7=> NRF_CLOCK_LF_ACCURACY_20_PPM 
// <8=> NRF_CLOCK_LF_ACCURACY_10_PPM 
// <9=> NRF_CLOCK_LF_ACCURACY_5_PPM 
// <10=> NRF_CLOCK_LF_ACCURACY_2_PPM 
// <11=> NRF_CLOCK_LF_ACCURACY_1_PPM 

#ifndef NRF_SDH_CLOCK_LF_ACCURACY
#define NRF_SDH_CLOCK_LF_ACCURACY 7
#endif

https://devzone.nordicsemi.com/f/nordic-q-a/35205/setting-xl1-xl2-as-gpio-does-not-work

What am I missing? Is there some other setting for P0.14 (likely in a TRACEDATA setting)? Is there some other sdk_config.h settings, or other build settings that need to be setup?

Thanks for the help!

Parents
  • Worth checking these (slightly confusing) mappings, as Button 1 isn't ..:

    #define BUTTON_2        14
    #define SPIM2_MISO_PIN  14  // SPI Master In Slave Out GPIO pin number.
    #define ARDUINO_3_PIN   14  // Digital pin 3
    
    #define #define BSP_BUTTON_1   BUTTON_2
    BUTTONS_LIST       { BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4 }

    There are a few others worth reviewing:

    #define BSP_BOARD_BUTTON_2 2
    
    #ifdef BSP_BUTTON_2
    #define BSP_BUTTON_2_MASK (1<<BSP_BUTTON_2)
    #define BUTTON_CAPSLOCK   BSP_BUTTON_2_MASK
    
    #define BTN_ID_WAKEUP             0  /**< ID of button used to wake up the application. */
    #define BTN_ID_SLEEP              0  /**< ID of button used to put the application into sleep mode. */
    #define BTN_ID_DISCONNECT         0  /**< ID of button used to gracefully terminate a connection on long press. */
    #define BTN_ID_WAKEUP_BOND_DELETE 1  /**< ID of button used to wake up the application and delete all bonding information. */
    #define BTN_ID_WHITELIST_OFF      1  /**< ID of button used to turn off usage of the whitelist. */

    Since Button 1 is really button 2 fiddling with (say) the whitelist can have unexpected pin assignments .. I was confused, if I recall ..

  • Fire up! I figured out the issue. Similar to your original suggestion, just in a different location. Simple, but still difficult to find. When I redefined the BSP_BUTTON_# for all 15 of my buttons, I accidentally defined the failing button as the following. 

       #ifdef BSP_BUTTON_10
        {BSP_BUTTON_11, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_10

    The correct definition (in bsp.c) should be as follows for more buttons. 

    #ifndef BSP_SIMPLE
    static const app_button_cfg_t app_buttons[BUTTONS_NUMBER] =
    {
        #ifdef BSP_BUTTON_0
        {BSP_BUTTON_0, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_0
    
        #ifdef BSP_BUTTON_1
        {BSP_BUTTON_1, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_1
    
        #ifdef BSP_BUTTON_2
        {BSP_BUTTON_2, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_2
    
        #ifdef BSP_BUTTON_3
        {BSP_BUTTON_3, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_3
    
        #ifdef BSP_BUTTON_4
        {BSP_BUTTON_4, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_4
    
        #ifdef BSP_BUTTON_5
        {BSP_BUTTON_5, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_5
    
        #ifdef BSP_BUTTON_6
        {BSP_BUTTON_6, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_6
    
        #ifdef BSP_BUTTON_7
        {BSP_BUTTON_7, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_7
    
        #ifdef BSP_BUTTON_8
        {BSP_BUTTON_8, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_8
    
        #ifdef BSP_BUTTON_9
        {BSP_BUTTON_9, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_9
    
        #ifdef BSP_BUTTON_10
        {BSP_BUTTON_10, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_10
    
        #ifdef BSP_BUTTON_11
        {BSP_BUTTON_11, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_11
    
        #ifdef BSP_BUTTON_12
        {BSP_BUTTON_12, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_12
    
        #ifdef BSP_BUTTON_13
        {BSP_BUTTON_13, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_13
    
        #ifdef BSP_BUTTON_14
        {BSP_BUTTON_14, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_14
    
    };

    This at least got me past that error, going to start testing the rest of it now.

Reply
  • Fire up! I figured out the issue. Similar to your original suggestion, just in a different location. Simple, but still difficult to find. When I redefined the BSP_BUTTON_# for all 15 of my buttons, I accidentally defined the failing button as the following. 

       #ifdef BSP_BUTTON_10
        {BSP_BUTTON_11, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_10

    The correct definition (in bsp.c) should be as follows for more buttons. 

    #ifndef BSP_SIMPLE
    static const app_button_cfg_t app_buttons[BUTTONS_NUMBER] =
    {
        #ifdef BSP_BUTTON_0
        {BSP_BUTTON_0, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_0
    
        #ifdef BSP_BUTTON_1
        {BSP_BUTTON_1, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_1
    
        #ifdef BSP_BUTTON_2
        {BSP_BUTTON_2, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_2
    
        #ifdef BSP_BUTTON_3
        {BSP_BUTTON_3, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_3
    
        #ifdef BSP_BUTTON_4
        {BSP_BUTTON_4, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_4
    
        #ifdef BSP_BUTTON_5
        {BSP_BUTTON_5, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_5
    
        #ifdef BSP_BUTTON_6
        {BSP_BUTTON_6, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_6
    
        #ifdef BSP_BUTTON_7
        {BSP_BUTTON_7, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_7
    
        #ifdef BSP_BUTTON_8
        {BSP_BUTTON_8, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_8
    
        #ifdef BSP_BUTTON_9
        {BSP_BUTTON_9, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_9
    
        #ifdef BSP_BUTTON_10
        {BSP_BUTTON_10, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_10
    
        #ifdef BSP_BUTTON_11
        {BSP_BUTTON_11, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_11
    
        #ifdef BSP_BUTTON_12
        {BSP_BUTTON_12, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_12
    
        #ifdef BSP_BUTTON_13
        {BSP_BUTTON_13, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_13
    
        #ifdef BSP_BUTTON_14
        {BSP_BUTTON_14, false, BUTTON_PULL, bsp_button_event_handler},
        #endif // BUTTON_14
    
    };

    This at least got me past that error, going to start testing the rest of it now.

Children
No Data
Related