Skip to content

Commit c3816a4

Browse files
committed
Enhance core operation model and documentation
1 parent 50fe713 commit c3816a4

37 files changed

Lines changed: 883 additions & 303 deletions

File tree

docs/basic_coding/core/core-assert.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ sidebar_position: 2
1111
## 致命错误处理接口
1212

1313
```cpp
14-
void libxr_fatal_error(const char *file, uint32_t line, bool in_isr);
14+
extern "C" void libxr_fatal_error(const char *file, uint32_t line, bool in_isr);
1515
```
1616
1717
该函数用于终止程序执行,可在正常或回调上下文中调用。发生断言失败时将自动调用,并可通过 `Assert` 类注册回调处理。

docs/basic_coding/core/core-cb.md

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,58 @@ template <typename ArgType, typename... Args>
1515
class CallbackBlock;
1616
```
1717

18-
用于封装一个具体的回调函数及其第一个绑定参数,支持中断上下文安全调用
18+
用于封装一个具体的回调函数及其第一个绑定参数,并提供重入保护(reentrancy guard),可在 ISR 或任务上下文触发
1919

2020
- `FunctionType`: 回调函数签名为 `void(bool in_isr, ArgType arg, Args... args)`
21-
- `Call(bool in_isr, Args&&...)`: 执行回调,传递额外参数
21+
- `Call(bool in_isr, Args... args)`: 触发回调执行,并透传额外参数
2222

2323
构造时即完成函数与绑定参数的绑定。支持移动构造与移动赋值,禁用拷贝。
2424

25+
### 重入保护语义
26+
27+
重入保护用于抑制回调链形成环时的栈递归增长(例如 A → B → C → A,使同一回调在其执行期间被间接再次触发)。
28+
29+
当同一 `CallbackBlock` 处于执行状态时再次触发:
30+
31+
- 不会形成新的嵌套调用栈帧(不递归调用);
32+
- 仅保留一次“待执行请求”(保存一份参数快照;后续重入会覆盖旧的待执行参数);
33+
- 当前执行结束后在同一调用点以循环方式补跑(trampoline 扁平化),直到没有待执行请求为止,从而避免无限嵌套。
34+
35+
> 备注:为缓存待执行参数,内部对 `Args...``std::decay_t` 形式按值保存一份可复制的参数快照。
36+
2537
## Callback
2638

2739
```cpp
2840
template <typename... Args>
2941
class Callback;
3042
```
3143

32-
`CallbackBlock` 的进一步封装,提供统一接口、类型擦除和创建工厂方法
44+
`CallbackBlock` 的进一步封装,提供统一接口、类型擦除和创建工厂方法
3345

3446
### 创建回调
3547

3648
```cpp
3749
LibXR::Callback<Args...> cb = LibXR::Callback<Args...>::Create(fun, bound_arg);
3850
```
3951

40-
- `fun`: 回调函数,格式为 `void(bool, BoundArgType, Args...)`
52+
- `fun`: 回调函数,格式为 `void(bool, BoundArgType, Args...)`,并且需要**可转换为函数指针**(例如普通函数、静态成员函数、无捕获 lambda 等)。
4153
- `bound_arg`: 回调函数的第一个绑定参数
4254

55+
> 注意:当前 `Create` 的实现会 `new CallbackBlock<BoundArgType, Args...>`,因此**包含动态内存分配**;同时 `Callback` 本身不管理释放。
56+
4357
### 执行回调
4458

4559
```cpp
4660
cb.Run(in_isr, arg1, arg2, ...);
4761
```
4862

49-
可传递任意数量的附加参数`in_isr` 指示是否在中断上下文中调用
63+
可传递附加参数`in_isr` 指示调用上下文;若回调为空,`Run` 为安全的空操作(no-op)
5064

51-
### 其他接口
65+
### 其他接口与语义
5266

53-
- `Empty()`: 判断回调是否为空
67+
- `Empty()`: 判断回调是否为空(内部 `cb_block_ == nullptr`
5468
- 支持默认构造、拷贝构造、移动构造与赋值
69+
- 拷贝为浅拷贝:多个 `Callback` 实例会共享同一回调块指针与调用入口。
5570

5671
## 使用示例
5772

@@ -72,10 +87,10 @@ ISR=0 context=42 msg=Hello
7287

7388
## 设计特点
7489

75-
- **无动态内存管理需求**除非用户自定义 CallbackBlock 派生类
76-
- **支持 ISR 上下文**:可在中断中安全调用
77-
- **类型安全封装**利用模板与类型推导实现参数绑定
78-
- **适用于嵌入式场景**非常轻量,占用资源小
90+
- **重入保护**回调重入时不递归,缓存一次待执行请求并在当前调用点补跑(trampoline 扁平化)
91+
- **支持 ISR 上下文**接口显式携带 `in_isr`可在中断中安全调用
92+
- **类型安全封装**利用模板与类型推导实现参数绑定与调用
93+
- **轻量可嵌入**结构简单,适用于 IO、定时器、事件发布等模块的回调传递
7994

8095
---
8196

docs/basic_coding/core/core-def.md

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,29 @@ sidebar_position: 1
2929

3030
枚举类型 `ErrorCode` 定义了统一的错误码系统,用于表示各类操作结果:
3131

32-
| 名称 || 含义 |
33-
|--------------|------|--------------------|
34-
| `OK` | 0 | 操作成功 |
35-
| `FAILED` | -1 | 操作失败 |
36-
| `INIT_ERR` | -2 | 初始化错误 |
37-
| `ARG_ERR` | -3 | 参数错误 |
38-
| `STATE_ERR` | -4 | 状态错误 |
39-
| `SIZE_ERR` | -5 | 尺寸错误 |
40-
| `CHECK_ERR` | -6 | 校验失败 |
41-
| `NOT_SUPPORT`| -7 | 功能不支持 |
42-
| `NOT_FOUND` | -8 | 未找到对象 |
43-
| `NO_RESPONSE` | -9 | 无响应 |
44-
| `NO_MEM` | -10 | 内存不足 |
45-
| `NO_BUFF` | -11 | 缓冲区不足 |
46-
| `TIMEOUT` | -12 | 操作超时 |
47-
| `EMPTY` | -13 | 数据为空 |
48-
| `FULL` | -14 | 数据已满 |
49-
| `BUSY` | -15 | 资源忙碌中 |
50-
| `PTR_NULL` | -16 | 空指针错误 |
51-
| `OUT_OF_RANGE`| -17 | 超出有效范围 |
32+
| 名称 || 含义 |
33+
| -------------- | --- | ------------ |
34+
| `PENDING` | 1 | 操作进行中 |
35+
| `OK` | 0 | 操作成功 |
36+
| `FAILED` | -1 | 操作失败 |
37+
| `INIT_ERR` | -2 | 初始化错误 |
38+
| `ARG_ERR` | -3 | 参数错误 |
39+
| `STATE_ERR` | -4 | 状态错误 |
40+
| `SIZE_ERR` | -5 | 尺寸错误 |
41+
| `CHECK_ERR` | -6 | 校验失败 |
42+
| `NOT_SUPPORT` | -7 | 功能不支持 |
43+
| `NOT_FOUND` | -8 | 未找到对象 |
44+
| `NO_RESPONSE` | -9 | 无响应 |
45+
| `NO_MEM` | -10 | 内存不足 |
46+
| `NO_BUFF` | -11 | 缓冲区不足 |
47+
| `TIMEOUT` | -12 | 操作超时 |
48+
| `EMPTY` | -13 | 数据为空 |
49+
| `FULL` | -14 | 数据已满 |
50+
| `BUSY` | -15 | 资源忙碌中 |
51+
| `PTR_NULL` | -16 | 空指针错误 |
52+
| `OUT_OF_RANGE` | -17 | 超出有效范围 |
53+
54+
约定:正值通常用于表示“非终态/进行中”(例如 `PENDING`),0 表示成功,负值表示失败原因。
5255

5356
## 尺寸限制模式(`SizeLimitMode`
5457

docs/basic_coding/core/core-mem.md

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,70 @@ sidebar_position: 11
44
title: 快速内存拷贝
55
---
66

7-
# Memory FastCopy
7+
# Memory FastCopy / FastSet / FastCmp
88

9-
`LibXR::Memory::FastCopy`
10-
是一条经过对齐与突发(burst)拷贝优化的内存复制路径,用于替代通用 `memcpy` 的热路径场景(如环形缓冲搬运、IO 收发缓存打包等)。它会根据源/目的指针的对齐关系,自动选择 8/4/2/1 字节的最优拷贝粒度,并进行环路展开以提升吞吐。
9+
`LibXR::Memory` 提供一组经过对齐与突发(burst)优化的内存操作路径,用于替代通用 `memcpy / memset / memcmp` 的热路径场景(如环形缓冲搬运、IO 收发缓存打包等)。实现会根据源/目的指针的对齐关系,自动选择更优的 8/4/2/1 字节粒度,并进行环路展开以提升吞吐。
1110

12-
> 本实现仅面向非重叠(non-overlapping)的拷贝语义。
11+
> `FastCopy` 仅面向非重叠(non-overlapping)的拷贝语义。
1312
1413
## API
1514

16-
``` cpp
15+
```cpp
1716
namespace LibXR {
1817
class Memory {
1918
public:
2019
/**
21-
* @brief 快速内存拷贝
20+
* @brief 快速内存拷贝(非重叠语义)
2221
* @param dst 目标地址
2322
* @param src 源地址
2423
* @param size 拷贝字节数
2524
*/
2625
static void FastCopy(void* dst, const void* src, size_t size);
26+
27+
/**
28+
* @brief 快速内存填充(类似 memset)
29+
* @param dst 目标地址
30+
* @param value 填充值(按字节重复)
31+
* @param size 填充字节数
32+
*/
33+
static void FastSet(void* dst, uint8_t value, size_t size);
34+
35+
/**
36+
* @brief 快速内存比较(类似 memcmp)
37+
* @param a 地址 A
38+
* @param b 地址 B
39+
* @param size 比较字节数
40+
* @return 0 表示相等;非 0 表示不等,符号与差值语义与 memcmp 一致(首个不同字节的差)
41+
*/
42+
static int FastCmp(const void* a, const void* b, size_t size);
2743
};
2844
} // namespace LibXR
2945
```
3046
47+
## FastCopy 语义说明
48+
49+
- 若 `dst` 与 `src` 具有相同的对齐相位(alignment offset),会先处理头部非对齐字节,然后进入按 `LIBXR_ALIGN_SIZE`(通常为 8 或 4)为粒度的突发拷贝,并做 8 倍展开。
50+
- 若两者对齐相位不同,会根据地址差尽可能选择更大的粒度:
51+
- 在 `LIBXR_ALIGN_SIZE == 8` 且地址差为 4 的倍数时,可退化为 4 字节突发拷贝;
52+
- 地址差为偶数时,可退化为 2 字节突发拷贝;
53+
- 其它情况回退到按字节复制。
54+
- 末尾不足一个“宽拷贝”粒度的部分会以字节方式补齐。
55+
56+
## FastSet 语义说明
57+
58+
- `size == 0` 时直接返回。
59+
- 先写入头部字节直到对齐,然后使用按 `LIBXR_ALIGN_SIZE`(8 或 4)宽度的 pattern 批量写入,并做 8 倍展开,最后写入尾部字节。
60+
61+
## FastCmp 语义说明
62+
63+
- 返回值语义与 `memcmp(a, b, size)` 一致:返回 0 表示相等;非 0 表示不等。
64+
- `size == 0` 或 `a == b` 时返回 0。
65+
- 在对齐条件满足时会进入按 `LIBXR_ALIGN_SIZE`(8 或 4)宽度的比较路径,并做 8 倍展开;一旦发现某个宽字不等,会回退到该宽字范围内的逐字节比较以获得与 `memcmp` 一致的返回值。
66+
- 对齐条件不满足时会回退到逐字节比较。
67+
3168
## 使用示例
3269
33-
``` cpp
70+
```cpp
3471
#include "libxr_def.hpp"
3572
3673
uint8_t src[256];
@@ -40,4 +77,17 @@ uint8_t dst[256];
4077
4178
// 非重叠快速复制
4279
LibXR::Memory::FastCopy(dst, src, sizeof(src));
80+
81+
// 快速填充
82+
LibXR::Memory::FastSet(dst, 0x00, sizeof(dst));
83+
84+
// 快速比较
85+
int diff = LibXR::Memory::FastCmp(dst, src, sizeof(src));
86+
if (diff == 0) {
87+
// equal
88+
} else if (diff < 0) {
89+
// dst < src
90+
} else {
91+
// dst > src
92+
}
4393
```

docs/basic_coding/core/core-op.md

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ sidebar_position: 9
66

77
# Operation 操作模型
88

9-
本模块定义了通用的 `Operation<Args...>` 模板类,用于描述具有完成反馈机制的异步操作。支持回调(Callback)、阻塞(Block)、轮询(Polling)三种模式,适用于嵌入式 I/O 操作中的统一完成处理。
9+
本模块定义通用的 `Operation<T>` 模板类,用于描述具有完成反馈机制的异步操作。支持回调(Callback)、阻塞(Block)、轮询(Polling)三种模式,适用于嵌入式 I/O 操作中的统一完成处理。
10+
11+
其中 `ReadOperation` / `WriteOperation` 是对 `Operation<ErrorCode>` 的别名,用于 I/O 完成时回传 `ErrorCode`
1012

1113
## 操作模式
1214

@@ -16,7 +18,7 @@ sidebar_position: 9
1618
enum class OperationType : uint8_t {
1719
CALLBACK, // 使用回调函数处理完成事件
1820
BLOCK, // 使用信号量阻塞等待
19-
POLLING, // 轮询标志位
21+
POLLING, // 轮询状态变量
2022
NONE // 不处理完成
2123
};
2224
```
@@ -27,7 +29,8 @@ enum class OperationType : uint8_t {
2729
enum class OperationPollingStatus : uint8_t {
2830
READY,
2931
RUNNING,
30-
DONE
32+
DONE,
33+
ERROR
3134
};
3235
```
3336

@@ -40,23 +43,32 @@ Operation();
4043
// 构造阻塞操作
4144
Operation(Semaphore &sem, uint32_t timeout = UINT32_MAX);
4245

43-
// 构造回调操作
44-
Operation(Callback<Args...> &cb);
46+
// 构造回调操作(T 为回调参数类型)
47+
Operation(Callback<T> &cb);
4548

4649
// 构造轮询操作
4750
Operation(OperationPollingStatus &status);
4851
```
4952
53+
另外,`Operation` 支持从另一个 `Operation` 实例初始化(复制/移动语义等价于赋值)。
54+
5055
## 状态更新
5156
5257
```cpp
53-
void UpdateStatus(bool in_isr, Args&&... args);
58+
template <typename Status>
59+
void UpdateStatus(bool in_isr, Status&& status);
60+
5461
void MarkAsRunning();
5562
```
5663

57-
- `UpdateStatus(...)` 会根据操作类型触发回调、释放信号量或设置轮询状态。
58-
- `MarkAsRunning()` 在 POLLING 模式下设置状态为 RUNNING。
59-
- 这两个函数通常由驱动主动调用,用户无需关心。
64+
- `UpdateStatus(...)` 会根据操作类型触发回调、解除阻塞或更新轮询状态:
65+
- CALLBACK:调用 `cb.Run(in_isr, status)`,其中 `status` 作为 `T` 类型的完成状态传递给回调。
66+
- BLOCK:调用信号量的 `PostFromCallback(in_isr)` 解除阻塞等待(完成状态本身不参与阻塞唤醒语义)。
67+
- POLLING:更新轮询状态变量 `OperationPollingStatus`:当 `status` 表示成功时置为 `DONE`,否则置为 `ERROR`。该规则对任意 `T` 一致;约定以 “0” 表示成功(例如 `ErrorCode::OK == 0` 或其它状态类型的 0 值)。
68+
- `MarkAsRunning()` 在 POLLING 模式下设置状态为 `RUNNING`
69+
-`in_isr == true` 且操作类型为 `BLOCK` 会主动断言失败。
70+
- 这两个函数通常由驱动/端口在合适的时机调用;用户侧只需选择合适的 `OperationType` 并传入即可。
71+
6072

6173
## 示例用法
6274

@@ -68,7 +80,7 @@ WriteOperation op_block(sem, 100);
6880
write_port(data, op_block);
6981
```
7082
71-
### 回调方式读取数据
83+
### 回调方式读取完成反馈
7284
7385
```cpp
7486
auto cb = Callback<ErrorCode>::Create([](bool in_isr, int context, ErrorCode ec) {
@@ -88,10 +100,12 @@ read_port(buffer, op_poll);
88100

89101
// 后续通过 status 查询是否完成
90102
if (status == LibXR::ReadOperation::OperationPollingStatus::DONE) {
91-
// 数据已读取完成
103+
// 成功完成
104+
} else if (status == LibXR::ReadOperation::OperationPollingStatus::ERROR) {
105+
// 完成但发生错误
92106
}
93107
```
94108
95109
---
96110
97-
`Operation` 是 LibXR I/O 操作的基础机制,适用于串口、网络、定时器等模块,统一管理完成行为,确保线程、中断上下文均安全
111+
`Operation` 是 LibXR I/O 操作的基础机制,适用于串口、网络、定时器等模块,统一管理完成行为,确保线程与中断上下文均安全

docs/basic_coding/core/core-pipe.md

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ sidebar_position: 12
1313
## 特性概览
1414

1515
- **零额外拷贝**:写端写入 → 直接进入共享队列 → 读端从同一队列取出。
16-
- **ISR 友好**可配置 `in_isr` 标志,使推进读端的过程遵循中断上下文限制
16+
- **ISR 友好**读端推进通过 `ProcessPendingReads(in_isr)`,可在 ISR 或任务上下文中触发
1717
- **语义与 `ReadPort`/`WritePort` 一致**:阻塞/回调/轮询等完成方式统一由 `Operation` 控制。
1818

1919
---
@@ -23,13 +23,13 @@ sidebar_position: 12
2323
```cpp
2424
class Pipe {
2525
public:
26-
// 使用给定共享数据队列容量(字节)构造;in_isr = true 表示回调可能在中断上下文执行
27-
Pipe(size_t buffer_size, bool in_isr = false);
26+
// 使用给定共享数据队列容量(字节)构造
27+
Pipe(size_t buffer_size);
2828

2929
// 非拷贝/非赋值
3030
Pipe(const Pipe&) = delete;
3131
Pipe& operator=(const Pipe&) = delete;
32-
~Pipe() = default;
32+
~Pipe();
3333

3434
// 端口访问
3535
ReadPort& GetReadPort();
@@ -38,6 +38,28 @@ public:
3838
```
3939
4040
- `buffer_size`:共享队列总容量(字节),用于承载写入的数据。创建后不可更改。
41-
- `in_isr`:指示 `WriteFun` 推进读端时是否按 ISR 语义处理(例如避免阻塞/仅做必要推进)。
41+
- `Pipe` 不直接暴露 `Size()/Reset()` 等方法——请通过 `GetReadPort()` / `GetWritePort()` 使用对应端口接口。
42+
43+
---
44+
45+
## 使用方式
46+
47+
把 `Pipe` 当作“自带回环驱动”的内存管道使用:写端写入会触发 `WriteFun`,进而推进读端处理挂起读取。
48+
49+
```cpp
50+
LibXR::Pipe pipe(256);
51+
52+
auto& r = pipe.GetReadPort();
53+
auto& w = pipe.GetWritePort();
54+
55+
// 典型:先发起读(可能进入 PENDING),再写入推进
56+
uint8_t buf[16];
57+
LibXR::ReadOperation rop(status_or_cb_or_sem);
58+
LibXR::WriteOperation wop(status_or_cb_or_sem);
59+
60+
r({buf, sizeof(buf)}, rop); // 可能挂起
61+
w({some_data, some_len}, wop); // 写入后会推进 r.ProcessPendingReads(...)
62+
```
63+
64+
> 备注:`Pipe` 的读侧是“被动推进”的:需要写侧触发(或外部主动调用 `ProcessPendingReads`)才能完成挂起读请求;这一点与 `ReadPort` 的模型保持一致。
4265

43-
> `Pipe` 不直接暴露 Size/Reset 等方法——请通过 `GetReadPort()` / `GetWritePort()` 使用对应端口接口。

0 commit comments

Comments
 (0)