From f25ff3d7507b19e72562d8c3f86b2c5365b5ba15 Mon Sep 17 00:00:00 2001 From: jhchun Date: Fri, 12 Jun 2026 15:28:27 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/drivers/echo_adc/echo_adc.c | 29 ++++++++++--- src/drivers/piezo/piezo.c | 38 +++++++++++++++++ src/main.c | 73 +++++++++++++++++++++++++-------- 3 files changed, 116 insertions(+), 24 deletions(-) diff --git a/src/drivers/echo_adc/echo_adc.c b/src/drivers/echo_adc/echo_adc.c index 4716ce2..2eda53c 100644 --- a/src/drivers/echo_adc/echo_adc.c +++ b/src/drivers/echo_adc/echo_adc.c @@ -18,30 +18,32 @@ #define ECHO_MISO_NODE DT_NODELABEL(echo_miso) #define ECHO_CS_NODE DT_NODELABEL(echo_cs) +/* ADC SPI 핀 */ static const struct gpio_dt_spec echo_sclk = GPIO_DT_SPEC_GET(ECHO_SCLK_NODE, gpios); static const struct gpio_dt_spec echo_miso = GPIO_DT_SPEC_GET(ECHO_MISO_NODE, gpios); static const struct gpio_dt_spec echo_cs = GPIO_DT_SPEC_GET(ECHO_CS_NODE, gpios); -/* - * NRFX_SPIM_INSTANCE() takes the peripheral register symbol (for example - * NRF_SPIM3), not a numeric instance index. Passing 3 makes p_reg invalid - * and causes a fault inside nrfx_spim_init(). - */ +/* SPIM3 레지스터 인스턴스 */ static nrfx_spim_t echo_spim = NRFX_SPIM_INSTANCE(NRF_SPIM3); static bool echo_adc_initialized; + +/* ADC 원본 수신 버퍼 */ static uint8_t raw_capture[ECHO_ADC_MAX_SAMPLES * 2]; +/* GPIO 포트 레지스터 선택 */ static NRF_GPIO_Type *gpio_reg_for_spec(const struct gpio_dt_spec *spec) { return (spec->port == DEVICE_DT_GET(DT_NODELABEL(gpio1))) ? NRF_P1 : NRF_P0; } +/* 포트 포함 절대 핀 번호 */ static uint32_t gpio_abs_pin(const struct gpio_dt_spec *spec) { uint32_t port = (spec->port == DEVICE_DT_GET(DT_NODELABEL(gpio1))) ? 1U : 0U; return NRF_GPIO_PIN_MAP(port, spec->pin); } +/* SPIM RX 전송 */ static int echo_adc_transfer_rx(uint8_t *buf, size_t len) { nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX(buf, len); @@ -56,6 +58,7 @@ static int echo_adc_transfer_rx(uint8_t *buf, size_t len) return 0; } +/* 12비트 샘플 추출 */ static void echo_adc_unpack_samples(uint16_t *samples, uint16_t num_samples) { for (uint16_t i = 0; i < num_samples; i++) @@ -66,6 +69,7 @@ static void echo_adc_unpack_samples(uint16_t *samples, uint16_t num_samples) } } +/* 무응답 샘플 확인 */ static bool echo_adc_samples_all_zero(const uint16_t *samples, uint16_t num_samples) { for (uint16_t i = 0; i < num_samples; i++) @@ -79,6 +83,7 @@ static bool echo_adc_samples_all_zero(const uint16_t *samples, uint16_t num_samp return true; } +/* 안정 우선 캡처 */ static int echo_adc_capture_slow(uint16_t *samples, uint16_t num_samples) { for (uint16_t i = 0; i < num_samples; i++) @@ -94,28 +99,33 @@ static int echo_adc_capture_slow(uint16_t *samples, uint16_t num_samples) return 0; } +/* 속도 우선 캡처 */ static int echo_adc_capture_fast(uint16_t *samples, uint16_t num_samples) { NRF_SPIM_Type *spim = echo_spim.p_reg; NRF_GPIO_Type *cs_port = gpio_reg_for_spec(&echo_cs); uint32_t cs_mask = BIT(echo_cs.pin); + /* SPIM 직접 제어 */ nrf_spim_enable(spim); spim->RXD.MAXCNT = 2U; for (uint16_t i = 0; i < num_samples; i++) { + /* CS 하강 후 2바이트 수신 */ cs_port->OUTCLR = cs_mask; spim->RXD.PTR = (uint32_t)&raw_capture[i * 2U]; spim->EVENTS_END = 0; spim->TASKS_START = 1; + /* 전송 완료 대기 */ uint32_t timeout = 10000U; while (!spim->EVENTS_END && (timeout > 0U)) { timeout--; } + /* CS 복귀 */ cs_port->OUTSET = cs_mask; if (timeout == 0U) @@ -131,12 +141,14 @@ static int echo_adc_capture_fast(uint16_t *samples, uint16_t num_samples) int echo_adc_init(void) { + /* 중복 초기화 방지 */ if (echo_adc_initialized || nrfx_spim_init_check(&echo_spim)) { echo_adc_initialized = true; return 0; } + /* GPIO 준비 확인 */ const struct gpio_dt_spec *pins[] = { &echo_sclk, &echo_miso, &echo_cs }; for (size_t i = 0; i < ARRAY_SIZE(pins); i++) @@ -148,6 +160,7 @@ int echo_adc_init(void) } } + /* ADC SPI 설정 */ nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG( gpio_abs_pin(&echo_sclk), NRF_SPIM_PIN_NOT_CONNECTED, @@ -162,7 +175,7 @@ int echo_adc_init(void) config.ss_active_high = false; nrfx_err_t err = nrfx_spim_init(&echo_spim, &config, NULL, NULL); - if (err != NRFX_SUCCESS) + if (err != 0) { DBG_PRINTF("[ECHO] init fail err=%d\r\n", err); return -EIO; @@ -175,6 +188,7 @@ int echo_adc_init(void) int echo_adc_wake(void) { + /* 더미 읽기 웨이크업 */ int err = echo_adc_init(); if (err) { @@ -187,6 +201,7 @@ int echo_adc_wake(void) int echo_adc_capture(uint16_t *samples, uint16_t num_samples) { + /* 입력값 검사 */ if (samples == NULL) { return -EINVAL; @@ -203,12 +218,14 @@ int echo_adc_capture(uint16_t *samples, uint16_t num_samples) return err; } + /* 빠른 캡처 우선 */ err = echo_adc_capture_fast(samples, num_samples); if ((err == 0) && !echo_adc_samples_all_zero(samples, num_samples)) { return 0; } + /* 실패 시 안정 캡처 */ DBG_PRINTF("[ECHO] fast capture fallback err=%d\r\n", err); return echo_adc_capture_slow(samples, num_samples); } diff --git a/src/drivers/piezo/piezo.c b/src/drivers/piezo/piezo.c index eb9504b..6aec34c 100644 --- a/src/drivers/piezo/piezo.c +++ b/src/drivers/piezo/piezo.c @@ -23,16 +23,20 @@ #define MUX_SEL0_NODE DT_NODELABEL(mux_sel0) #define MUX_SEL1_NODE DT_NODELABEL(mux_sel1) +/* 피에조 전원/구동 GPIO */ static const struct gpio_dt_spec piezo_pwr = GPIO_DT_SPEC_GET(PIEZO_PWR_NODE, gpios); static const struct gpio_dt_spec piezo_pe = GPIO_DT_SPEC_GET(PIEZO_PE_NODE, gpios); static const struct gpio_dt_spec piezo_p_out = GPIO_DT_SPEC_GET(PIEZO_P_OUT_NODE, gpios); static const struct gpio_dt_spec piezo_n_out = GPIO_DT_SPEC_GET(PIEZO_N_OUT_NODE, gpios); static const struct gpio_dt_spec piezo_dmp = GPIO_DT_SPEC_GET(PIEZO_DMP_NODE, gpios); + +/* 채널 선택 MUX GPIO */ static const struct gpio_dt_spec mux_en_a = GPIO_DT_SPEC_GET(MUX_EN_A_NODE, gpios); static const struct gpio_dt_spec mux_en_b = GPIO_DT_SPEC_GET(MUX_EN_B_NODE, gpios); static const struct gpio_dt_spec mux_sel0 = GPIO_DT_SPEC_GET(MUX_SEL0_NODE, gpios); static const struct gpio_dt_spec mux_sel1 = GPIO_DT_SPEC_GET(MUX_SEL1_NODE, gpios); +/* MUX 제어 상태 */ struct mux_state { uint8_t en_a; uint8_t en_b; @@ -40,6 +44,7 @@ struct mux_state { uint8_t sel1; }; +/* 채널별 MUX EN/SEL 조합 */ static const struct mux_state mux_map[PIEZO_NUM_CHANNELS] = { {1, 0, 0, 0}, {1, 0, 1, 0}, @@ -50,26 +55,33 @@ static const struct mux_state mux_map[PIEZO_NUM_CHANNELS] = { }; static bool piezo_initialized; + +/* 빠른 GPIO 제어용 절대 핀 */ static uint32_t piezo_pe_abs; static uint32_t piezo_p_out_abs; static uint32_t piezo_n_out_abs; static uint32_t piezo_dmp_abs; + +/* 포트 OUT 직접 갱신용 비트 마스크 */ static uint32_t piezo_pe_mask; static uint32_t piezo_p_out_mask; static uint32_t piezo_n_out_mask; static uint32_t piezo_dmp_mask; +/* 포트 포함 절대 핀 번호 */ static uint32_t gpio_abs_pin(const struct gpio_dt_spec *spec) { uint32_t port = (spec->port == DEVICE_DT_GET(DT_NODELABEL(gpio1))) ? 1U : 0U; return NRF_GPIO_PIN_MAP(port, spec->pin); } +/* 버스트 타이밍용 1사이클 지연 */ static inline void burst_nop(void) { __asm__ volatile("nop"); } +/* 짧은 반주기 보정 지연 */ static inline void nop_delay_9(void) { burst_nop(); burst_nop(); burst_nop(); @@ -77,6 +89,7 @@ static inline void nop_delay_9(void) burst_nop(); burst_nop(); burst_nop(); } +/* 긴 반주기 보정 지연 */ static inline void nop_delay_14(void) { burst_nop(); burst_nop(); burst_nop(); burst_nop(); @@ -85,6 +98,7 @@ static inline void nop_delay_14(void) burst_nop(); burst_nop(); } +/* 댐핑 펄스 폭 지연 */ static inline void nop_delay_32(void) { for (int i = 0; i < 32; i++) @@ -93,6 +107,7 @@ static inline void nop_delay_32(void) } } +/* 출력/MUX 안전 대기 상태 */ static void piezo_drive_idle(void) { nrf_gpio_pin_clear(piezo_pe_abs); @@ -108,11 +123,13 @@ static void piezo_drive_idle(void) int piezo_init(void) { + /* 중복 초기화 방지 */ if (piezo_initialized) { return 0; } + /* 모든 제어 핀 목록 */ const struct gpio_dt_spec *pins[] = { &piezo_pwr, &piezo_pe, &piezo_p_out, &piezo_n_out, @@ -121,12 +138,14 @@ int piezo_init(void) for (size_t i = 0; i < ARRAY_SIZE(pins); i++) { + /* GPIO 포트 준비 확인 */ if (!device_is_ready(pins[i]->port)) { DBG_PRINTF("[PIEZO] GPIO device not ready (%d)\r\n", (int)i); return -ENODEV; } + /* 초기 출력 Low */ int err = gpio_pin_configure_dt(pins[i], GPIO_OUTPUT_INACTIVE); if (err) { @@ -135,6 +154,7 @@ int piezo_init(void) } } + /* 직접 제어용 핀/마스크 캐시 */ piezo_pe_abs = gpio_abs_pin(&piezo_pe); piezo_p_out_abs = gpio_abs_pin(&piezo_p_out); piezo_n_out_abs = gpio_abs_pin(&piezo_n_out); @@ -152,27 +172,32 @@ int piezo_init(void) void piezo_power_on(void) { + /* 필요 시 자동 초기화 */ if (!piezo_initialized && piezo_init() != 0) { return; } + /* 피에조 전원 인가 */ gpio_pin_set_dt(&piezo_pwr, 1); } void piezo_power_off(void) { + /* 필요 시 자동 초기화 */ if (!piezo_initialized && piezo_init() != 0) { return; } + /* 출력 정지 후 전원 차단 */ piezo_drive_idle(); gpio_pin_set_dt(&piezo_pwr, 0); } int piezo_select_channel(uint8_t channel) { + /* 필요 시 자동 초기화 */ if (!piezo_initialized) { int err = piezo_init(); @@ -182,28 +207,35 @@ int piezo_select_channel(uint8_t channel) } } + /* 채널 범위 검사 */ if (channel >= PIEZO_NUM_CHANNELS) { return -EINVAL; } + /* MUX 채널 선택 */ gpio_pin_set_dt(&mux_en_a, mux_map[channel].en_a); gpio_pin_set_dt(&mux_en_b, mux_map[channel].en_b); gpio_pin_set_dt(&mux_sel0, mux_map[channel].sel0); gpio_pin_set_dt(&mux_sel1, mux_map[channel].sel1); + /* MUX 안정화 대기 */ k_busy_wait(PIEZO_MUX_SETTLE_US); return 0; } void piezo_burst_sw(uint8_t cycles) { + /* 초기화/횟수 검사 */ if (!piezo_initialized || cycles == 0U) { return; } + /* 타이밍 흔들림 방지 */ unsigned int key = irq_lock(); + + /* P1 비제어 핀 상태 보존 */ uint32_t saved_p1_out = NRF_P1->OUT; uint32_t p1_ctrl_mask = piezo_p_out_mask | piezo_n_out_mask | piezo_dmp_mask; uint32_t p1_all_low = saved_p1_out & ~p1_ctrl_mask; @@ -211,21 +243,27 @@ void piezo_burst_sw(uint8_t cycles) uint32_t p1_p_low_n_high = p1_all_low | piezo_n_out_mask; uint32_t p1_dmp_high = p1_all_low | piezo_dmp_mask; + /* 구동 Enable 전 초기 Low 정렬 */ NRF_P0->OUTCLR = piezo_pe_mask; NRF_P1->OUT = p1_all_low; NRF_P0->OUTSET = piezo_pe_mask; for (uint8_t i = 0; i < cycles; i++) { + /* P High / N Low */ NRF_P1->OUT = p1_p_high_n_low; nop_delay_14(); + /* P Low / N High */ NRF_P1->OUT = p1_p_low_n_high; nop_delay_9(); } + /* 잔류 전하 방전 */ NRF_P1->OUT = p1_dmp_high; nop_delay_32(); + + /* 출력 Low 복귀 */ NRF_P1->OUT = p1_all_low; NRF_P0->OUTCLR = piezo_pe_mask; irq_unlock(key); diff --git a/src/main.c b/src/main.c index a051ea3..6b5f9c2 100644 --- a/src/main.c +++ b/src/main.c @@ -33,18 +33,21 @@ LOG_MODULE_REGISTER(vesiscan, LOG_LEVEL_INF); #define BLE_CMD_MAX_LEN 256 #define BLE_CMD_WORKQ_STACK_SZ 8192 /* - * mbb?는 piezo sweep, ADC capture, BLE 응답 패킷 조립까지 한 스레드에서 처리한다. - * 초기 4096 바이트로는 "어떤 날은 되고 어떤 날은 리셋되는" 경계 상태가 날 수 있어서 - * 디버깅 중에는 여유 있게 8192 바이트로 올려 둔다. + * BLE 명령 처리 스택 + * - piezo sweep + * - ADC capture + * - BLE 응답 패킷 조립 + * - 디버깅 여유분 포함 */ #define BLE_CMD_WORKQ_PRIORITY 10 /*============================================================================== - * Devicetree GPOP Settings + * Devicetree GPIO Settings *============================================================================*/ -#define POWER_HOLD_NODE DT_NODELABEL(pwr_hold) // 전원 래치 -#define POWER_BTN_NODE DT_NODELABEL(button_check) // 전원 버튼 +#define POWER_HOLD_NODE DT_NODELABEL(pwr_hold) /* 전원 래치 */ +#define POWER_BTN_NODE DT_NODELABEL(button_check) /* 전원 버튼 */ +/* 전원 제어 GPIO */ static const struct gpio_dt_spec power_hold = GPIO_DT_SPEC_GET(POWER_HOLD_NODE, gpios); static const struct gpio_dt_spec power_btn = GPIO_DT_SPEC_GET(POWER_BTN_NODE, gpios); @@ -81,10 +84,10 @@ static bool power_btn_suspended; /* 측정 중 전원 버튼 상태 * k_work를 사용하면 시스템 워크큐 스레드에서 실행되므로 안전하게 BLE API 호출 가능. * main_s() 타이머 콜백에서 k_work_submit()으로 예약하여 사용한다. */ -static bool resume_without_power_button; -static uint32_t boot_reset_reason; -static struct k_work adv_start_work; -static struct k_work adv_stop_work; +static bool resume_without_power_button; /* 리셋 후 버튼 없이 복귀 */ +static uint32_t boot_reset_reason; /* RESETREAS 원본 값 */ +static struct k_work adv_start_work; /* advertising 시작 work */ +static struct k_work adv_stop_work; /* advertising 중지 work */ /* * BLE RX 콜백 안에서 무거운 일을 바로 처리하지 않기 위해 별도 work queue를 둔다. @@ -100,20 +103,21 @@ static struct k_work adv_stop_work; */ static struct k_work_q ble_cmd_work_q; K_THREAD_STACK_DEFINE(ble_cmd_workq_stack, BLE_CMD_WORKQ_STACK_SZ); -static struct k_work ble_cmd_work; -static struct k_spinlock ble_cmd_lock; -static uint8_t ble_cmd_buf[BLE_CMD_MAX_LEN]; -static uint16_t ble_cmd_len; -static bool ble_cmd_pending; +static struct k_work ble_cmd_work; /* BLE 명령 처리 work */ +static struct k_spinlock ble_cmd_lock; /* RX 공유 버퍼 보호 */ +static uint8_t ble_cmd_buf[BLE_CMD_MAX_LEN];/* RX 명령 복사 버퍼 */ +static uint16_t ble_cmd_len; /* RX 명령 길이 */ +static bool ble_cmd_pending; /* 처리 대기 명령 있음 */ static void ble_cmd_work_handler(struct k_work *work) { ARG_UNUSED(work); - /* work queue 스레드에서 쓸 로컬 복사본. 원본 공유 버퍼를 오래 잡고 있지 않기 위해 만든다. */ + /* work queue 로컬 복사본 */ uint8_t local_buf[BLE_CMD_MAX_LEN]; uint16_t local_len = 0U; + /* 공유 RX 버퍼 짧게 잠금 */ k_spinlock_key_t key = k_spin_lock(&ble_cmd_lock); if (ble_cmd_pending) { @@ -128,10 +132,11 @@ static void ble_cmd_work_handler(struct k_work *work) return; } - /* 여기서부터는 BLE 콜백 문맥이 아니라 일반 스레드 문맥이라 긴 작업을 해도 된다. */ + /* 일반 스레드 문맥 명령 처리 */ DBG_CORE("[BLE RX] worker dispatch len=%u\r\n", local_len); dr_parser(local_buf, local_len); + /* 명령 처리 완료 표시 */ key = k_spin_lock(&ble_cmd_lock); ble_cmd_pending = false; ble_cmd_len = 0U; @@ -157,6 +162,7 @@ static void adv_stop_work_handler(struct k_work *work) *============================================================================*/ static void ble_rx_handler(const uint8_t *data, uint16_t len) { + /* RX 데이터 앞부분 로그 */ DBG_CORE("[BLE RX] %u bytes:", len); for (uint16_t i = 0; i < len && i < 32; i++) { @@ -186,15 +192,18 @@ static void ble_rx_handler(const uint8_t *data, uint16_t len) return; } + /* 명령 버퍼 복사 */ memcpy(ble_cmd_buf, data, len); ble_cmd_len = len; ble_cmd_pending = true; k_spin_unlock(&ble_cmd_lock, key); + /* 명령 처리 work 예약 */ DBG_CORE("[BLE RX] queued len=%u\r\n", len); int err = k_work_submit_to_queue(&ble_cmd_work_q, &ble_cmd_work); if (err < 0) { + /* 예약 실패 시 pending 복구 */ key = k_spin_lock(&ble_cmd_lock); ble_cmd_pending = false; ble_cmd_len = 0U; @@ -212,7 +221,10 @@ static void ble_rx_handler(const uint8_t *data, uint16_t len) * 2초 후 main_s()에서 래치(HIGH) 설정 */ static void boot_context_detect(void) { + /* 부팅 원인 확인 */ boot_reset_reason = nrf_power_resetreas_get(NRF_POWER); + + /* 소프트 리셋 계열 자동 복귀 */ resume_without_power_button = (boot_reset_reason & (NRF_POWER_RESETREAS_SREQ_MASK | NRF_POWER_RESETREAS_DOG_MASK | @@ -221,6 +233,7 @@ static void boot_context_detect(void) if (boot_reset_reason != 0U) { + /* RESETREAS 플래그 정리 */ nrf_power_resetreas_clear(NRF_POWER, boot_reset_reason); } } @@ -228,11 +241,13 @@ static void boot_context_detect(void) static void power_hold_init(void) { #if defined(CONFIG_BOOTLOADER_MCUBOOT) + /* DFU 이미지 확인 전 전원 유지 */ bool dfu_confirm_pending = !boot_is_img_confirmed(); #else bool dfu_confirm_pending = false; #endif + /* 리셋 복귀/DFU 확인 대기 시 즉시 래치 */ gpio_pin_configure_dt(&power_hold, (resume_without_power_button || dfu_confirm_pending) ? GPIO_OUTPUT_ACTIVE : GPIO_OUTPUT_INACTIVE); @@ -267,6 +282,7 @@ static void gpio_init(void) *============================================================================*/ static void load_default_config(void) { + /* 기본 문자열 길이 제한 */ size_t serial_len = strlen(SERIAL_NUMBER); size_t hw_len = strlen(HARDWARE_VERSION); size_t passkey_len = strlen(DEFAULT_PASSKEY); @@ -287,12 +303,15 @@ static void load_default_config(void) memset(SERIAL_NO, 0, sizeof(SERIAL_NO)); memcpy(SERIAL_NO, SERIAL_NUMBER, serial_len); + /* 기본 HW 버전 복사 */ memset(HW_NO, 0, sizeof(HW_NO)); memcpy(HW_NO, HARDWARE_VERSION, hw_len); + /* 기본 BLE 패스키 복사 */ memset(m_static_passkey, 0, sizeof(m_static_passkey)); memcpy(m_static_passkey, DEFAULT_PASSKEY, passkey_len); + /* 기본 상태값 */ m_reset_status = 1; bond_data_delete = true; @@ -433,12 +452,19 @@ static void main_s(struct k_timer *timer) *============================================================================*/ static void timers_init(void) { + /* 전원 상태머신 타이머 */ k_timer_init(&m_power_on_delay_timer, main_s, NULL); k_timer_init(&m_power_off_delay_timer, t_power_off_timeout_handler, NULL); + + /* BLE advertising work */ k_work_init(&adv_start_work, adv_start_work_handler); k_work_init(&adv_stop_work, adv_stop_work_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); + + /* 전원 제어 타이머 */ power_timer_init(); } @@ -450,16 +476,19 @@ static void timers_start(void) static void resume_device_after_soft_reset(void) { + /* 일반 버튼 부팅이면 skip */ if (!resume_without_power_button) { return; } + /* 전원 래치 상태 복구 */ device_on = true; cnt_s = 0; boot_btn_released = (gpio_pin_get_dt(&power_btn) != 1); m_reset_status = 1; + /* 정상 ON 상태 서비스 재시작 */ power_control_handler(ON); led_set_state(LED_STATE_ADVERTISING); battery_timer_start(); @@ -471,6 +500,7 @@ static void resume_device_after_soft_reset(void) static void confirm_running_image(void) { #if defined(CONFIG_BOOTLOADER_MCUBOOT) + /* MCUboot revert 방지 */ if (!boot_is_img_confirmed()) { int err = boot_write_img_confirmed(); @@ -492,6 +522,7 @@ static void confirm_running_image(void) static const char *swap_type_to_str(int swap_type) { + /* MCUboot swap 상태 문자열 */ switch (swap_type) { case BOOT_SWAP_TYPE_NONE: @@ -512,6 +543,7 @@ static const char *swap_type_to_str(int swap_type) 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(); @@ -525,6 +557,7 @@ static void log_mcuboot_state(void) 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, @@ -546,22 +579,25 @@ static void log_mcuboot_state(void) *============================================================================*/ int main(void) { + /* 리셋/복귀 컨텍스트 */ boot_context_detect(); /*── Phase 1: 하드웨어 기본 초기화 ──*/ power_hold_init(); cnt_s = 0; + /* 버튼 부팅 기본 상태 */ device_on = false; boot_btn_released = false; confirm_running_image(); DBG_CORE("\r\n========================================\r\n"); DBG_CORE(" TEST BUILD %s (Zephyr)\r\n", FIRMWARE_VERSION); - DBG_CORE(" BUILD TAG: TEST-ADV-UNIT-000\r\n"); + DBG_CORE(" BUILD TAG: TEST-ADV-UNIT-001\r\n"); DBG_CORE("========================================\r\n"); DBG_CORE("[1] HW Init\r\n"); + /* 기본 하드웨어/센서 초기화 */ gpio_init(); timers_init(); log_mcuboot_state(); @@ -579,6 +615,7 @@ int main(void) if (ble_service_init(ble_rx_handler) == 0) { DBG_CORE(" ble/nus OK\r\n"); + /* 소프트 리셋 후 서비스 복구 */ resume_device_after_soft_reset(); } else