BLE TX Power 동적 제어 (기본 4 dBm / Boost 8 dBm / 복귀 4 dBm)
- 광고, 연결 모두 기본 4 dBm 강제 (컨트롤러 기본이 +8이므로 명시적으로 낮춤) - 연결 RSSI 추적 활성화(CONFIG_BT_CTLR_CONN_RSSI) + RSSI 모니터 재활성화
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
|
||||
CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
|
||||
CONFIG_BT_CTLR_CONN_RSSI=y
|
||||
|
||||
+88
-4
@@ -50,6 +50,7 @@ static int64_t last_rx_conn_param_update_ms;
|
||||
#define BLE_TX_STUCK_MS 200
|
||||
#define BLE_TX_SLOW_COUNT 3
|
||||
#define BLE_TX_BUSY_STRESS_RETRY 4
|
||||
#define BLE_TX_RECOVER_HOLD_MS 10000 // 마지막 트리거 이후 이 시간 동안 트리거 없는 경우 TX power 복귀
|
||||
|
||||
extern int bt_hci_get_conn_handle(const struct bt_conn *conn, uint16_t *conn_handle);
|
||||
|
||||
@@ -58,6 +59,7 @@ static bool current_conn_handle_valid;
|
||||
static int8_t current_tx_power_dbm = BLE_TX_POWER_NORMAL_DBM;
|
||||
static uint8_t low_rssi_count;
|
||||
static uint8_t slow_tx_count;
|
||||
static int64_t last_stress_ms;
|
||||
static struct k_work_delayable tx_power_monitor_work;
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_SMP)
|
||||
@@ -137,9 +139,64 @@ static int ble_set_conn_tx_power(int8_t dbm, const char *reason)
|
||||
|
||||
static void ble_tx_power_stress(const char *reason)
|
||||
{
|
||||
last_stress_ms = k_uptime_get(); // stress 발생 시각 기록 (복귀 판정 기준)
|
||||
(void)ble_set_conn_tx_power(BLE_TX_POWER_STRESS_DBM, reason);
|
||||
}
|
||||
|
||||
// 마지막 stress 이후 충분히 조용하면(BLE_TX_RECOVER_HOLD_MS) NORMAL(4)로 복귀
|
||||
static void ble_tx_power_try_recover(void)
|
||||
{
|
||||
if ((current_tx_power_dbm != BLE_TX_POWER_NORMAL_DBM) &&
|
||||
((k_uptime_get() - last_stress_ms) >= BLE_TX_RECOVER_HOLD_MS))
|
||||
{
|
||||
(void)ble_set_conn_tx_power(BLE_TX_POWER_NORMAL_DBM, "link-recovered");
|
||||
}
|
||||
}
|
||||
|
||||
// 컨트롤러에 설정된 현재 연결 TX power를 조회 (실제 적용값 확인용)
|
||||
static int ble_read_conn_tx_power(int8_t *dbm)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
struct net_buf *rsp;
|
||||
struct bt_hci_cp_vs_read_tx_power_level *cp;
|
||||
struct bt_hci_rp_vs_read_tx_power_level *rp;
|
||||
int err;
|
||||
|
||||
if (!current_conn_handle_valid || dbm == NULL)
|
||||
{
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
buf = bt_hci_cmd_alloc(K_NO_WAIT);
|
||||
if (buf == NULL)
|
||||
{
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
cp = net_buf_add(buf, sizeof(*cp));
|
||||
cp->handle_type = BT_HCI_VS_LL_HANDLE_TYPE_CONN;
|
||||
cp->handle = sys_cpu_to_le16(current_conn_handle);
|
||||
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_TX_POWER_LEVEL, buf, &rsp);
|
||||
if (err)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
rp = (void *)rsp->data;
|
||||
if (rp->status != 0U)
|
||||
{
|
||||
err = -EIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dbm = rp->tx_power_level;
|
||||
}
|
||||
|
||||
net_buf_unref(rsp);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ble_read_conn_rssi(int8_t *rssi)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
@@ -221,8 +278,10 @@ static void tx_power_monitor_handler(struct k_work *work)
|
||||
low_rssi_count = 0U;
|
||||
}
|
||||
|
||||
k_work_schedule(&tx_power_monitor_work,
|
||||
K_MSEC(BLE_RSSI_MONITOR_INTERVAL_MS));
|
||||
// 전송이 없어도 주기적으로 복귀 판정 (마지막 stress 후 충분히 조용하면 NORMAL)
|
||||
ble_tx_power_try_recover();
|
||||
|
||||
k_work_schedule(&tx_power_monitor_work, K_MSEC(BLE_RSSI_MONITOR_INTERVAL_MS));
|
||||
}
|
||||
|
||||
static void ble_log_local_identity(void)
|
||||
@@ -523,7 +582,7 @@ static const struct bt_data sd_dfu[] =
|
||||
BT_DATA_BYTES(BT_DATA_UUID128_SOME, SMP_BT_SVC_UUID_VAL),
|
||||
};
|
||||
|
||||
/* Connection callbacks */
|
||||
/* BLE TX Power Control */
|
||||
static void connected(struct bt_conn *conn, uint8_t err)
|
||||
{
|
||||
if (err)
|
||||
@@ -539,7 +598,25 @@ static void connected(struct bt_conn *conn, uint8_t err)
|
||||
current_tx_power_dbm = BLE_TX_POWER_NORMAL_DBM;
|
||||
low_rssi_count = 0U;
|
||||
slow_tx_count = 0U;
|
||||
(void)ble_set_conn_tx_power(BLE_TX_POWER_NORMAL_DBM, "connected");
|
||||
last_stress_ms = k_uptime_get();
|
||||
|
||||
// 컨트롤러 기본 출력이 최대(+8)이므로, 연결 시 NORMAL(4)로 강제 적용
|
||||
if (current_conn_handle_valid)
|
||||
{
|
||||
(void)ble_tx_power_write(BT_HCI_VS_LL_HANDLE_TYPE_CONN, current_conn_handle, BLE_TX_POWER_NORMAL_DBM, "connected");
|
||||
}
|
||||
|
||||
int8_t cur_txp = 0;
|
||||
int txp_ret = ble_read_conn_tx_power(&cur_txp);
|
||||
if (txp_ret == 0)
|
||||
{
|
||||
DBG_CORE("[BLE] TX power (current) = %d dBm\r\n", cur_txp);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG_CORE("[BLE] TX power read fail ret=%d\r\n", txp_ret);
|
||||
}
|
||||
|
||||
if (BLE_RSSI_MONITOR_ENABLED)
|
||||
{
|
||||
k_work_schedule(&tx_power_monitor_work, K_MSEC(BLE_RSSI_MONITOR_INTERVAL_MS));
|
||||
@@ -579,6 +656,7 @@ static void disconnected(struct bt_conn *conn, uint8_t reason)
|
||||
current_tx_power_dbm = BLE_TX_POWER_NORMAL_DBM;
|
||||
low_rssi_count = 0U;
|
||||
slow_tx_count = 0U;
|
||||
last_stress_ms = 0;
|
||||
|
||||
if (current_conn)
|
||||
{
|
||||
@@ -792,6 +870,9 @@ int ble_advertising_start(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
// 컨트롤러 기본 출력이 최대(+8)이므로, 광고는 항상 NORMAL(4)로 고정 (stress 무관)
|
||||
(void)ble_tx_power_write(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0, BLE_TX_POWER_NORMAL_DBM, "adv");
|
||||
|
||||
k_work_cancel_delayable(&adv_timeout_work);
|
||||
if (!advertising_unlimited) // DFU 광고 포함, 미연결 10분 시 전원 OFF
|
||||
{
|
||||
@@ -950,6 +1031,9 @@ int ble_data_send(const uint8_t *data, uint16_t len)
|
||||
else
|
||||
{
|
||||
slow_tx_count = 0U;
|
||||
|
||||
// 정상 전송 완료 → 마지막 stress 이후 충분히 조용했으면 복귀
|
||||
ble_tx_power_try_recover();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user