Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Switching Between Connectable Advertising and Beacon Advertising On BLE_GAP_EVT_ADV_SET_TERMINATED

Hi, I have the following code in main.c:

static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
    ret_code_t err_code;

    switch (ble_adv_evt)
    {
        case BLE_ADV_EVT_FAST:
            NRF_LOG_INFO("Fast advertising.");
            err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_ADV_EVT_IDLE:
						  NRF_LOG_INFO("AVD EVT IDLING");
					switch (advertising_mode_state)
					{
						case 1:          //advertising_beacon
						{
//									sd_ble_gap_adv_stop();
							connectable_advertising_init();
							advertising_start(BLE_ADV_MODE_SLOW);
							break;
						}
						case 2:          // advertising_connectable
						{
							beacon_advertising_init();
							advertising_start(BLE_ADV_MODE_SLOW);
							break;
						}
					}

        default:
            break;
    }
}


.
.
.
.


/**@brief Function for initializing the Advertising functionality.
 */
static void connectable_advertising_init(void)
{
	  NRF_LOG_INFO("Connectable ADV INIT");
    ret_code_t             err_code;
    ble_advertising_init_t init;

    memset(&init, 0, sizeof(init));
	
	  ble_advdata_manuf_data_t                  manuf_data; //Variable to hold manufacturer specific data
    uint8_t data                              = UNIT_SERIAL; //Our data to advertise
    manuf_data.data.p_data                    = &data;
    manuf_data.data.size                      = sizeof(data);
    init.advdata.p_manuf_specific_data = &manuf_data;


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

    init.config.ble_adv_fast_enabled  = true;
    init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
    init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;

    init.evt_handler = on_adv_evt;

    err_code = ble_advertising_init(&m_advertising, &init);
    APP_ERROR_CHECK(err_code);

    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
		
		advertising_mode_state = 2;
		
}

/**@brief Function for initializing the Advertising functionality.
 */
static void beacon_advertising_init(void)
{
	
		NRF_LOG_INFO("Beacon ADV INIT");
	/**@brief Struct that contains pointers to the encoded advertising data. */
static ble_gap_adv_data_t m_adv_data =
{
    .adv_data =
    {
        .p_data = m_enc_advdata,
        .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    },
    .scan_rsp_data =
    {
        .p_data = NULL,
        .len    = 0

    }
};

	
	static uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] =                    /**< Information advertised by the Beacon. */
{
    APP_DEVICE_TYPE,     // Manufacturer specific information. Specifies the device type in this
                         // implementation.
    APP_ADV_DATA_LENGTH, // Manufacturer specific information. Specifies the length of the
                         // manufacturer specific data in this implementation.
    APP_BEACON_UUID,     // 128 bit UUID value.
    APP_MAJOR_VALUE,     // Major arbitrary value that can be used to distinguish between Beacons.
    APP_MINOR_VALUE,     // Minor arbitrary value that can be used to distinguish between Beacons.
    APP_MEASURED_RSSI    // Manufacturer specific information. The Beacon's measured TX power in
                         // this implementation.
};

	  uint32_t      err_code;
    ble_advdata_t advdata;
    uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;

    ble_advdata_manuf_data_t manuf_specific_data;

    manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;

#if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
    // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
    // UICR instead of using the default values. The major and minor values obtained from the UICR
    // are encoded into advertising data in big endian order (MSB First).
    // To set the UICR used by this example to a desired value, write to the address 0x10001080
    // using the nrfjprog tool. The command to be used is as follows.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
    // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
    // the following command should be used.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
    uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
    uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF);

    uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;

    m_beacon_info[index++] = MSB_16(major_value);
    m_beacon_info[index++] = LSB_16(major_value);

    m_beacon_info[index++] = MSB_16(minor_value);
    m_beacon_info[index++] = LSB_16(minor_value);
#endif
	
	    manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
    manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;

    // Build and set advertising data.
		NRF_LOG_INFO("Build and set advertising data");
    memset(&advdata, 0, sizeof(advdata));

    advdata.name_type             = BLE_ADVDATA_NO_NAME;
    advdata.flags                 = flags;
    advdata.p_manuf_specific_data = &manuf_specific_data;

    // Initialize advertising parameters (used when starting advertising).
		NRF_LOG_INFO("Initialize advertising parameters");
    memset(&m_adv_params, 0, sizeof(m_adv_params));

    m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
    m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
    m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
    m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
    m_adv_params.duration        = APP_ADV_DURATION; 

    err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
    APP_ERROR_CHECK(err_code);
		NRF_LOG_INFO("Encode Finished");

    err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
		NRF_LOG_INFO("Err Code: %d", err_code);
    APP_ERROR_CHECK(err_code);
		NRF_LOG_INFO("Configure Finished");
		
    advertising_mode_state = 1;

}


.
.
.
.

/**@brief Function for starting connectable advertising.
 */
static void advertising_start(bool erase_bonds)
{
	
				NRF_LOG_INFO("Entering Connectable Advertising Start");
	
    if (erase_bonds == true)
    {
        delete_bonds();
        // Advertising is started by PM_EVT_PEERS_DELETED_SUCEEDED event
    }
    else
    {
        ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
		    NRF_LOG_INFO("Err Code: %d", err_code);
        APP_ERROR_CHECK(err_code);
    }
			  NRF_LOG_INFO("Leaving Connectable Advertising Start");
}

/**@brief Function for starting beacon advertising.
 */
/*static void beacon_advertising_start(void)
{
    ret_code_t err_code;

    err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
    APP_ERROR_CHECK(err_code);
	
	  NRF_LOG_INFO("Leaving Beacon Advertising Start");
	
}
*/

/**@brief Function for changing the tx power.
 */
