Files
DataRouter/DESIGN.md
7iwind 1c3e48d59f
CI / host (pull_request) Successful in 2s
CI / cortex-m (pull_request) Successful in 5s
feat: 新增接收dispatch反向路由
2026-07-30 10:49:44 +08:00

4.2 KiB
Raw Permalink Blame History

DataRouter 详细设计文档

1. 设计目标

轻量级 C 语言数据路由库。发送能力与接收能力分开声明,端口可独立设置 send_type 和 recv_type。发送时自动广播到所有匹配端口,接收时通过 dr_port_dispatch() 查表自动路由到回调。

核心设计

发送: dr_send_sensor(data, len)
        │
        ▼
    遍历端口表 → send_type 匹配?
        │
        ▼
    for each handler(port, data)  ─── UART / TCP / CAN

接收: dr_port_dispatch(port, data, len)
        │
        ▼
    查 recv_table[port.recv_type]
        │
        ▼
    dr_on_recv_rtcm(port, data, len)  ← 用户实现

2. 数据结构

2.1 port_entry_t

#define DR_MAX_HANDLERS_PER_PORT 4

typedef struct {
    int                send_type;   // DR_SEND_xxx / -1
    int                recv_type;   // DR_RECV_xxx / -1
    dr_send_handler_t  handlers[DR_MAX_HANDLERS_PER_PORT];
    int                count;
    uint8_t            in_use;
} port_entry_t;

2.2 接收回调函数指针表

// 编译期由 X-macro 生成,DR_RECV_rtcm 的枚举值即为数组下标
static void (*const recv_table[DR_RECV_CAP_COUNT])(uint32_t, const void*, size_t) = {
    dr_on_recv_rtcm,
    dr_on_recv_command,
};

2.3 端口表

#define DR_MAX_PORTS 64
static port_entry_t ports[DR_MAX_PORTS];
static uint8_t      initialized;

3. API

3.1 端口管理

dr_port_t dr_port_create(void);
void      dr_port_delete(dr_port_t port);

void      dr_port_set_send_type(port, int cap_id);
int       dr_port_get_send_type(port);
void      dr_port_set_recv_type(port, int cap_id);
int       dr_port_get_recv_type(port);

int       dr_port_add_handler(port, handler);
int       dr_port_remove_handler(port, handler);
void      dr_port_clear_handlers(port);
int       dr_port_handler_count(port);

void      dr_port_dispatch(port, data, len);  // ← 自动路由接收

3.2 发送触发

int dr_send_sensor(const void *data, size_t len);
int dr_send_status(const void *data, size_t len);

返回值:0 成功 / -1 未初始化 / -2 无匹配端口

3.3 接收回调

void dr_on_recv_rtcm(uint32_t port_id, const void *data, size_t len);
void dr_on_recv_command(uint32_t port_id, const void *data, size_t len);

4. 核心流程

4.1 发送

@startuml
actor App
participant dr_send_sensor as Send
participant ports[] as Table
participant handlers[] as H

App -> Send : send_sensor("temp", 9)
loop for p in 0..MAX_PORTS-1
  Send -> Table : in_use && send_type == SENSOR ?
  alt 匹配
    loop for h in handlers
      Send -> H : handlers[h](p, data, len)
    end
  end
end
alt 至少调了一次
  Send --> App : return 0
else 无匹配
  Send --> App : return -2
end
@enduml

4.2 接收(dispatch)

@startuml
actor 外设ISR as Dev
participant dr_port_dispatch as Dispatch
participant recv_table[] as Table
participant dr_on_recv_rtcm as Cb

Dev -> Dispatch : dispatch(port, data, len)
Dispatch -> Table : 查 recv_table[port.recv_type]
Dispatch -> Cb : recv_table[rid](port, data, len)
Cb --> Dev : void
@enduml

5. Dispatch 实现

dr_port_dispatch 是零分支的查表路由:

void dr_port_dispatch(dr_port_t port, const void *data, size_t len)
{
    if (!initialized) return;
    if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return;
    int rid = ports[port].recv_type;
    if (rid < 0 || rid >= DR_RECV_CAP_COUNT) return;
    recv_table[rid]((uint32_t)port, data, len);  // 直接函数指针调用
}

recv_table[] 是 const 数组,编译期由 X-macro 生成。DR_RECV_rtcm 的枚举值等于数组下标,查表时间为 O(1),无分支预测开销,适合 ISR。


6. 错误码

返回值 含义
0 成功
-1 库未初始化
-2 无端口匹配该 send_type

7. 约束

约束 说明
能力声明 编译期固定,修改需重新编译
最大端口数 默认 64,通过 -D 覆盖
每端口 handler 上限 默认 4,通过 -D 覆盖
线程安全 不支持(无锁),多线程需外部加锁
弱符号 GCC/Clang 原生支持
内存分配 纯静态,无 malloc/free