Browse Source

Merge pull request #4931 from ShermanShao/master

[components]rt-link v0.2.0 新特性:
Bernard Xiong 3 years ago
parent
commit
9cbb6a741c

+ 0 - 15
components/utilities/rt-link/Kconfig

@@ -14,21 +14,6 @@ if RT_USING_RT_LINK
             bool "use hardware crc device"
             bool "use hardware crc device"
     endchoice
     endchoice
 
 
-    menu "rt-link hardware device configuration"
-        config RT_LINK_HW_DEVICE_NAME
-            string "the name of base actual device"
-            default "uart2"
-
-        choice
-            prompt"hardware device is spi, uart or usb"
-            default RT_LINK_USING_UART
-
-            config RT_LINK_USING_UART
-                bool "use UART"
-        endchoice
-
-    endmenu
-
     menu "rt link debug option"
     menu "rt link debug option"
         config USING_RT_LINK_DEBUG
         config USING_RT_LINK_DEBUG
             bool "Enable RT-Link debug"
             bool "Enable RT-Link debug"

+ 0 - 14
components/utilities/rt-link/hw_port/SConscript

@@ -1,14 +0,0 @@
-import os
-from building import *
-import rtconfig
-
-cwd  = GetCurrentDir()
-src  = []
-CPPPATH = []
-
-if GetDepend('RT_LINK_USING_UART'):
-    src += ['uart/rtlink_port_uart.c']
-
-group = DefineGroup('rt-link-port', src, depend = ['RT_USING_RT_LINK'], CPPPATH = CPPPATH)
-
-Return('group')

+ 0 - 73
components/utilities/rt-link/hw_port/uart/rtlink_port_uart.c

@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date           Author       Notes
- * 2020-12-09     xiangxistu   the first version
- */
-
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#include <rtlink_port.h>
-
-#ifndef RT_LINK_HW_DEVICE_NAME
-    #define RT_LINK_HW_DEVICE_NAME "uart2"
-#endif
-
-#define DBG_TAG              "rtlink_port"
-#define DBG_LVL              DBG_INFO
-#include <rtdbg.h>
-
-static struct rt_device *hw_device = RT_NULL;
-rt_err_t rt_link_port_rx_ind(rt_device_t device, rt_size_t size)
-{
-    RT_ASSERT(device != RT_NULL);
-
-    rt_uint8_t buffer[RT_SERIAL_RB_BUFSZ] = {0};
-    rt_size_t length = 0;
-    length = rt_device_read(device, 0, buffer, sizeof(buffer));
-    rt_link_hw_write_cb(&buffer, length);
-    return RT_EOK;
-}
-
-rt_size_t rt_link_port_send(void *data, rt_size_t length)
-{
-    rt_size_t size = 0;
-    size = rt_device_write(hw_device, 0, data, length);
-    return size;
-}
-
-int rt_link_port_init(void)
-{
-    hw_device = rt_device_find(RT_LINK_HW_DEVICE_NAME);
-    if (hw_device)
-    {
-        rt_device_open(hw_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
-        rt_device_set_rx_indicate(hw_device, rt_link_port_rx_ind);
-    }
-    else
-    {
-        LOG_E("Not find device %s", RT_LINK_HW_DEVICE_NAME);
-        return -RT_ERROR;
-    }
-    return RT_EOK;
-}
-
-int rt_link_port_deinit(void)
-{
-    hw_device = rt_device_find(RT_LINK_HW_DEVICE_NAME);
-    if (hw_device)
-    {
-        rt_device_close(hw_device);
-        rt_device_set_rx_indicate(hw_device, RT_NULL);
-    }
-    else
-    {
-        LOG_E("Not find device %s", RT_LINK_HW_DEVICE_NAME);
-        return -RT_ERROR;
-    }
-    return RT_EOK;
-}

+ 107 - 72
components/utilities/rt-link/inc/rtlink.h

@@ -14,81 +14,102 @@
 
 
 #include <rtdef.h>
 #include <rtdef.h>
 
 
+#define RT_LINK_VER     "0.2.0"
+
 #define RT_LINK_AUTO_INIT
 #define RT_LINK_AUTO_INIT
 
 
-#define RT_LINK_FRAME_HEAD                 0x15
-#define RT_LINK_FRAME_HEAD_MASK            0x1F
-#define RT_LINK_MAX_DATA_LENGTH            2044 /*can exact divide by 4 bytes*/
-#define RT_LINK_FRAMES_MAX   0x03   /* The maximum number of split frames for a long package*/
+#define RT_LINK_FLAG_ACK            0x01
+#define RT_LINK_FLAG_CRC            0x02
+
+#define RT_LINK_FRAME_HEAD          0x15
+#define RT_LINK_FRAME_HEAD_MASK     0x1F
+/* The maximum number of split frames for a long package */
+#define RT_LINK_FRAMES_MAX          0x03
+/* The length in the rt_link_frame_head structure occupies 11 bits,
+so the value range after 4-byte alignment is 0-2044.*/
+#define RT_LINK_MAX_FRAME_LENGTH    1024
 
 
-#define RT_LINK_ACK_MAX   0x07
+#define RT_LINK_ACK_MAX             0x07
 #define RT_LINK_CRC_LENGTH          4
 #define RT_LINK_CRC_LENGTH          4
 #define RT_LINK_HEAD_LENGTH         4
 #define RT_LINK_HEAD_LENGTH         4
-#define RT_LINK_MAX_EXTEND_LENGTH       4
-#define RT_LINK_MAX_FRAME_LENGTH        (RT_LINK_HEAD_LENGTH + RT_LINK_MAX_EXTEND_LENGTH + RT_LINK_MAX_DATA_LENGTH + RT_LINK_CRC_LENGTH)
-#define RT_LINK_RECEIVE_BUFFER_LENGTH       (RT_LINK_MAX_FRAME_LENGTH * RT_LINK_FRAMES_MAX + RT_LINK_HEAD_LENGTH + RT_LINK_MAX_EXTEND_LENGTH)
+#define RT_LINK_EXTEND_LENGTH       4
+
+#define RT_LINK_MAX_DATA_LENGTH         (RT_LINK_MAX_FRAME_LENGTH - \
+                                        RT_LINK_HEAD_LENGTH - \
+                                        RT_LINK_EXTEND_LENGTH - \
+                                        RT_LINK_CRC_LENGTH)
+#define RT_LINK_RECEIVE_BUFFER_LENGTH   (RT_LINK_MAX_FRAME_LENGTH * \
+                                        RT_LINK_FRAMES_MAX + \
+                                        RT_LINK_HEAD_LENGTH + \
+                                        RT_LINK_EXTEND_LENGTH)
 
 
 typedef enum
 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;