static void tx_power_set(void)
{
    ret_code_t err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_advertising.adv_handle, TX_POWER_LEVEL);
    APP_ERROR_CHECK(err_code);
}
/**@brief Function for enabling the DC/DC Converter.
 */
static void dcdc_enable_init(void)
{
	sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE);
}

/**@brief Function for application main entry.
 */
int main(void)
{
    bool erase_bonds = false;

    // Initialize.
    log_init();
    timers_init();
//    buttons_leds_init(&erase_bonds);
    power_management_init();
    ble_stack_init();
//		timeslot_sd_init();
		adc_configure();
    gap_params_init();
    gatt_init();
		services_init();
    beacon_advertising_init();
    conn_params_init();
    peer_manager_init();
		dcdc_enable_init();

    // Start execution.
    NRF_LOG_INFO("Service started.");
    application_timers_start();
    advertising_start(erase_bonds);
		tx_power_set();

    // Enter main loop.
    for (;;)
    {
        idle_state_handle();
    }
}

If I initialize the beacon advertising first, which is the shown configuration, I get fatal error code 8 out of ble_advertising_start.

If I initialize the connectable advertising first, it does time out and as intended and tries to initialize  beacon_advertising_init() in on_adv_event, but fails with err code 4 at sd_ble_gap_adv_set_configure

