diff --git a/rt-thread-version/rt-thread-standard/_sidebar.md b/rt-thread-version/rt-thread-standard/_sidebar.md index f499dca77e6ec3fcc48383bc6816197b274216a7..1ebcd68e634d4731f27945c2f48528622be8211a 100644 --- a/rt-thread-version/rt-thread-standard/_sidebar.md +++ b/rt-thread-version/rt-thread-standard/_sidebar.md @@ -64,6 +64,7 @@ - [动态模块](/rt-thread-version/rt-thread-standard/programming-manual/dlmodule/dlmodule.md) - [POSIX接口](/rt-thread-version/rt-thread-standard/programming-manual/posix/posix.md) - [电源管理](/rt-thread-version/rt-thread-standard/programming-manual/pm/pm.md) + - [RT-Link 组件](/rt-thread-version/rt-thread-standard/programming-manual/rtlink/rtlink.md) - 软件包 - 物联网 diff --git "a/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/rtlink\345\272\224\347\224\250\346\241\206\346\236\266.jpg" "b/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/rtlink\345\272\224\347\224\250\346\241\206\346\236\266.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..29ef2ef2bb28551dc372ac9cfe946996f5f4f194 Binary files /dev/null and "b/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/rtlink\345\272\224\347\224\250\346\241\206\346\236\266.jpg" differ diff --git a/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/settings.jpg b/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/settings.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fa9f490bdf346682c7de2f3c4dbfe073436fe48e Binary files /dev/null and b/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/settings.jpg differ diff --git a/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/uart.jpg b/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/uart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..108f467b24a63c54f8d9d0e491fdbb1df50b8cfc Binary files /dev/null and b/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/uart.jpg differ diff --git "a/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/\346\224\266\345\217\221\346\265\213\350\257\225.jpg" "b/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/\346\224\266\345\217\221\346\265\213\350\257\225.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..e060f2fafa996cb93c18d2a8e0074565d5699e34 Binary files /dev/null and "b/rt-thread-version/rt-thread-standard/programming-manual/rtlink/figures/\346\224\266\345\217\221\346\265\213\350\257\225.jpg" differ diff --git a/rt-thread-version/rt-thread-standard/programming-manual/rtlink/rtlink.md b/rt-thread-version/rt-thread-standard/programming-manual/rtlink/rtlink.md new file mode 100644 index 0000000000000000000000000000000000000000..02223f0e2d165ccb51f8373832a89cb4951dea80 --- /dev/null +++ b/rt-thread-version/rt-thread-standard/programming-manual/rtlink/rtlink.md @@ -0,0 +1,243 @@ +# RT-Link 介绍 + +## 简介 + +RT-Link 是一套开放的链路层传输协议,设计的初衷是为了稳定、安全、高效率的完成设备间 点对点 的数据传输,并且接口简单、使用便捷。 + +## 目录结构 + +```shell +linklayer +├───hw_port // 对接硬件端口 +├───inc // 头文件 +├───src // rtlink源码文件 +├───Kconfig +└───SConscript +``` + +## 功能特点 + +- **稳定**:RT-Link 具有 数据重传、帧序号检查、状态同步等一系列能力,保证传输的稳定; +- **安全**:支持 CRC 校验,采用以太网检验协议; +- **高效**:协议头十分精简,只有 4 Byte,并且每一个 bit 位都有实际意义; +- **开放**:对下具有统一的操作API,可支持多种底层硬件接口,如UART、SPI、USB; +- **使用便捷**:对上只有 发送 和 注册接收回调 两个API,可以很方便的将 RT-Link 接入现有的上层应用中。具有很好的可移植性和兼容性。 + +# 工作原理 + +## 整体框架 +![rtlink整体框架](./figures/rtlink应用框架.jpg) + +最上层为 APP 应用服务层,提供发送和注册接收回调两个操作接口,使用非常便捷; +第二层为 RT-Link 传输层,是 RT-Link 核心功能的实现,用来保证数据传输功能的可靠稳定。 +第三层为 hardware 链路层,是用来对接具体的硬件端口,例如 UART、SPI、USB 等; +最下层为设备的 BSP 驱动层。 + + +# 使用指南 + +## 如何添加、使用 RT-Link + +这里以 studio 为例,在配置页找到 组件-->工具-->RT-Link,选择开启并进行配置。如下图所示。 +![rtlink整体框架](./figures/settings.jpg) + +- 配置 CRC 计算方式,软件 CRC 功能已包含在 RT-Link 中,硬件 CRC 需要根据不同平台自行对接相关接口; +- 配置设备名称及所使用的硬件接口,这里选择了 UART,如果需要添加其他端口可查看下方对应接口的介绍进行对接; +- 保存设置就可以将 RT-Link 添加到现在的工程中了,DEBUG 选项可根据调试需求选择开启,默认关闭。 + +- 还有一件事,别忘了打开要使用的硬件接口 +![rtlink整体框架](./figures/uart.jpg) + +- 这里选择了两块潘多拉开发板来测试运行效果,[示例代码](#示例代码) 在文档尾部↓↓↓。运行效果如下: +![rtlink整体框架](./figures/收发测试.jpg) + + +## 上层应用接口介绍 + +```c +/* rtlink init and deinit */ +int rt_link_init(void); +rt_err_t rt_link_deinit(void); +/* rtlink send data interface */ +rt_size_t rt_link_send(rt_link_service_t service, void *data, rt_size_t size); +/* rtlink service attach and detach */ +rt_err_t rt_link_service_attach(rt_link_service_t service, rt_err_t (*function)(void *data, rt_size_t size)); +rt_err_t rt_link_service_detach(rt_link_service_t service); +``` + +### 初始化 +```c +int rt_link_init(void); +``` +默认为自动初始化,可根据具体应用决定是否开启自动初始化,如需关闭自动初始化可在 `rtlink.h` 中注释掉宏定义 `RT_LINK_AUTO_INIT` +| 返回值 | 描述 | +| ------ | ---------- | +| RT_EOK | 初始化成功 | +| -RT_ENOMEM | 内存不足,空间申请失败 | +| -RT_ERROR | 初始化失败 | + +### 去初始化 +```c +rt_err_t rt_link_deinit(void); +``` +当不需要使用 RT-Link 时,可执行 deinit 删除处理线程,释放系统资源。 +| 返回值 | 描述 | +| ------ | ---------- | +| RT_EOK | 去初始化成功 | + +### 注册服务接收回调 +```c +rt_err_t rt_link_service_attach(rt_link_service_t service, rt_err_t (*function)(void *data, rt_size_t size)); +``` +```c +typedef enum +{ + RT_LINK_SERVICE_RTLINK = 0, + RT_LINK_SERVICE_LINK_SOCKET = 1, + RT_LINK_SERVICE_LINK_WIFI = 2, + RT_LINK_SERVICE_LINK_MNGT = 3, + RT_LINK_SERVICE_LINK_MSHTOOLS = 4, + RT_LINK_SERVICE_MAX +}rt_link_service_t; +``` + +| 参数 | 描述 | +| ------ | ---------- | +| service | 要注册的服务通道,可在`rt_link_service_t`中选择,或添加自定义服务类型 | +| function | 服务对应的接收回调函数,接收回调的参数为 `void *data, rt_size_t size`,返回值为 `rt_err_t` 类型,需要注意的是 **data 指向的空间由 RT-link 动态申请,应用层使用完毕后自行释放** | + +| 返回值 | 描述 | +| ------ | ---------- | +| RT_EOK | 注册成功 | + + +### 解除服务接收通道 +```c +rt_err_t rt_link_service_detach(rt_link_service_t service); +``` +| 参数 | 描述 | +| ------ | ---------- | +| service | 要解除的服务通道 | + +| 返回值 | 描述 | +| ------ | ---------- | +| RT_EOK | 解除成功 | + + +### 发送数据 +```c +rt_size_t rt_link_send(rt_link_service_t service, void *data, rt_size_t size); +``` +| 参数 | 描述 | +| ------ | ---------- | +| service | 数据所属的服务通道 | +| data | 发送的数据 | +| size | 数据的长度 | + +| 返回值 | 描述 | +| ------ | ---------- | +| 0 | 发送失败 | +| size | 发送的数据长度 | + + +## 底层链路对接接口介绍 +底层链路对接接口定义在 `rtlink_port.h` 中,需要在对接移植是实现。 +```c +/* Functions that need to be implemented at the hardware */ +int rt_link_port_init(void); +int rt_link_port_deinit(void); +rt_size_t rt_link_port_send(void *data, rt_size_t length); + +/* Called when the hardware receives data and the data is transferred to RTLink */ +rt_size_t rt_link_hw_write_cb(void *data, rt_size_t length); +``` + +### 初始化与去初始化 +```c +int rt_link_port_init(void); +int rt_link_port_deinit(void); +``` +主要用于初始化底层端口的资源,在 RT-Link 初始化和去初始化时会调用,这部分是需要在移植对接时自行实现。对于 UART、SPI 等在 RT-Thread 中则可使用 device 框架提供的相关接口。 + +### 数据发送 +```c +rt_size_t rt_link_port_send(void *data, rt_size_t length); +``` +此函数将会由 RT-Link 的核心逻辑调用,用于通过实际的端口发送数据。对于 UART 这类比较 **简单的** 接口,可以直接发送,不会影响系统的运行。对于比较 **复杂的** 通信接口,例如 **SPI, USB** 等可以通过事件、邮箱等机制来实现发送逻辑。 + +| 参数 | 描述 | +| ------ | ---------- | +| data | 发送的数据 | +| length | 数据的长度 | + +| 返回值 | 描述 | +| ------ | ---------- | +| 0 | 发送失败 | +| length | 发送的数据长度 | + + +### 数据写入 +```c +rt_size_t rt_link_hw_write_cb(void *data, rt_size_t length); +``` +在底层接口接收到数据时,可以直接调用该函数来向 RT-Link 发送数据,向上层服务提供接收的数据。 **该函数可在中断内直接调用。** + +| 参数 | 描述 | +| ------ | ---------- | +| data | 写入的数据 | +| length | 数据的长度 | + +| 返回值 | 描述 | +| ------ | ---------- | +| 0 | 写入失败 | +| > 0 | 实际写入的数据长度 | + + + +# 示例代码 + +```c +#include +#include + +#define DBG_ENABLE +#define DBG_TAG "rtlink" +#define DBG_LVL DBG_LOG +#include + +#define TEST_CONTEXT "This message is sent by RT-Link" + +rt_err_t rt_link_receive_example_callback(void *data, rt_size_t length) +{ + LOG_I("recv data %d",length); + LOG_HEX("example",8,data,length); /* 使用此接口打印 16 进制数据需要开启 ulog 组件*/ + rt_free(data); /* data 指向的空间由 rtlink 动态申请,应用层使用完毕后自行释放 */ + return RT_EOK; +} + +int rt_link_example_send(int argc, char **argv) +{ + char *receive = RT_NULL; + rt_size_t length = 0; + + if(argc == 1) + { + receive = rt_malloc(sizeof(TEST_CONTEXT)); + rt_memcpy(receive, TEST_CONTEXT, sizeof(TEST_CONTEXT) - 1); + length = rt_link_send(RT_LINK_SERVICE_RTLINK, receive, sizeof(TEST_CONTEXT) - 1); + LOG_I("send data length: %d.", length); + rt_free(receive); + } + return 0; +} +MSH_CMD_EXPORT(rt_link_example_send, rt link layer send test); + +int rt_link_example_init(void) +{ + /* 注册应用服务与接收回调 */ + rt_link_service_attach(RT_LINK_SERVICE_RTLINK, rt_link_receive_example_callback); + return RT_EOK; +} +MSH_CMD_EXPORT(rt_link_example_init, rt link layer example init); +``` +