+    RT_LINK_SERVICE_RTLINK   = 0,
+    RT_LINK_SERVICE_SOCKET   = 1,
+    RT_LINK_SERVICE_WIFI     = 2,
+    RT_LINK_SERVICE_MNGT     = 3,
+    RT_LINK_SERVICE_MSHTOOLS = 4,
 
 
-enum
-{
-    FRAME_EXTEND = 1 << 0,
-    FRAME_CRC    = 1 << 1,
-    FRAME_ACK    = 1 << 2
-};
+    /* Expandable to a maximum of 31 */
+    RT_LINK_SERVICE_MAX
+} rt_link_service_e;
 
 
 typedef enum
 typedef enum
 {
 {
-    RT_LINK_RESERVE_FRAME = 0,
+    RT_LINK_RESEND_FRAME     = 0,
+    RT_LINK_CONFIRM_FRAME    = 1,
+
+    RT_LINK_HANDSHAKE_FRAME  = 2,
+    RT_LINK_DETACH_FRAME     = 3,   /* service is not online */
+    RT_LINK_SESSION_END      = 4,   /* The retring failed to end the session */
 
 
-    RT_LINK_RESEND_FRAME,
-    RT_LINK_CONFIRM_FRAME,
-    RT_LINK_SHORT_DATA_FRAME,
-    RT_LINK_LONG_DATA_FRAME,
-    RT_LINK_SESSION_END,  /* The retring failed to end the session */
+    RT_LINK_LONG_DATA_FRAME  = 5,
+    RT_LINK_SHORT_DATA_FRAME = 6,
 
 
-    RT_LINK_HANDSHAKE_FRAME
-} rt_link_frame_attribute_t;
+    RT_LINK_RESERVE_FRAME    = 7
+} rt_link_frame_attr_e;
 
 
 typedef enum
 typedef enum
 {
 {
     /* receive event */
     /* receive event */
-    RT_LINK_READ_CHECK_EVENT            = 1 << 0,
-    RT_LINK_RECV_TIMEOUT_FRAME_EVENT    = 1 << 1,
-    RT_LINK_RECV_TIMEOUT_LONG_EVENT     = 1 << 2,
+    RT_LINK_READ_CHECK_EVENT          = 1 << 0,
+    RT_LINK_RECV_TIMEOUT_FRAME_EVENT  = 1 << 1,
+    RT_LINK_RECV_TIMEOUT_LONG_EVENT   = 1 << 2,
 
 
     /* send event */
     /* send event */
     RT_LINK_SEND_READY_EVENT    = 1 << 4,
     RT_LINK_SEND_READY_EVENT    = 1 << 4,
     RT_LINK_SEND_OK_EVENT       = 1 << 5,
     RT_LINK_SEND_OK_EVENT       = 1 << 5,
     RT_LINK_SEND_FAILED_EVENT   = 1 << 6,
     RT_LINK_SEND_FAILED_EVENT   = 1 << 6,
     RT_LINK_SEND_TIMEOUT_EVENT  = 1 << 7
     RT_LINK_SEND_TIMEOUT_EVENT  = 1 << 7
-} rt_link_notice_t;
+} rt_link_notice_e;
 
 
 typedef enum
 typedef enum
 {
 {
-    RT_LINK_ESTABLISHING = 0,
-    RT_LINK_NO_RESPONSE,
-    RT_LINK_CONNECT_DONE,
-} rt_link_linkstatus_t;
+    RT_LINK_INIT    = 0,
+    RT_LINK_DISCONN = 1,
+    RT_LINK_CONNECT = 2,
+} rt_link_linkstate_e;
 
 
 typedef enum
 typedef enum
 {
 {
-    RECVTIMER_NONE = 0,
-    RECVTIMER_FRAME,
-    RECVTIMER_LONGFRAME
-} rt_link_recvtimer_status_t;
+    RT_LINK_EOK         = 0,
+    RT_LINK_ERR         = 1,
+    RT_LINK_ETIMEOUT    = 2,
+    RT_LINK_EFULL       = 3,
+    RT_LINK_EEMPTY      = 4,
+    RT_LINK_ENOMEM      = 5,
+    RT_LINK_EIO         = 6,
+    RT_LINK_ESESSION    = 7,
+    RT_LINK_ESERVICE    = 8,
+
+    RT_LINK_EMAX
+} rt_link_err_e;
 
 
 struct rt_link_receive_buffer
 struct rt_link_receive_buffer
 {
 {
-    rt_uint8_t data[RT_LINK_RECEIVE_BUFFER_LENGTH]; /* rt-link receive data buffer */
+    /* rt-link receive data buffer */
+    rt_uint8_t data[RT_LINK_RECEIVE_BUFFER_LENGTH];
     rt_uint8_t *read_point;
     rt_uint8_t *read_point;
     rt_uint8_t *write_point;
     rt_uint8_t *write_point;
     rt_uint8_t *end_point;
     rt_uint8_t *end_point;
@@ -100,15 +121,16 @@ struct rt_link_frame_head
     rt_uint8_t extend  : 1;
     rt_uint8_t extend  : 1;
     rt_uint8_t crc     : 1;
     rt_uint8_t crc     : 1;
     rt_uint8_t ack     : 1;
     rt_uint8_t ack     : 1;
+
     rt_uint8_t sequence;
     rt_uint8_t sequence;
-    rt_uint16_t channel: 5;
-    rt_uint16_t length : 11;
+    rt_uint16_t service: 5;
+    rt_uint16_t length : 11; /* range 0~2047 */
 };
 };
 
 
 /* record frame information that opposite */
 /* record frame information that opposite */
 struct rt_link_record
 struct rt_link_record
 {
 {
-    rt_uint8_t rx_seq; /* record the opposite sequence */
+    rt_uint8_t rx_seq;      /* record the opposite sequence */
     rt_uint8_t total;       /* the number of long frame number */
     rt_uint8_t total;       /* the number of long frame number */
     rt_uint8_t long_count;  /* long packet recv counter */
     rt_uint8_t long_count;  /* long packet recv counter */
     rt_uint8_t *dataspace;  /* the space of long frame */
     rt_uint8_t *dataspace;  /* the space of long frame */
@@ -116,58 +138,71 @@ struct rt_link_record
 
 
 struct rt_link_extend
 struct rt_link_extend
 {
 {
-    rt_uint16_t attribute;           /* rt_link_frame_attribute_t */
+    rt_uint16_t attribute;  /* rt_link_frame_attr_e */
     rt_uint16_t parameter;
     rt_uint16_t parameter;
 };
 };
 
 
 struct rt_link_frame
 struct rt_link_frame
 {
 {
-    struct rt_link_frame_head head;         /* frame head */
-    struct rt_link_extend extend;           /* frame extend data */
-    rt_uint8_t *real_data;                  /* the origin data */
-    rt_uint32_t crc;                        /* CRC result */
+    struct rt_link_frame_head head;  /* frame head */
+    struct rt_link_extend extend;    /* frame extend data */
+    rt_uint8_t *real_data;           /* the origin data */
+    rt_uint32_t crc;                 /* CRC result */
 
 
-    rt_uint16_t data_len;         /* the length of frame length */
-    rt_uint16_t attribute;        /* this will show frame attribute , rt_link_frame_attribute_t */
+    rt_uint16_t data_len;   /* the length of frame length */
+    rt_uint16_t attribute;  /* rt_link_frame_attr_e */
 
 
-    rt_uint8_t index;              /* the index frame for long frame */
-    rt_uint8_t total;               /* the total frame for long frame */
+    rt_uint8_t issent;
+    rt_uint8_t index;       /* the index frame for long frame */
+    rt_uint8_t total;       /* the total frame for long frame */
 
 
-    rt_slist_t slist;            /* the frame will hang on the send list on session */
+    rt_slist_t slist;       /* the frame will hang on the send list on session */
 };
 };
 
 
 struct rt_link_service
 struct rt_link_service
 {
 {
-    rt_err_t (*upload_callback)(void *data, rt_size_t size);
+    rt_int32_t timeout_tx;
+    void (*send_cb)(struct rt_link_service *service, void *buffer);
+    void (*recv_cb)(struct rt_link_service *service, void *data, rt_size_t size);
+    void *user_data;
+
+    rt_uint8_t flag;            /* Whether to use the CRC and ACK */
+    rt_link_service_e service;
+    rt_link_linkstate_e state;  /* channel link state */
+    rt_link_err_e err;
 };
 };
 
 
 struct rt_link_session
 struct rt_link_session
 {
 {
-    rt_link_linkstatus_t link_status;   /* Link connection status*/
-    struct rt_event event;      /* the event that core logic */
-    struct rt_link_service channel[RT_LINK_SERVICE_MAX]; /* thansfer to app layer */
+    struct rt_event event;
+    struct rt_link_service *service[RT_LINK_SERVICE_MAX];
 
 
+    rt_uint8_t tx_seq;  /* Sequence number of the send data frame */
     rt_slist_t tx_data_slist;
     rt_slist_t tx_data_slist;
-    rt_uint8_t tx_seq;     /* sequence for frame */
-    struct rt_mutex tx_lock;    /* protect send data interface, only one thread can hold it */
-    struct rt_timer sendtimer;  /* send function timer for rt link */
+    rt_uint8_t sendbuffer[RT_LINK_MAX_FRAME_LENGTH];
+    struct rt_event sendevent;
+    struct rt_timer sendtimer;
 
 
-    struct rt_link_record rx_record;    /* the memory of receive status */
-    struct rt_timer recvtimer;          /* receive a frame timer for rt link */
-    struct rt_timer longframetimer;     /* receive long frame timer for rt link */
+    struct rt_link_record rx_record;  /* the memory of receive status */
+    struct rt_timer recvtimer;        /* receive a frame timer for rt link */
+    struct rt_timer longframetimer;   /* receive long frame timer for rt link */
 
 
-    struct rt_link_receive_buffer *rx_buffer; /* the buffer will store data */
-    rt_uint32_t (*calculate_crc)(rt_uint8_t using_buffer_ring, rt_uint8_t *data, rt_size_t size); /* this function will calculate crc */
+    struct rt_link_receive_buffer *rx_buffer;
+    rt_uint32_t (*calculate_crc)(rt_uint8_t using_buffer_ring, rt_uint8_t *data, rt_size_t size);
+    rt_link_linkstate_e state;  /* Link status */
 };
 };
 
 
-/* rtlink init and deinit */
+#define SERV_ERR_GET(service)   (service->err)
+
+/* rtlink init and deinit, default is automatic initialization*/
 int rt_link_init(void);
 int rt_link_init(void);
 rt_err_t rt_link_deinit(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);
+
+rt_size_t rt_link_send(struct rt_link_service *service, const void *data, rt_size_t size);
+
 /* rtlink service attach and detach */
 /* 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);
+rt_err_t rt_link_service_attach(struct rt_link_service *service);
+rt_err_t rt_link_service_detach(struct rt_link_service *service);
 
 
 /* Private operator function */
 /* Private operator function */
 struct rt_link_session *rt_link_get_scb(void);
 struct rt_link_session *rt_link_get_scb(void);

+ 41 - 0
components/utilities/rt-link/inc/rtlink_dev.h

@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-06-15     Sherman      the first version
+ */
+
+#include <rtthread.h>
+#include <rtlink.h>
+
+#define RT_LINK_RX_NONBLOCKING       0x1000
+#define RT_LINK_RX_BLOCKING          0x2000
+#define RT_LINK_TX_NONBLOCKING       0x4000
+#define RT_LINK_TX_BLOCKING          0x8000
+#define RT_LINK_DEVICE_MASK          0xf000
+
+struct rtlink_recv_list
+{
+    void *data;
+    rt_size_t size;
+    rt_size_t index;
+    struct rt_slist_node list;
+};
+
+struct rt_link_device
+{
+    struct rt_device parent;
+    struct rt_link_service service;
+    struct rt_slist_node recv_head; /* recv data list, struct rtlink_recv_list  */
+};
+
+/*
+ * rtlink device register
+ */
+rt_err_t rt_link_dev_register(struct rt_link_device *rtlink,
+                              const char              *name,
+                              rt_uint32_t              flag,
+                              void                    *data);

+ 3 - 1
components/utilities/rt-link/inc/rtlink_hw.h

@@ -6,6 +6,7 @@
  * Change Logs:
  * Change Logs:
  * Date           Author       Notes
  * Date           Author       Notes
  * 2021-02-02     xiangxistu   the first version
  * 2021-02-02     xiangxistu   the first version
+ * 2021-07-13     Sherman      add reconnect API
  *
  *
  */
  */
 #ifndef __RT_LINK_HW_H__
 #ifndef __RT_LINK_HW_H__
@@ -19,6 +20,7 @@ void rt_link_hw_buffer_point_shift(rt_uint8_t **pointer_address, rt_size_t lengt
 
 
 rt_err_t rt_link_hw_init(void);
 rt_err_t rt_link_hw_init(void);
 rt_err_t rt_link_hw_deinit(void);
 rt_err_t rt_link_hw_deinit(void);
-rt_err_t rt_link_hw_send(void *data, rt_size_t length);
+rt_err_t rt_link_hw_reconnect(void);
+rt_size_t rt_link_hw_send(void *data, rt_size_t length);
 
 
 #endif /* _RT_LINK_PORT_INTERNAL_H_ */
 #endif /* _RT_LINK_PORT_INTERNAL_H_ */

+ 4 - 2
components/utilities/rt-link/inc/rtlink_port.h

@@ -7,6 +7,7 @@
  * Date           Author       Notes
  * Date           Author       Notes
  * 2021-02-02     xiangxistu   the first version
  * 2021-02-02     xiangxistu   the first version
  * 2021-05-15     Sherman      function rename
  * 2021-05-15     Sherman      function rename
+ * 2021-07-13     Sherman      add reconnect API
  */
  */
 #ifndef __RT_LINK_PORT_H__
 #ifndef __RT_LINK_PORT_H__
 #define __RT_LINK_PORT_H__
 #define __RT_LINK_PORT_H__
@@ -14,8 +15,9 @@
 #include <rtdef.h>
 #include <rtdef.h>
 
 
 /* Functions that need to be implemented at the hardware */
 /* Functions that need to be implemented at the hardware */
-int rt_link_port_init(void);
-int rt_link_port_deinit(void);
+rt_err_t rt_link_port_init(void);
+rt_err_t rt_link_port_deinit(void);
+rt_err_t rt_link_port_reconnect(void);
 rt_size_t rt_link_port_send(void *data, rt_size_t length);
 rt_size_t rt_link_port_send(void *data, rt_size_t length);
 
 
 #ifdef RT_LINK_USING_HW_CRC
 #ifdef RT_LINK_USING_HW_CRC

File diff suppressed because it is too large
+ 395 - 287
components/utilities/rt-link/src/rtlink.c


+ 396 - 0
components/utilities/rt-link/src/rtlink_dev.c

@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-06-15     Sherman      the first version
+ */
+
+#define DBG_TAG    "RTLINK_DEV"
+#define DBG_LVL    DBG_LOG
+#include <rtdbg.h>
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <rtlink_dev.h>
+
+#define RTLINK_SERV(dev)  (((struct rt_link_device*)dev)->service)
+
+#ifdef RT_USING_POSIX
+#include <dfs_posix.h>
+#include <dfs_poll.h>
+
+int rtlink_fops_open(struct dfs_fd *fd)
+{
+    rt_uint16_t flags = 0;
+    rt_device_t device;
+
+    switch (fd->flags & O_ACCMODE)
+    {
+    case O_RDONLY:
+        LOG_D("fops open: O_RDONLY!");
+        flags = RT_DEVICE_FLAG_RDONLY;
+        break;
+    case O_WRONLY:
+        LOG_D("fops open: O_WRONLY!");
+        flags = RT_DEVICE_FLAG_WRONLY;
+        break;
+    case O_RDWR:
+        LOG_D("fops open: O_RDWR!");
+        flags = RT_DEVICE_FLAG_RDWR;
+        break;
+    default:
+        LOG_E("fops open: unknown mode - %d!", fd->flags & O_ACCMODE);
+        break;
+    }
+
+    device = (rt_device_t)fd->data;
+    if (fd->flags & O_NONBLOCK)
+    {
+        rt_device_control(device, RT_LINK_TX_NONBLOCKING | RT_LINK_RX_NONBLOCKING, RT_NULL);
+    }
+
+    return rt_device_open(device, flags);
+}
+
+int rtlink_fops_close(struct dfs_fd *fd)
+{
+    rt_device_t device;
+    device = (rt_device_t)fd->data;
+
+    rt_device_set_rx_indicate(device, RT_NULL);
+    return rt_device_close(device);
+}
+
+int rtlink_fops_ioctl(struct dfs_fd *fd, int cmd, void *args)
+{
+    rt_device_t device;
+    device = (rt_device_t)fd->data;
+
+    if (cmd == O_NONBLOCK)
+    {
+        return rt_device_control(device, RT_LINK_TX_NONBLOCKING | RT_LINK_RX_NONBLOCKING, RT_NULL);
+    }
+    else
+    {
+        return rt_device_control(device, cmd, args);
+    }
+}
+
+int rtlink_fops_read(struct dfs_fd *fd, void *buf, size_t count)
+{
+    int size = 0;
+    rt_device_t device;
+    device = (rt_device_t)fd->data;
+
+    size = rt_device_read(device, -1,  buf, count);
+    if (size <= 0)
+    {
+        size = -EAGAIN;
+    }
+    return size;
+}
+
+int rtlink_fops_write(struct dfs_fd *fd, const void *buf, size_t count)
+{
+    int size = 0;
+    rt_device_t device;
+    device = (rt_device_t)fd->data;
+
+    size = rt_device_write(device, -1, buf, count);
+    if (size <= 0)
+    {
+        size = -EAGAIN;
+    }
+    return size;
+}
+
+int rtlink_fops_poll(struct dfs_fd *fd, struct rt_pollreq *req)
+{
+    int mask = 0;
+    int flags = 0;
+    rt_device_t device;
+    struct rt_link_device *rtlink_dev;
+
+    device = (rt_device_t)fd->data;
+    RT_ASSERT(device != RT_NULL);
+
+    rtlink_dev = (struct rt_link_device *)device;
+
+    flags = fd->flags & O_ACCMODE;
+    if (flags == O_RDONLY || flags == O_RDWR)
+    {
+        rt_base_t level;
+        rt_poll_add(&(device->wait_queue), req);
+
+        level = rt_hw_interrupt_disable();
+        if (RT_NULL != rt_slist_first(&rtlink_dev->recv_head))
+            mask |= POLLIN;
+        rt_hw_interrupt_enable(level);
+    }
+    mask |= POLLOUT;
+
+    return mask;
+}
+
+const static struct dfs_file_ops _rtlink_fops =
+{
+    rtlink_fops_open,
+    rtlink_fops_close,
+    rtlink_fops_ioctl,
+    rtlink_fops_read,
+    rtlink_fops_write,
+    RT_NULL, /* flush */
+    RT_NULL, /* lseek */
+    RT_NULL, /* getdents */
+    rtlink_fops_poll,
+};
+#endif /* RT_USING_POSIX */
+
+/* The event type for the service channel number,
+ * which is used to wake up the service thread in blocking receive mode */
+struct rt_event recv_event;
+
+static rt_err_t rt_link_event_send(struct rt_link_service *serv)
+{
+    RT_ASSERT(serv != RT_NULL);
+    RT_ASSERT(serv->service < RT_LINK_SERVICE_MAX);
+    rt_uint32_t set = 0x01 << serv->service;
+    return rt_event_send(&recv_event, set);
+}
+
+static rt_err_t rt_link_event_recv(struct rt_link_service *service)
+{
+    RT_ASSERT(service != RT_NULL);
+    RT_ASSERT(service->service < RT_LINK_SERVICE_MAX);
+
+    rt_uint32_t set = 0x01 << service->service;
+    rt_uint32_t recved = 0;
+    rt_err_t ret = rt_event_recv(&recv_event,
+                                 set,
+                                 RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,
+                                 RT_WAITING_FOREVER,
+                                 &recved);
+    if (recved & set)
+    {
+        return ret;
+    }
+    return RT_ERROR;
+}
+
+static void send_cb(struct rt_link_service *service, void *buffer)
+{
+    RT_ASSERT(service != RT_NULL);
+    RT_ASSERT(buffer != RT_NULL);
+    struct rt_link_device *rtlink = (struct rt_link_device *)service->user_data;
+
+    if (rtlink && rtlink->parent.tx_complete)
+    {
+        rtlink->parent.tx_complete(&rtlink->parent, buffer);
+    }
+}
+
+static void recv_cb(struct rt_link_service *service, void *data, rt_size_t size)
+{
+    RT_ASSERT(service != RT_NULL);
+    struct rt_link_device *rtlink = (struct rt_link_device *)service->user_data;
+
+    if (rtlink)
+    {
+        struct rtlink_recv_list *node = rt_malloc(sizeof(struct rtlink_recv_list));
+        node->data = data;
+        node->size = size;
+        node->index = 0;
+        rt_slist_append(&rtlink->recv_head, &node->list);
+        rt_link_event_send(service);
+
+        if (rtlink->parent.rx_indicate)
+        {
+            rtlink->parent.rx_indicate(&rtlink->parent, size);
+        }
+    }
+    else
+    {
+        rt_free(data);
+    }
+}
+
+rt_err_t  rt_link_dev_init(rt_device_t dev)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+    dev->rx_indicate = RT_NULL;
+    dev->tx_complete = RT_NULL;
+
+    struct rt_link_device *rtlink = (struct rt_link_device *)dev;
+    rtlink->service.service = RT_LINK_SERVICE_MAX;
+    rtlink->service.recv_cb = RT_NULL;
+    rtlink->service.send_cb = RT_NULL;
+    rtlink->service.timeout_tx = RT_WAITING_NO;
+    rtlink->service.user_data = (void *)dev;
+
+    rt_slist_init(&rtlink->recv_head);
+    return RT_EOK;
+}
+
+rt_err_t  rt_link_dev_open(rt_device_t dev, rt_uint16_t oflag)
+{
+    RT_ASSERT(dev != RT_NULL);
+    struct rt_link_device *rtlink = (struct rt_link_device *)dev;
+
+    rtlink->service.recv_cb = recv_cb;
+    rtlink->service.send_cb = send_cb;
+
+    dev->open_flag = oflag & RT_DEVICE_OFLAG_MASK;
+    if (dev->open_flag == RT_DEVICE_OFLAG_RDONLY)
+    {
+        rtlink->service.send_cb = RT_NULL;
+    }
+    else if (dev->open_flag == RT_DEVICE_OFLAG_WRONLY)
+    {
+        rtlink->service.recv_cb = RT_NULL;
+    }
+    return rt_link_service_attach(&rtlink->service);
+}
+
+rt_err_t  rt_link_dev_close(rt_device_t dev)
+{
+    RT_ASSERT(dev != RT_NULL);
+    struct rt_link_device *rtlink = (struct rt_link_device *)dev;
+    return rt_link_service_detach(&rtlink->service);
+}
+
+rt_size_t rt_link_dev_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+    RT_ASSERT(dev != RT_NULL);
+    RT_ASSERT(buffer != RT_NULL);
+    RT_ASSERT(size != 0);
+
+    struct rt_link_device *rtlink = (struct rt_link_device *)dev;
+    struct rtlink_recv_list *node;
+    rt_size_t read_len = 0;
+    rt_size_t unread_len = 0;
+
+    if (dev->rx_indicate == RT_NULL)
+    {
+        /* RT_LINK_RX_BLOCKING, wait service receive data event */
+        rt_link_event_recv(&rtlink->service);
+    }
+
+    if (rt_slist_first(&rtlink->recv_head) != RT_NULL)
+    {
+        node = rt_container_of(rt_slist_next(&rtlink->recv_head), struct rtlink_recv_list, list);
+        unread_len = (node->size) - (node->index);
+        read_len = (size > unread_len) ? unread_len : size;
+        rt_memcpy(buffer, (rt_uint8_t *)node->data + node->index, read_len);
+        node->index += read_len;
+
+        if (node->index >= node->size)
+        {
+            rt_slist_remove(&rtlink->recv_head, &node->list);
+            node->index = 0;
+            rt_free(node->data);
+            rt_free(node);
+        }
+        if (rt_slist_first(&rtlink->recv_head) != RT_NULL)
+        {
+            rt_link_event_send(&rtlink->service);
+        }
+    }
+    return read_len;
+}
+
+rt_size_t rt_link_dev_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+    RT_ASSERT(dev != RT_NULL);
+    RT_ASSERT(buffer != RT_NULL);
+    RT_ASSERT(size != 0);
+
+    return rt_link_send(&RTLINK_SERV(dev), buffer, size);
+}
+
+rt_err_t  rt_link_dev_control(rt_device_t dev, int cmd, void *args)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+    if (cmd & RT_DEVICE_CTRL_CONFIG)
+    {
+        if (args == RT_NULL)
+            return RT_EINVAL;
+        RTLINK_SERV(dev).service = ((struct rt_link_service *)args)->service;
+        RTLINK_SERV(dev).timeout_tx = ((struct rt_link_service *)args)->timeout_tx;
+        RTLINK_SERV(dev).flag = ((struct rt_link_service *)args)->flag;
+    }
+
+    if (cmd & RT_LINK_RX_BLOCKING)
+    {
+        dev->rx_indicate = RT_NULL;
+    }
+    if (cmd & RT_LINK_TX_BLOCKING)
+    {
+        RTLINK_SERV(dev).timeout_tx = RT_WAITING_FOREVER;
+        dev->tx_complete = RT_NULL;
+    }
+    if (cmd & RT_LINK_TX_NONBLOCKING)
+    {
+        RTLINK_SERV(dev).timeout_tx = RT_WAITING_NO;
+    }
+
+    return RT_EOK;
+}
+
+#ifdef RT_USING_DEVICE_OPS
+const static struct rt_device_ops rtlink_ops =
+{
+    rt_link_dev_init,
+    rt_link_dev_open,
+    rt_link_dev_close,
+    rt_link_dev_read,
+    rt_link_dev_write,
+    rt_link_dev_control
+};
+#endif /* RT_USING_DEVICE_OPS */
+
+/*
+ * rtlink device register
+ */
+rt_err_t rt_link_dev_register(struct rt_link_device *rtlink,
+                              const char              *name,
+                              rt_uint32_t              flag,
+                              void                    *data)
+{
+    rt_err_t ret;
+    struct rt_device *device;
+    RT_ASSERT(rtlink != RT_NULL);
+
+    device = (struct rt_device *)rtlink;
+    device->type        = RT_Device_Class_Char;
+    device->rx_indicate = RT_NULL;
+    device->tx_complete = RT_NULL;
+
+#ifdef RT_USING_DEVICE_OPS
+    device->ops         = &rtlink_ops;
+#else
+    device->init        = rt_link_dev_init;
+    device->open        = rt_link_dev_open;
+    device->close       = rt_link_dev_close;
+    device->read        = rt_link_dev_read;
+    device->write       = rt_link_dev_write;
+    device->control     = rt_link_dev_control;
+#endif
+    device->user_data   = data;
+
+    /* register a character device */
+    ret = rt_device_register(device, name, flag);
+
+#if defined(RT_USING_POSIX)
+    /* set fops */
+    device->fops        = &_rtlink_fops;
+#endif
+
+    rt_event_init(&recv_event, "rtlink_dev", RT_IPC_FLAG_FIFO);
+    return ret;
+}

