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

Device seems to crash when adding new BLE service

I've been trying to add a new BLE service to my device. I've followed the instructions in this tutorial, up to step 7 (so no characteristics or anything), but the device is not advertising. In fact, the software seems to fail entirely; it does not seem to make it past the advertising_init and services_init functions in the initialization sequence. (In main() the device is supposed to blink an LED after this sequence is finished, which it does not.)

I've done nothing to modify the code other than these changes specified in the tutorial. The software compiles and loads on the device without any warnings or errors. I've posted the relevant code below; let me know if you need any more information.

// main.c

static ble_uuid_t m_adv_uuids[] = {{BLE_UUID_HEART_RATE_SERVICE,         BLE_UUID_TYPE_BLE},
																	 {BLE_UUID_BATTERY_SERVICE,            BLE_UUID_TYPE_BLE},
																	 {BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE},
																	 {BLE_UUID_OUR_SERVICE, BLE_UUID_TYPE_VENDOR_BEGIN}};
ble_os_t m_our_service;

static void services_init(void) {

	uint32_t       err_code;
	ble_hrs_init_t hrs_init;
	ble_bas_init_t bas_init;
	ble_dis_init_t dis_init;
	uint8_t        body_sensor_location;

	// Initialize Heart Rate Service.
	body_sensor_location = BLE_HRS_BODY_SENSOR_LOCATION_FINGER;

	memset(&hrs_init, 0, sizeof(hrs_init));

	hrs_init.evt_handler                 = NULL;
	hrs_init.is_sensor_contact_supported = true;
	hrs_init.p_body_sensor_location      = &body_sensor_location;

	// Here the sec level for the Heart Rate Service can be changed/increased.
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&hrs_init.hrs_hrm_attr_md.cccd_write_perm);
	BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hrs_init.hrs_hrm_attr_md.read_perm);
	BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hrs_init.hrs_hrm_attr_md.write_perm);

	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&hrs_init.hrs_bsl_attr_md.read_perm);
	BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hrs_init.hrs_bsl_attr_md.write_perm);

	err_code = ble_hrs_init(&m_hrs, &hrs_init);
	APP_ERROR_CHECK(err_code);

	// Initialize Battery Service.
	memset(&bas_init, 0, sizeof(bas_init));

	// Here the sec level for the Battery Service can be changed/increased.
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.cccd_write_perm);
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.read_perm);
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.write_perm);

	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_report_read_perm);

	bas_init.evt_handler          = NULL;
	bas_init.support_notification = true;
	bas_init.p_report_ref         = NULL;
	bas_init.initial_batt_level   = 100;

	err_code = ble_bas_init(&m_bas, &bas_init);
	APP_ERROR_CHECK(err_code);

	// Initialize Device Information Service.
	memset(&dis_init, 0, sizeof(dis_init));

	ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, (char *)MANUFACTURER_NAME);

	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.write_perm);

	err_code = ble_dis_init(&dis_init);
	APP_ERROR_CHECK(err_code);

	#ifdef BLE_DFU_APP_SUPPORT
		/** @snippet [DFU BLE Service initialization] */
		ble_dfu_init_t   dfus_init;

		// Initialize the Device Firmware Update Service.
		memset(&dfus_init, 0, sizeof(dfus_init));

		dfus_init.evt_handler   = dfu_app_on_dfu_evt;
		dfus_init.error_handler = NULL;
		dfus_init.evt_handler   = dfu_app_on_dfu_evt;
		dfus_init.revision      = DFU_REVISION;

		err_code = ble_dfu_init(&m_dfus, &dfus_init);
		APP_ERROR_CHECK(err_code);
		
		dfu_app_reset_prepare_set(reset_prepare);
		dfu_app_dm_appl_instance_set(m_app_handle);
		
		our_service_init(&m_our_service);
		/** @snippet [DFU BLE Service initialization] */
	#endif // BLE_DFU_APP_SUPPORT
}

