Initial Commit

This commit is contained in:
2026-07-06 11:14:35 +09:00
parent e6de6e8cc3
commit e55b283b39
31 changed files with 1023 additions and 2123 deletions
+34 -75
View File
@@ -31,9 +31,7 @@
LOG_MODULE_REGISTER(ble_svc, LOG_LEVEL_INF);
/*==============================================================================
* Module variables
*============================================================================*/
/* Module variables */
static struct bt_conn *current_conn;
static ble_data_rx_cb_t rx_callback;
static bool dfu_advertising_mode;
@@ -43,6 +41,7 @@ static int64_t last_rx_conn_param_update_ms;
#define BLE_TX_POWER_NORMAL_DBM 4
#define BLE_TX_POWER_STRESS_DBM 8
#define BLE_RSSI_MONITOR_ENABLED 0
#define BLE_RSSI_STRESS_DBM (-80)
#define BLE_RSSI_STRESS_COUNT 3
#define BLE_RSSI_MONITOR_INTERVAL_MS 500
@@ -68,7 +67,7 @@ static uint32_t pairing_passkey = BT_PASSKEY_RAND;
/*
* - mutex: 여러 곳에서 동시에 NUS 전송을 시작하지 못하게 막음
* - sem : "직전 전송이 정말 끝났는지" 기다리는 신호
* - sem : 직전 전송이 정말 끝났는지 기다리는 신호
*/
static struct k_mutex nus_tx_lock;
static struct k_sem nus_tx_done_sem;
@@ -195,6 +194,11 @@ static void tx_power_monitor_handler(struct k_work *work)
return;
}
if (!BLE_RSSI_MONITOR_ENABLED)
{
return;
}
err = ble_read_conn_rssi(&rssi);
if (err)
{
@@ -221,23 +225,6 @@ static void tx_power_monitor_handler(struct k_work *work)
K_MSEC(BLE_RSSI_MONITOR_INTERVAL_MS));
}
static const char *ble_addr_type_str(uint8_t type)
{
switch (type)
{
case BT_ADDR_LE_PUBLIC:
return "public";
case BT_ADDR_LE_RANDOM:
return "random";
case BT_ADDR_LE_PUBLIC_ID:
return "public-id";
case BT_ADDR_LE_RANDOM_ID:
return "random-id";
default:
return "unknown";
}
}
static void ble_log_local_identity(void)
{
bt_addr_le_t addr = {0};
@@ -463,8 +450,7 @@ static int ble_request_preferred_conn_params(bool count_attempt)
err = bt_conn_le_param_update(current_conn, &conn_param);
if (err)
{
DBG_ERR("[BLE] Param update failed err=%d -> disconnect\r\n", err);
(void)bt_conn_disconnect(current_conn, BT_HCI_ERR_UNACCEPT_CONN_PARAM);
DBG_ERR("[BLE] Param update failed err=%d\r\n", err);
return err;
}
@@ -493,25 +479,21 @@ static void conn_param_update_handler(struct k_work *work)
}
}
/*==============================================================================
* Advertising data
*============================================================================*/
/* Advertising data */
static const struct bt_data sd[] =
{
/* 평상시 Web Bluetooth 앱이 찾을 수 있도록 NUS UUID 광고 */
BT_DATA_BYTES(BT_DATA_UUID128_SOME, BT_UUID_NUS_VAL),
// 평상시 Web Bluetooth 앱이 찾을 수 있도록 NUS UUID 광고
BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_VAL),
};
static const struct bt_data sd_dfu[] =
{
/* DFU 진입 후 mcumgr 앱이 찾을 수 있도록 SMP UUID 광고 */
// DFU 진입 후 mcumgr 앱이 찾을 수 있도록 SMP UUID 광고
BT_DATA_BYTES(BT_DATA_UUID128_SOME, SMP_BT_SVC_UUID_VAL),
};
/*==============================================================================
* Connection callbacks
*============================================================================*/
/* Connection callbacks */
static void connected(struct bt_conn *conn, uint8_t err)
{
if (err)
@@ -528,7 +510,10 @@ static void connected(struct bt_conn *conn, uint8_t err)
low_rssi_count = 0U;
slow_tx_count = 0U;
(void)ble_set_conn_tx_power(BLE_TX_POWER_NORMAL_DBM, "connected");
k_work_schedule(&tx_power_monitor_work, K_MSEC(BLE_RSSI_MONITOR_INTERVAL_MS));
if (BLE_RSSI_MONITOR_ENABLED)
{
k_work_schedule(&tx_power_monitor_work, K_MSEC(BLE_RSSI_MONITOR_INTERVAL_MS));
}
/* 연결 정보 출력 */
char addr_str[BT_ADDR_LE_STR_LEN];
@@ -537,8 +522,6 @@ static void connected(struct bt_conn *conn, uint8_t err)
conn_param_update_attempts = 0U;
last_rx_conn_param_update_ms = 0;
k_work_schedule(&conn_param_update_work,
K_MSEC(BLE_CONN_PARAM_FIRST_DELAY_MS));
#if IS_ENABLED(CONFIG_BT_SMP)
err = bt_conn_set_security(conn, BLE_REQUIRED_SECURITY_LEVEL);
@@ -578,29 +561,14 @@ static void disconnected(struct bt_conn *conn, uint8_t reason)
reason,
advertising_unlimited ? "unlimited" : "10min");
/* 워크큐에서 advertising 재시작 */
// 워크큐에서 advertising 재시작
k_work_submit(&adv_restart_work);
}
static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
{
ARG_UNUSED(conn);
if (!ble_conn_param_is_preferred(param->interval_min,
param->latency,
param->timeout) ||
(param->interval_max != BLE_MAX_CONN_INTERVAL))
{
DBG_PRINTF("[BLE] Override requested params: min=%u max=%u latency=%u timeout=%u\r\n",
param->interval_min,
param->interval_max,
param->latency,
param->timeout);
param->interval_min = BLE_MIN_CONN_INTERVAL;
param->interval_max = BLE_MAX_CONN_INTERVAL;
param->latency = BLE_SLAVE_LATENCY;
param->timeout = BLE_CONN_SUP_TIMEOUT;
}
ARG_UNUSED(param);
return true;
}
@@ -646,9 +614,7 @@ BT_CONN_CB_DEFINE(conn_callbacks) =
#endif
};
/*==============================================================================
* NUS callbacks
*============================================================================*/
/* NUS callbacks */
static void nus_received(struct bt_conn *conn, const uint8_t *data, uint16_t len)
{
#if IS_ENABLED(CONFIG_BT_SMP)
@@ -661,18 +627,13 @@ static void nus_received(struct bt_conn *conn, const uint8_t *data, uint16_t len
ARG_UNUSED(conn);
#endif
DBG_CORE("[NUS RX] len=%u\r\n", len);
//DBG_CORE("[NUS RX] len=%u\r\n", len);
if (current_conn == conn)
{
int64_t now_ms = k_uptime_get();
if ((last_rx_conn_param_update_ms == 0) ||
((now_ms - last_rx_conn_param_update_ms) >= BLE_CONN_PARAM_RETRY_INTERVAL_MS))
{
last_rx_conn_param_update_ms = now_ms;
(void)ble_request_preferred_conn_params(false);
}
ARG_UNUSED(now_ms);
}
if (rx_callback)
@@ -684,7 +645,7 @@ static void nus_received(struct bt_conn *conn, const uint8_t *data, uint16_t len
static void nus_sent(struct bt_conn *conn)
{
ARG_UNUSED(conn);
/* 직전 NUS 패킷 전송 완료 */
// 직전 NUS 패킷 전송 완료
k_sem_give(&nus_tx_done_sem);
//DBG_CORE("[NUS TX] complete\r\n");
}
@@ -695,9 +656,7 @@ static struct bt_nus_cb nus_cb =
.sent = nus_sent,
};
/*==============================================================================
* Public functions
*============================================================================*/
/* Public functions */
int ble_service_init(ble_data_rx_cb_t rx_cb)
{
int err;
@@ -711,7 +670,7 @@ int ble_service_init(ble_data_rx_cb_t rx_cb)
k_work_init_delayable(&conn_param_update_work, conn_param_update_handler);
k_work_init_delayable(&tx_power_monitor_work, tx_power_monitor_handler);
/* Enable BLE stack */
// Enable BLE stack
err = bt_enable(NULL);
if (err)
{
@@ -740,7 +699,7 @@ int ble_service_init(ble_data_rx_cb_t rx_cb)
}
#endif
/* Initialize NUS */
// Initialize NUS
err = bt_nus_init(&nus_cb);
if (err)
{
@@ -766,9 +725,9 @@ int ble_advertising_start(void)
struct bt_le_adv_param adv_param = BT_LE_ADV_PARAM_INIT(
BT_LE_ADV_OPT_CONN,
APP_ADV_INTERVAL, /* min interval */
APP_ADV_INTERVAL, /* max interval */
NULL /* undirected */
APP_ADV_INTERVAL, // min interval
APP_ADV_INTERVAL, // max interval
NULL // undirected
);
err = bt_set_name(SERIAL_NO);
@@ -817,7 +776,7 @@ int ble_dfu_advertising_enable(void)
return -EALREADY;
}
/* mdf? 응답 전송 후 현재 연결을 끊고 SMP UUID 광고로 재시작 */
// mdf? 응답 전송 후 현재 연결을 끊고 SMP UUID 광고로 재시작
dfu_advertising_mode = true;
DBG_PRINTF("[BLE] DFU advertising mode enabled\r\n");
@@ -860,10 +819,10 @@ int ble_data_send(const uint8_t *data, uint16_t len)
}
#endif
/* 먼저 들어온 전송이 끝나기 전 다음 전송이 겹치지 않게 잠금 (NUS는 한 번에 한 패킷씩 보내는 것이 안전) */
// 먼저 들어온 전송이 끝나기 전 다음 전송이 겹치지 않게 잠금 (NUS는 한 번에 한 패킷씩 보내는 것이 안전)
k_mutex_lock(&nus_tx_lock, K_FOREVER);
/* 혹시 남아 있는 완료 신호가 있으면 비우고 이번 전송 전용 상태로 만듦 */
// 혹시 남아 있는 완료 신호가 있으면 비우고 이번 전송 전용 상태로 만듦
while (k_sem_take(&nus_tx_done_sem, K_NO_WAIT) == 0) {
}
@@ -895,7 +854,7 @@ int ble_data_send(const uint8_t *data, uint16_t len)
return err;
}
/* bt_nus_send() 성공 후 sent 콜백이 올 때까지 기다림 (다음 패킷을 보내도 되는 시점) */
// bt_nus_send() 성공 후 sent 콜백이 올 때까지 기다림 (다음 패킷을 보내도 되는 시점)
err = k_sem_take(&nus_tx_done_sem, K_MSEC(BLE_TX_STUCK_MS));
if (err)
{