<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>nRF5340 power consumption on bt_le_adv_stop()</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/82046/nrf5340-power-consumption-on-bt_le_adv_stop</link><description>Hi Nordic Semi 
 I have implemented a basic BLE peripheral on a nRF5340 using the nRF Connect SDK 1.7.0.0. 
 The product we are developing have strict power consumption requirements. 
 I thus want to limit the BLE advertising period and upon expiration</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 29 Nov 2021 14:40:16 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/82046/nrf5340-power-consumption-on-bt_le_adv_stop" /><item><title>RE: nRF5340 power consumption on bt_le_adv_stop()</title><link>https://devzone.nordicsemi.com/thread/341113?ContentTypeID=1</link><pubDate>Mon, 29 Nov 2021 14:40:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:dd3e736b-fc13-4115-b508-63b37789ffd5</guid><dc:creator>helsing</dc:creator><description>&lt;p&gt;Hi Tonny, great to hear you figured it out.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF5340 power consumption on bt_le_adv_stop()</title><link>https://devzone.nordicsemi.com/thread/340821?ContentTypeID=1</link><pubDate>Fri, 26 Nov 2021 06:41:29 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:1b936eb1-3d65-4a6c-98b7-1b8367e53e1e</guid><dc:creator>TBing</dc:creator><description>&lt;p&gt;&lt;span&gt;Hi H&amp;aring;kon&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I found the answer.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;em&gt;bt_le_adv_stop() &lt;/em&gt;cannot be called from a k_timer handler that executes in timer irq context.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The Zephyr documentation states:&amp;nbsp;&lt;em&gt;Use a timer to initiate an &lt;span style="text-decoration:underline;"&gt;asynchronous&lt;/span&gt; operation&amp;nbsp;..&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A bit fluffy, but it gave a hint.&lt;/p&gt;
&lt;p&gt;The solution was (as also specified in the documentation) to dispatch the timeout to a Worker Queue, and&lt;/p&gt;
&lt;p&gt;have a handler call &lt;em&gt;bt_le_adv_stop()&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/em&gt;&lt;span&gt;from its worker context.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="text"&gt;static void onAdvertiseTimeoutIrq(struct k_timer *timer)
{
	k_work_submit(&amp;amp;advertiseTimeoutWork);
}

static void onAdvertiseTimeoutWork(struct k_work *work)
{
	bt_le_adv_stop();
}&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF5340 power consumption on bt_le_adv_stop()</title><link>https://devzone.nordicsemi.com/thread/340649?ContentTypeID=1</link><pubDate>Thu, 25 Nov 2021 07:56:28 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:76c7c7d8-3e97-4615-b728-61a403fa8266</guid><dc:creator>TBing</dc:creator><description>&lt;p&gt;Hi H&amp;aring;kon&lt;/p&gt;
&lt;p&gt;&lt;span&gt;CONFIG_SERIAL was already set to n.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I have isolated the BLE&amp;nbsp;related code in the code below.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The example advertises for 15 sec. and then calls&amp;nbsp;&lt;/span&gt;&lt;em&gt;bt_le_adv_stop&lt;/em&gt;&lt;span&gt;&lt;em&gt;()&lt;/em&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;When debugging this code I can see what happens: calling&amp;nbsp;bt_le_adv_stop() cause the MCU to restart.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Try setting a breakpoint in &lt;em&gt;main&lt;/em&gt; and in &lt;em&gt;onAdvertiseTimeout.&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;When I debug the sample, the breakpoint in&amp;nbsp;&lt;em&gt;main&amp;nbsp;&lt;/em&gt;is hit after&amp;nbsp;&lt;em&gt;bt_le_adv_stop&lt;/em&gt;&lt;em&gt;()&lt;/em&gt;&lt;em&gt;&lt;/em&gt; is called.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Regards Tonny&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;#include &amp;lt;zephyr/types.h&amp;gt;
#include &amp;lt;stddef.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;errno.h&amp;gt;
#include &amp;lt;sys/printk.h&amp;gt;
#include &amp;lt;sys/byteorder.h&amp;gt;
#include &amp;lt;zephyr.h&amp;gt;
#include &amp;lt;drivers/gpio.h&amp;gt;
#include &amp;lt;soc.h&amp;gt;

#include &amp;lt;bluetooth/bluetooth.h&amp;gt;
#include &amp;lt;bluetooth/hci.h&amp;gt;
#include &amp;lt;bluetooth/conn.h&amp;gt;
#include &amp;lt;bluetooth/uuid.h&amp;gt;
#include &amp;lt;bluetooth/gatt.h&amp;gt;
#include &amp;lt;bluetooth/gatt_dm.h&amp;gt;
#include &amp;lt;settings/settings.h&amp;gt;
#include &amp;lt;pm/pm.h&amp;gt;

//### PREDECLARATIONS
ssize_t onBleWrite(struct bt_conn *conn, const struct bt_gatt_attr *attr,
					 const void *buf, uint16_t len, uint16_t offset,
					 uint8_t flags);

