Initial Commit
This commit is contained in:
+111
-167
@@ -1,27 +1,8 @@
|
||||
/*******************************************************************************
|
||||
* @file main.c
|
||||
* @brief VesiScan-Basic
|
||||
*
|
||||
* 부팅 흐름:
|
||||
* 1. 리셋/DFU 복구 상태 확인, 전원 유지 핀 초기 설정
|
||||
* 2. GPIO, 타이머, workqueue, LED, 배터리 ADC, IMU, piezo 설정 초기화
|
||||
* 3. BLE 스택 + NUS 초기화
|
||||
* 4. 전원 버튼 상태머신 시작
|
||||
*
|
||||
* 일반 버튼 부팅:
|
||||
* - 버튼을 BOOT_THRESHOLD 동안 유지하면 P0.08 전원 래치 ON
|
||||
* - 래치 후 LED advertising 패턴, 배터리 모니터, BLE advertising 시작
|
||||
* - 기준 시간 = POWER_ON_DELAY * BOOT_THRESHOLD
|
||||
*
|
||||
* 리셋/DFU 복구:
|
||||
* - 버튼 없이 전원 래치와 advertising을 자동 복구할 수 있음
|
||||
*
|
||||
* 전원 버튼 상태머신:
|
||||
* [OFF→ON] 2초 이상 버튼 유지 → 전원 래치 ON (초기화 시간 고려 체감상 2초, 실제 코드상 1초)
|
||||
* 임계 시간 전에 놓으면 전원 래치 해제
|
||||
* [ON→OFF] 버튼 유지 → advertising 중지 + POWER_OFF_DELAY 후 전원 차단
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
@@ -37,6 +18,7 @@
|
||||
#include "battery_adc.h"
|
||||
#include "parser.h"
|
||||
#include "imu_i2c.h"
|
||||
#include "piezo_measure.h"
|
||||
|
||||
LOG_MODULE_REGISTER(vesiscan, LOG_LEVEL_INF);
|
||||
|
||||
@@ -55,51 +37,45 @@ 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) /* 전원 버튼 */
|
||||
/* Devicetree GPIO Settings */
|
||||
#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);
|
||||
|
||||
/*==============================================================================
|
||||
* Timer
|
||||
*============================================================================*/
|
||||
static struct k_timer m_power_on_delay_timer; /* 전원 버튼 폴링용 (5ms 싱글샷) */
|
||||
static struct k_timer m_power_off_delay_timer; /* 전원 OFF 지연용 (3초 후 전원 차단) */
|
||||
/* 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; /* 본딩 데이터 삭제 요청 */
|
||||
uint32_t m_life_cycle = 0; /* 디바이스 수명 카운터 */
|
||||
uint8_t m_reset_status = 1; /* 리셋 상태 코드 */
|
||||
char SERIAL_NO[SERIAL_NO_BUF_SIZE]; /* 시리얼 번호 */
|
||||
char HW_NO[HW_NO_BUF_SIZE]; /* 하드웨어 번호 */
|
||||
char m_static_passkey[PASSKEY_BUF_SIZE]; /* BLE 정적 패스키 */
|
||||
uint8_t m_passkey_changed; /* 패스키 변경은 출고 후 1회만 허용 */
|
||||
/* 전역 변수 */
|
||||
volatile bool ble_connection_st = false; // BLE 연결 상태
|
||||
volatile bool processing = false; // 센서 데이터 처리 중 플래그
|
||||
bool bond_data_delete = true; // 본딩 데이터 삭제 요청
|
||||
uint32_t m_life_cycle = 0; // 디바이스 수명 카운터
|
||||
uint8_t m_reset_status = 1; // 리셋 상태 코드
|
||||
char SERIAL_NO[SERIAL_NO_BUF_SIZE]; // 시리얼 번호
|
||||
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; /* 측정 중 전원 버튼 상태머신 일시 정지 */
|
||||
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 bool dfu_led_active; /* DFU 업로드 중 초록 LED ON */
|
||||
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 bool dfu_led_active; // DFU 업로드 중 초록 LED ON
|
||||
static const char *power_off_pending_reason = "none";
|
||||
|
||||
static enum mgmt_cb_return dfu_status_cb(uint32_t event,
|
||||
@@ -137,21 +113,21 @@ static struct mgmt_callback smp_cmd_status_callback = {
|
||||
*/
|
||||
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; /* 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 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 명령 슬롯 보호: 현재 구조는 한 번에 한 명령만 보관 */
|
||||
// 공유 RX 명령 슬롯 보호: 현재 구조는 한 번에 한 명령만 보관
|
||||
k_spinlock_key_t key = k_spin_lock(&ble_cmd_lock);
|
||||
if (ble_cmd_pending)
|
||||
{
|
||||
@@ -166,11 +142,11 @@ static void ble_cmd_work_handler(struct k_work *work)
|
||||
return;
|
||||
}
|
||||
|
||||
/* 일반 스레드 문맥 명령 처리 */
|
||||
// 일반 스레드 문맥 명령 처리
|
||||
//DBG_CORE("[BLE RX] worker dispatch len=%u\r\n", local_len);
|
||||
ble_cmd_dispatch(local_buf, local_len);
|
||||
|
||||
/* 명령 처리 완료 표시 */
|
||||
// 명령 처리 완료 표시
|
||||
key = k_spin_lock(&ble_cmd_lock);
|
||||
ble_cmd_pending = false;
|
||||
ble_cmd_len = 0U;
|
||||
@@ -191,9 +167,7 @@ static void adv_stop_work_handler(struct k_work *work)
|
||||
ble_advertising_stop();
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* BLE RX 콜백
|
||||
*============================================================================*/
|
||||
/* BLE RX 콜백 */
|
||||
static void ble_rx_handler(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
if (len > BLE_CMD_MAX_LEN)
|
||||
@@ -202,7 +176,7 @@ static void ble_rx_handler(const uint8_t *data, uint16_t len)
|
||||
return;
|
||||
}
|
||||
|
||||
/* 공유 RX 명령 슬롯 보호: 현재 구조는 한 번에 한 명령만 보관 */
|
||||
// 공유 RX 명령 슬롯 보호: 현재 구조는 한 번에 한 명령만 보관
|
||||
k_spinlock_key_t key = k_spin_lock(&ble_cmd_lock);
|
||||
if (ble_cmd_pending)
|
||||
{
|
||||
@@ -211,13 +185,13 @@ 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 예약 */
|
||||
// 명령 처리 work 예약
|
||||
int err = k_work_submit_to_queue(&ble_cmd_work_q, &ble_cmd_work);
|
||||
if (err < 0)
|
||||
{
|
||||
@@ -230,15 +204,13 @@ static void ble_rx_handler(const uint8_t *data, uint16_t len)
|
||||
}
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* 전원 유지 (POWER_HOLD) 제어
|
||||
*============================================================================*/
|
||||
/* 전원 유지 (POWER_HOLD) 제어 */
|
||||
static void boot_context_detect(void)
|
||||
{
|
||||
/* 부팅 원인 확인 */
|
||||
// 부팅 원인 확인
|
||||
boot_reset_reason = nrf_power_resetreas_get(NRF_POWER);
|
||||
|
||||
/* DFU 완료 직후 리셋인지 확인 */
|
||||
// DFU 완료 직후 리셋인지 확인
|
||||
#if NRF_POWER_HAS_GPREGRET
|
||||
dfu_reset_resume_request = (nrf_power_gpregret_get(NRF_POWER, DFU_RESUME_GPREGRET_REG) == DFU_RESUME_MAGIC);
|
||||
if (dfu_reset_resume_request)
|
||||
@@ -249,7 +221,7 @@ static void boot_context_detect(void)
|
||||
dfu_reset_resume_request = false;
|
||||
#endif
|
||||
|
||||
/* 소프트 리셋 계열 자동 복귀 */
|
||||
// 소프트 리셋 계열 자동 복귀
|
||||
resume_without_power_button =
|
||||
(boot_reset_reason & (NRF_POWER_RESETREAS_SREQ_MASK |
|
||||
NRF_POWER_RESETREAS_DOG_MASK |
|
||||
@@ -258,7 +230,7 @@ static void boot_context_detect(void)
|
||||
|
||||
if (boot_reset_reason != 0U)
|
||||
{
|
||||
/* RESETREAS 플래그 정리 */
|
||||
// RESETREAS 플래그 정리
|
||||
nrf_power_resetreas_clear(NRF_POWER, boot_reset_reason);
|
||||
}
|
||||
}
|
||||
@@ -266,13 +238,13 @@ static void boot_context_detect(void)
|
||||
static void power_hold_init(void)
|
||||
{
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||
/* DFU 이미지 확인 전 전원 유지 */
|
||||
// DFU 이미지 확인 전 전원 유지
|
||||
dfu_confirm_pending_boot = !boot_is_img_confirmed();
|
||||
#else
|
||||
dfu_confirm_pending_boot = false;
|
||||
#endif
|
||||
|
||||
/* 리셋 복귀/DFU 확인 대기 시 즉시 래치 */
|
||||
// 리셋 복귀/DFU 확인 대기 시 즉시 래치
|
||||
gpio_pin_configure_dt(&power_hold,
|
||||
(resume_without_power_button ||
|
||||
dfu_confirm_pending_boot ||
|
||||
@@ -295,30 +267,26 @@ static void power_control_handler(on_off_cont_t device_power_st, const char *rea
|
||||
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 → 전원 래치 해제 → 전원 차단 */
|
||||
gpio_pin_set_dt(&power_hold, 0); // P0.08 LOW → 전원 래치 해제 → 전원 차단
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_pin_set_dt(&power_hold, 1); /* P0.08 HIGH → 전원 유지 */
|
||||
gpio_pin_set_dt(&power_hold, 1); // P0.08 HIGH → 전원 유지
|
||||
}
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* GPIO 초기화
|
||||
*============================================================================*/
|
||||
/* GPIO 초기화 */
|
||||
static void gpio_init(void)
|
||||
{
|
||||
gpio_pin_configure_dt(&power_btn, GPIO_INPUT); /* 전원 버튼(P1.08) 입력 설정 */
|
||||
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)
|
||||
{
|
||||
/* 기본 문자열 길이 제한 */
|
||||
// 기본 문자열 길이 제한
|
||||
size_t serial_len = strlen(SERIAL_NUMBER);
|
||||
size_t hw_len = strlen(HARDWARE_VERSION);
|
||||
size_t passkey_len = strlen(DEFAULT_PASSKEY);
|
||||
@@ -339,15 +307,15 @@ static void load_default_config(void)
|
||||
memset(SERIAL_NO, 0, sizeof(SERIAL_NO));
|
||||
memcpy(SERIAL_NO, SERIAL_NUMBER, serial_len);
|
||||
|
||||
/* 기본 HW Version 복사 */
|
||||
// 기본 HW Version 복사
|
||||
memset(HW_NO, 0, sizeof(HW_NO));
|
||||
memcpy(HW_NO, HARDWARE_VERSION, hw_len);
|
||||
|
||||
/* 기본 BLE 패스키 복사 */
|
||||
// 기본 BLE 패스키 복사
|
||||
memset(m_static_passkey, 0, sizeof(m_static_passkey));
|
||||
memcpy(m_static_passkey, DEFAULT_PASSKEY, passkey_len);
|
||||
|
||||
/* NVS 로드 전 기본값은 변경 가능 상태 */
|
||||
// NVS 로드 전 기본값은 변경 가능 상태
|
||||
m_passkey_changed = 0U;
|
||||
|
||||
/* 기본 상태값 */
|
||||
@@ -357,10 +325,7 @@ static void load_default_config(void)
|
||||
DBG_CORE("[INIT] Default (S/N=%s)\r\n", SERIAL_NO);
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* 전원 OFF 타임아웃 콜백
|
||||
* LED 표시 후 3초(POWER_OFF_DELAY) 경과 시 호출되어 물리적 전원 차단
|
||||
*============================================================================*/
|
||||
/* 전원 OFF 타임아웃 콜백 */
|
||||
static void t_power_off_timeout_handler(struct k_timer *timer)
|
||||
{
|
||||
ARG_UNUSED(timer);
|
||||
@@ -369,10 +334,7 @@ static void t_power_off_timeout_handler(struct k_timer *timer)
|
||||
power_control_handler(OFF, "off-timeout");
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* 슬립 모드 / 전원 OFF
|
||||
* LED로 사용자에게 알린 후 3초 뒤 전원 차단
|
||||
*============================================================================*/
|
||||
/* 슬립 모드 / 전원 OFF: LED 표시 후 3초 뒤 전원 차단 */
|
||||
static void power_off_schedule(const char *reason, led_state_t led_state)
|
||||
{
|
||||
power_off_pending_reason = reason ? reason : "unknown";
|
||||
@@ -412,25 +374,13 @@ void device_power_keep_on(void)
|
||||
|
||||
void power_button_suspend(bool suspend)
|
||||
{
|
||||
/* 측정 시간이 긴 커맨드 처리 중에만 버튼 폴링 판단 잠시 멈춤 */
|
||||
// 측정 시간이 긴 커맨드 처리 중에만 버튼 폴링 판단 잠시 멈춤
|
||||
power_btn_suspended = suspend;
|
||||
cnt_s = 0;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* 전원 버튼 상태머신 (5ms 폴링)
|
||||
*
|
||||
* [부팅 시퀀스] (device_on == false)
|
||||
* 1. 버튼 누름 → 전원 공급 → MCU 부팅 → 5ms마다 폴링 시작
|
||||
* 2. cnt_s < 200 (2초 미만)에서 놓으면 → 전원 OFF (래치 안 됨)
|
||||
* 3. cnt_s == 200 (2초) 도달 → P0.08 래치 ON + 녹색 LED 깜빡임
|
||||
* 4. 버튼 놓으면 → 깜빡임 유지, 폴링 계속
|
||||
*
|
||||
* [전원 OFF 시퀀스] (device_on == true)
|
||||
* 1. 버튼 2초 이상 누름 → sleep_mode_enter() → 전원 차단
|
||||
* 2. 버튼 2초 미만 놓으면 → 카운터 리셋, 무시
|
||||
*============================================================================*/
|
||||
#define BOOT_THRESHOLD 200 /* 5ms x 400 = 2초 -> 초기화 시간 고려 체감상 2초에 맞춤 */
|
||||
/* 전원 버튼 상태머신 (5ms 폴링) */
|
||||
#define BOOT_THRESHOLD 200 // 5ms x 400 = 2초 -> 초기화 시간 고려 체감상 2초에 맞춤
|
||||
|
||||
static void main_s(struct k_timer *timer)
|
||||
{
|
||||
@@ -444,23 +394,23 @@ static void main_s(struct k_timer *timer)
|
||||
return;
|
||||
}
|
||||
|
||||
/* 부팅 시퀀스 (OFF → ON) */
|
||||
// 부팅 시퀀스 (OFF → ON)
|
||||
if (!device_on)
|
||||
{
|
||||
if (!button_pressed) /* 버튼 놓음 → 2초 미만이면 전원 OFF */
|
||||
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 /* 버튼 계속 누르고 있음 */
|
||||
else // 버튼 계속 누르고 있음
|
||||
{
|
||||
cnt_s++;
|
||||
|
||||
if (cnt_s == BOOT_THRESHOLD) /* 2초 도달: 래치 + 부팅 완료 */
|
||||
if (cnt_s == BOOT_THRESHOLD) // 2초 도달: 래치 + 부팅 완료
|
||||
{
|
||||
device_on = true;
|
||||
cnt_s = 0; /* 카운터 리셋: 안 하면 다음 틱에서 ON→OFF 분기가 cnt_s >= 200 조건을 즉시 만족하여 전원 OFF됨 */
|
||||
cnt_s = 0; // 카운터 리셋: 안 하면 다음 틱에서 ON→OFF 분기가 cnt_s >= 200 조건을 즉시 만족하여 전원 OFF됨
|
||||
power_control_handler(ON, "button-2s-latch");
|
||||
led_set_state(LED_STATE_ADVERTISING);
|
||||
k_work_submit(&adv_start_work);
|
||||
@@ -472,18 +422,18 @@ static void main_s(struct k_timer *timer)
|
||||
/* 전원 OFF 시퀀스 (ON → OFF) */
|
||||
else
|
||||
{
|
||||
if (!boot_btn_released) /* 부팅 시 눌렀던 버튼을 아직 안 놓음 → 대기 */
|
||||
if (!boot_btn_released) // 부팅 시 눌렀던 버튼을 아직 안 놓음 → 대기
|
||||
{
|
||||
if (!button_pressed)
|
||||
{
|
||||
boot_btn_released = true;
|
||||
}
|
||||
}
|
||||
else if (button_pressed) /* 버튼 새로 누르고 있음 */
|
||||
else if (button_pressed) // 버튼 새로 누르고 있음
|
||||
{
|
||||
cnt_s++;
|
||||
|
||||
if (cnt_s >= BOOT_THRESHOLD) /* 2초 이상 → 전원 OFF */
|
||||
if (cnt_s >= BOOT_THRESHOLD) // 2초 이상 → 전원 OFF
|
||||
{
|
||||
battery_timer_stop();
|
||||
k_work_submit(&adv_stop_work);
|
||||
@@ -494,7 +444,7 @@ static void main_s(struct k_timer *timer)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else /* 버튼 놓음 → 카운터 리셋 */
|
||||
else // 버튼 놓음 → 카운터 리셋
|
||||
{
|
||||
if (cnt_s > 0)
|
||||
{
|
||||
@@ -507,30 +457,28 @@ static void main_s(struct k_timer *timer)
|
||||
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 */
|
||||
// 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 */
|
||||
// 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();
|
||||
|
||||
/* DFU 업로드 상태를 LED에 반영 */
|
||||
// DFU 업로드 상태를 LED에 반영
|
||||
mgmt_callback_register(&dfu_status_callback);
|
||||
|
||||
/* DFU 명령 실패 시 LED 상태 복구 */
|
||||
// DFU 명령 실패 시 LED 상태 복구
|
||||
mgmt_callback_register(&smp_cmd_status_callback);
|
||||
}
|
||||
|
||||
@@ -557,26 +505,26 @@ static enum mgmt_cb_return dfu_status_cb(uint32_t event,
|
||||
|
||||
switch (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();
|
||||
break;
|
||||
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();
|
||||
break;
|
||||
|
||||
case MGMT_EVT_OP_IMG_MGMT_DFU_PENDING:
|
||||
/* 업로드 완료 후 리셋 전까지 초록 LED ON */
|
||||
dfu_led_active = true;
|
||||
led_ble_solid();
|
||||
case MGMT_EVT_OP_IMG_MGMT_DFU_PENDING:
|
||||
// 업로드 완료 후 리셋 전까지 초록 LED ON
|
||||
dfu_led_active = true;
|
||||
led_ble_solid();
|
||||
|
||||
/* DFU 리셋 후 버튼 없이 전원 ON */
|
||||
// DFU 리셋 후 버튼 없이 전원 ON
|
||||
#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:
|
||||
/* 실패나 중단 시 일반 광고 LED로 복귀 */
|
||||
// 실패나 중단 시 일반 광고 LED로 복귀
|
||||
if (dfu_led_active)
|
||||
{
|
||||
dfu_led_active = false;
|
||||
@@ -612,7 +560,7 @@ static enum mgmt_cb_return smp_cmd_status_cb(uint32_t event,
|
||||
|
||||
const struct mgmt_evt_op_cmd_arg *cmd = data;
|
||||
|
||||
/* 이미지 업로드/test 명령 실패 시 DFU LED 고정 해제 */
|
||||
// 이미지 업로드/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)
|
||||
@@ -622,7 +570,7 @@ static enum mgmt_cb_return smp_cmd_status_cb(uint32_t event,
|
||||
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
|
||||
@@ -633,21 +581,19 @@ static enum mgmt_cb_return smp_cmd_status_cb(uint32_t event,
|
||||
|
||||
static void resume_device_after_soft_reset(void)
|
||||
{
|
||||
/* 일반 버튼 부팅이면 skip */
|
||||
if (!resume_without_power_button &&
|
||||
!dfu_confirm_pending_boot &&
|
||||
!dfu_reset_resume_request)
|
||||
// 일반 버튼 부팅이면 skip
|
||||
if (!resume_without_power_button && !dfu_confirm_pending_boot && !dfu_reset_resume_request)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* 리셋 복귀나 DFU test 부팅은 버튼 없이도 ON 상태로 복구 */
|
||||
// 리셋 복귀나 DFU test 부팅은 버튼 없이도 ON 상태로 복구
|
||||
device_on = true;
|
||||
cnt_s = 0;
|
||||
boot_btn_released = (gpio_pin_get_dt(&power_btn) != 1);
|
||||
m_reset_status = 1;
|
||||
|
||||
/* 정상 ON 상태 서비스 재시작 */
|
||||
// 정상 ON 상태 서비스 재시작
|
||||
power_control_handler(ON, "resume-after-reset");
|
||||
led_set_state(LED_STATE_ADVERTISING);
|
||||
battery_timer_start();
|
||||
@@ -659,7 +605,7 @@ static void resume_device_after_soft_reset(void)
|
||||
static void confirm_running_image(void)
|
||||
{
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||
/* 기본 초기화와 BLE 준비가 끝난 뒤 MCUboot revert 방지 */
|
||||
// 기본 초기화와 BLE 준비가 끝난 뒤 MCUboot revert 방지
|
||||
if (!boot_is_img_confirmed())
|
||||
{
|
||||
int err = boot_write_img_confirmed();
|
||||
@@ -681,7 +627,7 @@ static void confirm_running_image(void)
|
||||
|
||||
static const char *swap_type_to_str(int swap_type)
|
||||
{
|
||||
/* MCUboot swap 상태 문자열 */
|
||||
// MCUboot swap 상태 문자열
|
||||
switch (swap_type)
|
||||
{
|
||||
case BOOT_SWAP_TYPE_NONE:
|
||||
@@ -702,7 +648,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();
|
||||
@@ -733,30 +679,28 @@ static void log_mcuboot_state(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* 메인 함수
|
||||
*============================================================================*/
|
||||
/* 메인 함수 */
|
||||
int main(void)
|
||||
{
|
||||
/* 리셋/복귀 컨텍스트 */
|
||||
// 리셋/복귀 컨텍스트
|
||||
boot_context_detect();
|
||||
|
||||
/* 하드웨어 기본 초기화 */
|
||||
// 하드웨어 기본 초기화
|
||||
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-002\r\n");
|
||||
DBG_CORE(" BUILD TAG: TEST-003 - tx power dynamic control\r\n");
|
||||
DBG_CORE("========================================\r\n");
|
||||
|
||||
DBG_CORE("[INIT] HW Init\r\n");
|
||||
/* 기본 하드웨어/센서 초기화 */
|
||||
// 기본 하드웨어/센서 초기화
|
||||
gpio_init();
|
||||
timers_init();
|
||||
log_mcuboot_state();
|
||||
@@ -768,14 +712,14 @@ int main(void)
|
||||
piezo_config_init();
|
||||
DBG_CORE("[INIT] HW - gpio/timer/config/led/batt/imu/temp/piezo-cfg OK\r\n");
|
||||
|
||||
/* BLE 스택 + NUS */
|
||||
// BLE 스택 + NUS
|
||||
DBG_CORE("[INIT] BLE Init\r\n");
|
||||
if (ble_service_init(ble_rx_handler) == 0)
|
||||
{
|
||||
DBG_CORE("[INIT] BLE - ble/nus OK\r\n");
|
||||
/* 소프트 리셋 후 서비스 복구 */
|
||||
// 소프트 리셋 후 서비스 복구
|
||||
resume_device_after_soft_reset();
|
||||
/* BLE 준비까지 확인한 뒤 DFU test 이미지를 확정 */
|
||||
// BLE 준비까지 확인한 뒤 DFU test 이미지를 확정
|
||||
confirm_running_image();
|
||||
}
|
||||
else
|
||||
@@ -787,10 +731,10 @@ int main(void)
|
||||
DBG_CORE(" READY [%s]\r\n", SERIAL_NO);
|
||||
DBG_CORE("========================================\r\n");
|
||||
|
||||
/* 전원 버튼 상태머신 시작 (부팅 시 버튼이 눌려있는 상태) */
|
||||
// 전원 버튼 상태머신 시작 (부팅 시 버튼이 눌려있는 상태)
|
||||
timers_start();
|
||||
|
||||
/* 메인 루프 - idle */
|
||||
// 메인 루프 - idle
|
||||
for (;;)
|
||||
{
|
||||
k_msleep(100);
|
||||
|
||||
Reference in New Issue
Block a user