This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Using GPIOTE with S130 in the BLE UART example

I've been using the ble_app_uart example with S130 on a nRF51 DK board. I wanted to add an interrupt with some GPIO pins. So I added GPIOTE interrupt handler but the compiler returned an error:

linking... ._build\nrf51422_xxac_s120.axf: Error: L6200E: Symbol GPIOTE_IRQHandler multiply defined (by nrf_drv_gpiote.o and main.o). Not enough information to list image symbols. Not enough information to list the image map. Finished: 2 information, 0 warning and 1 error messages. "._build\nrf51422_xxac_s120.axf" - 1 Error(s), 0 Warning(s).

I only added two function: stimulus_init and the interrupt handler.

void stimulus_init(void) 
{
  nrf_gpio_cfg_sense_input(16, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
  NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk;
  NVIC_EnableIRQ(GPIOTE_IRQn);
}
void GPIOTE_IRQHandler(void)
{
  if(NRF_GPIOTE->EVENTS_PORT)
  {
    NRF_GPIOTE->EVENTS_PORT = 0;
  }
}

I am aware of the function "app_button_init" to initialise GPIO pins. But it seems that it uses timer for polling. I need to use interrupt in order to minimise delay which needs to be within 1 ms.


Update: 02/12/2015

After I could get the gpiote event working on its own (without any softdevice), I added the code below to main.c and called it in the main function. The idea is that when button 1 (AUDIO_STIM_PIN) is pressed, "A" is sent over BLE UART.

But then the entire code stopped working. Even after commenting everything after nrf_drv_gpiote_init(), the code stopped working.

Any suggestions on what went wrong?

void stimulus_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) 
{
	uint8_t data_array[1] = "A";
	uint16_t len = 1;
	ret_code_t err_code = ble_uart_c_write_string(&m_ble_uart_c, data_array, len);
  if (err_code != NRF_ERROR_INVALID_STATE)
  {
    APP_ERROR_CHECK(err_code);
  }
}

void gpiote_init(void)
{
	uint32_t gpiote_event_addr;
	ret_code_t err_code;
	
	err_code = nrf_drv_gpiote_init();
  APP_ERROR_CHECK(err_code);
	
  nrf_drv_gpiote_in_config_t event_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);

  err_code = nrf_drv_gpiote_in_init(AUDIO_STIM_PIN, &event_config, stimulus_handler);
  APP_ERROR_CHECK(err_code);
  
	gpiote_event_addr = nrf_drv_gpiote_in_event_addr_get(AUDIO_STIM_PIN);
  
	nrf_drv_gpiote_in_event_enable(AUDIO_STIM_PIN, true);
}
  • Update answer:

    The gpiote driver is already initialized so nrf_drv_gpiote_init() will return error and either stop the code or reset the chip depending if DEBUG is defined (see the code in app_error_handler(...)). Change to this code:

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

    Update 09.12.2015: The GPIOTE handler is running at APP_PRIORITY_HIGH, which means that sd_ble_gattc_write(...) is called at this level. It is not allowed to do SoftDevice calls at APP_PRIORITY_HIGH, and if attempted to do so, the application will run into hardfault. SoftDevice calls have to be made in main context or at APP_PRIORITY_LOW.

  • Thanks for that. I just discovered this too after stepping through in Debug.

    I also decided to use another pin (P0.15) and placed another button switch there so that it will call my event handler instead of gpiote_event_handler. I also had to use the high accuracy option (nrf_drv_gpiote_in_config_t event_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);). After these two changes and adding the init check (nrf_drv_gpiote_is_init) that you pointed out, the code worked as original.

    Interestingly, when I pressed the new button, the BLE link was disconnected. The red LED on the dongle changed from on (connected state) to blinking (disconnected). I expected stimulus_handler to be executed which sent the string "A" to the dongle. If the reset button the DK board is pressed, the BLE link was connected again. But pressing the button disconnected the ink again.

  • Any error (leds lit up)? Go into debug and set a breakpoint at while(1) in app_error_handler, check the error code, line number and file variables.

  • That's the wierd part. There was no error. The LEDs didn't lit up.

    In debug mode, I could see that pressing the button switch invoked the gpiote event handler and could step through the lines. Suddenly, the red LED on the dongle went blinking - BLE was disconnected. I could still step through the code until it "froze" usually at sd_ble_gattc_write(m_tx_buffer[m_tx_index].conn_handle, &m_tx_buffer[m_tx_index].req.write_req.gattc_params); or memcpy(p_msg->req.write_req.gattc_value,p_str,p_str_len); in ble_uart_c_write_string.

    So it never went to app_error_handler.

    EDIT: I commented out the code in the gpiote event handler stimulus_handler. If the code is running not in the debug mode, pressing the button switch does not make the BLE link disconnected.

    But if the code is running in the debug mode, the BLE link got disconnected after pressing the button.

  • When you step through the code, the chip will stop and the link will timeout and be lost. Also, the SoftDevice may stop working correctly and cause a hardfault. Therefore step debugging should be approached carefully. If the disconnection is not caused by an error condition you can check the disconnect reason in BLE_GAP_EVT_DISCONNECTED event, it should be in p_ble_evt->evt.gap_evt.params.disconnected.reason. If you have a spare nRF dongle or a board you can also try the sniffer to see what is going on over the air, see here.

Related