static void advertising_init(void) {
    
    ble_advdata_t srdata;
    memset(&srdata, 0, sizeof(srdata));
    srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    srdata.uuids_complete.p_uuids = m_adv_uuids;

	uint32_t      err_code;
	ble_advdata_t advdata;

	// Build advertising data struct to pass into @ref ble_advertising_init.
	memset(&advdata, 0, sizeof(advdata));

	advdata.name_type               = BLE_ADVDATA_FULL_NAME;
	advdata.include_appearance      = true;
	advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
	advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
	advdata.uuids_complete.p_uuids  = m_adv_uuids;

	ble_adv_modes_config_t options = {0};
	options.ble_adv_slow_enabled  = BLE_ADV_SLOW_ENABLED;
	options.ble_adv_slow_interval = APP_ADV_INTERVAL;
	options.ble_adv_slow_timeout  = APP_ADV_TIMEOUT_IN_SECONDS;

	err_code = ble_advertising_init(&advdata, &srdata, &options, on_adv_evt, NULL);
	APP_ERROR_CHECK(err_code);
}

int main(void){

	uint32_t err_code;
	
	SEGGER_RTT_WriteString(0, "Exectuing program.\n");

	timers_init();
	ble_stack_init();
	device_manager_init(1);   // i set erase_bonds to 1 so the embedivet won't do that annoying thing where it refuses to bond with the central after you change the central's firmware
	gap_params_init();
	services_init();
	advertising_init();
	conn_params_init();

	setupPins();

	nrf_gpio_pin_write(MODE, 1); //enable the load switch

	flashGreen();  // test green led
	twi_init();    // initialize the i2c bus
	ledFlash();    // indicate success
	rtcSetup();    // reach out to the accelerometer
	ledFlash();    // indicate success
	
	// Run the rest of the program; the code never makes it to this point
}

// our_service.h

#ifndef OUR_SERVICE_H__
#define OUR_SERVICE_H__

#include <stdint.h>
#include "ble.h"
#include "ble_srv_common.h"

#define BLE_UUID_OUR_BASE_UUID {{0x23, 0xD1, 0x13, 0xEF, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00}} // 128-bit base UUID
#define BLE_UUID_OUR_SERVICE 0xABCD // Just a random, but recognizable value

/**
 * @brief This structure contains various status information for our service. 
 * It only holds one entry now, but will be populated with more items as we go.
 * The name is based on the naming convention used in Nordic's SDKs. 
 * 'ble’ indicates that it is a Bluetooth Low Energy relevant structure and 
 * ‘os’ is short for Our Service). 
 */
typedef struct
{
    uint16_t    service_handle;     /**< Handle of Our Service (as provided by the BLE stack). */
}ble_os_t;

/**@brief Function for initializing our new service.
 *
 * @param[in]   p_our_service       Pointer to Our Service structure.
 */
void our_service_init(ble_os_t * p_our_service);

#endif  /* _ OUR_SERVICE_H__ */

// our_service.c

#include <stdint.h>
#include <string.h>
#include "our_service.h"
#include "ble_srv_common.h"
#include "app_error.h"
#include "SEGGER_RTT.h"

/**@brief Function for initiating our new service.
 *
 * @param[in]   p_our_service        Our Service structure.
 *
 */
void our_service_init(ble_os_t * p_our_service)
{
    // STEP 3: Declare 16 bit service and 128 bit base UUIDs and add them to BLE stack table     
    uint32_t err_code;
    ble_uuid_t service_uuid;
    ble_uuid128_t base_uuid = BLE_UUID_OUR_BASE_UUID;
    service_uuid.uuid = BLE_UUID_OUR_SERVICE;
    err_code = sd_ble_uuid_vs_add(&base_uuid, &service_uuid.type);
    APP_ERROR_CHECK(err_code);
    
    // STEP 4: Add our service
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                    &service_uuid,
                                    &p_our_service->service_handle);
    APP_ERROR_CHECK(err_code);
    
    // Print messages to Segger Real Time Terminal
    // UNCOMMENT THE FOUR LINES BELOW AFTER INITIALIZING THE SERVICE OR THE EXAMPLE WILL NOT COMPILE.
    SEGGER_RTT_WriteString(0, "Exectuing our_service_init().\n"); // Print message to RTT to the application flow
    SEGGER_RTT_printf(0, "Service UUID: 0x%#04x\n", service_uuid.uuid); // Print service UUID should match definition BLE_UUID_OUR_SERVICE
    SEGGER_RTT_printf(0, "Service UUID type: 0x%#02x\n", service_uuid.type); // Print UUID type. Should match BLE_UUID_TYPE_VENDOR_BEGIN. Search for BLE_UUID_TYPES in ble_types.h for more info
    SEGGER_RTT_printf(0, "Service handle: 0x%#04x\n", p_our_service->service_handle); // Print out the service handle. Should match service handle shown in MCP under Attribute values
}

Parents Reply Children
Related