+ 55 - 15
components/utilities/rt-link/src/rtlink_hw.c

@@ -85,18 +85,39 @@ static rt_size_t rt_link_hw_buffer_write(void *data, rt_size_t count)
 /* increases buffer pointer by one and circle around if necessary */
 /* increases buffer pointer by one and circle around if necessary */
 void rt_link_hw_buffer_point_shift(rt_uint8_t **pointer_address, rt_size_t length)
 void rt_link_hw_buffer_point_shift(rt_uint8_t **pointer_address, rt_size_t length)
 {
 {
-    rt_uint8_t *pointer = RT_NULL;
+    rt_uint8_t *pointer = *pointer_address + length;
 
 
-    pointer = *pointer_address + length;
-    if (pointer >= rx_buffer->end_point)
+    if (rx_buffer->write_point >= rx_buffer->read_point)
     {
     {
-        rt_size_t offset = 0;
-        offset = pointer - rx_buffer->end_point;
-        *pointer_address = rx_buffer->data + offset;
+        if (pointer >= rx_buffer->write_point)
+        {
+            *pointer_address = rx_buffer->write_point;
+        }
+        else
+        {
+            *pointer_address = pointer;
+        }
     }
     }
     else
     else
     {
     {
-        *pointer_address = *pointer_address + length;
+        if (pointer >= rx_buffer->end_point)
+        {
+            *pointer_address = rx_buffer->data;
+            pointer = pointer - rx_buffer->end_point + rx_buffer->data;
+
+            if (pointer >= rx_buffer->write_point)
+            {
+                *pointer_address = rx_buffer->write_point;
+            }
+            else
+            {
+                *pointer_address = pointer;
+            }
+        }
+        else
+        {
+            *pointer_address = pointer;
+        }
     }
     }
 }
 }
 
 
