How to use bt_ctlr_set_public_addr()

Hi!

This is my setup:
- dev tools: VSCode + nRF Connect extension
- hardware: nRF52840DK
- SDK: nRF Connect SDK v2.1.0
- sample project: central_and_peripheral_hr

By default, the example app uses a random address for advertising.  I want to make it a fixed public address.

Here is a snippet of my code.

	{
		uint8_t  BDA[BT_ADDR_SIZE] = { 0x46, 0xda, 0x08, 0x88, 0x15, 0x00 } ;
		bt_ctlr_set_public_addr(BDA);
	}
	err = bt_enable(NULL);
	if (err) {
		return;
	}

	if (IS_ENABLED(CONFIG_SETTINGS)) {
		settings_load();
	}

	err = bt_hrs_client_init(&hrs_c);
	if (err) {
		printk("Heart Rate Service client failed to init (err %d)\n", err);
		return;
	}

	scan_init();

	err = scan_start();
	if (err) {
		return;
	}

	printk("Scanning started\n");

	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
			      sd, ARRAY_SIZE(sd));
	if (err) {
		printk("Advertising failed to start (err %d)\n", err);
		return;
	}

Other than the inserted call to bt_ctlr_set_public_addr(), there are no other changes to the example code.
The first time I run it, bt_ctlr_set_public_addr() did not take effect.  The app is still advertising with a random address.

Then I comment out the call to settings_load().  I get the error below:

No ID address. App must call settings_load()

For the third run, I put back the call to settings_load().  I still get the "No ID address" error, but this time bt_ctlr_set_public_addr() took effect and the app is advertising with the address that I specified.


Can someone please explain (or point to the document with the explanation) what is going on?  How can I make bt_ctlr_set_public_addr() work the first time?

Thanks and best regards,
Joey

Parents
  • Hi joey81,

    The behavior you described is very strange. Could you please erase your device and flash your working hex just once and see what happened?

    By the way, how are you performing the flashing?

    Best regards,

    Hieu

  • Hello Hieu!

    Thank you so much for the response.

    Somehow I could no longer replicate the scenario I described above.  Anyway, it was just my initial attempts with  bt_ctlr_set_public_addr().

    I now have another scenario (which is closer to what we want to achieve) that is repeatable.

    	bt_ctlr_set_public_addr(m_BDA);
    	err = bt_enable(NULL);
    	load_settings();
    	while (1) {
    		k_sleep(K_SECONDS(10));
    		start_scan_and_gather_info();
    		k_sem_take(&wait_for_info_available,K_FOREVER);
    
    		if  ( do_connectable )
    		{
    			adv_param->options = BT_LE_ADV_OPT_CONNECTABLE;
    		}
    		else
    		{
    			adv_param->options = BT_LE_ADV_OPT_NONE;
    		}
    
    		err = bt_le_adv_start(adv_param, m_adv_data, m_adv_count, p_resp_data, m_resp_count);
    		k_sleep(K_SECONDS(10));
    		bt_le_adv_stop();
    	}

    The value of  do_connectable  is determined in another thread, depending on the results of the scan.

    When do_connectable is true, the advertising proceeds using the public address that I specified.   However, when it is false (advertising PDU type is ADV_NONCONN_IND), it uses a random address.

    BTW, I am flash the board using the Debug tool in the nRF Connect extension of VSCode

    Best regards,
    Joey

  • Hi Joey,

    It seems that when the advertising is non-connectable, you need to use the advertising option BT_LE_ADV_OPT_USE_IDENTITY for the device to advertise with its public address.

    So instead of BT_LE_ADV_OPT_NONE, use something that set BT_LE_ADV_OPT_USE_IDENTITY bit.

    Best regards,

    Hieu

  • Hi Hieu!

    That did the trick! 

    And your reply came just in time.  I was just starting to analyze bt_id_set_adv_own_addr();

    Best regards,

    Joey

Reply Children
No Data
Related