DFU 진행 watchdog

- 앱만 멈추고 BLE 링크가 유지되는 경우 대비
- DFU 업로드 중 30초동안 CHUNK가 오지 않는 경우 강제 disconnect 후 SMP로 재광고(초록 LED 점멸, 10분 타임아웃)
- 초록 LED 무한 점등 상황 방지
This commit is contained in:
2026-07-14 16:10:45 +09:00
parent 7fb01e3968
commit 281aa36f32
3 changed files with 40 additions and 13 deletions
+27 -13
View File
@@ -31,6 +31,7 @@ LOG_MODULE_REGISTER(vesiscan, LOG_LEVEL_INF);
#define BLE_CMD_WORKQ_STACK_SZ 8192
#define DFU_RESUME_MAGIC 0xD5U
#define DFU_RESUME_GPREGRET_REG 1U
#define DFU_STALL_TIMEOUT_SEC 30 // DFU 업로드 무진행 시 강제 disconnect 임계
#define IMG_MGMT_ID_STATE 0U
#define IMG_MGMT_ID_UPLOAD 1U
/*
@@ -88,6 +89,8 @@ static struct k_work bond_reset_work; // 전원 버튼 15초 롱프레스
static bool dfu_led_active; // DFU 업로드 중 초록 LED ON
static const char *power_off_pending_reason = "none";
static bool bond_reset_pending; // 본드 삭제 work 중복 예약 방지
static struct k_work_delayable dfu_watchdog_work; // DFU 업로드 무진행 감시 work
static void dfu_watchdog_handler(struct k_work *work);
static enum mgmt_cb_return dfu_status_cb(uint32_t event,
enum mgmt_cb_return prev_status,
@@ -524,6 +527,9 @@ static void timers_init(void)
// 전원 버튼 15초 롱프레스 본드 삭제 work
k_work_init(&bond_reset_work, bond_reset_work_handler);
// DFU 업로드 무진행 감시 work
k_work_init_delayable(&dfu_watchdog_work, dfu_watchdog_handler);
// BLE 명령 처리 work queue
k_work_init(&ble_cmd_work, ble_cmd_work_handler);
k_work_queue_start(&ble_cmd_work_q, ble_cmd_workq_stack, K_THREAD_STACK_SIZEOF(ble_cmd_workq_stack), BLE_CMD_WORKQ_PRIORITY, NULL);
@@ -544,13 +550,21 @@ static void timers_start(void)
k_timer_start(&m_power_on_delay_timer, K_MSEC(POWER_ON_DELAY), K_NO_WAIT);
}
static enum mgmt_cb_return dfu_status_cb(uint32_t event,
enum mgmt_cb_return prev_status,
int32_t *rc,
uint16_t *group,
bool *abort_more,
void *data,
size_t data_size)
/* DFU 업로드가 멈춘 채(청크 무진행) 링크만 살아있는 경우, 연결을 강제로 끊어
* SMP 재광고(10분 타임아웃)로 전환한다. 초록 LED 무한 점등/무한 대기 방지. */
static void dfu_watchdog_handler(struct k_work *work)
{
ARG_UNUSED(work);
if (ble_is_connected())
{
DBG_PRINTF("[DFU] upload stalled (%ds), forcing disconnect\r\n",
DFU_STALL_TIMEOUT_SEC);
(void)ble_disconnect_active();
}
}
static enum mgmt_cb_return dfu_status_cb(uint32_t event, enum mgmt_cb_return prev_status, int32_t *rc, uint16_t *group, bool *abort_more, void *data, size_t data_size)
{
ARG_UNUSED(prev_status);
ARG_UNUSED(rc);
@@ -563,19 +577,19 @@ static enum mgmt_cb_return dfu_status_cb(uint32_t event,
{
case MGMT_EVT_OP_IMG_MGMT_DFU_STARTED:
case MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK:
// DFU 업로드 중에는 초록 LED ON
dfu_led_active = true;
led_ble_solid();
led_ble_solid(); // DFU 업로드 중에는 초록 LED ON
// 청크가 올 때마다 무진행 감시 타이머 리셋
k_work_reschedule(&dfu_watchdog_work, K_SECONDS(DFU_STALL_TIMEOUT_SEC));
break;
case MGMT_EVT_OP_IMG_MGMT_DFU_PENDING:
// 업로드 완료 후 리셋 전까지 초록 LED ON
dfu_led_active = true;
led_ble_solid();
led_ble_solid(); // 업로드 완료 후 리셋 전까지 초록 LED ON
k_work_cancel_delayable(&dfu_watchdog_work); // 업로드 완료: 감시 종료
// DFU 리셋 후 버튼 없이 전원 ON
#if NRF_POWER_HAS_GPREGRET
nrf_power_gpregret_set(NRF_POWER, DFU_RESUME_GPREGRET_REG, DFU_RESUME_MAGIC);
nrf_power_gpregret_set(NRF_POWER, DFU_RESUME_GPREGRET_REG, DFU_RESUME_MAGIC); // DFU 리셋 후 버튼 없이 전원 ON
#endif
break;