Compare commits
7 Commits
b8fa7831c7
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| abb8d6078a | |||
| b6d79ad16a | |||
| 0fc578fb50 | |||
| d3513e3985 | |||
| 14fba03b62 | |||
| e3225215c5 | |||
| b086b0f366 |
+7
-2
@@ -10,6 +10,9 @@ target_include_directories(app PRIVATE
|
|||||||
src/command
|
src/command
|
||||||
src/command/handlers
|
src/command/handlers
|
||||||
src/ble
|
src/ble
|
||||||
|
src/power
|
||||||
|
src/dfu
|
||||||
|
src/nvs
|
||||||
src/drivers/battery
|
src/drivers/battery
|
||||||
src/drivers/echo_adc
|
src/drivers/echo_adc
|
||||||
src/drivers/led
|
src/drivers/led
|
||||||
@@ -20,15 +23,17 @@ target_include_directories(app PRIVATE
|
|||||||
|
|
||||||
target_sources(app PRIVATE
|
target_sources(app PRIVATE
|
||||||
src/main.c
|
src/main.c
|
||||||
src/app_nvs.c
|
src/nvs/app_nvs.c
|
||||||
src/command/parser.c
|
src/command/parser.c
|
||||||
|
src/command/ble_cmd_queue.c
|
||||||
src/command/cmd_common.c
|
src/command/cmd_common.c
|
||||||
src/command/cmd_table.c
|
src/command/cmd_table.c
|
||||||
src/command/handlers/cmd_device.c
|
src/command/handlers/cmd_device.c
|
||||||
src/command/handlers/cmd_info.c
|
src/command/handlers/cmd_info.c
|
||||||
src/command/handlers/cmd_piezo.c
|
src/command/handlers/cmd_piezo.c
|
||||||
src/command/handlers/cmd_sensor.c
|
src/command/handlers/cmd_sensor.c
|
||||||
src/power_control.c
|
src/power/power_control.c
|
||||||
|
src/dfu/dfu_manager.c
|
||||||
src/measurement/piezo_measure.c
|
src/measurement/piezo_measure.c
|
||||||
src/ble/ble_service.c
|
src/ble/ble_service.c
|
||||||
src/ble/ble_tx_power.c
|
src/ble/ble_tx_power.c
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ CONFIG_BOOTLOADER_MCUBOOT=y
|
|||||||
# Enable zcbor library used by mcumgr/SMP/DFU CBOR payloads.
|
# Enable zcbor library used by mcumgr/SMP/DFU CBOR payloads.
|
||||||
CONFIG_ZCBOR=y
|
CONFIG_ZCBOR=y
|
||||||
# Version string used by MCUboot imgtool signing and versioned DFU zip naming.
|
# Version string used by MCUboot imgtool signing and versioned DFU zip naming.
|
||||||
CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION="0.0.2+26"
|
CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION="0.0.0+0"
|
||||||
|
|
||||||
# Internal flash
|
# Internal flash
|
||||||
# Enable internal flash driver.
|
# Enable internal flash driver.
|
||||||
@@ -181,9 +181,4 @@ CONFIG_MCUMGR_GRP_OS=y
|
|||||||
# Enable image manager for MCUboot image state/verify/confirm operations.
|
# Enable image manager for MCUboot image state/verify/confirm operations.
|
||||||
CONFIG_IMG_MANAGER=y
|
CONFIG_IMG_MANAGER=y
|
||||||
# Write uploaded image data to flash as a stream.
|
# Write uploaded image data to flash as a stream.
|
||||||
CONFIG_STREAM_FLASH=y
|
CONFIG_STREAM_FLASH=y
|
||||||
|
|
||||||
# Netcore HCI IPC
|
|
||||||
# nRF52840 build does not use network core HCI IPC.
|
|
||||||
#CONFIG_SB_CONFIG_NETCORE_HCI_IPC=y
|
|
||||||
#SB_CONFIG_NETCORE_HCI_IPC=y
|
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* @file ble_cmd_queue.c
|
||||||
|
* @brief BLE RX command queue
|
||||||
|
******************************************************************************/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
|
#include "ble_cmd_queue.h"
|
||||||
|
#include "debug_print.h"
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
#define BLE_CMD_MAX_LEN 256
|
||||||
|
#define BLE_CMD_QUEUE_DEPTH 8 // RX command ring buffer depth
|
||||||
|
#define BLE_CMD_WORKQ_STACK_SZ 8192
|
||||||
|
#define BLE_CMD_WORKQ_PRIORITY 10
|
||||||
|
|
||||||
|
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 command worker
|
||||||
|
static struct k_spinlock ble_cmd_lock; // RX queue lock
|
||||||
|
|
||||||
|
static uint8_t ble_cmd_q_buf[BLE_CMD_QUEUE_DEPTH][BLE_CMD_MAX_LEN]; // command data
|
||||||
|
static uint16_t ble_cmd_q_len[BLE_CMD_QUEUE_DEPTH]; // command length
|
||||||
|
static uint8_t ble_cmd_q_head; // next pop slot
|
||||||
|
static uint8_t ble_cmd_q_tail; // next push slot
|
||||||
|
static uint8_t ble_cmd_q_count; // queued command count
|
||||||
|
|
||||||
|
/* Queue에 쌓인 BLE 명령을 parser로 전달 */
|
||||||
|
static void ble_cmd_work_handler(struct k_work *work)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(work);
|
||||||
|
|
||||||
|
uint8_t local_buf[BLE_CMD_MAX_LEN];
|
||||||
|
uint16_t local_len;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
k_spinlock_key_t key = k_spin_lock(&ble_cmd_lock);
|
||||||
|
if (ble_cmd_q_count == 0U)
|
||||||
|
{
|
||||||
|
k_spin_unlock(&ble_cmd_lock, key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
local_len = ble_cmd_q_len[ble_cmd_q_head];
|
||||||
|
memcpy(local_buf, ble_cmd_q_buf[ble_cmd_q_head], local_len);
|
||||||
|
ble_cmd_q_head = (uint8_t)((ble_cmd_q_head + 1U) % BLE_CMD_QUEUE_DEPTH);
|
||||||
|
ble_cmd_q_count--;
|
||||||
|
k_spin_unlock(&ble_cmd_lock, key);
|
||||||
|
|
||||||
|
if (local_len == 0U)
|
||||||
|
{
|
||||||
|
DBG_ERR("[BLE RX] worker: empty\r\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ble_cmd_dispatch(local_buf, local_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BLE RX 명령 처리 queue 초기화 */
|
||||||
|
void ble_cmd_queue_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BLE RX 콜백에서 호출되는 명령 enqueue 함수 */
|
||||||
|
void ble_cmd_queue_rx_handler(const uint8_t *data, uint16_t len)
|
||||||
|
{
|
||||||
|
if (len > BLE_CMD_MAX_LEN)
|
||||||
|
{
|
||||||
|
DBG_ERR("[BLE RX] drop: len=%u exceeds %d\r\n", len, BLE_CMD_MAX_LEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_spinlock_key_t key = k_spin_lock(&ble_cmd_lock);
|
||||||
|
if (ble_cmd_q_count >= BLE_CMD_QUEUE_DEPTH)
|
||||||
|
{
|
||||||
|
k_spin_unlock(&ble_cmd_lock, key);
|
||||||
|
DBG_ERR("[BLE RX] drop: queue full\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ble_cmd_q_buf[ble_cmd_q_tail], data, len);
|
||||||
|
ble_cmd_q_len[ble_cmd_q_tail] = len;
|
||||||
|
ble_cmd_q_tail = (uint8_t)((ble_cmd_q_tail + 1U) % BLE_CMD_QUEUE_DEPTH);
|
||||||
|
ble_cmd_q_count++;
|
||||||
|
k_spin_unlock(&ble_cmd_lock, key);
|
||||||
|
|
||||||
|
int err = k_work_submit_to_queue(&ble_cmd_work_q, &ble_cmd_work);
|
||||||
|
if (err < 0)
|
||||||
|
{
|
||||||
|
DBG_ERR("[BLE RX] queue submit fail err=%d\r\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* @file ble_cmd_queue.h
|
||||||
|
* @brief BLE RX command queue
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef BLE_CMD_QUEUE_H__
|
||||||
|
#define BLE_CMD_QUEUE_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void ble_cmd_queue_init(void);
|
||||||
|
void ble_cmd_queue_rx_handler(const uint8_t *data, uint16_t len);
|
||||||
|
|
||||||
|
#endif /* BLE_CMD_QUEUE_H__ */
|
||||||
@@ -277,7 +277,7 @@ int cmd_maa(const uint8_t *data, uint8_t data_len)
|
|||||||
|
|
||||||
if (status == ECHO_STATUS_OK) // Piezo GPIO, power, ADC initialization/wake succeeded
|
if (status == ECHO_STATUS_OK) // Piezo GPIO, power, ADC initialization/wake succeeded
|
||||||
{
|
{
|
||||||
DBG_PRINTF("[MBB] piezo sweep start\r\n");
|
DBG_PRINTF("[MAA] piezo sweep start\r\n");
|
||||||
status = piezo_measure_sweep();
|
status = piezo_measure_sweep();
|
||||||
if (status == ECHO_STATUS_OK)
|
if (status == ECHO_STATUS_OK)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -688,7 +688,6 @@ int imu_fifo_read_latest(uint8_t *sample_bytes,
|
|||||||
|
|
||||||
{
|
{
|
||||||
record_count = imu_fifo_compact_records(record_count);
|
record_count = imu_fifo_compact_records(record_count);
|
||||||
DBG_PRINTF("[IMU FIFO] compact %u -> %u\r\n", raw_count, record_count);
|
|
||||||
}
|
}
|
||||||
if (record_count > max_samples)
|
if (record_count > max_samples)
|
||||||
{
|
{
|
||||||
|
|||||||
+34
-133
@@ -1,6 +1,12 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* @file main.c
|
* @file main.c
|
||||||
* @brief VesiScan-Basic
|
* @brief VesiScan-Basic
|
||||||
|
*
|
||||||
|
* - 앱 공통 전역 상태 보관
|
||||||
|
* - 부팅 직후 전원 유지 판단
|
||||||
|
* - NVS 로드 전 기본값 초기화
|
||||||
|
* - 각 모듈 초기화 순서 조립
|
||||||
|
* - main loop 유지
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
@@ -14,24 +20,12 @@
|
|||||||
#include "led_control.h"
|
#include "led_control.h"
|
||||||
#include "ble_service.h"
|
#include "ble_service.h"
|
||||||
#include "battery_adc.h"
|
#include "battery_adc.h"
|
||||||
#include "parser.h"
|
#include "ble_cmd_queue.h"
|
||||||
#include "imu_i2c.h"
|
#include "imu_i2c.h"
|
||||||
#include "piezo_measure.h"
|
#include "piezo_measure.h"
|
||||||
|
|
||||||
LOG_MODULE_REGISTER(vesiscan, LOG_LEVEL_INF);
|
LOG_MODULE_REGISTER(vesiscan, LOG_LEVEL_INF);
|
||||||
|
|
||||||
#define BLE_CMD_MAX_LEN 256
|
|
||||||
#define BLE_CMD_QUEUE_DEPTH 8 // RX 명령 링버퍼 깊이(버스트 흡수)
|
|
||||||
#define BLE_CMD_WORKQ_STACK_SZ 8192
|
|
||||||
/*
|
|
||||||
* BLE 명령 처리 스택
|
|
||||||
* - piezo sweep
|
|
||||||
* - ADC capture
|
|
||||||
* - BLE 응답 패킷 조립
|
|
||||||
* - 디버깅 여유분 포함
|
|
||||||
*/
|
|
||||||
#define BLE_CMD_WORKQ_PRIORITY 10
|
|
||||||
|
|
||||||
volatile bool ble_connection_st = false; // BLE 연결 상태
|
volatile bool ble_connection_st = false; // BLE 연결 상태
|
||||||
volatile bool processing = false; // 센서 데이터 처리 중 플래그
|
volatile bool processing = false; // 센서 데이터 처리 중 플래그
|
||||||
bool bond_data_delete = true; // 본딩 데이터 삭제 요청
|
bool bond_data_delete = true; // 본딩 데이터 삭제 요청
|
||||||
@@ -46,96 +40,19 @@ 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 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 큐 보호
|
|
||||||
|
|
||||||
// RX 명령 링버퍼: 들어온 순서대로 쌓고 워커가 순차 처리 (head=꺼낼 위치, tail=넣을 위치)
|
/* 부팅 후 전원 유지 판단 및 모듈 초기화 순서 조립 */
|
||||||
static uint8_t ble_cmd_q_buf[BLE_CMD_QUEUE_DEPTH][BLE_CMD_MAX_LEN]; // 명령 데이터
|
|
||||||
static uint16_t ble_cmd_q_len[BLE_CMD_QUEUE_DEPTH]; // 각 명령 길이
|
|
||||||
static uint8_t ble_cmd_q_head; // 다음에 꺼낼 슬롯
|
|
||||||
static uint8_t ble_cmd_q_tail; // 다음에 넣을 슬롯
|
|
||||||
static uint8_t ble_cmd_q_count; // 큐에 쌓인 명령 수
|
|
||||||
|
|
||||||
static void ble_cmd_work_handler(struct k_work *work)
|
|
||||||
{
|
|
||||||
ARG_UNUSED(work);
|
|
||||||
|
|
||||||
// work queue 로컬 복사본
|
|
||||||
uint8_t local_buf[BLE_CMD_MAX_LEN];
|
|
||||||
uint16_t local_len;
|
|
||||||
|
|
||||||
// 큐가 빌 때까지 head에서 하나씩 꺼내 순차 처리 (dispatch는 락 밖에서)
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
k_spinlock_key_t key = k_spin_lock(&ble_cmd_lock);
|
|
||||||
if (ble_cmd_q_count == 0U)
|
|
||||||
{
|
|
||||||
k_spin_unlock(&ble_cmd_lock, key);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
local_len = ble_cmd_q_len[ble_cmd_q_head];
|
|
||||||
memcpy(local_buf, ble_cmd_q_buf[ble_cmd_q_head], local_len);
|
|
||||||
ble_cmd_q_head = (uint8_t)((ble_cmd_q_head + 1U) % BLE_CMD_QUEUE_DEPTH);
|
|
||||||
ble_cmd_q_count--;
|
|
||||||
k_spin_unlock(&ble_cmd_lock, key);
|
|
||||||
|
|
||||||
if (local_len == 0U)
|
|
||||||
{
|
|
||||||
DBG_ERR("[BLE RX] worker: empty\r\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 일반 스레드 문맥 명령 처리
|
|
||||||
//DBG_CORE("[BLE RX] worker dispatch len=%u\r\n", local_len);
|
|
||||||
ble_cmd_dispatch(local_buf, local_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* BLE RX 콜백 */
|
|
||||||
static void ble_rx_handler(const uint8_t *data, uint16_t len)
|
|
||||||
{
|
|
||||||
if (len > BLE_CMD_MAX_LEN)
|
|
||||||
{
|
|
||||||
DBG_ERR("[BLE RX] drop: len=%u exceeds %d\r\n", len, BLE_CMD_MAX_LEN);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 공유 RX 큐 보호: tail 슬롯에 명령 적재 (FIFO)
|
|
||||||
k_spinlock_key_t key = k_spin_lock(&ble_cmd_lock);
|
|
||||||
if (ble_cmd_q_count >= BLE_CMD_QUEUE_DEPTH)
|
|
||||||
{
|
|
||||||
k_spin_unlock(&ble_cmd_lock, key);
|
|
||||||
DBG_ERR("[BLE RX] drop: queue full\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 명령 버퍼 복사
|
|
||||||
memcpy(ble_cmd_q_buf[ble_cmd_q_tail], data, len);
|
|
||||||
ble_cmd_q_len[ble_cmd_q_tail] = len;
|
|
||||||
ble_cmd_q_tail = (uint8_t)((ble_cmd_q_tail + 1U) % BLE_CMD_QUEUE_DEPTH);
|
|
||||||
ble_cmd_q_count++;
|
|
||||||
k_spin_unlock(&ble_cmd_lock, key);
|
|
||||||
|
|
||||||
// 명령 처리 work 예약 (워커는 큐가 빌 때까지 처리하므로 중복 예약은 무해)
|
|
||||||
// 실패해도 항목은 큐에 유효하게 남아 있고, 다음 RX의 submit이 함께 처리하므로 롤백하지 않음
|
|
||||||
int err = k_work_submit_to_queue(&ble_cmd_work_q, &ble_cmd_work);
|
|
||||||
if (err < 0)
|
|
||||||
{
|
|
||||||
DBG_ERR("[BLE RX] queue submit fail err=%d\r\n", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 전원 유지 (POWER_HOLD) 제어 */
|
|
||||||
static void boot_context_detect(void)
|
static void boot_context_detect(void)
|
||||||
{
|
{
|
||||||
// 부팅 원인 확인
|
// 부팅 원인 확인
|
||||||
boot_reset_reason = nrf_power_resetreas_get(NRF_POWER);
|
boot_reset_reason = nrf_power_resetreas_get(NRF_POWER);
|
||||||
|
|
||||||
// DFU 완료 직후 리셋인지 확인
|
// DFU rest (DFU 완료 후 재부팅)
|
||||||
|
// GPREGRET은 reset 후에도 유지되는 작은 상태 표시용 레지스터
|
||||||
#if NRF_POWER_HAS_GPREGRET
|
#if NRF_POWER_HAS_GPREGRET
|
||||||
dfu_reset_resume_request = (nrf_power_gpregret_get(NRF_POWER, DFU_RESUME_GPREGRET_REG) == DFU_RESUME_MAGIC);
|
dfu_reset_resume_request = (nrf_power_gpregret_get(NRF_POWER, DFU_RESUME_GPREGRET_REG) == DFU_RESUME_MAGIC);
|
||||||
|
|
||||||
|
// DFU reset 표시 확인 후 다음 부팅 오판 방지를 위해 정리
|
||||||
if (dfu_reset_resume_request)
|
if (dfu_reset_resume_request)
|
||||||
{
|
{
|
||||||
nrf_power_gpregret_set(NRF_POWER, DFU_RESUME_GPREGRET_REG, 0U);
|
nrf_power_gpregret_set(NRF_POWER, DFU_RESUME_GPREGRET_REG, 0U);
|
||||||
@@ -144,23 +61,25 @@ static void boot_context_detect(void)
|
|||||||
dfu_reset_resume_request = false;
|
dfu_reset_resume_request = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 소프트 리셋 계열 자동 복귀
|
// soft reset 후 복귀 (전원 버튼 새 부팅 X)
|
||||||
resume_without_power_button = (boot_reset_reason & (NRF_POWER_RESETREAS_SREQ_MASK | NRF_POWER_RESETREAS_DOG_MASK | NRF_POWER_RESETREAS_LOCKUP_MASK | NRF_POWER_RESETREAS_RESETPIN_MASK)) != 0U;
|
resume_without_power_button = (boot_reset_reason & (NRF_POWER_RESETREAS_SREQ_MASK | NRF_POWER_RESETREAS_DOG_MASK | NRF_POWER_RESETREAS_LOCKUP_MASK | NRF_POWER_RESETREAS_RESETPIN_MASK)) != 0U;
|
||||||
|
|
||||||
|
// 다음 부팅 오판 방지를 위해 RESETREAS 플래그 정리
|
||||||
if (boot_reset_reason != 0U)
|
if (boot_reset_reason != 0U)
|
||||||
{
|
{
|
||||||
// RESETREAS 플래그 정리
|
|
||||||
nrf_power_resetreas_clear(NRF_POWER, boot_reset_reason);
|
nrf_power_resetreas_clear(NRF_POWER, boot_reset_reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NVS 값이 없을 때 사용할 기본값 초기화 (앱 전역 상태 기본값) - NVS 값이 있는 경우 이후 NVS 값으로 덮어씀 */
|
||||||
static void load_default_config(void)
|
static void load_default_config(void)
|
||||||
{
|
{
|
||||||
// 기본 문자열 길이 제한
|
// 기본 문자열 길이 계산
|
||||||
size_t serial_len = strlen(SERIAL_NUMBER);
|
size_t serial_len = strlen(SERIAL_NUMBER);
|
||||||
size_t hw_len = strlen(HARDWARE_VERSION);
|
size_t hw_len = strlen(HARDWARE_VERSION);
|
||||||
size_t passkey_len = strlen(DEFAULT_PASSKEY);
|
size_t passkey_len = strlen(DEFAULT_PASSKEY);
|
||||||
|
|
||||||
|
// 버퍼 오버플로우 방지 - 기본 문자열 길이 제한 (긴 경우 잘라내기)
|
||||||
if (serial_len > SERIAL_NO_LENGTH)
|
if (serial_len > SERIAL_NO_LENGTH)
|
||||||
{
|
{
|
||||||
serial_len = SERIAL_NO_LENGTH;
|
serial_len = SERIAL_NO_LENGTH;
|
||||||
@@ -176,6 +95,8 @@ static void load_default_config(void)
|
|||||||
passkey_len = PASSKEY_LENGTH;
|
passkey_len = PASSKEY_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 복사할 때 버퍼를 먼저 0으로 채우고 복사 -> 문자열 종료 NUL 보장
|
||||||
|
// 기본 Serial Number 복사
|
||||||
memset(SERIAL_NO, 0, sizeof(SERIAL_NO));
|
memset(SERIAL_NO, 0, sizeof(SERIAL_NO));
|
||||||
memcpy(SERIAL_NO, SERIAL_NUMBER, serial_len);
|
memcpy(SERIAL_NO, SERIAL_NUMBER, serial_len);
|
||||||
|
|
||||||
@@ -187,52 +108,35 @@ static void load_default_config(void)
|
|||||||
memset(m_static_passkey, 0, sizeof(m_static_passkey));
|
memset(m_static_passkey, 0, sizeof(m_static_passkey));
|
||||||
memcpy(m_static_passkey, DEFAULT_PASSKEY, passkey_len);
|
memcpy(m_static_passkey, DEFAULT_PASSKEY, passkey_len);
|
||||||
|
|
||||||
// NVS 로드 전 기본값은 변경 가능 상태
|
m_passkey_changed = 0U; // 패스키 변경 여부 초기화
|
||||||
m_passkey_changed = 0U;
|
|
||||||
|
|
||||||
// 기본 상태값
|
m_reset_status = 1; // 기본 reset 상태 코드 설정
|
||||||
m_reset_status = 1;
|
bond_data_delete = true; // 기본 상태는 bond 삭제 완료 삭제로 초기화
|
||||||
bond_data_delete = true;
|
|
||||||
|
|
||||||
DBG_CORE("[INIT] Default (S/N=%s)\r\n", SERIAL_NO);
|
DBG_CORE("[INIT] Default (S/N=%s)\r\n", SERIAL_NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 타이머 초기화 */
|
|
||||||
static void timers_init(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 메인 함수 */
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
// 리셋/복귀 컨텍스트
|
|
||||||
boot_context_detect();
|
boot_context_detect();
|
||||||
|
|
||||||
// 하드웨어 기본 초기화
|
|
||||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||||
dfu_confirm_pending_boot = dfu_is_confirm_pending_boot();
|
dfu_confirm_pending_boot = dfu_is_confirm_pending_boot(); // MCUboot test 이미지 상태인지 확인
|
||||||
#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();
|
||||||
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);
|
||||||
DBG_CORE(" BUILD TAG: %s\r\n", CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION);
|
DBG_CORE(" BUILD TAG: %s\r\n", CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION);
|
||||||
DBG_CORE("========================================\r\n");
|
DBG_CORE("========================================\r\n");
|
||||||
|
|
||||||
DBG_CORE("[INIT] HW Init\r\n");
|
// 각 모듈 초기화
|
||||||
// 기본 하드웨어/센서 초기화
|
|
||||||
power_control_init();
|
power_control_init();
|
||||||
timers_init();
|
ble_cmd_queue_init();
|
||||||
dfu_manager_init();
|
dfu_manager_init();
|
||||||
dfu_log_mcuboot_state();
|
dfu_log_mcuboot_state();
|
||||||
load_default_config();
|
load_default_config();
|
||||||
@@ -241,20 +145,17 @@ int main(void)
|
|||||||
battery_timer_init();
|
battery_timer_init();
|
||||||
imu_init();
|
imu_init();
|
||||||
piezo_config_init();
|
piezo_config_init();
|
||||||
DBG_CORE("[INIT] HW - gpio/timer/config/led/batt/imu/temp/piezo-cfg OK\r\n");
|
|
||||||
|
|
||||||
// BLE 스택 + NUS
|
// BLE Stack/NUS 초기화 (0=성공)
|
||||||
DBG_CORE("[INIT] BLE Init\r\n");
|
if (ble_service_init(ble_cmd_queue_rx_handler) == 0) // BLE RX 콜백은 command queue로 연결
|
||||||
if (ble_service_init(ble_rx_handler) == 0)
|
|
||||||
{
|
{
|
||||||
DBG_CORE("[INIT] BLE - ble/nus OK\r\n");
|
// 버튼 없이 정상 ON 상태로 복구하는 경우
|
||||||
// 소프트 리셋 후 서비스 복구
|
|
||||||
if (resume_without_power_button || dfu_confirm_pending_boot || dfu_reset_resume_request)
|
if (resume_without_power_button || dfu_confirm_pending_boot || dfu_reset_resume_request)
|
||||||
{
|
{
|
||||||
power_control_resume_after_reset(boot_reset_reason);
|
power_control_resume_after_reset(boot_reset_reason);
|
||||||
}
|
}
|
||||||
// BLE 준비까지 확인한 뒤 DFU test 이미지를 확정
|
|
||||||
dfu_confirm_running_image();
|
dfu_confirm_running_image(); // BLE 준비까지 확인한 뒤 DFU test 이미지 확정(confirm)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -265,10 +166,10 @@ int main(void)
|
|||||||
DBG_CORE(" READY [%s]\r\n", SERIAL_NO);
|
DBG_CORE(" READY [%s]\r\n", SERIAL_NO);
|
||||||
DBG_CORE("========================================\r\n");
|
DBG_CORE("========================================\r\n");
|
||||||
|
|
||||||
// 전원 버튼 상태머신 시작 (부팅 시 버튼이 눌려있는 상태)
|
power_control_start(); // 전원 버튼 상태머신 시작 (부팅 시 버튼이 눌려있는 상태)
|
||||||
power_control_start();
|
|
||||||
|
|
||||||
// 메인 루프 - idle
|
// main loop - idle
|
||||||
|
// callback, work queue 기반 동작 유지
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
k_msleep(100);
|
k_msleep(100);
|
||||||
|
|||||||
@@ -17,11 +17,12 @@
|
|||||||
#include "ble_service.h"
|
#include "ble_service.h"
|
||||||
#include "battery_adc.h"
|
#include "battery_adc.h"
|
||||||
|
|
||||||
#define POWER_HOLD_NODE DT_NODELABEL(pwr_hold) // 전원 래치
|
#define POWER_HOLD_NODE DT_NODELABEL(pwr_hold) // 전원 래치
|
||||||
#define POWER_BTN_NODE DT_NODELABEL(button_check) // 전원 버튼
|
#define POWER_BTN_NODE DT_NODELABEL(button_check) // 전원 버튼
|
||||||
#define POWER_LOOP_INTERVAL 20 // 전원 시퀀스 타이머 간격(ms)
|
#define POWER_LOOP_INTERVAL 20 // 전원 시퀀스 타이머 간격(ms)
|
||||||
#define BOOT_THRESHOLD 350 // power button hold threshold
|
#define POWER_ON_THRESHOLD 350 // power button hold threshold(off -> on)
|
||||||
#define BOND_RESET_THRESHOLD (15000 / POWER_ON_DELAY) // 15s long press bond reset
|
#define POWER_OFF_THRESHOLD 500 // power button hold threshold(on -> off)
|
||||||
|
#define BOND_RESET_THRESHOLD (15000 / POWER_ON_DELAY) // 15s long press bond reset
|
||||||
|
|
||||||
static const struct gpio_dt_spec power_hold = GPIO_DT_SPEC_GET(POWER_HOLD_NODE, gpios); // 전원 유지 출력
|
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); // 전원 버튼 입력
|
static const struct gpio_dt_spec power_btn = GPIO_DT_SPEC_GET(POWER_BTN_NODE, gpios); // 전원 버튼 입력
|
||||||
@@ -211,7 +212,7 @@ static void main_s(struct k_timer *timer)
|
|||||||
{
|
{
|
||||||
cnt_s++;
|
cnt_s++;
|
||||||
|
|
||||||
if (cnt_s == BOOT_THRESHOLD) // 임계 시간 도달 시 전원 ON 확정
|
if (cnt_s == POWER_ON_THRESHOLD) // 임계 시간 도달 시 전원 ON 확정
|
||||||
{
|
{
|
||||||
device_on = true;
|
device_on = true;
|
||||||
power_control_handler(ON, "button-2s-latch");
|
power_control_handler(ON, "button-2s-latch");
|
||||||
@@ -248,7 +249,7 @@ static void main_s(struct k_timer *timer)
|
|||||||
{
|
{
|
||||||
cnt_s++;
|
cnt_s++;
|
||||||
|
|
||||||
if (cnt_s >= BOOT_THRESHOLD)
|
if (cnt_s >= POWER_OFF_THRESHOLD)
|
||||||
{
|
{
|
||||||
battery_timer_stop();
|
battery_timer_stop();
|
||||||
k_work_submit(&adv_stop_work);
|
k_work_submit(&adv_stop_work);
|
||||||
@@ -364,7 +365,7 @@ void power_control_start(void)
|
|||||||
k_timer_start(&m_power_on_delay_timer, K_MSEC(POWER_ON_DELAY), K_NO_WAIT);
|
k_timer_start(&m_power_on_delay_timer, K_MSEC(POWER_ON_DELAY), K_NO_WAIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 소프트 리셋/DFU 리셋 후 버튼 없이 ON 상태 복구 */
|
/* soft reset/DFU reset/test image 부팅 시 버튼 없이 정상 ON 상태로 복구 */
|
||||||
void power_control_resume_after_reset(uint32_t reset_reason)
|
void power_control_resume_after_reset(uint32_t reset_reason)
|
||||||
{
|
{
|
||||||
device_on = true;
|
device_on = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user