diff --git a/src/command/ble_cmd_queue.c b/src/command/ble_cmd_queue.c new file mode 100644 index 0000000..605e74f --- /dev/null +++ b/src/command/ble_cmd_queue.c @@ -0,0 +1,97 @@ +/******************************************************************************* + * @file ble_cmd_queue.c + * @brief BLE RX command queue + ******************************************************************************/ +#include +#include +#include + +#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); + } +} \ No newline at end of file diff --git a/src/command/ble_cmd_queue.h b/src/command/ble_cmd_queue.h new file mode 100644 index 0000000..62be35b --- /dev/null +++ b/src/command/ble_cmd_queue.h @@ -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 + +void ble_cmd_queue_init(void); +void ble_cmd_queue_rx_handler(const uint8_t *data, uint16_t len); + +#endif /* BLE_CMD_QUEUE_H__ */ \ No newline at end of file diff --git a/src/main.c b/src/main.c index 48423fb..47cb923 100644 --- a/src/main.c +++ b/src/main.c @@ -14,24 +14,12 @@ #include "led_control.h" #include "ble_service.h" #include "battery_adc.h" -#include "parser.h" +#include "ble_cmd_queue.h" #include "imu_i2c.h" #include "piezo_measure.h" 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 processing = false; // 센서 데이터 처리 중 플래그 bool bond_data_delete = true; // 본딩 데이터 삭제 요청 @@ -46,87 +34,6 @@ 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_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) { @@ -197,17 +104,6 @@ static void load_default_config(void) 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) { @@ -232,7 +128,7 @@ int main(void) DBG_CORE("[INIT] HW Init\r\n"); // 기본 하드웨어/센서 초기화 power_control_init(); - timers_init(); + ble_cmd_queue_init(); dfu_manager_init(); dfu_log_mcuboot_state(); load_default_config(); @@ -245,7 +141,7 @@ int main(void) // BLE 스택 + NUS DBG_CORE("[INIT] BLE Init\r\n"); - if (ble_service_init(ble_rx_handler) == 0) + if (ble_service_init(ble_cmd_queue_rx_handler) == 0) { DBG_CORE("[INIT] BLE - ble/nus OK\r\n"); // 소프트 리셋 후 서비스 복구