189 lines
4.2 KiB
Markdown
189 lines
4.2 KiB
Markdown
# 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`
|
||
|
||
```c
|
||
#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 接收回调函数指针表
|
||
|
||
```c
|
||
// 编译期由 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 端口表
|
||
|
||
```c
|
||
#define DR_MAX_PORTS 64
|
||
static port_entry_t ports[DR_MAX_PORTS];
|
||
static uint8_t initialized;
|
||
```
|
||
|
||
---
|
||
|
||
## 3. API
|
||
|
||
### 3.1 端口管理
|
||
|
||
```c
|
||
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 发送触发
|
||
|
||
```c
|
||
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 接收回调
|
||
|
||
```c
|
||
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 发送
|
||
|
||
```plantuml
|
||
@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)
|
||
|
||
```plantuml
|
||
@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` 是零分支的查表路由:
|
||
|
||
```c
|
||
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 |
|