static void onCccCfgchanged(const struct bt_gatt_attr *attr, uint16_t value);

static void onAdvertiseTimeout(struct k_timer *timer);

//### GLOBALS AND MACROS
#define DEVICE_NAME             CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN         (sizeof(DEVICE_NAME) - 1)

static bool pipeClientRegistered = false;

static struct bt_uuid_128 serviceUuid = BT_UUID_INIT_128(
	BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x6789, 0xACA8, 0x123456789ABC));

static const struct bt_uuid_128 pipeCharacteristicUuid = BT_UUID_INIT_128(
	BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x6789, 0xACA8, 0x123456789ABC));

static struct bt_gatt_attr serviceAttributes[] = {
    BT_GATT_PRIMARY_SERVICE(&amp;amp;serviceUuid),
    BT_GATT_CHARACTERISTIC(&amp;amp;pipeCharacteristicUuid.uuid,
        BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
        BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, NULL, onBleWrite, NULL),
    BT_GATT_CCC(onCccCfgchanged, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
};

static struct bt_gatt_service bleService = BT_GATT_SERVICE(serviceAttributes);

// Manufacturer specific data
static uint8_t msd[] = {
	0xA0, 0x02,
	0xB0 /* Some data ... */
};

// Advertise packet
static const struct bt_data advertiseData[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
	BT_DATA(BT_DATA_MANUFACTURER_DATA, msd, sizeof(msd))
};

//### UTILS

static const char *phy2str(uint8_t phy)
{
	switch (phy) {
	case 0: return &amp;quot;No packets&amp;quot;;
	case BT_GAP_LE_PHY_1M: return &amp;quot;LE 1M&amp;quot;;
	case BT_GAP_LE_PHY_2M: return &amp;quot;LE 2M&amp;quot;;
	case BT_GAP_LE_PHY_CODED: return &amp;quot;LE Coded&amp;quot;;
	default: return &amp;quot;Unknown&amp;quot;;
	}
}

K_TIMER_DEFINE(advertiseTimer, onAdvertiseTimeout, NULL);

//### CONNECTION STATUS CALLBACKS
static void onConnected(struct bt_conn *conn, uint8_t err)
{
	if (err) {
		printk(&amp;quot;Connection failed (err 0x%02x)\n&amp;quot;, err);
		return;
	}
}

static void onDisconnected(struct bt_conn *conn, uint8_t reason)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	printk(&amp;quot;Disconnected from %s (reason 0x%02x)\n&amp;quot;, addr, reason);
}

static void onSecurityChanged(struct bt_conn *conn, bt_security_t level,
			     enum bt_security_err err)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (!err) {
		printk(&amp;quot;Security changed: %s level %u\n&amp;quot;, addr, level);
	} else {
		printk(&amp;quot;Security failed: %s level %u err %d\n&amp;quot;, addr, level,
			err);
	}
}

//### CONNECTION PARAMERTER NEGOTIATION CALLBACKS

static bool onBleParameterRequest(struct bt_conn *conn, struct bt_le_conn_param *param)
{
	printk(&amp;quot;Connection parameters update request received.\n&amp;quot;);
	printk(&amp;quot;Minimum interval: %d, Maximum interval: %d\n&amp;quot;,
	       param-&amp;gt;interval_min, param-&amp;gt;interval_max);
	printk(&amp;quot;Latency: %d, Timeout: %d\n&amp;quot;, param-&amp;gt;latency, param-&amp;gt;timeout);

	return true;
}

static void onBleParamtereupdated(struct bt_conn *conn, uint16_t interval,
			     uint16_t latency, uint16_t timeout)
{
	printk(&amp;quot;Connection parameters updated.\n&amp;quot;
	       &amp;quot; interval: %d, latency: %d, timeout: %d\n&amp;quot;,
	       interval, latency, timeout);
}

static void onBlePhyUpdated(struct bt_conn *conn,
			   struct bt_conn_le_phy_info *param)
{
	printk(&amp;quot;LE PHY updated: TX PHY %s, RX PHY %s\n&amp;quot;,
	       phy2str(param-&amp;gt;tx_phy), phy2str(param-&amp;gt;rx_phy));
}

static void onBleDataLengthUpdated(struct bt_conn *conn,
				   struct bt_conn_le_data_len_info *info)
{
	printk(&amp;quot;LE data len updated: TX (len: %d time: %d)&amp;quot;
	       &amp;quot; RX (len: %d time: %d)\n&amp;quot;, info-&amp;gt;tx_max_len,
	       info-&amp;gt;tx_max_time, info-&amp;gt;rx_max_len, info-&amp;gt;rx_max_time);
}

static struct bt_conn_cb connectionCallbacks = {
	.connected = onConnected,
	.disconnected = onDisconnected,
	.security_changed = onSecurityChanged,
	.le_param_req = onBleParameterRequest,
	.le_param_updated = onBleParamtereupdated,
	.le_phy_updated = onBlePhyUpdated,
	.le_data_len_updated = onBleDataLengthUpdated};

