-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathslip.c
402 lines (342 loc) · 9.45 KB
/
slip.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#ifndef __patmos__
#include <termios.h>
#else
#include <machine/patmos.h>
#endif
#include "slip.h"
#include "config.h"
#define END 0xc0
#define ESC 0xdb
#define ESC_END 0xdc
#define ESC_ESC 0xdd
#define MAX 2000
static int fd;
static unsigned char rxbuf[MAX];
static int is_esc = 0;
static int cnt = 0;
static int rxfull = 0;
static int slipoutcnt = 0;
static unsigned char txbuf[MAX];
// TODO some counters and flags for TX
int tpip_slip_init(char *str) {
#ifdef __patmos__
#endif
#ifndef __patmos__
// O_NDELAY returns 0 when no character available, useful for polling
fd = open(str, O_RDONLY | O_NDELAY);
printf("SLIP open: %s %d\n", str, fd);
#endif
return 0;
}
int tpip_slip_getchar(unsigned char *cptr) {
#ifdef __patmos__
volatile _IODEV int *uart2_ptr = (volatile _IODEV int *)0xF00e0004;
volatile _IODEV int *uart2_status_ptr = (volatile _IODEV int *)0xF00e0000;
if (((*(uart2_status_ptr)) & 0x02) != 0) {
*cptr = *uart2_ptr;
return 1;
} else {
return 0;
}
#endif
#ifndef __patmos__
return read(fd, cptr, 1);
#endif
}
void tpip_slip_putchar(unsigned char c) {
// TODO send one character
#ifdef __patmos__
volatile _IODEV int *uart2_ptr = (volatile _IODEV int *)0xF00e0004;
volatile _IODEV int *uart2_status_ptr = (volatile _IODEV int *)0xF00e0000;
// MS: should try once and not have a busy wait here
while (((*(uart2_status_ptr)) & 0x01) == 0); // busy wait
*uart2_ptr = c;
//printf("%02d:tpip_slip_putchar(0x%02x)\n", slipoutcnt, c);
slipoutcnt++;
#endif
}
int tpip_slip_is_end(unsigned char c){
if (c == END)
return 1;
else
return 0;
}
int tpip_slip_is_esc(unsigned char c){
if (c == ESC)
return 1;
else
return 0;
}
int tpip_slip_was_esc(unsigned char c){
if (c == ESC_ESC)
return ESC;
else if (c == ESC_END)
return END;
else {
printf("slip esc error: 0x%02x\n", c);
return c;
}
}
void tpip_slip_put_end(){
tpip_slip_putchar(END);
}
void tpip_slip_put_esc(){
tpip_slip_putchar(ESC);
}
void tpip_slip_put_esc_esc(){
tpip_slip_putchar(ESC_ESC);
}
void tpip_slip_put_esc_end(){
tpip_slip_putchar(ESC_END);
}
// peridic stuff
// TODO: sometimes a wrong end of packet detection. Worked in the non-polling mode :-()
// TODO: should also contain the sending
// noline for WCET analysis
__attribute__((noinline)) void tpip_slip_run();
void tpip_slip_run() {
unsigned char c;
// MS: why is this loop not recognized by platin?
// _Pragma("loopbound min 4 max 4")
// for(int i=0; i<4; ++i) {
if(tpip_slip_getchar(&c) == 1) {
if (is_esc) {
if (c == ESC_ESC) {
rxbuf[cnt++] = ESC;
} else if (c == ESC_END) {
rxbuf[cnt++] = END;
}
is_esc = 0;
} else if (c == ESC) {
is_esc = 1;
} else if (c == END) {
rxfull = 1;
} else {
rxbuf[cnt++] = c;
}
if (cnt == 2000) cnt = 0;
}
// }
}
int tpip_slip_rxfull() {
return rxfull;
}
int tpip_slip_rxread(unsigned char buf[]) {
int i;
for (i=0; i<cnt; ++i) {
buf[i] = rxbuf[i];
}
rxfull = 0;
cnt = 0;
return i;
}
int tpip_slip_txempty() {
return 0;
}
void tpip_slip_txwrite(unsigned char buf[], int len) {
}
// slip
// SLIP sending:
// if SLIP_ESC 0xDB is in the datagram then these two bytes are sent
// SLIP_ESC 0xDB -> SLIP_ESC 0xDB + SLIP_ESC_ESC 0xDD
// if SLIP_END 0xC0 is in the datagram then two bytes are sent
// SLIP_END 0xC0 -> SLIP_ESC 0xDB + SLIP_ESC_END 0xDC
// finally append an END byte
// SLIP_END 0xC0
// SLIP receiving:
// if SLIP_ESC 0xDB is received then the next byte is either
// 0xDC (SLIP_ESC_END); really meaning 0xC0
// 0xDB + 0xDC -> 0xC0
// 0xDD (SLIP_ESC_ESC); really meaning 0xDB
// 0xDB + 0xDD -> 0xDD
// done when the END byte is detected
// SLIP_END 0xC0; stop
#ifndef __patmos__
int set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0)
{
printf("Error from tcgetattr: %s\n", strerror(errno));
return -1;
}
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit characters */
tty.c_cflag &= ~PARENB; /* no parity bit */
tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
/* setup for non-canonical mode */
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tty.c_oflag &= ~OPOST;
/* fetch bytes as they become available */
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 1;
if (tcsetattr(fd, TCSANOW, &tty) != 0)
{
printf("Error from tcsetattr: %s\n", strerror(errno));
return -1;
}
return 0;
}
void set_mincount(int fd, int mcount)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0)
{
printf("Error tcgetattr: %s\n", strerror(errno));
return;
}
tty.c_cc[VMIN] = mcount ? 1 : 0;
tty.c_cc[VTIME] = 5; /* half second timer */
if (tcsetattr(fd, TCSANOW, &tty) < 0)
printf("Error tcsetattr: %s\n", strerror(errno));
}
static int fd;
int initserial()
{
char *portname = "/dev/ttyUSB1";
fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
{
printf("Error opening %s: %s\n", portname, strerror(errno));
return -1;
}
/*baudrate 115200, 8 bits, no parity, 1 stop bit */
set_interface_attribs(fd, B115200);
set_mincount(fd, 0); /* set to pure timed read */
return 1;
}
// returns number of bytes cleared from in-buffer
// the function should be called before the serial port is used to make sure
// some old data in the serial in-buffer does not disrupt the program
int serialclear()
{
int rdlenall = 0;
int rdlen = -1;
do
{
unsigned char buf[2000];
rdlen = read(fd, buf, sizeof(buf) - 1);
if (rdlen > 0)
{
unsigned char *p;
printf("Cleared %2d bytes from serial\n", rdlen);
rdlenall += rdlen;
int i = 0;
for (p = buf; rdlen-- > 0; p++)
{
printf("%02d: 0x%02x\n", i, *p);
i++;
}
}
else if (rdlen < 0)
{
printf("Error from clear read: %d: %s\n", rdlen, strerror(errno));
}
/* repeat to fully clear buffer */
} while (rdlen > 0);
printf("serial cleared %d bytes:\n", rdlenall);
// how many characters were in the buffer
return rdlenall;
}
// it appends SLIP_END as the last byte
int serialsend(unsigned char *bufin, int cnt)
{
int txcnt = 0;
int wlen;
for(int i=0; i < cnt; i++, bufin++){
wlen = write(fd, bufin, 1);
txcnt += wlen;
if (wlen != 1) printf("Error from write: %d, %d\n", wlen, errno);
for(int i = 0; i < 100; i++)
tcdrain(fd);
}
static unsigned char endslip = END;
wlen = write(fd, &endslip, 1);
txcnt += wlen;
tcdrain(fd);
if (wlen != 1) printf("Error from write: %d, %d\n", wlen, errno);
for(int i = 0; i < 100; i++)
tcdrain(fd);
return txcnt;
}
// returns number of bytes received when SLIP_END is received
int serialreceive(unsigned char *bufin, int max)
{
int wlen;
int rdlenall = 0;
unsigned long words_to_get;
unsigned char *bufintmp = bufin;
/* simple noncanonical input */
unsigned char c = 0x00;
do
{
int rdlen;
unsigned char buf[2000];
rdlen = read(fd, buf, sizeof(buf) - 1);
if (rdlen > 0)
{
unsigned char *p;
printf("Read %2d bytes from serial\n", rdlen);
rdlenall += rdlen;
int i = 0;
for (p = buf; rdlen-- > 0; p++)
{
printf("%02d: 0x%02x\n", i, *p);
i++;
*bufin = *p;
c = *p;
bufin++;
}
//printf("\n");
}
else if (rdlen < 0)
{
printf("Error from read: %d: %s\n", rdlen, strerror(errno));
printf("Error info: Ensure that the serial port is active (i.e., run 'make tpippatmos' first.)\n");
break;
}
/* repeat read to get full message */
} while (c != END && rdlenall <= max);
printf("serial received %d \"slip\" bytes:\n", rdlenall);
// i is slip, j is data
int j =0;
for(int i = 0; i < rdlenall-1; i++)
{
unsigned char c = *(bufintmp+i);
// check if END was transmitted alsl as the first character
// which we do to make SLIP more resilient
if ((i == 0) && (c == END)){
i++;
} else if (c == ESC) {
c = *(bufintmp + (i++));
if(c == ESC_END) {
c = END;
}
else if(c == ESC_ESC) {
c = ESC_ESC;
} else {
printf("slip error on receive index %d, expected ESC_END or ESC_ESC but got 0x%02x\n",
i, c);
}
}
*(bufintmp+j) = c;
j++;
}
// clear SLIP_END
*(bufintmp+j) = 0x00;
printf("\n");
printf("serial received data %d bytes:\n", j);
return j;
}
#endif