1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-02-02     xiangxistu   the first version
9  * 2021-05-08     Sherman      Optimize the operation function on the rt_link_receive_buffer
10  */
11 
12 #include <rtthread.h>
13 
14 #include <rtlink.h>
15 #include <rtlink_hw.h>
16 #include <rtlink_port.h>
17 #include <rtlink_utils.h>
18 
19 #define DBG_TAG "rtlink_hw"
20 #ifdef USING_RT_LINK_HW_DEBUG
21     #define DBG_LVL DBG_LOG
22 #else
23     #define DBG_LVL DBG_INFO
24 #endif
25 #define DBG_COLOR
26 #include <rtdbg.h>
27 
28 static struct rt_link_receive_buffer *rx_buffer = RT_NULL;
29 
rt_link_hw_buffer_init(void * parameter)30 struct rt_link_receive_buffer *rt_link_hw_buffer_init(void *parameter)
31 {
32     rx_buffer = rt_malloc(sizeof(struct rt_link_receive_buffer));
33     if (rx_buffer != RT_NULL)
34     {
35         rt_memset(rx_buffer, 0, sizeof(struct rt_link_receive_buffer));
36         rx_buffer->read_point = rx_buffer->data;
37         rx_buffer->write_point = rx_buffer->data;
38         rx_buffer->end_point = rx_buffer->data + RT_LINK_RECEIVE_BUFFER_LENGTH; /* Point to memory that has no access rights */
39     }
40     else
41     {
42         LOG_E("receive buffer alloc failed, init failed.");
43     }
44 
45     return rx_buffer;
46 }
47 
rt_link_hw_buffer_write(void * data,rt_size_t count)48 static rt_ssize_t rt_link_hw_buffer_write(void *data, rt_size_t count)
49 {
50     rt_size_t surplus = 0;
51     if (rx_buffer == RT_NULL)
52     {
53         return 0;
54     }
55     /* (data)----(r)----(w)----(end) */
56     if (rx_buffer->write_point >= rx_buffer->read_point)
57     {
58         rt_size_t w2end = rx_buffer->end_point - rx_buffer->write_point;
59         surplus = RT_LINK_RECEIVE_BUFFER_LENGTH - (rx_buffer->write_point - rx_buffer->read_point);
60         count = count > surplus ? surplus : count;
61         if (count >= w2end)
62         {
63             rt_memcpy(rx_buffer->write_point, data, w2end);
64             rx_buffer->write_point = rx_buffer->data;
65 
66             rt_memcpy(rx_buffer->write_point, (rt_uint8_t *)data + w2end, (count - w2end));
67             rx_buffer->write_point += (count - w2end);
68         }
69         else
70         {
71             rt_memcpy(rx_buffer->write_point, data, count);
72             rx_buffer->write_point += count;
73         }
74     }
75     else    /* (data)----(w)----(r)----(end) */
76     {
77         surplus = rx_buffer->read_point - rx_buffer->write_point;
78         count = count > surplus ? surplus : count;
79         rt_memcpy(rx_buffer->write_point, data, count);
80         rx_buffer->write_point += count;
81     }
82     return count;
83 }
84 
85 /* increases buffer pointer by one and circle around if necessary */
rt_link_hw_buffer_point_shift(rt_uint8_t ** pointer_address,rt_size_t length)86 void rt_link_hw_buffer_point_shift(rt_uint8_t **pointer_address, rt_size_t length)
87 {
88     rt_uint8_t *pointer = *pointer_address + length;
89 
90     if (rx_buffer->write_point >= rx_buffer->read_point)
91     {
92         if (pointer >= rx_buffer->write_point)
93         {
94             *pointer_address = rx_buffer->write_point;
95         }
96         else
97         {
98             *pointer_address = pointer;
99         }
100     }
101     else
102     {
103         if (pointer >= rx_buffer->end_point)
104         {
105             *pointer_address = rx_buffer->data;
106             pointer = pointer - rx_buffer->end_point + rx_buffer->data;
107 
108             if (pointer >= rx_buffer->write_point)
109             {
110                 *pointer_address = rx_buffer->write_point;
111             }
112             else
113             {
114                 *pointer_address = pointer;
115             }
116         }
117         else
118         {
119             *pointer_address = pointer;
120         }
121     }
122 }
123 
124 /* copy data from receive buffer */
rt_link_hw_copy(rt_uint8_t * dst,rt_uint8_t * src,rt_size_t count)125 void rt_link_hw_copy(rt_uint8_t *dst, rt_uint8_t *src, rt_size_t count)
126 {
127     rt_uint8_t *pointer = RT_NULL;
128 
129     pointer = src + count;
130     if (pointer >= rx_buffer->end_point)
131     {
132         rt_size_t offset = 0;
133         offset = rx_buffer->end_point - src;
134         rt_memcpy(dst, src, offset);
135         rt_memcpy(dst + offset,  rx_buffer->data, pointer - rx_buffer->end_point);
136     }
137     else
138     {
139         rt_memcpy(dst, src, count);
140     }
141 }
142 
143 /* Length of data received */
rt_link_hw_recv_len(struct rt_link_receive_buffer * buffer)144 rt_size_t rt_link_hw_recv_len(struct rt_link_receive_buffer *buffer)
145 {
146     if (buffer == RT_NULL)
147     {
148         return 0;
149     }
150     if (buffer->write_point >= buffer->read_point)
151     {
152         return (buffer->write_point - buffer->read_point);
153     }
154     else
155     {
156         return (RT_LINK_RECEIVE_BUFFER_LENGTH - (buffer->read_point - buffer->write_point));
157     }
158 }
159 
rt_link_reset_crc32(void)160 rt_err_t rt_link_reset_crc32(void)
161 {
162 #ifdef RT_LINK_USING_HW_CRC
163     return rt_link_hw_crc32_reset();
164 #else
165     return rt_link_sf_crc32_reset();
166 #endif
167 }
168 
rt_link_crc32(rt_uint8_t * data,rt_size_t u32_size)169 rt_uint32_t rt_link_crc32(rt_uint8_t *data, rt_size_t u32_size)
170 {
171 #ifdef RT_LINK_USING_HW_CRC
172     return rt_link_hw_crc32(data, u32_size);
173 #else
174     return rt_link_sf_crc32(data, u32_size);
175 #endif
176 }
177 
rt_link_get_crc(rt_uint8_t using_buffer_ring,rt_uint8_t * data,rt_size_t size)178 rt_uint32_t rt_link_get_crc(rt_uint8_t using_buffer_ring, rt_uint8_t *data, rt_size_t size)
179 {
180     rt_uint32_t crc32 = 0x0;
181     rt_size_t surplus = 0;
182 
183     if (data == RT_NULL)
184     {
185         LOG_D("warning, the parameter error: %d, data: 0x%08d.", size, data);
186         return 0;
187     }
188 
189     rt_link_reset_crc32();
190     if (using_buffer_ring == 1)
191     {
192         /* modify the missing character */
193         surplus = rx_buffer->end_point - data;
194         if (surplus >= size)
195         {
196             crc32 = rt_link_crc32(data, size);
197         }
198         else
199         {
200             rt_link_crc32(data, surplus);
201             crc32 = rt_link_crc32(rx_buffer->data, size - surplus);
202         }
203     }
204     else
205     {
206         crc32 = rt_link_crc32(data, size);
207     }
208     return crc32;
209 }
210 
rt_link_hw_send(void * data,rt_size_t length)211 rt_size_t rt_link_hw_send(void *data, rt_size_t length)
212 {
213     rt_size_t send_len = 0;
214     send_len = rt_link_port_send(data, length);
215     if (send_len <= 0)
216     {
217         rt_link_port_reconnect();
218         send_len = rt_link_port_send(data, length);
219     }
220     return send_len;
221 }
222 
rt_link_hw_write_cb(void * data,rt_size_t length)223 rt_size_t rt_link_hw_write_cb(void *data, rt_size_t length)
224 {
225     /* write real data into rtlink receive buffer */
226     rt_size_t len = rt_link_hw_buffer_write(data, length);
227     struct rt_link_session *scb = rt_link_get_scb();
228     if (scb)
229     {
230         rt_event_send(&scb->event, RT_LINK_READ_CHECK_EVENT);
231     }
232     return len;
233 }
234 
rt_link_hw_init(void)235 rt_err_t rt_link_hw_init(void)
236 {
237     struct rt_link_session *scb = rt_link_get_scb();
238     if ((rx_buffer != RT_NULL) || (scb == RT_NULL))
239     {
240         return -RT_ERROR;
241     }
242 
243     /* alloc receive buffer to store data */
244     if (rt_link_hw_buffer_init(RT_NULL) == RT_NULL)
245     {
246         return -RT_ENOMEM;
247     }
248     scb->rx_buffer = rx_buffer;
249     scb->calculate_crc = rt_link_get_crc;
250 
251     if (RT_EOK != rt_link_port_init())
252     {
253         return -RT_ERROR;
254     }
255 
256 #ifdef LINK_LAYER_USING_HW_CRC
257     /* crc hardware device for mcu and node */
258     if (RT_EOK != rt_link_hw_crc32_init())
259     {
260         return -RT_ERROR;
261     }
262 #endif
263 
264     LOG_I("link layer hardware environment init successful.");
265     return RT_EOK;
266 }
267 
rt_link_hw_deinit(void)268 rt_err_t rt_link_hw_deinit(void)
269 {
270     if (rx_buffer)
271     {
272         rt_free(rx_buffer);
273         rx_buffer = RT_NULL;
274     }
275     struct rt_link_session *scb = rt_link_get_scb();
276     if (scb)
277     {
278         scb->rx_buffer = rx_buffer;
279         scb->calculate_crc = RT_NULL;
280     }
281     if (RT_EOK != rt_link_port_deinit())
282     {
283         return -RT_ERROR;
284     }
285 
286 #ifdef LINK_LAYER_USING_HW_CRC
287     /* crc hardware device for mcu and node */
288     if (RT_EOK != rt_link_hw_crc32_deinit())
289     {
290         return -RT_ERROR;
291     }
292 #endif
293 
294     LOG_I("rtlink hardware deinit successful.");
295     return RT_EOK;
296 }
297