I think I am really close here -- any thoughts on what I am doing wrong?

  • In my attempting to solve this problem, I thought the problem may be in my advertising data, so I have restructured the code and for the time being, removed the beacon advertising initialization, just attempting to get the connectable advertising to work with sd_ble_gap_adv_start. The program runs with no errors, but even though it exits the start_advertising with nrf_success, I get no noticeable advertising when scanning with nrf connect. 

    /**@brief Function for initializing the connectable advertisement parameters.
     *
     * @details This function initializes the advertisement parameters to values that will put
     *          the application in connectable mode.
     *
     */
    static void connectable_adv_init(void)
    {
        // Initialize advertising parameters (used when starting advertising).
        memset(&m_adv_params, 0, sizeof(m_adv_params));
    
        m_adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
        m_adv_params.duration        = APP_ADV_DURATION;
    
        m_adv_params.p_peer_addr   = NULL;
        m_adv_params.filter_policy = BLE_GAP_ADV_FP_ANY;
        m_adv_params.interval      = APP_ADV_INTERVAL;
        m_adv_params.primary_phy   = BLE_GAP_PHY_1MBPS;
    }
    
    
    /**@brief Function for initializing the Advertising functionality.
     */
    static void advertising_init(void)
    {
        ret_code_t               err_code;
        ble_advdata_t            advdata;
        ble_advdata_manuf_data_t manuf_data;
        uint8_t                  flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
        APP_ERROR_CHECK_BOOL(sizeof(flags) == ADV_FLAGS_LEN);  // Assert that these two values of the same.
    
        // Build and set advertising data
        memset(&advdata, 0, sizeof(advdata));
    
        manuf_data.company_identifier = COMPANY_IDENTIFIER;
        manuf_data.data.size          = ADV_ADDL_MANUF_DATA_LEN;
        manuf_data.data.p_data        = m_addl_adv_manuf_data;
        advdata.flags                 = flags;
        advdata.p_manuf_specific_data = &manuf_data;
    
        if(m_is_non_connectable_mode)
        {
            err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, NULL, &m_adv_params);
            APP_ERROR_CHECK(err_code);
        }
        else
        {
            err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    /**@brief Function for initializing buttons and leds.
     *
     * @param[out] p_erase_bonds  Will be true if the clear bonding button was pressed to wake the application up.
     */
    /*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);
    }*/
    
    
    /**@brief Function for initializing the nrf log module.
     */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling the idle state (main loop).
     *
     * @details If there is no pending log operation, then sleep until next the next event occurs.
     */
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    
    /**@brief Function for starting advertising.
     */
    static void advertising_start(void)
    {
        ret_code_t err_code;
    
        err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
    	  NRF_LOG_INFO("err_code: %d", err_code);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for application main entry.
     */
    int main(void)
    {
    
        // Initialize.
        log_init();
        timers_init();
        power_management_init();
        ble_stack_init();
    	  adc_configure();
    	  NRF_LOG_INFO("adc congigured.");
        gap_params_init();
    	  NRF_LOG_INFO("gap params init.");
        gatt_init();
    	  NRF_LOG_INFO("gatt init.");
    		services_init();
    	  NRF_LOG_INFO("services init.");
    	  connectable_adv_init();
    	  NRF_LOG_INFO("connectable adv init.");
        advertising_init();
    	  NRF_LOG_INFO("adv init.");
        conn_params_init();
    	  NRF_LOG_INFO("conn params init.");
        peer_manager_init();
    		NRF_LOG_INFO("peer mngr init.");
    
        // Start execution.
        NRF_LOG_INFO("Template example started.");
        application_timers_start();
    
        advertising_start();
    		NRF_LOG_INFO("Advertising Started");
    
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
        }
    }
    
    
    /**
     * @}
     */
    
     

  • After again restructuring the layout, I am able to get both beacons to advertise individually, by disabling the initialization of the other. However, when I attempt to switch for the first time, I get err code 4 out of ble_advertising_init. When I dig into the error point with the debugger, it looks like the failure is in the appearance size.

    However, this seems unlikely, because I have set include_appearance to false. Because each advertiser will run fine on its own, but the program crashes when I attempt to switch between them, it makes me think that the advertising data from one is combining with the data from the other and causing an overflow. Not sure how to fix this though.

    static void adv_switch_timeout_handler(void * p_context)
    {
    	ret_code_t err_code;
    	
    	UNUSED_PARAMETER(p_context);
    	
      NRF_LOG_INFO("Entered ADV Switch Handler .");
    	
    	if (beacon_adv_mode)
    	{
    		NRF_LOG_INFO("Beacon Adv Mode True.");
    		err_code = sd_ble_gap_adv_stop(m_adv_handle);
    		APP_ERROR_CHECK(err_code);
    		NRF_LOG_INFO("Stopping Beacon Adv.");
    		advertising_init();
    		NRF_LOG_INFO("Conn Adv Init.");
    		advertising_start(false);
    	  NRF_LOG_INFO("Con Adv Started.");
    		beacon_adv_mode = false;
    	}
    	else
    	{
    	  NRF_LOG_INFO("Beacon Adv Mode False.");
    	  err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_IDLE);
    		APP_ERROR_CHECK(err_code);
    		NRF_LOG_INFO("Stopping Connectable Adv.");
    		beacon_advertising_init();
    		NRF_LOG_INFO("Beacon Adv Init.");
    		beacon_advertising_start();
    	  NRF_LOG_INFO("Beacon Adv Started.");
    		beacon_adv_mode = true;
    	}
    }
    
    
    
    /**@brief Function for the Timer initialization.
     *
     * @details Initializes the timer module. This creates and starts application timers.
     */
    static void timers_init(void)
    {
        // Initialize timer module.
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    
        // Create timers.
    		err_code = app_timer_create(&m_saadc_timer_id, APP_TIMER_MODE_REPEATED, saadc_meas_timeout_handler);
        APP_ERROR_CHECK(err_code);
    		NRF_LOG_INFO(" SAADC Timer Initialized.");
    	
    		err_code = app_timer_create(&m_adv_timer_id, APP_TIMER_MODE_REPEATED, adv_switch_timeout_handler);
        APP_ERROR_CHECK(err_code);
    		NRF_LOG_INFO(" ADV Timer Initialized.");
    
        /* YOUR_JOB: Create any timers to be used by the application.
                     Below is an example of how to create a timer.
                     For every new timer needed, increase the value of the macro APP_TIMER_MAX_TIMERS by
                     one.
           ret_code_t err_code;
           err_code = app_timer_create(&m_app_timer_id, APP_TIMER_MODE_REPEATED, timer_timeout_handler);
           APP_ERROR_CHECK(err_code); */
    }
    
    
    /**@brief Function for the GAP initialization.
     *
     * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
     *          device including the device name, appearance, and the preferred connection parameters.
     */
    static void gap_params_init(void)
    {
        ret_code_t              err_code;
        ble_gap_conn_params_t   gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)DEVICE_NAME,
                                              strlen(DEVICE_NAME));
        APP_ERROR_CHECK(err_code);
    
        /* YOUR_JOB: Use an appearance value matching the application's use case.
           err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_);
           APP_ERROR_CHECK(err_code); */
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
        gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
        gap_conn_params.slave_latency     = SLAVE_LATENCY;
        gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing the GATT module.
     */
    static void gatt_init(void)
    {
        ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling Queued Write Module errors.
     *
     * @details A pointer to this function will be passed to each service which may need to inform the
     *          application about an error.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void nrf_qwr_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    /**@brief Function for handling the YYY Service events.
     * YOUR_JOB implement a service handler function depending on the event the service you are using can generate
     *
     * @details This function will be called for all YY Service events which are passed to
     *          the application.
     *
     * @param[in]   p_yy_service   YY Service structure.
     * @param[in]   p_evt          Event received from the YY Service.
     *
     *
    static void on_yys_evt(ble_yy_service_t     * p_yy_service,
                           ble_yy_service_evt_t * p_evt)
    {
        switch (p_evt->evt_type)
        {
            case BLE_YY_NAME_EVT_WRITE:
                APPL_LOG("[APPL]: charact written with value %s. ", p_evt->params.char_xx.value.p_str);
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    */
    
    static void on_tas_evt(ble_tas_t     * p_tas_service, ble_tas_evt_t * p_evt)
    {
    //	  ret_code_t         err_code;
        switch(p_evt->evt_type)
        {
    /*		  case BLE_TAS_EVT_NOTIFICATION_ENABLED:
    					   err_code = app_timer_start(m_notification_timer_id, NOTIFICATION_INTERVAL, NULL);
                 APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_TAS_EVT_NOTIFICATION_DISABLED:
    					  err_code = app_timer_stop(m_notification_timer_id);
                APP_ERROR_CHECK(err_code);
                break;
    */			
            case BLE_TAS_EVT_CONNECTED:
                break;
    
            case BLE_TAS_EVT_DISCONNECTED:
                  break;
    
            default:
                  // No implementation needed.
                  break;
        }
    }
     
    
    /**@brief Function for initializing services that will be used by the application.
     */
    static void services_init(void)
    {
        ret_code_t         err_code;
        nrf_ble_qwr_init_t qwr_init = {0};
    
        // Initialize Queued Write Module.
        qwr_init.error_handler = nrf_qwr_error_handler;
    
        err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
        APP_ERROR_CHECK(err_code);
    
        /* YOUR_JOB: Add code to initialize the services used by the application.
           ble_xxs_init_t                     xxs_init;
           ble_yys_init_t                     yys_init;
    
           // Initialize XXX Service.
           memset(&xxs_init, 0, sizeof(xxs_init));
    
           xxs_init.evt_handler                = NULL;
           xxs_init.is_xxx_notify_supported    = true;
           xxs_init.ble_xx_initial_value.level = 100;
    
           err_code = ble_bas_init(&m_xxs, &xxs_init);
           APP_ERROR_CHECK(err_code);
    
           // Initialize YYY Service.
           memset(&yys_init, 0, sizeof(yys_init));
           yys_init.evt_handler                  = on_yys_evt;
           yys_init.ble_yy_initial_value.counter = 0;
    
           err_code = ble_yy_service_init(&yys_init, &yy_init);
           APP_ERROR_CHECK(err_code);
         */
    		 
    		 		 ble_tas_init_t                     tas_init;
    		 
    		 // Initialize TAS Service init structure to zero.
         memset(&tas_init, 0, sizeof(tas_init));
    		 
    		 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&tas_init.tas_value_char_attr_md.read_perm);
    		 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&tas_init.tas_value_char_attr_md.write_perm);
    		 
    		 // Set the tas event handler
         tas_init.evt_handler          = on_tas_evt;
    		 
    		 NRF_LOG_INFO("entering tas init");
    		 err_code = ble_tas_init(&m_tas, &tas_init);
    		 NRF_LOG_INFO("dev nm: %d",err_code);
         APP_ERROR_CHECK(err_code);
    		 
    }
    
    
    /**@brief Function for handling the Connection Parameters Module.
     *
     * @details This function will be called for all events in the Connection Parameters Module which
     *          are passed to the application.
     *          @note All this function does is to disconnect. This could have been done by simply
     *                setting the disconnect_on_fail config parameter, but instead we use the event
     *                handler mechanism to demonstrate its use.
     *
     * @param[in] p_evt  Event received from the Connection Parameters Module.
     */
    static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
    {
        ret_code_t err_code;
    
        if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
        {
            err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    /**@brief Function for handling a Connection Parameters error.
     *
     * @param[in] nrf_error  Error code containing information about what went wrong.
     */
    static void conn_params_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    /**@brief Function for initializing the Connection Parameters module.
     */
    static void conn_params_init(void)
    {
        ret_code_t             err_code;
        ble_conn_params_init_t cp_init;
    
        memset(&cp_init, 0, sizeof(cp_init));
    
        cp_init.p_conn_params                  = NULL;
        cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
        cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
        cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
        cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
        cp_init.disconnect_on_fail             = false;
        cp_init.evt_handler                    = on_conn_params_evt;
        cp_init.error_handler                  = conn_params_error_handler;
    
        err_code = ble_conn_params_init(&cp_init);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for starting timers.
     */
    static void application_timers_start(void)
    {
        /* YOUR_JOB: Start your timers. below is an example of how to start a timer.
           ret_code_t err_code;
           err_code = app_timer_start(m_app_timer_id, TIMER_INTERVAL, NULL);
           APP_ERROR_CHECK(err_code); */
    
    		   ret_code_t err_code;
           err_code = app_timer_start(m_saadc_timer_id, SAADC_MEASUREMENT_INTERVAL, NULL);
           APP_ERROR_CHECK(err_code);
    	
           err_code = app_timer_start(m_adv_timer_id, ADV_SWITCH_INTERVAL, NULL);
           APP_ERROR_CHECK(err_code);
    	
    }
    
    
    /**@brief Function for putting the chip into sleep mode.
     *
     * @note This function will not return.
     */
    /*static void sleep_mode_enter(void)
    {
        ret_code_t err_code;
    
        err_code = bsp_indication_set(BSP_INDICATE_IDLE);
        APP_ERROR_CHECK(err_code);
    
        // Prepare wakeup buttons.
        err_code = bsp_btn_ble_sleep_mode_prepare();
        APP_ERROR_CHECK(err_code);
    
        // Go to system-off mode (this function will not return; wakeup will cause a reset).
        err_code = sd_power_system_off();
        APP_ERROR_CHECK(err_code);
    }*/
    
    
    /**@brief Function for handling advertising events.
     *
     * @details This function will be called for advertising events which are passed to the application.
     *
     * @param[in] ble_adv_evt  Advertising event.
     */
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
    {
        ret_code_t err_code;
    
        switch (ble_adv_evt)
        {
            case BLE_ADV_EVT_FAST:
                NRF_LOG_INFO("Fast advertising.");
                err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_ADV_EVT_IDLE:
                ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
                break;
    
            default:
                break;
        }
    }
    
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code = NRF_SUCCESS;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected.");
                // LED indication will be changed when advertising starts.
                break;
    
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("Connected.");
                err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
                APP_ERROR_CHECK(err_code);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.
                NRF_LOG_DEBUG("GATT Client Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                // Disconnect on GATT Server timeout event.
                NRF_LOG_DEBUG("GATT Server Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    
    /**@brief Function for the Peer Manager initialization.
     */
    static void peer_manager_init(void)
    {
        ble_gap_sec_params_t sec_param;
        ret_code_t           err_code;
    
        err_code = pm_init();
        APP_ERROR_CHECK(err_code);
    
        memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
    
        // Security parameters to be used for all security procedures.
        sec_param.bond           = SEC_PARAM_BOND;
        sec_param.mitm           = SEC_PARAM_MITM;
        sec_param.lesc           = SEC_PARAM_LESC;
        sec_param.keypress       = SEC_PARAM_KEYPRESS;
        sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
        sec_param.oob            = SEC_PARAM_OOB;
        sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
        sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
        sec_param.kdist_own.enc  = 1;
        sec_param.kdist_own.id   = 1;
        sec_param.kdist_peer.enc = 1;
        sec_param.kdist_peer.id  = 1;
    
        err_code = pm_sec_params_set(&sec_param);
        APP_ERROR_CHECK(err_code);
    
        err_code = pm_register(pm_evt_handler);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Clear bond information from persistent storage.
     */
    static void delete_bonds(void)
    {
        ret_code_t err_code;
    
        NRF_LOG_INFO("Erase bonds!");
    
        err_code = pm_peers_delete();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling events from the BSP module.
     *
     * @param[in]   event   Event generated when button is pressed.
     */
    /*static void bsp_event_handler(bsp_event_t event)
    {
        ret_code_t err_code;
    
        switch (event)
        {
            case BSP_EVENT_SLEEP:
                sleep_mode_enter();
                break; // BSP_EVENT_SLEEP
    
            case BSP_EVENT_DISCONNECT:
                err_code = sd_ble_gap_disconnect(m_conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                if (err_code != NRF_ERROR_INVALID_STATE)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break; // BSP_EVENT_DISCONNECT
    
            case BSP_EVENT_WHITELIST_OFF:
                if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
                {
                    err_code = ble_advertising_restart_without_whitelist(&m_advertising);
                    if (err_code != NRF_ERROR_INVALID_STATE)
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                }
                break; // BSP_EVENT_KEY_0
    
            default:
                break;
        }
    }
    */
    
    /**@brief Function for initializing the Advertising functionality.
     */
    static void advertising_init(void)
    {
        ret_code_t             err_code;
        ble_advertising_init_t init;
    
        memset(&init, 0, sizeof(init));
    
        init.advdata.name_type               = BLE_ADVDATA_SHORT_NAME;
    	  init.advdata.short_name_len = 2; // Advertise only first 2 letters of name
        init.advdata.include_appearance      = false;
        init.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
    
        init.config.ble_adv_fast_enabled  = true;
        init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
        init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    
        init.evt_handler = on_adv_evt;
    
        err_code = ble_advertising_init(&m_advertising, &init);
    	  NRF_LOG_INFO("Err_Code: %d", err_code);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    
    static void beacon_advertising_init(void)
    {
    	
    static uint8_t              m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];  /**< Buffer for storing an encoded advertising set. */
    	
    	/**@brief Struct that contains pointers to the encoded advertising data. */
    static ble_gap_adv_data_t m_adv_data =
    {
        .adv_data =
        {
            .p_data = m_enc_advdata,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
        },
        .scan_rsp_data =
        {
            .p_data = NULL,
            .len    = 0
    
        }
    };
    	
    static uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] =                    /**< Information advertised by the Beacon. */
    {
        APP_DEVICE_TYPE,     // Manufacturer specific information. Specifies the device type in this
                             // implementation.
        APP_ADV_DATA_LENGTH, // Manufacturer specific information. Specifies the length of the
                             // manufacturer specific data in this implementation.
        APP_BEACON_UUID,     // 128 bit UUID value.
        APP_MAJOR_VALUE,     // Major arbitrary value that can be used to distinguish between Beacons.
        APP_MINOR_VALUE,     // Minor arbitrary value that can be used to distinguish between Beacons.
        APP_MEASURED_RSSI    // Manufacturer specific information. The Beacon's measured TX power in
                             // this implementation.
    };
    
    
        uint32_t      err_code;
        ble_advdata_t advdata;
        uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
    
        ble_advdata_manuf_data_t manuf_specific_data;
    
        manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;
    
    #if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
        // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
        // UICR instead of using the default values. The major and minor values obtained from the UICR
        // are encoded into advertising data in big endian order (MSB First).
        // To set the UICR used by this example to a desired value, write to the address 0x10001080
        // using the nrfjprog tool. The command to be used is as follows.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
        // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
        // the following command should be used.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
        uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
        uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF);
    
        uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;
    
        m_beacon_info[index++] = MSB_16(major_value);
        m_beacon_info[index++] = LSB_16(major_value);
    
        m_beacon_info[index++] = MSB_16(minor_value);
        m_beacon_info[index++] = LSB_16(minor_value);
    #endif
    
        manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
        manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type             = BLE_ADVDATA_NO_NAME;
        advdata.flags                 = flags;
        advdata.p_manuf_specific_data = &manuf_specific_data;
    
        // Initialize advertising parameters (used when starting advertising).
        memset(&m_adv_params, 0, sizeof(m_adv_params));
    
        m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
        m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
        m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
        m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
        m_adv_params.duration        = 0;       // Never time out.
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);
    
        err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for starting advertising.
     */
    static void beacon_advertising_start(void)
    {
        ret_code_t err_code;
    
        err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
        APP_ERROR_CHECK(err_code);
    }
    
    
    
    
    
    /**@brief Function for initializing buttons and leds.
     *
     * @param[out] p_erase_bonds  Will be true if the clear bonding button was pressed to wake the application up.
     */
    /*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);
    }
    */
    
    /**@brief Function for initializing the nrf log module.
     */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling the idle state (main loop).
     *
     * @details If there is no pending log operation, then sleep until next the next event occurs.
     */
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    
    /**@brief Function for starting advertising.
     */
    static void advertising_start(bool erase_bonds)
    {
        if (erase_bonds == true)
        {
            delete_bonds();
            // Advertising is started by PM_EVT_PEERS_DELETED_SUCEEDED event
        }
        else
        {
            ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    /**@brief Function for application main entry.
     */
    int main(void)
    {
        bool erase_bonds = false;
    
        // Initialize.
        log_init();
        timers_init();
    //    buttons_leds_init(&erase_bonds);
        power_management_init();
        ble_stack_init();
    		adc_configure();
        gap_params_init();
        gatt_init();
    	  services_init();
    	  NRF_LOG_INFO("Services Init.");
    //    advertising_init();
    	  beacon_advertising_init();
    		NRF_LOG_INFO("Beacon Adv Init.");
        conn_params_init();
        peer_manager_init();
    
        // Start execution.
        NRF_LOG_INFO("Template example started.");
        application_timers_start();
    
    //    advertising_start(erase_bonds);
          beacon_advertising_start();
    		  NRF_LOG_INFO("Beacon Adv Start.");
    
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
        }
    }
    
    
    /**
     * @}
     */
    

  • I believe I have made progress here, but I am now running into err code 12 NRF_ERROR_DATA_SIZE out of ble_advdata_encode in the beacon advertising init function. The debugger shows me to the appearance or the flag length, it seems to return on both.

    The timer that switches the packets is on 100ms. I really appreciate any help with this.

    static void adv_switch_timeout_handler(void * p_context)
    {
    	ret_code_t err_code;
    	
    	UNUSED_PARAMETER(p_context);
    	
    //  NRF_LOG_INFO("Entered ADV Switch Handler .");
    	
    	if (beacon_adv_mode)
    	{
    //		NRF_LOG_INFO("Beacon Adv Mode True.");
    		err_code = sd_ble_gap_adv_stop(m_adv_handle);
    		APP_ERROR_CHECK(err_code);
    //		NRF_LOG_INFO("Stopping Beacon Adv.");
    		advertising_init();
    //		NRF_LOG_INFO("Conn Adv Init.");
    		beacon_advertising_start();
    //	  NRF_LOG_INFO("Con Adv Started.");
    		beacon_adv_mode = false;
    	}
    	else
    	{
    //	  NRF_LOG_INFO("Beacon Adv Mode False.");
    		err_code = sd_ble_gap_adv_stop(m_adv_handle);
    		APP_ERROR_CHECK(err_code);
    //		NRF_LOG_INFO("Stopping Connectable Adv.");
    		beacon_advertising_init();
    //		NRF_LOG_INFO("Beacon Adv Init.");
    		beacon_advertising_start();
    //	  NRF_LOG_INFO("Beacon Adv Started.");
    		beacon_adv_mode = true;
    	}
    }
    
    
    
    /**@brief Function for the Timer initialization.
     *
     * @details Initializes the timer module. This creates and starts application timers.
     */
    static void timers_init(void)
    {
        // Initialize timer module.
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    
        // Create timers.
    		err_code = app_timer_create(&m_saadc_timer_id, APP_TIMER_MODE_REPEATED, saadc_meas_timeout_handler);
        APP_ERROR_CHECK(err_code);
    		NRF_LOG_INFO(" SAADC Timer Initialized.");
    	
    		err_code = app_timer_create(&m_adv_timer_id, APP_TIMER_MODE_REPEATED, adv_switch_timeout_handler);
        APP_ERROR_CHECK(err_code);
    		NRF_LOG_INFO(" ADV Timer Initialized.");
    	
    }
    
    
    /**@brief Function for the GAP initialization.
     *
     * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
     *          device including the device name, appearance, and the preferred connection parameters.
     */
    static void gap_params_init(void)
    {
        ret_code_t              err_code;
        ble_gap_conn_params_t   gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)DEVICE_NAME,
                                              strlen(DEVICE_NAME));
        APP_ERROR_CHECK(err_code);
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
        gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
        gap_conn_params.slave_latency     = SLAVE_LATENCY;
        gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing the GATT module.
     */
    static void gatt_init(void)
    {
        ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling Queued Write Module errors.
     *
     * @details A pointer to this function will be passed to each service which may need to inform the
     *          application about an error.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void nrf_qwr_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    static void on_tas_evt(ble_tas_t     * p_tas_service, ble_tas_evt_t * p_evt)
    {
    //	  ret_code_t         err_code;
        switch(p_evt->evt_type)
        {
    /*		  case BLE_TAS_EVT_NOTIFICATION_ENABLED:
    					   err_code = app_timer_start(m_notification_timer_id, NOTIFICATION_INTERVAL, NULL);
                 APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_TAS_EVT_NOTIFICATION_DISABLED:
    					  err_code = app_timer_stop(m_notification_timer_id);
                APP_ERROR_CHECK(err_code);
                break;
    */			
            case BLE_TAS_EVT_CONNECTED:
                break;
    
            case BLE_TAS_EVT_DISCONNECTED:
                  break;
    
            default:
                  // No implementation needed.
                  break;
        }
    }
     
    
    /**@brief Function for initializing services that will be used by the application.
     */
    static void services_init(void)
    {
        ret_code_t         err_code;
        nrf_ble_qwr_init_t qwr_init = {0};
    
        // Initialize Queued Write Module.
        qwr_init.error_handler = nrf_qwr_error_handler;
    
        err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
        APP_ERROR_CHECK(err_code);
    		 
    		 		 ble_tas_init_t                     tas_init;
    		 
    		 // Initialize TAS Service init structure to zero.
         memset(&tas_init, 0, sizeof(tas_init));
    		 
    		 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&tas_init.tas_value_char_attr_md.read_perm);
    		 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&tas_init.tas_value_char_attr_md.write_perm);
    		 
    		 // Set the tas event handler
         tas_init.evt_handler          = on_tas_evt;
    		 
    		 NRF_LOG_INFO("entering tas init");
    		 err_code = ble_tas_init(&m_tas, &tas_init);
    		 NRF_LOG_INFO("dev nm: %d",err_code);
         APP_ERROR_CHECK(err_code);
    		 
    }
    
    
    /**@brief Function for handling the Connection Parameters Module.
     *
     * @details This function will be called for all events in the Connection Parameters Module which
     *          are passed to the application.
     *          @note All this function does is to disconnect. This could have been done by simply
     *                setting the disconnect_on_fail config parameter, but instead we use the event
     *                handler mechanism to demonstrate its use.
     *
     * @param[in] p_evt  Event received from the Connection Parameters Module.
     */
    static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
    {
        ret_code_t err_code;
    
        if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
        {
            err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    /**@brief Function for handling a Connection Parameters error.
     *
     * @param[in] nrf_error  Error code containing information about what went wrong.
     */
    static void conn_params_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    /**@brief Function for initializing the Connection Parameters module.
     */
    static void conn_params_init(void)
    {
        ret_code_t             err_code;
        ble_conn_params_init_t cp_init;
    
        memset(&cp_init, 0, sizeof(cp_init));
    
        cp_init.p_conn_params                  = NULL;
        cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
        cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
        cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
        cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
        cp_init.disconnect_on_fail             = false;
        cp_init.evt_handler                    = on_conn_params_evt;
        cp_init.error_handler                  = conn_params_error_handler;
    
        err_code = ble_conn_params_init(&cp_init);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for starting timers.
     */
    static void application_timers_start(void)
    {
    
    		   ret_code_t err_code;
           err_code = app_timer_start(m_saadc_timer_id, SAADC_MEASUREMENT_INTERVAL, NULL);
           APP_ERROR_CHECK(err_code);
    	
           err_code = app_timer_start(m_adv_timer_id, ADV_SWITCH_INTERVAL, NULL);
           APP_ERROR_CHECK(err_code);
    	
    }
    
    
    /**@brief Function for putting the chip into sleep mode.
     *
     * @note This function will not return.
     */
    /*static void sleep_mode_enter(void)
    {
        ret_code_t err_code;
    
        err_code = bsp_indication_set(BSP_INDICATE_IDLE);
        APP_ERROR_CHECK(err_code);
    
        // Prepare wakeup buttons.
        err_code = bsp_btn_ble_sleep_mode_prepare();
        APP_ERROR_CHECK(err_code);
    
        // Go to system-off mode (this function will not return; wakeup will cause a reset).
        err_code = sd_power_system_off();
        APP_ERROR_CHECK(err_code);
    }*/
    
    
    /**@brief Function for handling advertising events.
     *
     * @details This function will be called for advertising events which are passed to the application.
     *
     * @param[in] ble_adv_evt  Advertising event.
     */
    /*static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
    {
        ret_code_t err_code;
    
        switch (ble_adv_evt)
        {
            case BLE_ADV_EVT_FAST:
                NRF_LOG_INFO("Fast advertising.");
                err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_ADV_EVT_IDLE:
     //           ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
                break;
    
            default:
                break;
        }
    }
    */
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code = NRF_SUCCESS;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_DISCONNECTED:
    					  err_code = app_timer_start(m_adv_timer_id, ADV_SWITCH_INTERVAL, NULL);
                APP_ERROR_CHECK(err_code);
                NRF_LOG_INFO("Disconnected.");
                // LED indication will be changed when advertising starts.
                break;
    
            case BLE_GAP_EVT_CONNECTED:
    					  err_code = app_timer_stop(m_adv_timer_id);
                APP_ERROR_CHECK(err_code);
                NRF_LOG_INFO("Connected.");
                err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
                APP_ERROR_CHECK(err_code);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.
                NRF_LOG_DEBUG("GATT Client Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                // Disconnect on GATT Server timeout event.
                NRF_LOG_DEBUG("GATT Server Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    
    /**@brief Function for the Peer Manager initialization.
     */
    static void peer_manager_init(void)
    {
        ble_gap_sec_params_t sec_param;
        ret_code_t           err_code;
    
        err_code = pm_init();
        APP_ERROR_CHECK(err_code);
    
        memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
    
        // Security parameters to be used for all security procedures.
        sec_param.bond           = SEC_PARAM_BOND;
        sec_param.mitm           = SEC_PARAM_MITM;
        sec_param.lesc           = SEC_PARAM_LESC;
        sec_param.keypress       = SEC_PARAM_KEYPRESS;
        sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
        sec_param.oob            = SEC_PARAM_OOB;
        sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
        sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
        sec_param.kdist_own.enc  = 1;
        sec_param.kdist_own.id   = 1;
        sec_param.kdist_peer.enc = 1;
        sec_param.kdist_peer.id  = 1;
    
        err_code = pm_sec_params_set(&sec_param);
        APP_ERROR_CHECK(err_code);
    
        err_code = pm_register(pm_evt_handler);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Clear bond information from persistent storage.
     */
    static void delete_bonds(void)
    {
        ret_code_t err_code;
    
        NRF_LOG_INFO("Erase bonds!");
    
        err_code = pm_peers_delete();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling events from the BSP module.
     *
     * @param[in]   event   Event generated when button is pressed.
     */
    /*static void bsp_event_handler(bsp_event_t event)
    {
        ret_code_t err_code;
    
        switch (event)
        {
            case BSP_EVENT_SLEEP:
                sleep_mode_enter();
                break; // BSP_EVENT_SLEEP
    
            case BSP_EVENT_DISCONNECT:
                err_code = sd_ble_gap_disconnect(m_conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                if (err_code != NRF_ERROR_INVALID_STATE)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break; // BSP_EVENT_DISCONNECT
    
            case BSP_EVENT_WHITELIST_OFF:
                if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
                {
                    err_code = ble_advertising_restart_without_whitelist(&m_advertising);
                    if (err_code != NRF_ERROR_INVALID_STATE)
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                }
                break; // BSP_EVENT_KEY_0
    
            default:
                break;
        }
    }
    */
    
    /**@brief Function for initializing the Advertising functionality.
     */
    static void advertising_init(void)
    {	
    		
    //		static uint8_t                  m_addl_adv_manuf_data[APP_ADV_DATA_LENGTH];
    		
    		memset(&m_adv_params, 0, sizeof(m_adv_params));
    
        m_adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
        m_adv_params.duration        = 0;
        m_adv_params.p_peer_addr     = NULL;
        m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
        m_adv_params.interval        = APP_ADV_INTERVAL;
        m_adv_params.primary_phy     = BLE_GAP_PHY_1MBPS;
    		
    		ret_code_t               err_code;
        ble_advdata_t            advdata;
    //    ble_advdata_manuf_data_t manuf_specific_data;
    //    uint8_t                  flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
     //   APP_ERROR_CHECK_BOOL(sizeof(flags) == ADV_FLAGS_LEN);  // Assert that these two values of the same.
    
        // Build and set advertising data
        memset(&advdata, 0, sizeof(advdata));
    		
    		advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance      = false;
        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;
    		
    /*
        manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;
        manuf_specific_data.data.size          = APP_BEACON_INFO_LENGTH;
        manuf_specific_data.data.p_data        = m_addl_adv_manuf_data;
        advdata.flags                          = flags;
        advdata.p_manuf_specific_data          = &manuf_specific_data;
    */
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
    //		NRF_LOG_INFO("Err Code: %d", err_code);
    //		NRF_LOG_INFO("Adv Set Encode.");
        APP_ERROR_CHECK(err_code);
    		
    		err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
    //	  NRF_LOG_INFO("Err Code: %d", err_code);
    //		NRF_LOG_INFO("Adv Set Configure.");
        APP_ERROR_CHECK(err_code);
    		
    }
    
    static void beacon_advertising_init(void)
    {
    
        uint32_t      err_code;
        ble_advdata_t advdata;
        uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
    
        ble_advdata_manuf_data_t manuf_specific_data;
    	
    	  manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;
    
    #if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
        // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
        // UICR instead of using the default values. The major and minor values obtained from the UICR
        // are encoded into advertising data in big endian order (MSB First).
        // To set the UICR used by this example to a desired value, write to the address 0x10001080
        // using the nrfjprog tool. The command to be used is as follows.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
        // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
        // the following command should be used.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
        uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
        uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF);
    
        uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;
    
        m_beacon_info[index++] = MSB_16(major_value);
        m_beacon_info[index++] = LSB_16(major_value);
    
        m_beacon_info[index++] = MSB_16(minor_value);
        m_beacon_info[index++] = LSB_16(minor_value);
    #endif
    
        manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
        manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type             = BLE_ADVDATA_NO_NAME;
        advdata.flags                 = flags;
        advdata.p_manuf_specific_data = &manuf_specific_data;
    
        // Initialize advertising parameters (used when starting advertising).
        memset(&m_adv_params, 0, sizeof(m_adv_params));
    
        m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
        m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
        m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
        m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
        m_adv_params.duration        = 0;       // Never time out.
    
    //    NRF_LOG_INFO("Starting Data Encode.");
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
    	  NRF_LOG_INFO("Err Code: %d", err_code);
        APP_ERROR_CHECK(err_code);
    
    		NRF_LOG_INFO("Starting Adv Set Configure.");
        err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
    	  NRF_LOG_INFO("Err Code: %d", err_code);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for starting advertising.
     */
    static void beacon_advertising_start(void)
    {
        ret_code_t err_code;
    
        err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing buttons and leds.
     *
     * @param[out] p_erase_bonds  Will be true if the clear bonding button was pressed to wake the application up.
     */
    /*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);
    }
    */
    
    /**@brief Function for initializing the nrf log module.
     */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling the idle state (main loop).
     *
     * @details If there is no pending log operation, then sleep until next the next event occurs.
     */
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    
    /**@brief Function for starting advertising.
     */
    /*static void advertising_start(bool erase_bonds)
    {
        if (erase_bonds == true)
        {
            delete_bonds();
            // Advertising is started by PM_EVT_PEERS_DELETED_SUCEEDED event
        }
        else
        {
            ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    
            APP_ERROR_CHECK(err_code);
        }
    }*/
    
    
    /**@brief Function for application main entry.
     */
    int main(void)
    {
    //    bool erase_bonds = false;
    
        // Initialize.
        log_init();
        timers_init();
    //    buttons_leds_init(&erase_bonds);
        power_management_init();
        ble_stack_init();
    		adc_configure();
        gap_params_init();
        gatt_init();
    	  services_init();
    	  NRF_LOG_INFO("Services Init.");
        advertising_init();
    //	  beacon_advertising_init();
    		NRF_LOG_INFO("Beacon Adv Init.");
        conn_params_init();
        peer_manager_init();
    
        // Start execution.
        NRF_LOG_INFO("Template example started.");
        application_timers_start();
    
    //    advertising_start(erase_bonds);
          beacon_advertising_start();
    		  NRF_LOG_INFO("Beacon Adv Start.");
    
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
        }
    }
    
    
    /**
     * @}
     */

  • Hi!

    Sorry about the delay.

    As you have made some progress, I guess we can ignore the error codes etc. from the original post and focus on your last reply.

    From your last reply:
    The main purpose here is to start advertising either as a beacon or a connectable advertisement, then being able to swap between them?

    To acheive this, you need to start advertising, stop the advertisement, update the advertising data and then restart the advertisement.

    I'm trying to understand how your code works. From what I can see; When you enter the switch and beacon_adv_mode = false (i.e you want to start advertising as a beacon?), you start by calling ble_advertising_start. Why is that?

    Liam said:
    I get err code 4 out of ble_advertising_init

     Error code 4, which is the NRF_ERROR_NO_MEM error code, would imply that you are trying to add too much data to the advertisement packet.

    I'll take a closer look at your code, and try to set up an example to demonstrate how I would do this.
    Please provide me with the SDK version you are using, as the approach might vary depending on the SDK version.

    Best regards,
    Joakim

  • Hi Joakim, thank you for your reply. Were you able to see my update from approx. 6 hours ago? I have moved away from the advertising module and directly to sd_ble_gap_adv_start for both the connectable and non-connectable advertising, removing that start function. 

    I am using SDK 15 -- which is requiring me to use the encode and set_configure functions.

Related