주석 추가
This commit is contained in:
+55
-18
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user