@@ -119,9 +140,13 @@ void rt_link_hw_copy(rt_uint8_t *dst, rt_uint8_t *src, rt_size_t count)
     }
     }
 }
 }
 
 
-/* Tells, how many chars are saved into the buffer */
+/* Length of data received */
 rt_size_t rt_link_hw_recv_len(struct rt_link_receive_buffer *buffer)
 rt_size_t rt_link_hw_recv_len(struct rt_link_receive_buffer *buffer)
 {
 {
+    if (buffer == RT_NULL)
+    {
+        return 0;
+    }
     if (buffer->write_point >= buffer->read_point)
     if (buffer->write_point >= buffer->read_point)
     {
     {
         return (buffer->write_point - buffer->read_point);
         return (buffer->write_point - buffer->read_point);
@@ -183,15 +208,18 @@ rt_uint32_t rt_link_get_crc(rt_uint8_t using_buffer_ring, rt_uint8_t *data, rt_s
     return crc32;
     return crc32;
 }
 }
 
 
-rt_err_t rt_link_hw_send(void *data, rt_size_t length)
+rt_size_t rt_link_hw_send(void *data, rt_size_t length)
 {
 {
     rt_size_t send_len = 0;
     rt_size_t send_len = 0;
     send_len = rt_link_port_send(data, length);
     send_len = rt_link_port_send(data, length);
-    LOG_D("hw_send len= %d", send_len);
+    if (send_len <= 0)
+    {
+        rt_link_port_reconnect();
+        send_len = rt_link_port_send(data, length);
+    }
     return send_len;
     return send_len;
 }
 }
 
 
-/* provide this function to hardware spi/uart/usb to store data */
 rt_size_t rt_link_hw_write_cb(void *data, rt_size_t length)
 rt_size_t rt_link_hw_write_cb(void *data, rt_size_t length)
 {
 {
     /* write real data into rtlink receive buffer */
     /* write real data into rtlink receive buffer */
@@ -220,11 +248,17 @@ rt_err_t rt_link_hw_init(void)
     scb->rx_buffer = rx_buffer;
     scb->rx_buffer = rx_buffer;
     scb->calculate_crc = rt_link_get_crc;
     scb->calculate_crc = rt_link_get_crc;
 
 
-    rt_link_port_init();
+    if (RT_EOK != rt_link_port_init())
+    {
+        return -RT_ERROR;
+    }
 
 
 #ifdef LINK_LAYER_USING_HW_CRC
 #ifdef LINK_LAYER_USING_HW_CRC
     /* crc hardware device for mcu and node */
     /* crc hardware device for mcu and node */
-    rt_link_hw_crc32_init();
+    if (RT_EOK != rt_link_hw_crc32_init())
+    {
+        return -RT_ERROR;
+    }
 #endif
 #endif
 
 
     LOG_I("link layer hardware environment init successful.");
     LOG_I("link layer hardware environment init successful.");
@@ -244,11 +278,17 @@ rt_err_t rt_link_hw_deinit(void)
         scb->rx_buffer = rx_buffer;
         scb->rx_buffer = rx_buffer;
         scb->calculate_crc = RT_NULL;
         scb->calculate_crc = RT_NULL;
     }
     }
-    rt_link_port_deinit();
+    if (RT_EOK != rt_link_port_deinit())
+    {
+        return -RT_ERROR;
+    }
 
 
 #ifdef LINK_LAYER_USING_HW_CRC
 #ifdef LINK_LAYER_USING_HW_CRC
     /* crc hardware device for mcu and node */
     /* crc hardware device for mcu and node */
-    rt_link_hw_crc32_deinit();
+    if (RT_EOK != rt_link_hw_crc32_deinit())
+    {
+        return -RT_ERROR;
+    }
 #endif
 #endif
 
 
     LOG_I("rtlink hardware deinit successful.");
     LOG_I("rtlink hardware deinit successful.");

+ 395 - 0
examples/rt-link/rtlink_dev_example.c

@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-06-19     Sherman    the first version
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#define DBG_TAG    "example"
+#define DBG_LVL    DBG_LOG
+#include <rtdbg.h>
+#include <rtlink_dev.h>
+
+enum
+{
+    NONE_TEST = 0,
+    SHORT_FRAME_TEST,
+    LONG_FRAME_TEST
+};
+static rt_uint8_t speed_test_type = NONE_TEST;
+
+static struct rt_link_device rtlink_dev = {0};
+#define  RTLINK01       "rtlink01"
+#define TEST_CONTEXT    "This message is sent by RT-Link"
+rt_uint8_t test_buff[1024] = {0};
+
+static rt_err_t rtlink_dev_rx_ind(rt_device_t dev, rt_size_t size)
+{
+    RT_ASSERT(dev != RT_NULL);
+    LOG_I("rx_ind: dev name %s, rx size %d", dev->parent.name, size);
+    return RT_EOK;
+}
+
+static rt_err_t rtlink_dev_tx_done(rt_device_t dev, void *buffer)
+{
+    RT_ASSERT(dev != RT_NULL);
+    struct rt_link_device *rtlink_dev = (struct rt_link_device *)dev;
+    LOG_I("tx_done: dev name %s, buffer 0x%p errno %d", dev->parent.name, buffer, rtlink_dev->service.err);
+    rt_free(buffer);
+    return RT_EOK;
+}
+
+#ifdef RT_USING_POSIX
+#include <dfs_posix.h>
+#include <dfs_poll.h>
+#include <dfs_select.h>
+
+#define RTLINK01_PATH "/dev/rtlink01"
+int fd  = -1;
+
+static void rtlink_fopen(int argc, char *argv[])
+{
+    fd = open(RTLINK01_PATH, O_RDWR | O_NONBLOCK);
+
+    if (fd < 0)
+    {
+        LOG_E("open rt_link failed!");
+    }
+}
+MSH_CMD_EXPORT(rtlink_fopen, rtlink posix interface example);
+
+static void rtlink_fclose(int argc, char *argv[])
+{
+    LOG_D("colse %d", fd);
+    close(fd);
+    fd = -1;
+}
+MSH_CMD_EXPORT(rtlink_fclose, rtlink posix interface example);
+
+static void rtlink_fread(int argc, char *argv[])
+{
+    int read_len;
+    read_len = read(fd, test_buff, sizeof(test_buff));
+    LOG_D("read len %d", read_len);
+    LOG_HEX("read", 8, test_buff, 32);
+}
+MSH_CMD_EXPORT(rtlink_fread, rtlink posix interface example);
+
+static void rtlink_fwrite(int argc, char *argv[])
+{
+    char *data = RT_NULL;
+    rt_size_t length = 0;
+    rt_uint16_t count = 0;
+    rt_size_t ret = 0;
+
+    if (argc == 1)
+    {
+        data = rt_malloc(sizeof(TEST_CONTEXT));
+        if (data)
+        {
+            length = sizeof(TEST_CONTEXT) - 1;
+            rt_memcpy(data, TEST_CONTEXT, sizeof(TEST_CONTEXT) - 1);
+            ret = write(fd, data, length);
+        }
+        LOG_I("write data(0x%p) result: %d.", data, ret);
+    }
+    else if (argc >= 3)
+    {
+        if (strcmp(argv[1], "-l") == 0)
+        {
+            data = rt_malloc(atoi((const char *)argv[2]));
+            if (data)
+            {
+                for (count = 0; count < atoi((const char *)argv[2]); count++)
+                {
+                    data[count] = (count % 93 + 33);
+                }
+                length = atoi((const char *)argv[2]);
+                ret = write(fd, data, length);
+            }
+            LOG_I("write data(0x%p) result: %d.", data, ret);
+        }
+        else
+        {
+            LOG_E("Invalid parameter.");
+        }
+    }
+}
+MSH_CMD_EXPORT(rtlink_fwrite, rtlink posix interface example);
+
+#define RTLINK02         "rtlink02"
+#define RTLINK02_PATH    "/dev/rtlink02"
+static struct rt_link_device rtlink_fd = {0};
+rt_uint8_t fd_buff[1024] = {0};
+
+static void listen_thread(void *param)
+{
+    int fd  = open(RTLINK02_PATH, O_RDWR | O_NONBLOCK);
+    if (fd < 0)
+    {
+        LOG_E("open (%s) failed", RTLINK02);
+        return;
+    }
+    while (1)
+    {
+        rt_uint8_t *write_buf = RT_NULL;
+        int write_len = 0;
+        fd_set readfds, writefds;
+        FD_ZERO(&readfds);
+        FD_ZERO(&writefds);
+        FD_SET(fd, &readfds);
+        FD_SET(fd, &writefds);
+
+        int ret = select(fd + 1, &readfds, &writefds, RT_NULL, RT_NULL);
+        LOG_D("select ret(%d), read (%d), write (%d)", ret, readfds, writefds);
+        if (FD_ISSET(fd, &readfds))
+        {
+            LOG_I("POLLIN");
+            int read_len = read(fd, fd_buff, sizeof(test_buff));
+            LOG_D("read len %d", read_len);
+            LOG_HEX("read", 8, test_buff, 32);
+        }
+
+        if (FD_ISSET(fd, &writefds))
+        {
+            LOG_I("POLLOUT");
+            write_buf = rt_malloc(1024);
+            if (write_buf)
+            {
+                write_len = write(fd, write_buf, 1024);
+                LOG_D("write %d", write_len);
+            }
+        }
+
+        rt_thread_delay(500);
+    }
+    LOG_I("fd (%s) listen thread exit", RTLINK02);
+}
+
+static void rtlink_fselect()
+{
+    /* step1: register rtlink to to the device framework */
+    rt_link_dev_register(&rtlink_fd, RTLINK02,
+                         RT_DEVICE_FLAG_RDWR |
+                         RT_DEVICE_FLAG_REMOVABLE |
+                         RT_DEVICE_FLAG_STANDALONE,
+                         RT_NULL);
+
+    /* step2: Initialize the rlink device as the default configuration,  */
+    rt_device_t device = rt_device_find(RTLINK02);
+    if (device == RT_NULL)
+    {
+        LOG_E("device not find!");
+        return ;
+    }
+    rt_device_init(device);
+
+    /* step3: config rtlink device rx/tx callback, channel, send timeout */
+    rt_device_set_rx_indicate(device, rtlink_dev_rx_ind);
+    rt_device_set_tx_complete(device, rtlink_dev_tx_done);
+    struct rt_link_service service;
+    service.service = RT_LINK_SERVICE_MNGT;
+    service.timeout_tx = RT_WAITING_NO;
+    rt_device_control(device, RT_DEVICE_CTRL_CONFIG, &service);
+
+    rt_thread_t tid = rt_thread_create(RTLINK02, listen_thread, RT_NULL, 1024, 21, 20);
+    if (tid)
+    {
+        rt_thread_startup(tid);
+    }
+}
+MSH_CMD_EXPORT(rtlink_fselect, rtlink posix interface example);
+#endif  /* RT_USING_POSIX */
+
+static void rtlink_dread(void)
+{
+    rt_size_t read_len = 0;
+    rt_device_t dev = rt_device_find(RTLINK01);
+    if (dev == RT_NULL)
+    {
+        LOG_E("dev %s not find ", RTLINK01);
+        return;
+    }
+
+    read_len = rt_device_read(dev, 0, test_buff, sizeof(test_buff));
+
+    LOG_D("read len %d", read_len);
+    LOG_HEX("read", 8, test_buff, 32);
+}
+MSH_CMD_EXPORT(rtlink_dread, rtlink device interface example);
+
+void rt_link_speed_test(void *paremeter)
+{
+    int ret;
+    rt_uint8_t *send_buf, *data;
+    rt_size_t bufflen = 0;
+    rt_size_t sentlen = 0;
+    rt_size_t count = 0;
+    rt_tick_t tick1, tick2;
+    rt_size_t total = 0;
+    rt_uint32_t integer, decimal;
+    rt_device_t dev = rt_device_find(RTLINK01);
+    if (dev == RT_NULL)
+    {
+        LOG_E("dev %s not find!", RTLINK01);
+        return ;
+    }
+
+    if (speed_test_type == SHORT_FRAME_TEST)
+    {
+        bufflen = 988;
+    }
+    else
+    {
+        bufflen = 3036;
+    }
+
+    send_buf = rt_malloc(bufflen);
+    if (send_buf != RT_NULL)
+    {
+        data = send_buf;
+        for (count = 0; count < bufflen; count++)
+        {
+            *data++ = (count % 93 + 33);
+        }
+    }
+    else
+    {
+        rt_kprintf("speed of send buffer malloc failed.");
+        return;
+    }
+
+    tick1 = rt_tick_get();
+    while (speed_test_type)
+    {
+        ret = rt_device_write(dev, 0, send_buf, bufflen);
+
+        if (ret == RT_EOK)
+        {
+            sentlen += bufflen;
+        }
+
+        tick2 = rt_tick_get();
+        if (tick2 - tick1 >= RT_TICK_PER_SECOND)
+        {
+            total = sentlen * RT_TICK_PER_SECOND / 125 / (tick2 - tick1);
+            integer = total / 1000;
+            decimal = total % 1000;
+            LOG_I("%d.%03d0 Mbps!", integer, decimal);
+            sentlen = 0;
+            tick1 = tick2;
+        }
+    }
+    rt_free(send_buf);
+    LOG_W("speed test end, type %d", speed_test_type);
+}
+
+void create_thead_to_test_speed(rt_uint8_t mutil_num)
+{
+    rt_uint8_t i = 0;
+
+    LOG_D("Speed test type [%02d], mutil [%02d]", speed_test_type, mutil_num);
+    for (i = 0; i < mutil_num; i++)
+    {
+        rt_thread_t tid;
+        char tid_name[RT_NAME_MAX + 1] = {0};
+
+        rt_snprintf(tid_name, sizeof(tid_name), "lny_s%03d", i + 1);
+        tid = rt_thread_create(tid_name, rt_link_speed_test, RT_NULL, 1024, 20, 10);
+        rt_thread_startup(tid);
+        LOG_I("Speed test thread[%s] startup", tid_name);
+    }
+}
+
+static void rtlink_dwrite(int argc, char *argv[])
+{
+    char *data = RT_NULL;
+    rt_size_t length = 0;
+    rt_uint16_t count = 0;
+    rt_size_t ret = RT_ERROR;
+
+    rt_device_t dev = rt_device_find(RTLINK01);
+    if (dev == RT_NULL)
+    {
+        LOG_E("device not find!");
+        return ;
+    }
+
+    if (argc == 1)
+    {
+        data = rt_malloc(sizeof(TEST_CONTEXT));
+        length = sizeof(TEST_CONTEXT) - 1;
+        rt_memcpy(data, TEST_CONTEXT, sizeof(TEST_CONTEXT) - 1);
+
+        ret = rt_device_write(dev, 0, data, length);
+        LOG_I("write data(0x%p) result: %d.", data, ret);
+    }
+    else if (argc >= 3)
+    {
+        if (strcmp(argv[1], "-l") == 0)
+        {
+            data = rt_malloc(atoi((const char *)argv[2]));
+            for (count = 0; count < atoi((const char *)argv[2]); count++)
+            {
+                data[count] = (count % 93 + 33);
+            }
+            length = atoi((const char *)argv[2]);
+            ret = rt_device_write(dev, 0, data, length);
+            LOG_I("write data(0x%p) result: %d.", data, ret);
+        }
+        else
+        {
+            LOG_E("Invalid parameter.");
+        }
+    }
+}
+MSH_CMD_EXPORT(rtlink_dwrite, rtlink device interface example);
+
+static void rtlink_dinit(void)
+{
+    /* step1: register rtlink to to the device framework */
+    rt_link_dev_register(&rtlink_dev, RTLINK01,
+                         RT_DEVICE_FLAG_RDWR |
+                         RT_DEVICE_FLAG_REMOVABLE |
+                         RT_DEVICE_FLAG_STANDALONE,
+                         RT_NULL);
+
+    /* step2: Initialize the rlink device as the default configuration,  */
+    rt_device_t device = rt_device_find(RTLINK01);
+    if (device == RT_NULL)
+    {
+        LOG_E("device not find!");
+        return ;
+    }
+    rt_device_init(device);
+
+    /* step3: config rtlink device rx/tx callback, channel, send timeout */
+    rt_device_set_rx_indicate(device, rtlink_dev_rx_ind);
+    rt_device_set_tx_complete(device, rtlink_dev_tx_done);
+    struct rt_link_service service;
+    service.service = RT_LINK_SERVICE_SOCKET;
+    service.timeout_tx = RT_WAITING_FOREVER;
+    service.flag = RT_LINK_FLAG_ACK | RT_LINK_FLAG_CRC;
+    rt_device_control(device, RT_DEVICE_CTRL_CONFIG, &service);
+}
+MSH_CMD_EXPORT(rtlink_dinit, rtlink device interface example);
+
+static void rtlink_dopen()
+{
+    /* step4: open rtlink device, attach the service channel */
+    rt_device_t device = rt_device_find(RTLINK01);
+    if (device == RT_NULL)
+    {
+        LOG_E("device not find!");
+        return ;
+    }
+    rt_err_t ret = rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
+    LOG_I("dev open ret %d", ret);
+}
+MSH_CMD_EXPORT(rtlink_dopen, rtlink device interface example);

+ 73 - 46
examples/rt-link/rtlink_example.c

@@ -1,4 +1,3 @@
-
 /*
 /*
  * Copyright (c) 2006-2021, RT-Thread Development Team
  * Copyright (c) 2006-2021, RT-Thread Development Team
  *
  *
@@ -7,6 +6,7 @@
  * Change Logs:
  * Change Logs:
  * Date           Author       Notes
  * Date           Author       Notes
  * 2021-05-15     Sherman      the first version
  * 2021-05-15     Sherman      the first version
+ * 2021-08-04     Sherman      Adapted to new version of rt-link API
  */
  */
 
 
 #include <stdlib.h>
 #include <stdlib.h>
@@ -30,33 +30,25 @@ enum
 
 
 void rt_link_speed_test(void *paremeter);
 void rt_link_speed_test(void *paremeter);
 static rt_uint8_t speed_test_type = NONE_TEST;
 static rt_uint8_t speed_test_type = NONE_TEST;
+static struct rt_link_service serv_socket;
+static struct rt_link_service serv_wifi;
 
 
-rt_err_t rt_link_receive_example_callback(void *data, rt_size_t length)
+static void send_cb(struct rt_link_service *service, void *buffer)
 {
 {
-    LOG_I("recv data %d",length);
-    LOG_HEX("example",8,data,length);
-    rt_free(data);
-    return RT_EOK;
+    LOG_I("send_cb: service (%d) buffer (0x%p) err(%d)", service->service, buffer, service->err);
 }
 }
 
 
-void create_thead_to_test_speed(rt_uint8_t mutil_num)
+static void recv_cb(struct rt_link_service *service, void *data, rt_size_t size)
 {
 {
-    rt_uint8_t i = 0;
+    LOG_I("service (%d) size (%d) data(0x%p)", service->service, size, data);
 
 
-    LOG_D("Speed test type [%02d], mutil [%02d]", speed_test_type, mutil_num);
-    for(i = 0; i< mutil_num; i++)
+    if (size)
     {
     {
-        rt_thread_t tid;
-        char tid_name[RT_NAME_MAX + 1] = {0};
-
-        rt_snprintf(tid_name, sizeof(tid_name), "lny_s%03d", i + 1);
-        tid = rt_thread_create(tid_name, rt_link_speed_test, RT_NULL, 1024, 20, 10);
-        rt_thread_startup(tid);
-        LOG_I("Speed test thread[%s] startup", tid_name);
+        rt_free(data);
     }
     }
 }
 }
 
 
-void rt_link_speed_test(void *paremeter)
+static void rt_link_speed_test(void *paremeter)
 {
 {
     int ret;
     int ret;
     rt_uint8_t *send_buf, *data;
     rt_uint8_t *send_buf, *data;
@@ -67,20 +59,20 @@ void rt_link_speed_test(void *paremeter)
     rt_size_t total = 0;
     rt_size_t total = 0;
     rt_uint32_t integer, decimal;
     rt_uint32_t integer, decimal;
 
 
-    if(speed_test_type == SHORT_FRAME_TEST)
+    if (speed_test_type == SHORT_FRAME_TEST)
     {
     {
-        bufflen = 2044;
+        bufflen = RT_LINK_MAX_DATA_LENGTH;
     }
     }
     else
     else
     {
     {
-        bufflen = 6132;
+        bufflen = RT_LINK_MAX_DATA_LENGTH * RT_LINK_FRAMES_MAX;
     }
     }
 
 
     send_buf = rt_malloc(bufflen);
     send_buf = rt_malloc(bufflen);
-    if(send_buf != RT_NULL)
+    if (send_buf != RT_NULL)
     {
     {
         data = send_buf;
         data = send_buf;
-        for(count = 0;count < bufflen; count++)
+        for (count = 0; count < bufflen; count++)
         {
         {
             *data++ = (count % 93 + 33);
             *data++ = (count % 93 + 33);
         }
         }
@@ -94,70 +86,94 @@ void rt_link_speed_test(void *paremeter)
     tick1 = rt_tick_get();
     tick1 = rt_tick_get();
     while (speed_test_type)
     while (speed_test_type)
     {
     {
-        ret = rt_link_send(RT_LINK_SERVICE_RTLINK, send_buf, bufflen);
-        if(ret > 0)
+        ret = rt_link_send(&serv_socket, send_buf, bufflen);
+        if (ret > 0)
         {
         {
             sentlen += ret;
             sentlen += ret;
         }
         }
+        else
+        {
+            log_w("send err %d", ret);
+        }
 
 
         tick2 = rt_tick_get();
         tick2 = rt_tick_get();
-        if (tick2 - tick1 >= RT_TICK_PER_SECOND)//* 10
+        if (tick2 - tick1 >= RT_TICK_PER_SECOND)
         {
         {
             total = sentlen * RT_TICK_PER_SECOND / 125 / (tick2 - tick1);
             total = sentlen * RT_TICK_PER_SECOND / 125 / (tick2 - tick1);
-            integer = total/1000;
-            decimal = total%1000;
+            integer = total / 1000;
+            decimal = total % 1000;
             LOG_I("%d.%03d0 Mbps!", integer, decimal);
             LOG_I("%d.%03d0 Mbps!", integer, decimal);
             sentlen = 0;
             sentlen = 0;
             tick1 = tick2;
             tick1 = tick2;
         }
         }
     }
     }
     rt_free(send_buf);
     rt_free(send_buf);
-    LOG_W("speed test end, type %d",speed_test_type);
+    LOG_W("speed test end, type %d", speed_test_type);
+}
+
+static void create_thead_to_test_speed(rt_uint8_t mutil_num)
+{
+    rt_uint8_t i = 0;
+
+    LOG_D("Speed test type [%02d], mutil [%02d]", speed_test_type, mutil_num);
+    for (i = 0; i < mutil_num; i++)
+    {
+        rt_thread_t tid;
+        char tid_name[RT_NAME_MAX + 1] = {0};
+
+        rt_snprintf(tid_name, sizeof(tid_name), "lny_s%03d", i + 1);
+        tid = rt_thread_create(tid_name, rt_link_speed_test, RT_NULL, 1024, 20, 10);
+        if (tid)
+        {
+            rt_thread_startup(tid);
+            LOG_I("Speed test thread[%s] startup", tid_name);
+        }
+    }
 }
 }
 
 
-int rt_link_example_send(int argc, char **argv)
+static int rtlink_exsend(int argc, char **argv)
 {
 {
     char *receive = RT_NULL;
     char *receive = RT_NULL;
     rt_size_t length = 0;
     rt_size_t length = 0;
     rt_uint16_t count = 0;
     rt_uint16_t count = 0;
 
 
-    if(argc == 1)
+    if (argc == 1)
     {
     {
         receive = rt_malloc(sizeof(TEST_CONTEXT));
         receive = rt_malloc(sizeof(TEST_CONTEXT));
         rt_memcpy(receive, TEST_CONTEXT, sizeof(TEST_CONTEXT) - 1);
         rt_memcpy(receive, TEST_CONTEXT, sizeof(TEST_CONTEXT) - 1);
-        length = rt_link_send(RT_LINK_SERVICE_RTLINK, receive, sizeof(TEST_CONTEXT) - 1);
+        length = rt_link_send(&serv_socket, receive, sizeof(TEST_CONTEXT) - 1);
         LOG_I("send data length: %d.", length);
         LOG_I("send data length: %d.", length);
         rt_free(receive);
         rt_free(receive);
     }
     }
-        else if(argc >= 3)
+    else if (argc >= 3)
     {
     {
-        if(strcmp(argv[1], "-l") == 0)
+        if (strcmp(argv[1], "-l") == 0)
         {
         {
             receive = rt_malloc(atoi((const char *)argv[2]));
             receive = rt_malloc(atoi((const char *)argv[2]));
-            for(count = 0;count < atoi((const char *)argv[2]); count++)
+            for (count = 0; count < atoi((const char *)argv[2]); count++)
             {
             {
                 *receive++ = (count % 93 + 33);
                 *receive++ = (count % 93 + 33);
             }
             }
-            length = rt_link_send(RT_LINK_SERVICE_RTLINK, receive - atoi((const char *)argv[2]), atoi((const char *)argv[2]));
+            length = rt_link_send(&serv_socket, receive - atoi((const char *)argv[2]), atoi((const char *)argv[2]));
             rt_free(receive - atoi((const char *)argv[2]));
             rt_free(receive - atoi((const char *)argv[2]));
 
 
             LOG_I("send data length: %d.", length);
             LOG_I("send data length: %d.", length);
         }
         }
-        else if(strcmp(argv[1], "-s") == 0)
+        else if (strcmp(argv[1], "-s") == 0)
         {
         {
-            if(speed_test_type == NONE_TEST)
+            if (speed_test_type == NONE_TEST)
             {
             {
                 rt_uint8_t mutil_num = 1;
                 rt_uint8_t mutil_num = 1;
-                if(argc > 3)
+                if (argc > 3)
                 {
                 {
                     mutil_num = atoi((const char *)argv[3]);
                     mutil_num = atoi((const char *)argv[3]);
                 }
                 }
 
 
-                if(strncmp(argv[2], "-s", rt_strlen(argv[2])) == 0)
+                if (strncmp(argv[2], "-s", rt_strlen(argv[2])) == 0)
                 {
                 {
                     speed_test_type = SHORT_FRAME_TEST;
                     speed_test_type = SHORT_FRAME_TEST;
                 }
                 }
-                else if(strncmp(argv[2], "-l", rt_strlen(argv[2])) == 0)
+                else if (strncmp(argv[2], "-l", rt_strlen(argv[2])) == 0)
                 {
                 {
                     speed_test_type = LONG_FRAME_TEST;
                     speed_test_type = LONG_FRAME_TEST;
                 }
                 }
@@ -176,12 +192,23 @@ int rt_link_example_send(int argc, char **argv)
     }
     }
     return 0;
     return 0;
 }
 }
-MSH_CMD_EXPORT(rt_link_example_send, rt link layer send test);
+MSH_CMD_EXPORT(rtlink_exsend, rt link layer send test);
 
 
-int rt_link_example_init(void)
+int rtlink_exinit(void)
 {
 {
-
-    rt_link_service_attach(RT_LINK_SERVICE_RTLINK, rt_link_receive_example_callback);
+    serv_socket.service = RT_LINK_SERVICE_SOCKET;
+    serv_socket.timeout_tx = RT_WAITING_FOREVER;
+    serv_socket.flag = RT_LINK_FLAG_ACK | RT_LINK_FLAG_CRC;
+    serv_socket.recv_cb = recv_cb;
+    serv_socket.send_cb = send_cb;
+    rt_link_service_attach(&serv_socket);
+
+    serv_wifi.service = RT_LINK_SERVICE_WIFI;
+    serv_wifi.timeout_tx = RT_WAITING_FOREVER;
+    serv_wifi.flag = RT_NULL;
+    serv_wifi.recv_cb = recv_cb;
+    serv_wifi.send_cb = send_cb;
+    rt_link_service_attach(&serv_wifi);
     return RT_EOK;
     return RT_EOK;
 }
 }
-MSH_CMD_EXPORT(rt_link_example_init, rt link layer example init);
+MSH_CMD_EXPORT(rtlink_exinit, rt link example init);

Some files were not shown because too many files changed in this diff