DFU 모듈 분리
This commit is contained in:
@@ -0,0 +1,238 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* @file dfu_manager.c
|
||||||
|
* @brief DFU state, watchdog, and MCUboot image control
|
||||||
|
******************************************************************************/
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/dfu/mcuboot.h>
|
||||||
|
#include <zephyr/mgmt/mcumgr/mgmt/callbacks.h>
|
||||||
|
#include <hal/nrf_power.h>
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "dfu_manager.h"
|
||||||
|
#include "debug_print.h"
|
||||||
|
#include "led_control.h"
|
||||||
|
#include "ble_service.h"
|
||||||
|
|
||||||
|
#define DFU_STALL_TIMEOUT_SEC 30 // DFU upload stall disconnect threshold
|
||||||
|
#define IMG_MGMT_ID_STATE 0U
|
||||||
|
#define IMG_MGMT_ID_UPLOAD 1U
|
||||||
|
|
||||||
|
static bool dfu_led_active; // DFU upload green LED state
|
||||||
|
static struct k_work_delayable dfu_watchdog_work; // DFU upload stall watchdog
|
||||||
|
|
||||||
|
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,
|
||||||
|
int32_t *rc,
|
||||||
|
uint16_t *group,
|
||||||
|
bool *abort_more,
|
||||||
|
void *data,
|
||||||
|
size_t data_size);
|
||||||
|
|
||||||
|
static enum mgmt_cb_return smp_cmd_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);
|
||||||
|
|
||||||
|
static struct mgmt_callback dfu_status_callback = {
|
||||||
|
.callback = dfu_status_cb,
|
||||||
|
.event_id = MGMT_EVT_OP_IMG_MGMT_DFU_STARTED |
|
||||||
|
MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK |
|
||||||
|
MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK_WRITE_COMPLETE |
|
||||||
|
MGMT_EVT_OP_IMG_MGMT_DFU_PENDING |
|
||||||
|
MGMT_EVT_OP_IMG_MGMT_DFU_STOPPED,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct mgmt_callback smp_cmd_status_callback = {
|
||||||
|
.callback = smp_cmd_status_cb,
|
||||||
|
.event_id = MGMT_EVT_OP_CMD_DONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* DFU watchdog와 mcumgr 콜백 초기화 */
|
||||||
|
void dfu_manager_init(void)
|
||||||
|
{
|
||||||
|
k_work_init_delayable(&dfu_watchdog_work, dfu_watchdog_handler);
|
||||||
|
mgmt_callback_register(&dfu_status_callback);
|
||||||
|
mgmt_callback_register(&smp_cmd_status_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 현재 이미지가 confirm 대기 상태인지 확인 */
|
||||||
|
bool dfu_is_confirm_pending_boot(void)
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||||
|
return !boot_is_img_confirmed();
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 실행 중 이미지 confirm 처리 */
|
||||||
|
void dfu_confirm_running_image(void)
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||||
|
if (!boot_is_img_confirmed())
|
||||||
|
{
|
||||||
|
int err = boot_write_img_confirmed();
|
||||||
|
if (err == 0)
|
||||||
|
{
|
||||||
|
DBG_CORE("[DFU] Running image confirmed\r\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG_ERR("[DFU] Image confirm failed (err %d)\r\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG_CORE("[DFU] Running image already confirmed\r\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MCUboot swap 상태 문자열 변환 */
|
||||||
|
static const char *swap_type_to_str(int swap_type)
|
||||||
|
{
|
||||||
|
switch (swap_type)
|
||||||
|
{
|
||||||
|
case BOOT_SWAP_TYPE_NONE:
|
||||||
|
return "none";
|
||||||
|
case BOOT_SWAP_TYPE_TEST:
|
||||||
|
return "test";
|
||||||
|
case BOOT_SWAP_TYPE_PERM:
|
||||||
|
return "perm";
|
||||||
|
case BOOT_SWAP_TYPE_REVERT:
|
||||||
|
return "revert";
|
||||||
|
case BOOT_SWAP_TYPE_FAIL:
|
||||||
|
return "fail";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MCUboot 이미지 상태 로그 출력 */
|
||||||
|
void dfu_log_mcuboot_state(void)
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||||
|
struct mcuboot_img_header header;
|
||||||
|
uint8_t active_slot = boot_fetch_active_slot();
|
||||||
|
int swap_type = mcuboot_swap_type();
|
||||||
|
int err = boot_read_bank_header(active_slot, &header, sizeof(header));
|
||||||
|
|
||||||
|
DBG_CORE("[DFU] active_slot=%u swap_type=%s(%d) confirmed=%d\r\n",
|
||||||
|
active_slot,
|
||||||
|
swap_type_to_str(swap_type),
|
||||||
|
swap_type,
|
||||||
|
boot_is_img_confirmed());
|
||||||
|
|
||||||
|
if (err == 0)
|
||||||
|
{
|
||||||
|
DBG_CORE("[DFU] image version %u.%u.%u+%u size=0x%x\r\n",
|
||||||
|
header.h.v1.sem_ver.major,
|
||||||
|
header.h.v1.sem_ver.minor,
|
||||||
|
header.h.v1.sem_ver.revision,
|
||||||
|
header.h.v1.sem_ver.build_num,
|
||||||
|
header.h.v1.image_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG_ERR("[DFU] image header read failed (slot %u, err %d)\r\n",
|
||||||
|
active_slot,
|
||||||
|
err);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DFU 업로드 무진행 시 BLE 연결 강제 해제 */
|
||||||
|
static void dfu_watchdog_handler(struct k_work *work)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(work);
|
||||||
|
|
||||||
|
if (ble_is_connected())
|
||||||
|
{
|
||||||
|
DBG_CORE("[DFU] upload stalled (%ds), forcing disconnect\r\n", DFU_STALL_TIMEOUT_SEC);
|
||||||
|
(void)ble_disconnect_active();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DFU 업로드 상태에 따라 LED와 watchdog 제어 */
|
||||||
|
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);
|
||||||
|
ARG_UNUSED(group);
|
||||||
|
ARG_UNUSED(abort_more);
|
||||||
|
ARG_UNUSED(data);
|
||||||
|
ARG_UNUSED(data_size);
|
||||||
|
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case MGMT_EVT_OP_IMG_MGMT_DFU_STARTED:
|
||||||
|
case MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK:
|
||||||
|
case MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK_WRITE_COMPLETE:
|
||||||
|
dfu_led_active = true;
|
||||||
|
led_ble_solid();
|
||||||
|
k_work_reschedule(&dfu_watchdog_work, K_SECONDS(DFU_STALL_TIMEOUT_SEC));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MGMT_EVT_OP_IMG_MGMT_DFU_PENDING:
|
||||||
|
dfu_led_active = true;
|
||||||
|
led_ble_solid();
|
||||||
|
k_work_cancel_delayable(&dfu_watchdog_work);
|
||||||
|
|
||||||
|
#if NRF_POWER_HAS_GPREGRET
|
||||||
|
nrf_power_gpregret_set(NRF_POWER, DFU_RESUME_GPREGRET_REG, DFU_RESUME_MAGIC);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MGMT_EVT_OP_IMG_MGMT_DFU_STOPPED:
|
||||||
|
k_work_cancel_delayable(&dfu_watchdog_work);
|
||||||
|
if (dfu_led_active)
|
||||||
|
{
|
||||||
|
dfu_led_active = false;
|
||||||
|
led_set_state(LED_STATE_ADVERTISING);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MGMT_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DFU 명령 실패 시 LED와 resume 플래그 복구 */
|
||||||
|
static enum mgmt_cb_return smp_cmd_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(event);
|
||||||
|
ARG_UNUSED(prev_status);
|
||||||
|
ARG_UNUSED(rc);
|
||||||
|
ARG_UNUSED(group);
|
||||||
|
ARG_UNUSED(abort_more);
|
||||||
|
|
||||||
|
if (data == NULL || data_size != sizeof(struct mgmt_evt_op_cmd_arg))
|
||||||
|
{
|
||||||
|
return MGMT_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct mgmt_evt_op_cmd_arg *cmd = data;
|
||||||
|
|
||||||
|
if (cmd->group == MGMT_GROUP_ID_IMAGE &&
|
||||||
|
(cmd->id == IMG_MGMT_ID_UPLOAD || cmd->id == IMG_MGMT_ID_STATE) &&
|
||||||
|
cmd->err != MGMT_ERR_EOK)
|
||||||
|
{
|
||||||
|
DBG_ERR("[DFU] command failed id=%u err=%d\r\n", cmd->id, cmd->err);
|
||||||
|
|
||||||
|
dfu_led_active = false;
|
||||||
|
led_set_state(LED_STATE_ADVERTISING);
|
||||||
|
|
||||||
|
#if NRF_POWER_HAS_GPREGRET
|
||||||
|
nrf_power_gpregret_set(NRF_POWER, DFU_RESUME_GPREGRET_REG, 0U);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return MGMT_CB_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* @file dfu_manager.h
|
||||||
|
* @brief DFU state, watchdog, and MCUboot image control
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef DFU_MANAGER_H__
|
||||||
|
#define DFU_MANAGER_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define DFU_RESUME_MAGIC 0xD5U
|
||||||
|
#define DFU_RESUME_GPREGRET_REG 1U
|
||||||
|
|
||||||
|
void dfu_manager_init(void);
|
||||||
|
bool dfu_is_confirm_pending_boot(void);
|
||||||
|
void dfu_confirm_running_image(void);
|
||||||
|
void dfu_log_mcuboot_state(void);
|
||||||
|
|
||||||
|
#endif /* DFU_MANAGER_H__ */
|
||||||
+6
-227
@@ -5,13 +5,12 @@
|
|||||||
|
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <zephyr/sys/printk.h>
|
#include <zephyr/sys/printk.h>
|
||||||
#include <zephyr/dfu/mcuboot.h>
|
|
||||||
#include <zephyr/mgmt/mcumgr/mgmt/callbacks.h>
|
|
||||||
#include <hal/nrf_power.h>
|
#include <hal/nrf_power.h>
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "debug_print.h"
|
#include "debug_print.h"
|
||||||
#include "power_control.h"
|
#include "power_control.h"
|
||||||
|
#include "dfu_manager.h"
|
||||||
#include "led_control.h"
|
#include "led_control.h"
|
||||||
#include "ble_service.h"
|
#include "ble_service.h"
|
||||||
#include "battery_adc.h"
|
#include "battery_adc.h"
|
||||||
@@ -24,11 +23,6 @@ LOG_MODULE_REGISTER(vesiscan, LOG_LEVEL_INF);
|
|||||||
#define BLE_CMD_MAX_LEN 256
|
#define BLE_CMD_MAX_LEN 256
|
||||||
#define BLE_CMD_QUEUE_DEPTH 8 // RX 명령 링버퍼 깊이(버스트 흡수)
|
#define BLE_CMD_QUEUE_DEPTH 8 // RX 명령 링버퍼 깊이(버스트 흡수)
|
||||||
#define BLE_CMD_WORKQ_STACK_SZ 8192
|
#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
|
|
||||||
/*
|
/*
|
||||||
* BLE 명령 처리 스택
|
* BLE 명령 처리 스택
|
||||||
* - piezo sweep
|
* - piezo sweep
|
||||||
@@ -52,45 +46,6 @@ static bool resume_without_power_button; // 리셋 후 버튼 없이 복귀
|
|||||||
static bool dfu_confirm_pending_boot; // DFU test 이미지 확인 전 자동 복귀
|
static bool dfu_confirm_pending_boot; // DFU test 이미지 확인 전 자동 복귀
|
||||||
static bool dfu_reset_resume_request; // DFU 완료 리셋 후 자동 복귀
|
static bool dfu_reset_resume_request; // DFU 완료 리셋 후 자동 복귀
|
||||||
static uint32_t boot_reset_reason; // RESETREAS 원본 값
|
static uint32_t boot_reset_reason; // RESETREAS 원본 값
|
||||||
static bool dfu_led_active; // DFU 업로드 중 초록 LED ON
|
|
||||||
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,
|
|
||||||
int32_t *rc,
|
|
||||||
uint16_t *group,
|
|
||||||
bool *abort_more,
|
|
||||||
void *data,
|
|
||||||
size_t data_size);
|
|
||||||
|
|
||||||
static enum mgmt_cb_return smp_cmd_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);
|
|
||||||
|
|
||||||
static struct mgmt_callback dfu_status_callback = {
|
|
||||||
.callback = dfu_status_cb,
|
|
||||||
.event_id = MGMT_EVT_OP_IMG_MGMT_DFU_STARTED |
|
|
||||||
MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK |
|
|
||||||
MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK_WRITE_COMPLETE |
|
|
||||||
MGMT_EVT_OP_IMG_MGMT_DFU_PENDING |
|
|
||||||
MGMT_EVT_OP_IMG_MGMT_DFU_STOPPED,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct mgmt_callback smp_cmd_status_callback = {
|
|
||||||
.callback = smp_cmd_status_cb,
|
|
||||||
.event_id = MGMT_EVT_OP_CMD_DONE,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BLE RX 콜백 안에서 무거운 일을 바로 처리하지 않기 위해 별도 work queue를 둠
|
|
||||||
* - 연결 직후 초기화 버스트 등 명령이 몰릴 때 대비해 링버퍼(FIFO)로 흡수
|
|
||||||
* - 큐가 가득 차면(BLE_CMD_QUEUE_DEPTH) 그 때만 drop
|
|
||||||
*/
|
|
||||||
static struct k_work_q ble_cmd_work_q;
|
static struct k_work_q ble_cmd_work_q;
|
||||||
K_THREAD_STACK_DEFINE(ble_cmd_workq_stack, BLE_CMD_WORKQ_STACK_SZ);
|
K_THREAD_STACK_DEFINE(ble_cmd_workq_stack, BLE_CMD_WORKQ_STACK_SZ);
|
||||||
static struct k_work ble_cmd_work; // BLE 명령 처리 work
|
static struct k_work ble_cmd_work; // BLE 명령 처리 work
|
||||||
@@ -246,188 +201,11 @@ static void load_default_config(void)
|
|||||||
static void timers_init(void)
|
static void timers_init(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
// DFU 업로드 무진행 감시 work
|
|
||||||
k_work_init_delayable(&dfu_watchdog_work, dfu_watchdog_handler);
|
|
||||||
|
|
||||||
// BLE 명령 처리 work queue
|
// BLE 명령 처리 work queue
|
||||||
k_work_init(&ble_cmd_work, ble_cmd_work_handler);
|
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);
|
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);
|
||||||
|
|
||||||
|
|
||||||
// DFU 업로드 상태를 LED에 반영
|
|
||||||
mgmt_callback_register(&dfu_status_callback);
|
|
||||||
|
|
||||||
// DFU 명령 실패 시 LED 상태 복구
|
|
||||||
mgmt_callback_register(&smp_cmd_status_callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void dfu_watchdog_handler(struct k_work *work)
|
|
||||||
{
|
|
||||||
ARG_UNUSED(work);
|
|
||||||
|
|
||||||
if (ble_is_connected())
|
|
||||||
{
|
|
||||||
DBG_CORE("[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);
|
|
||||||
ARG_UNUSED(group);
|
|
||||||
ARG_UNUSED(abort_more);
|
|
||||||
ARG_UNUSED(data);
|
|
||||||
ARG_UNUSED(data_size);
|
|
||||||
|
|
||||||
switch (event)
|
|
||||||
{
|
|
||||||
case MGMT_EVT_OP_IMG_MGMT_DFU_STARTED:
|
|
||||||
case MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK:
|
|
||||||
case MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK_WRITE_COMPLETE:
|
|
||||||
dfu_led_active = true;
|
|
||||||
led_ble_solid(); // DFU 업로드 중에는 초록 LED ON
|
|
||||||
// 청크 수신/flash write 완료 때마다 무진행 감시 타이머 리셋
|
|
||||||
k_work_reschedule(&dfu_watchdog_work, K_SECONDS(DFU_STALL_TIMEOUT_SEC));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MGMT_EVT_OP_IMG_MGMT_DFU_PENDING:
|
|
||||||
dfu_led_active = true;
|
|
||||||
led_ble_solid(); // 업로드 완료 후 리셋 전까지 초록 LED ON
|
|
||||||
k_work_cancel_delayable(&dfu_watchdog_work); // 업로드 완료: 감시 종료
|
|
||||||
|
|
||||||
#if NRF_POWER_HAS_GPREGRET
|
|
||||||
nrf_power_gpregret_set(NRF_POWER, DFU_RESUME_GPREGRET_REG, DFU_RESUME_MAGIC); // DFU 리셋 후 버튼 없이 전원 ON
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MGMT_EVT_OP_IMG_MGMT_DFU_STOPPED:
|
|
||||||
k_work_cancel_delayable(&dfu_watchdog_work); // 중단/실패: 감시 종료
|
|
||||||
if (dfu_led_active)
|
|
||||||
{
|
|
||||||
dfu_led_active = false;
|
|
||||||
led_set_state(LED_STATE_ADVERTISING); // 실패나 중단 시 일반 광고 LED로 복귀
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MGMT_CB_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum mgmt_cb_return smp_cmd_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(event);
|
|
||||||
ARG_UNUSED(prev_status);
|
|
||||||
ARG_UNUSED(rc);
|
|
||||||
ARG_UNUSED(group);
|
|
||||||
ARG_UNUSED(abort_more);
|
|
||||||
|
|
||||||
if (data == NULL || data_size != sizeof(struct mgmt_evt_op_cmd_arg))
|
|
||||||
{
|
|
||||||
return MGMT_CB_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct mgmt_evt_op_cmd_arg *cmd = data;
|
|
||||||
|
|
||||||
// 이미지 업로드/test 명령 실패 시 DFU LED 고정 해제
|
|
||||||
if (cmd->group == MGMT_GROUP_ID_IMAGE &&
|
|
||||||
(cmd->id == IMG_MGMT_ID_UPLOAD || cmd->id == IMG_MGMT_ID_STATE) &&
|
|
||||||
cmd->err != MGMT_ERR_EOK)
|
|
||||||
{
|
|
||||||
DBG_ERR("[DFU] command failed id=%u err=%d\r\n", cmd->id, cmd->err);
|
|
||||||
|
|
||||||
dfu_led_active = false;
|
|
||||||
led_set_state(LED_STATE_ADVERTISING);
|
|
||||||
|
|
||||||
// 실패 후 리셋 복구 표식이 남지 않게 정리
|
|
||||||
#if NRF_POWER_HAS_GPREGRET
|
|
||||||
nrf_power_gpregret_set(NRF_POWER, DFU_RESUME_GPREGRET_REG, 0U);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return MGMT_CB_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void confirm_running_image(void)
|
|
||||||
{
|
|
||||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
|
||||||
// 기본 초기화와 BLE 준비가 끝난 뒤 MCUboot revert 방지
|
|
||||||
if (!boot_is_img_confirmed())
|
|
||||||
{
|
|
||||||
int err = boot_write_img_confirmed();
|
|
||||||
if (err == 0)
|
|
||||||
{
|
|
||||||
DBG_CORE("[DFU] Running image confirmed\r\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG_ERR("[DFU] Image confirm failed (err %d)\r\n", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG_CORE("[DFU] Running image already confirmed\r\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *swap_type_to_str(int swap_type)
|
|
||||||
{
|
|
||||||
// MCUboot swap 상태 문자열
|
|
||||||
switch (swap_type)
|
|
||||||
{
|
|
||||||
case BOOT_SWAP_TYPE_NONE:
|
|
||||||
return "none";
|
|
||||||
case BOOT_SWAP_TYPE_TEST:
|
|
||||||
return "test";
|
|
||||||
case BOOT_SWAP_TYPE_PERM:
|
|
||||||
return "perm";
|
|
||||||
case BOOT_SWAP_TYPE_REVERT:
|
|
||||||
return "revert";
|
|
||||||
case BOOT_SWAP_TYPE_FAIL:
|
|
||||||
return "fail";
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_mcuboot_state(void)
|
|
||||||
{
|
|
||||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
|
||||||
// 현재 부팅 슬롯/교체 상태
|
|
||||||
struct mcuboot_img_header header;
|
|
||||||
uint8_t active_slot = boot_fetch_active_slot();
|
|
||||||
int swap_type = mcuboot_swap_type();
|
|
||||||
int err = boot_read_bank_header(active_slot, &header, sizeof(header));
|
|
||||||
|
|
||||||
DBG_CORE("[DFU] active_slot=%u swap_type=%s(%d) confirmed=%d\r\n",
|
|
||||||
active_slot,
|
|
||||||
swap_type_to_str(swap_type),
|
|
||||||
swap_type,
|
|
||||||
boot_is_img_confirmed());
|
|
||||||
|
|
||||||
if (err == 0)
|
|
||||||
{
|
|
||||||
/* 실행 이미지 버전 */
|
|
||||||
DBG_CORE("[DFU] image version %u.%u.%u+%u size=0x%x\r\n",
|
|
||||||
header.h.v1.sem_ver.major,
|
|
||||||
header.h.v1.sem_ver.minor,
|
|
||||||
header.h.v1.sem_ver.revision,
|
|
||||||
header.h.v1.sem_ver.build_num,
|
|
||||||
header.h.v1.image_size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG_ERR("[DFU] image header read failed (slot %u, err %d)\r\n",
|
|
||||||
active_slot,
|
|
||||||
err);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 메인 함수 */
|
/* 메인 함수 */
|
||||||
@@ -438,13 +216,13 @@ int main(void)
|
|||||||
|
|
||||||
// 하드웨어 기본 초기화
|
// 하드웨어 기본 초기화
|
||||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||||
dfu_confirm_pending_boot = !boot_is_img_confirmed();
|
dfu_confirm_pending_boot = dfu_is_confirm_pending_boot();
|
||||||
#else
|
#else
|
||||||
dfu_confirm_pending_boot = false;
|
dfu_confirm_pending_boot = false;
|
||||||
#endif
|
#endif
|
||||||
power_control_latch_init(resume_without_power_button || dfu_confirm_pending_boot || dfu_reset_resume_request);
|
power_control_latch_init(resume_without_power_button || dfu_confirm_pending_boot || dfu_reset_resume_request);
|
||||||
power_control_reset_state();
|
power_control_reset_state();
|
||||||
confirm_running_image();
|
dfu_confirm_running_image();
|
||||||
|
|
||||||
DBG_CORE("\r\n========================================\r\n");
|
DBG_CORE("\r\n========================================\r\n");
|
||||||
DBG_CORE(" TEST BUILD %s (Zephyr)\r\n", FIRMWARE_VERSION);
|
DBG_CORE(" TEST BUILD %s (Zephyr)\r\n", FIRMWARE_VERSION);
|
||||||
@@ -455,7 +233,8 @@ int main(void)
|
|||||||
// 기본 하드웨어/센서 초기화
|
// 기본 하드웨어/센서 초기화
|
||||||
power_control_init();
|
power_control_init();
|
||||||
timers_init();
|
timers_init();
|
||||||
log_mcuboot_state();
|
dfu_manager_init();
|
||||||
|
dfu_log_mcuboot_state();
|
||||||
load_default_config();
|
load_default_config();
|
||||||
led_init();
|
led_init();
|
||||||
battery_adc_init();
|
battery_adc_init();
|
||||||
@@ -475,7 +254,7 @@ int main(void)
|
|||||||
power_control_resume_after_reset(boot_reset_reason);
|
power_control_resume_after_reset(boot_reset_reason);
|
||||||
}
|
}
|
||||||
// BLE 준비까지 확인한 뒤 DFU test 이미지를 확정
|
// BLE 준비까지 확인한 뒤 DFU test 이미지를 확정
|
||||||
confirm_running_image();
|
dfu_confirm_running_image();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user