전원 모듈 분리
This commit is contained in:
+14
-319
@@ -4,16 +4,10 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/sys/reboot.h>
|
||||
#include <zephyr/dfu/mcuboot.h>
|
||||
#include <zephyr/mgmt/mcumgr/mgmt/callbacks.h>
|
||||
#include <hal/nrf_power.h>
|
||||
#if IS_ENABLED(CONFIG_BT_SMP)
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
#include "debug_print.h"
|
||||
@@ -44,23 +38,6 @@ LOG_MODULE_REGISTER(vesiscan, LOG_LEVEL_INF);
|
||||
*/
|
||||
#define BLE_CMD_WORKQ_PRIORITY 10
|
||||
|
||||
/* Devicetree GPIO Settings */
|
||||
#define POWER_HOLD_NODE DT_NODELABEL(pwr_hold) // 전원 래치
|
||||
#define POWER_BTN_NODE DT_NODELABEL(button_check) // 전원 버튼
|
||||
|
||||
/* 전원 버튼 상태머신 (5ms 폴링) */
|
||||
#define BOOT_THRESHOLD 350 // 5ms x 400 = 2초 -> 초기화 시간 고려 체감상 2초에 맞춤
|
||||
#define BOND_RESET_THRESHOLD (15000 / POWER_ON_DELAY) // 전원 ON 상태에서 15초 롱프레스 → 본드 삭제
|
||||
|
||||
/* 전원 제어 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);
|
||||
|
||||
/* Timer */
|
||||
static struct k_timer m_power_on_delay_timer; // 전원 버튼 폴링용 (5ms 싱글샷)
|
||||
static struct k_timer m_power_off_delay_timer; // 전원 OFF 지연용 (3초 후 전원 차단)
|
||||
|
||||
/* 전역 변수 */
|
||||
volatile bool ble_connection_st = false; // BLE 연결 상태
|
||||
volatile bool processing = false; // 센서 데이터 처리 중 플래그
|
||||
bool bond_data_delete = true; // 본딩 데이터 삭제 요청
|
||||
@@ -71,25 +48,11 @@ char HW_NO[HW_NO_BUF_SIZE]; // 하드웨어 번호
|
||||
char m_static_passkey[PASSKEY_BUF_SIZE]; // BLE 정적 패스키
|
||||
uint8_t m_passkey_changed; // 패스키 변경은 출고 후 1회만 허용
|
||||
|
||||
static uint16_t cnt_s; // 전원 버튼 폴링 카운터 (5ms 단위)
|
||||
static bool device_on = false; // 디바이스 전원 상태 (래치 완료 여부)
|
||||
static bool boot_btn_released = false; // 부팅 후 버튼 놓았는지 여부
|
||||
static bool power_btn_suspended; // 측정 중 전원 버튼 상태머신 일시 정지
|
||||
|
||||
/*
|
||||
* BLE advertising 제어용 워크 아이템
|
||||
* - main_s()에서 k_work_submit()으로 예약하여 사용
|
||||
*/
|
||||
static bool resume_without_power_button; // 리셋 후 버튼 없이 복귀
|
||||
static bool dfu_confirm_pending_boot; // DFU test 이미지 확인 전 자동 복귀
|
||||
static bool dfu_reset_resume_request; // DFU 완료 리셋 후 자동 복귀
|
||||
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
|
||||
static struct k_work bond_reset_work; // 전원 버튼 15초 롱프레스 본드 삭제 work
|
||||
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);
|
||||
|
||||
@@ -175,50 +138,6 @@ static void ble_cmd_work_handler(struct k_work *work)
|
||||
}
|
||||
}
|
||||
|
||||
/* 시스템 워크큐에서 BLE advertising 시작 */
|
||||
static void adv_start_work_handler(struct k_work *work)
|
||||
{
|
||||
ARG_UNUSED(work);
|
||||
ble_advertising_start();
|
||||
}
|
||||
|
||||
/* 시스템 워크큐에서 BLE advertising 중지 */
|
||||
static void adv_stop_work_handler(struct k_work *work)
|
||||
{
|
||||
ARG_UNUSED(work);
|
||||
ble_advertising_stop();
|
||||
}
|
||||
|
||||
/* 전원 버튼 15초 롱프레스: BLE 본드 삭제 후 리부트 */
|
||||
static void bond_reset_work_handler(struct k_work *work)
|
||||
{
|
||||
ARG_UNUSED(work);
|
||||
|
||||
DBG_ERR("[BTN] 15s long press -> BLE bond reset\r\n");
|
||||
battery_timer_stop();
|
||||
ble_advertising_stop();
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_SMP)
|
||||
int err = bt_unpair(BT_ID_DEFAULT, NULL);
|
||||
if (err)
|
||||
{
|
||||
DBG_ERR("[BTN] bt_unpair failed err=%d\r\n", err);
|
||||
}
|
||||
else
|
||||
{
|
||||
bond_data_delete = true;
|
||||
DBG_PRINTF("[BTN] BLE bond data deleted\r\n");
|
||||
}
|
||||
#else
|
||||
bond_data_delete = true;
|
||||
DBG_PRINTF("[BTN] BLE bond delete skipped (BT_SMP disabled)\r\n");
|
||||
#endif
|
||||
|
||||
led_set_state(LED_STATE_BOND_DELETE); // 삭제 완료 확인 주황 LED ON
|
||||
k_msleep(1500);
|
||||
sys_reboot(SYS_REBOOT_COLD);
|
||||
}
|
||||
|
||||
/* BLE RX 콜백 */
|
||||
static void ble_rx_handler(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
@@ -280,52 +199,6 @@ static void boot_context_detect(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void power_hold_init(void)
|
||||
{
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||
// DFU 이미지 확인 전 전원 유지
|
||||
dfu_confirm_pending_boot = !boot_is_img_confirmed();
|
||||
#else
|
||||
dfu_confirm_pending_boot = false;
|
||||
#endif
|
||||
|
||||
// 리셋 복귀/DFU 확인 대기 시 즉시 래치
|
||||
gpio_pin_configure_dt(&power_hold, (resume_without_power_button || dfu_confirm_pending_boot || dfu_reset_resume_request) ? GPIO_OUTPUT_ACTIVE : GPIO_OUTPUT_INACTIVE);
|
||||
}
|
||||
|
||||
/* 전원 ON/OFF 제어 - P0.08 핀으로 물리적 전원 래치/해제 */
|
||||
static void power_control_handler(on_off_cont_t device_power_st, const char *reason)
|
||||
{
|
||||
if (device_power_st == OFF)
|
||||
{
|
||||
/*
|
||||
DBG_ERR("[PWR] OFF latch release reason=%s pending=%s device_on=%u btn=%d cnt=%u suspended=%u dfu_adv=%u dfu_confirm=%u dfu_resume=%u\r\n",
|
||||
reason ? reason : "unknown",
|
||||
power_off_pending_reason,
|
||||
device_on ? 1U : 0U,
|
||||
gpio_pin_get_dt(&power_btn),
|
||||
cnt_s,
|
||||
power_btn_suspended ? 1U : 0U,
|
||||
ble_dfu_advertising_is_enabled() ? 1U : 0U,
|
||||
dfu_confirm_pending_boot ? 1U : 0U,
|
||||
dfu_reset_resume_request ? 1U : 0U);*/
|
||||
gpio_pin_set_dt(&power_hold, 0); // P0.08 LOW → 전원 래치 해제 → 전원 차단
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_pin_set_dt(&power_hold, 1); // P0.08 HIGH → 전원 유지
|
||||
}
|
||||
}
|
||||
|
||||
/* GPIO 초기화 */
|
||||
static void gpio_init(void)
|
||||
{
|
||||
gpio_pin_configure_dt(&power_btn, GPIO_INPUT); // 전원 버튼(P1.08) 입력 설정
|
||||
DBG_PRINTF("[INIT] HW - GPIO OK (POWER BTN=%d)\r\n", gpio_pin_get_dt(&power_btn));
|
||||
|
||||
}
|
||||
|
||||
/* 기본 설정값 로드 */
|
||||
static void load_default_config(void)
|
||||
{
|
||||
// 기본 문자열 길이 제한
|
||||
@@ -369,160 +242,9 @@ static void load_default_config(void)
|
||||
DBG_CORE("[INIT] Default (S/N=%s)\r\n", SERIAL_NO);
|
||||
}
|
||||
|
||||
/* 전원 OFF 타임아웃 콜백 */
|
||||
static void t_power_off_timeout_handler(struct k_timer *timer)
|
||||
{
|
||||
ARG_UNUSED(timer);
|
||||
DBG_ERR("[PWR] OFF timeout reason=%s\r\n", power_off_pending_reason);
|
||||
led_set_state(LED_STATE_OFF);
|
||||
power_control_handler(OFF, "off-timeout");
|
||||
}
|
||||
|
||||
/* 슬립 모드 / 전원 OFF: LED 표시 후 3초 뒤 전원 차단 */
|
||||
static void power_off_schedule(const char *reason, led_state_t led_state)
|
||||
{
|
||||
power_off_pending_reason = reason ? reason : "unknown";
|
||||
//DBG_ERR("[PWR] OFF scheduled reason = %s\r\n", power_off_pending_reason);
|
||||
led_set_state(led_state);
|
||||
k_timer_start(&m_power_off_delay_timer, K_MSEC(POWER_OFF_DELAY), K_NO_WAIT);
|
||||
}
|
||||
|
||||
void sleep_mode_enter_reason(const char *reason)
|
||||
{
|
||||
power_off_schedule(reason, LED_STATE_POWER_ON);
|
||||
}
|
||||
|
||||
void sleep_mode_enter(void)
|
||||
{
|
||||
sleep_mode_enter_reason("sleep_mode_enter");
|
||||
}
|
||||
|
||||
void device_power_off(void)
|
||||
{
|
||||
device_power_off_reason("device_power_off");
|
||||
}
|
||||
|
||||
void device_power_off_reason(const char *reason)
|
||||
{
|
||||
power_off_schedule(reason, LED_STATE_POWER_OFF);
|
||||
}
|
||||
|
||||
void device_power_keep_on(void)
|
||||
{
|
||||
k_timer_stop(&m_power_off_delay_timer);
|
||||
device_on = true;
|
||||
boot_btn_released = (gpio_pin_get_dt(&power_btn) != 1);
|
||||
cnt_s = 0;
|
||||
power_control_handler(ON, "keep-on");
|
||||
}
|
||||
|
||||
void power_button_suspend(bool suspend)
|
||||
{
|
||||
// 측정 시간이 긴 커맨드 처리 중에만 버튼 폴링 판단 잠시 멈춤
|
||||
power_btn_suspended = suspend;
|
||||
cnt_s = 0;
|
||||
}
|
||||
|
||||
static void main_s(struct k_timer *timer)
|
||||
{
|
||||
ARG_UNUSED(timer);
|
||||
|
||||
bool button_pressed = (gpio_pin_get_dt(&power_btn) == 1);
|
||||
|
||||
if (power_btn_suspended)
|
||||
{
|
||||
k_timer_start(&m_power_on_delay_timer, K_MSEC(POWER_ON_DELAY), K_NO_WAIT);
|
||||
return;
|
||||
}
|
||||
|
||||
// 부팅 시퀀스 (OFF → ON)
|
||||
if (!device_on)
|
||||
{
|
||||
if (!button_pressed) // 버튼 놓음 → 2초 미만이면 전원 OFF
|
||||
{
|
||||
//DBG_PRINTF("[BTN] Short press (%d) -> OFF\r\n", cnt_s);
|
||||
power_control_handler(OFF, "boot-button-released-before-latch");
|
||||
cnt_s = 0;
|
||||
}
|
||||
else // 버튼 계속 누르고 있음
|
||||
{
|
||||
cnt_s++;
|
||||
|
||||
if (cnt_s == BOOT_THRESHOLD) // 2초 도달: 래치 + 부팅 완료
|
||||
{
|
||||
device_on = true;
|
||||
// cnt_s는 리셋하지 않음: 부팅 누름을 놓기 전(!boot_btn_released)까지 15초 본드 삭제 카운트를 연속 유지(놓는 순간 아래 분기에서 0으로 리셋)
|
||||
power_control_handler(ON, "button-2s-latch");
|
||||
led_set_state(LED_STATE_ADVERTISING);
|
||||
k_work_submit(&adv_start_work);
|
||||
battery_timer_start();
|
||||
m_reset_status = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 전원 OFF 시퀀스 (ON → OFF) */
|
||||
else
|
||||
{
|
||||
if (!boot_btn_released) // 부팅 때 누른 버튼을 아직 안 놓음
|
||||
{
|
||||
if (!button_pressed) // 놓음 → 이후부터 새 누름을 전원 OFF로 인식
|
||||
{
|
||||
boot_btn_released = true;
|
||||
cnt_s = 0;
|
||||
}
|
||||
else // 전원 ON부터 계속 유지 중 → 15초 넘으면 본드 삭제 + 리부트
|
||||
{
|
||||
cnt_s++;
|
||||
|
||||
if ((cnt_s >= BOND_RESET_THRESHOLD) && !bond_reset_pending)
|
||||
{
|
||||
bond_reset_pending = true;
|
||||
k_work_submit(&bond_reset_work);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (button_pressed) // 켜진 뒤 새로 누름 → 2초 이상이면 자동 전원 OFF
|
||||
{
|
||||
cnt_s++;
|
||||
|
||||
if (cnt_s >= BOOT_THRESHOLD)
|
||||
{
|
||||
battery_timer_stop();
|
||||
k_work_submit(&adv_stop_work);
|
||||
device_on = false;
|
||||
boot_btn_released = false;
|
||||
cnt_s = 0;
|
||||
sleep_mode_enter_reason("button-long-press");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else // 버튼 놓음 → 카운터 리셋
|
||||
{
|
||||
if (cnt_s > 0)
|
||||
{
|
||||
DBG_PRINTF("[BTN] Short press (%d) -> ignored\r\n", cnt_s);
|
||||
}
|
||||
cnt_s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
k_timer_start(&m_power_on_delay_timer, K_MSEC(POWER_ON_DELAY), K_NO_WAIT);
|
||||
}
|
||||
|
||||
/* 타이머 초기화 / 시작 */
|
||||
/* 타이머 초기화 */
|
||||
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);
|
||||
|
||||
// 전원 버튼 15초 롱프레스 본드 삭제 work
|
||||
k_work_init(&bond_reset_work, bond_reset_work_handler);
|
||||
|
||||
// DFU 업로드 무진행 감시 work
|
||||
k_work_init_delayable(&dfu_watchdog_work, dfu_watchdog_handler);
|
||||
@@ -531,8 +253,6 @@ static void timers_init(void)
|
||||
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();
|
||||
|
||||
// DFU 업로드 상태를 LED에 반영
|
||||
mgmt_callback_register(&dfu_status_callback);
|
||||
@@ -541,13 +261,7 @@ static void timers_init(void)
|
||||
mgmt_callback_register(&smp_cmd_status_callback);
|
||||
}
|
||||
|
||||
/* 전원 버튼 폴링 시작 (5ms 후 main_s 콜백) */
|
||||
static void timers_start(void)
|
||||
{
|
||||
k_timer_start(&m_power_on_delay_timer, K_MSEC(POWER_ON_DELAY), K_NO_WAIT);
|
||||
}
|
||||
|
||||
/* DFU 업로드가 멈춘 채(청크 무진행) 링크만 살아있는 경우 강제 disconnect 후 SMP 재광고(10분 타임아웃) 전환 - 초록 LED 무한 점등/무한 대기 방지 */
|
||||
static void dfu_watchdog_handler(struct k_work *work)
|
||||
{
|
||||
ARG_UNUSED(work);
|
||||
@@ -639,29 +353,6 @@ static enum mgmt_cb_return smp_cmd_status_cb(uint32_t event, enum mgmt_cb_return
|
||||
return MGMT_CB_OK;
|
||||
}
|
||||
|
||||
static void resume_device_after_soft_reset(void)
|
||||
{
|
||||
// 일반 버튼 부팅이면 skip
|
||||
if (!resume_without_power_button && !dfu_confirm_pending_boot && !dfu_reset_resume_request)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 리셋 복귀나 DFU test 부팅은 버튼 없이도 ON 상태로 복구
|
||||
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, "resume-after-reset");
|
||||
led_set_state(LED_STATE_ADVERTISING);
|
||||
battery_timer_start();
|
||||
k_work_submit(&adv_start_work);
|
||||
|
||||
DBG_CORE("[BOOT] Resume after resetreas=0x%08x\r\n", boot_reset_reason);
|
||||
}
|
||||
|
||||
static void confirm_running_image(void)
|
||||
{
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||
@@ -746,12 +437,13 @@ int main(void)
|
||||
boot_context_detect();
|
||||
|
||||
// 하드웨어 기본 초기화
|
||||
power_hold_init();
|
||||
cnt_s = 0;
|
||||
|
||||
// 버튼 부팅 기본 상태
|
||||
device_on = false;
|
||||
boot_btn_released = false;
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||
dfu_confirm_pending_boot = !boot_is_img_confirmed();
|
||||
#else
|
||||
dfu_confirm_pending_boot = false;
|
||||
#endif
|
||||
power_control_latch_init(resume_without_power_button || dfu_confirm_pending_boot || dfu_reset_resume_request);
|
||||
power_control_reset_state();
|
||||
confirm_running_image();
|
||||
|
||||
DBG_CORE("\r\n========================================\r\n");
|
||||
@@ -761,7 +453,7 @@ int main(void)
|
||||
|
||||
DBG_CORE("[INIT] HW Init\r\n");
|
||||
// 기본 하드웨어/센서 초기화
|
||||
gpio_init();
|
||||
power_control_init();
|
||||
timers_init();
|
||||
log_mcuboot_state();
|
||||
load_default_config();
|
||||
@@ -778,7 +470,10 @@ int main(void)
|
||||
{
|
||||
DBG_CORE("[INIT] BLE - ble/nus OK\r\n");
|
||||
// 소프트 리셋 후 서비스 복구
|
||||
resume_device_after_soft_reset();
|
||||
if (resume_without_power_button || dfu_confirm_pending_boot || dfu_reset_resume_request)
|
||||
{
|
||||
power_control_resume_after_reset(boot_reset_reason);
|
||||
}
|
||||
// BLE 준비까지 확인한 뒤 DFU test 이미지를 확정
|
||||
confirm_running_image();
|
||||
}
|
||||
@@ -792,7 +487,7 @@ int main(void)
|
||||
DBG_CORE("========================================\r\n");
|
||||
|
||||
// 전원 버튼 상태머신 시작 (부팅 시 버튼이 눌려있는 상태)
|
||||
timers_start();
|
||||
power_control_start();
|
||||
|
||||
// 메인 루프 - idle
|
||||
for (;;)
|
||||
|
||||
Reference in New Issue
Block a user