BLE RX 명령 큐 모듈 분리
This commit is contained in:
@@ -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__ */
|
||||
Reference in New Issue
Block a user