//### CONNECTION AUTHORISATION CALLBACKS

static void onAuthorizationCancel(struct bt_conn *conn)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	printk(&amp;quot;Pairing cancelled: %s\n&amp;quot;, addr);
}

static void onPairingConfirm(struct bt_conn *conn)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	bt_conn_auth_pairing_confirm(conn);

	printk(&amp;quot;Pairing confirmed: %s\n&amp;quot;, addr);
}

static void onPairingComplete(struct bt_conn *conn, bool bonded)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	printk(&amp;quot;Pairing completed: %s, bonded: %d\n&amp;quot;, addr, bonded);
}

static void onPairingFailed(struct bt_conn *conn, enum bt_security_err reason)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	printk(&amp;quot;Pairing failed conn: %s, reason %d\n&amp;quot;, addr, reason);
}

static struct bt_conn_auth_cb connectionAuthorizationCallbacks = {
	.cancel = onAuthorizationCancel,
	.pairing_confirm = onPairingConfirm,
	.pairing_complete = onPairingComplete,
	.pairing_failed = onPairingFailed
};


static void onCccCfgchanged(const struct bt_gatt_attr *attr, uint16_t value)
{
    pipeClientRegistered = (value == BT_GATT_CCC_NOTIFY) ? true : false;

	printk(&amp;quot;Notification status changed: %d\n&amp;quot;, pipeClientRegistered);
}

ssize_t onBleWrite(struct bt_conn *conn, const struct bt_gatt_attr *attr,
					 const void *buf, uint16_t len, uint16_t offset,
					 uint8_t flags)
{
	printk(&amp;quot;Received: %d bytes\n&amp;quot;, len);

	// Loopback data
	bt_gatt_notify(conn, &amp;amp;serviceAttributes[1], buf, len);

	return len;
}

static void onAdvertiseTimeout(struct k_timer *timer)
{
	bt_le_adv_stop();

	// Stopping advertising leads to increased power consumption for some reason.
	// Forcing the MCU into power save helps on the problem but does not completely solve it.
	// See issue: https://github.com/zephyrproject-rtos/zephyr/issues/3192
	// pm_power_state_force((struct pm_state_info){PM_STATE_SUSPEND_TO_IDLE,0,0});
}

//### MAIN

void main(void)
{
	int err;

	printk(&amp;quot;Starting GATT Discovery Manager example\n&amp;quot;);

	err = bt_enable(NULL);
	if (err) {
		printk(&amp;quot;BLE init failed with error code %d\n&amp;quot;, err);
		return;
	}

	// Load application settings where bonding information is stored.
	// Regarding info log statement &amp;quot;bt_hci_core: No ID address. App must call settings_load,
	// see link: https://lists.zephyrproject.org/g/devel/topic/is_bluetooth_sample/28575293.
	if (IS_ENABLED(CONFIG_SETTINGS)) {
		printk(&amp;quot;Loading settings\n&amp;quot;);
		settings_load();
	}

	err = bt_gatt_service_register(&amp;amp;bleService);
	if (err) {
		printk(&amp;quot;BLE service registration failed %d\n&amp;quot;, err);
		return;
	}

	bt_conn_cb_register(&amp;amp;connectionCallbacks);
	if (err) {
		printk(&amp;quot;Failed to register connection callbacks.\n&amp;quot;);
		return;
	}

	err = bt_conn_auth_cb_register(&amp;amp;connectionAuthorizationCallbacks);
	if (err) {
		printk(&amp;quot;Failed to register authorization callbacks.\n&amp;quot;);
		return;
	}

	k_timer_start(&amp;amp;advertiseTimer, K_SECONDS(15), K_HOURS(15));

	err = bt_le_adv_start(BT_LE_ADV_CONN, advertiseData, ARRAY_SIZE(advertiseData),
			      NULL, 0);
	if (err) {
		printk(&amp;quot;Advertising failed to start (err %d)\n&amp;quot;, err);
		return;
	}

	printk(&amp;quot;Advertising successfully started\n&amp;quot;);
}
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF5340 power consumption on bt_le_adv_stop()</title><link>https://devzone.nordicsemi.com/thread/340579?ContentTypeID=1</link><pubDate>Wed, 24 Nov 2021 14:54:56 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:acd0b194-3670-4399-a7a9-734b64dc2a3e</guid><dc:creator>helsing</dc:creator><description>&lt;p&gt;Hi Tonny,&lt;/p&gt;
&lt;p&gt;Try disabling serial communication by adding &lt;span&gt;&lt;code&gt;CONFIG_SERIAL=n&lt;/code&gt; to &lt;em&gt;prj.conf&lt;/em&gt;. Do you still get the same current? &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;What is the current consumption before you start advertising?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Would you be able to share a code snippet? We will try to reproduce this. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Regards, &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Håkon&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>