4.2 KiB
4.2 KiB
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 |