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

SPI calls and bluetooth send from GPIOTE handler

Hello!

I have based myself on the ble_app_uart example, taken out the UART bit, and all that remains is the bluetooth functionality.

I have also implemented SPI communication which works fine in a Timer and directly in the main loop.

However, it seems to go into a hard fault when I am using a GPIOTE handler:

#define SCHED_MAX_EVENT_DATA_SIZE       sizeof(app_timer_event_t)                   /**< Maximum size of scheduler events. Note that scheduler BLE stack events do not contain any data, as the events are being pulled from the stack in the event handler. */
#define SCHED_QUEUE_SIZE                10                                          /**< Maximum number of events in the scheduler queue. */

static void gpio_init(void)
{
	ret_code_t err_code;

	nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
	//in_config.pull = NRF_GPIO_PIN_PULLUP;

	err_code = nrf_drv_gpiote_in_init(ADXL362_INTERRUPT_PIN, &in_config, in_pin_handler);
	APP_ERROR_CHECK(err_code);

	nrf_drv_gpiote_in_event_enable(ADXL362_INTERRUPT_PIN, true);
}

// .....
    
void in_pin_handler(void *data, uint16_t size)
{
	// Call SPI spi_master_send_recv
	// Call ble_nus_string_send
}

This didn't work out, so I tried app_scheduler.

static void scheduler_init()
{
	APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
}

// ...

void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{	
	UNUSED_VARIABLE(m_buffer);
	app_sched_event_put(NULL, 0, in_pin_scheduler_func);
}

// ...

int main(void)
{
	uint32_t err_code;
	timers_init();
	gpio_init(); // GPIOTE
	scheduler_init();
	ble_stack_init();
	gap_params_init();
	services_init();
	advertising_init();
	conn_params_init();		
	err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
	APP_ERROR_CHECK(err_code);
	Adxl362_Initialize();  // SPI
	nrf_drv_gpiote_out_set(BSP_LED_0);
	// Enter main loop.
	for (;;)
	{
		app_sched_execute();
		power_manage();
	}
}

So when the ADXL362 interrupt goes high, then it does trigger the GPIOTE interrupt, and according to ADXL362 's spec I need to invoke STATUS read from it to reset the event ( for it to go low ). This is where it crashes.

Is it supposed to hard fault like this?