/[H8]/trunk/docs/Microchip TCP_IP stack/TCPIP Stack/SLIP.c
ViewVC logotype

Contents of /trunk/docs/Microchip TCP_IP stack/TCPIP Stack/SLIP.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (show annotations) (download)
Thu Apr 19 09:01:15 2007 UTC (17 years, 1 month ago) by hedin
File MIME type: text/plain
File size: 17258 byte(s)
added the TCP/IP stack, source code.
1 /*********************************************************************
2 *
3 * Medium Access Control (MAC) Layer for Serial Line Internet
4 * Protocol (SLIP)
5 * Module for Microchip TCP/IP Stack
6 * -Provides access to the Internet over a RS232 serial link
7 * -Reference: RFC 1055
8 *
9 *********************************************************************
10 * FileName: SLIP.c
11 * Dependencies: stacktsk.h
12 * mac.h
13 * Processor: PIC18
14 * Complier: MCC18 v1.00.50 or higher
15 * HITECH PICC-18 V8.10PL1 or higher
16 * Company: Microchip Technology, Inc.
17 *
18 * Software License Agreement
19 *
20 * This software is owned by Microchip Technology Inc. ("Microchip")
21 * and is supplied to you for use exclusively as described in the
22 * associated software agreement. This software is protected by
23 * software and other intellectual property laws. Any use in
24 * violation of the software license may subject the user to criminal
25 * sanctions as well as civil liability. Copyright 2007 Microchip
26 * Technology Inc. All rights reserved.
27 *
28 * This software is provided "AS IS." MICROCHIP DISCLAIMS ALL
29 * WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, NOT LIMITED
30 * TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
31 * INFRINGEMENT. Microchip shall in no event be liable for special,
32 * incidental, or consequential damages.
33 *
34 *
35 * Author Date Comment
36 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37 * Nilesh Rajbharti 11/27/01 Original (Rev 1.0)
38 * Nilesh Rajbharti 2/9/02 Cleanup
39 ********************************************************************/
40 #define THIS_IS_MAC_LAYER
41
42 #include "TCPIP Stack/TCPIP.h"
43
44 #if defined(STACK_USE_SLIP)
45
46 #define MAX_SLIP_BUFFER_SIZE MAC_TX_BUFFER_SIZE
47
48 #if (MAX_SLIP_BUFFER_SIZE > 250)
49 #error Invalid MAX_SLIP_BUFFER_SIZE detected
50 #endif
51
52 #define BAUD_RATE (38400) // bps
53
54 #define USART_USE_BRGH_LOW
55 #if defined(USART_USE_BRGH_LOW)
56 #define SPBRG_VAL ( ((CLOCK_FREQ/BAUD_RATE)/64) - 1)
57 #else
58 #define SPBRG_VAL ( ((CLOCK_FREQ/BAUD_RATE)/16) - 1)
59 #endif
60
61 #if SPBRG_VAL > 255
62 #error "Calculated SPBRG value is out of range for currnet CLOCK_FREQ."
63 #endif
64
65 typedef struct _SLIP_TX_BUFFER
66 {
67 BYTE Length;
68 BYTE IOAccess;
69 BYTE CallerAccess;
70 union
71 {
72 struct
73 {
74 unsigned int bIsModemString : 1;
75 } bits;
76 BYTE byte;
77 } Flags;
78 BYTE Data[MAX_SLIP_BUFFER_SIZE];
79 } SLIP_TX_BUFFER;
80
81 typedef struct _SLIP_RX_BUFFER
82 {
83 BYTE CurrentPacket;
84 BYTE PacketCount;
85 BYTE IOAccess;
86 BYTE CallerAccess;
87 BYTE Data[MAX_SLIP_BUFFER_SIZE]; // Format: <Next>[<Data>...]
88 } SLIP_RX_BUFFER;
89
90 #pragma udata SLIP_TX_BUFFER_SEG = 0x400
91 SLIP_TX_BUFFER TxBuffer;
92
93 #pragma udata SLIP_RX_BUFFER_SEG = 0x300
94 SLIP_RX_BUFFER RxBuffer;
95
96 #pragma udata
97
98 static BOOL bIsRxActive;
99
100
101 /*
102 * SLIP escape character as per RFC 1055
103 */
104 #define END (0xc0)
105 #define ESC (0xdb)
106 #define ESC_END (0xdc)
107 #define ESC_ESC (0xdd)
108
109 typedef enum _SM_SLIP
110 {
111 SM_SLIP_SOF = 0,
112 SM_MODEM_CMD,
113 SM_MODEM_CMD_AT,
114 SM_SLIP_DATA,
115 SM_SLIP_ESC,
116 SM_SLIP_OVERFLOW
117 } SM_SLIP;
118
119 static struct
120 {
121 BYTE tempData;
122 BYTE currentPacket;
123 SM_SLIP smSLIP;
124 BYTE currentLength;
125 union
126 {
127 struct
128 {
129 unsigned int bIsDataReady : 1;
130 unsigned int bIsPacketDone : 1;
131 } bits;
132 BYTE byte;
133 } Flags;
134 } ISRLocals;
135
136
137 void MACISR(void)
138 {
139 /*
140 * If we have received an character, handle it.
141 */
142 if ( PIR1bits.RCIF && PIE1bits.RCIE )
143 {
144 /*
145 * Check for any error, and clear it if there is any.
146 */
147 if ( RCSTA & 0x06 )
148 {
149 RCSTAbits.CREN = 0;
150 RCSTAbits.CREN = 1;
151 ISRLocals.smSLIP = SM_SLIP_OVERFLOW;
152 }
153
154 ISRLocals.tempData = RCREG;
155
156 ISRLocals.Flags.bits.bIsDataReady = FALSE;
157
158 switch(ISRLocals.smSLIP)
159 {
160 default: // case SM_SLIP_SOF:
161 /*
162 * Remember current packet start location in a RxBuffer.
163 * This will be useful when buffer overflows and we need to
164 * discard packet that was overflown, keeping previously
165 * loaded packets intact.
166 */
167 ISRLocals.currentPacket = RxBuffer.IOAccess;
168 ISRLocals.currentLength = 0;
169
170 if ( ISRLocals.tempData == END )
171 ISRLocals.smSLIP = SM_SLIP_DATA;
172
173 /*
174 * Handle modem commands differently.
175 */
176 else if ( ISRLocals.tempData == 'A' )
177 {
178 ISRLocals.Flags.bits.bIsDataReady = TRUE;
179 ISRLocals.smSLIP = SM_MODEM_CMD_AT;
180 }
181 break;
182
183 case SM_MODEM_CMD:
184 ISRLocals.Flags.bits.bIsDataReady = TRUE;
185 if ( ISRLocals.tempData == '\r' )
186 {
187 ISRLocals.Flags.bits.bIsPacketDone = TRUE;
188 }
189 break;
190
191 case SM_MODEM_CMD_AT:
192 ISRLocals.Flags.bits.bIsDataReady = TRUE;
193 if ( ISRLocals.tempData == 'T' )
194 ISRLocals.smSLIP = SM_MODEM_CMD;
195 else
196 ISRLocals.smSLIP = SM_SLIP_OVERFLOW;
197 break;
198
199 case SM_SLIP_DATA:
200 ISRLocals.Flags.bits.bIsDataReady = TRUE;
201 /*
202 * If this is a escape character, wait for next
203 * character to determine its value.
204 */
205 if ( ISRLocals.tempData == ESC )
206 {
207 ISRLocals.Flags.bits.bIsDataReady = FALSE;
208 ISRLocals.smSLIP = SM_SLIP_ESC;
209 }
210
211 else if ( ISRLocals.tempData == END )
212 {
213 /*
214 * End of packet is received.
215 * Make sure that we have at least one data byte
216 * before declaring that new packet is received.
217 */
218 if ( ISRLocals.currentLength )
219 {
220 ISRLocals.Flags.bits.bIsPacketDone = TRUE;
221
222 /*
223 * Even though we are saving END character,
224 * it will be overwritten by next packet as per
225 * bIsPacketDone logic.
226 * This saves some code space as we do not have to
227 * wrap IOAccess index twice.
228 */
229 }
230 else
231 ISRLocals.Flags.bits.bIsDataReady = FALSE;
232 }
233
234 break;
235
236 case SM_SLIP_ESC:
237 // Save the data.
238 ISRLocals.Flags.bits.bIsDataReady = TRUE;
239 ISRLocals.smSLIP = SM_SLIP_DATA;
240
241 if ( ISRLocals.tempData == ESC_END )
242 ISRLocals.tempData = END;
243
244 else if ( ISRLocals.tempData == ESC_ESC )
245 ISRLocals.tempData = ESC;
246
247 else
248 /*
249 * This is an invalid character sequence.
250 * Do not save it.
251 */
252 {
253 ISRLocals.Flags.bits.bIsDataReady = FALSE;
254 ISRLocals.smSLIP = SM_SLIP_SOF;
255 }
256 break;
257
258 case SM_SLIP_OVERFLOW:
259 RxBuffer.IOAccess = ISRLocals.currentPacket;
260 ISRLocals.smSLIP = SM_SLIP_SOF;
261 break;
262 }
263
264 if ( ISRLocals.Flags.bits.bIsDataReady )
265 {
266 RxBuffer.IOAccess++;
267 if ( RxBuffer.IOAccess >= MAX_SLIP_BUFFER_SIZE )
268 RxBuffer.IOAccess = 0;
269
270 /*
271 * Make sure that we have not reached end of buffer.
272 */
273 if ( RxBuffer.IOAccess != RxBuffer.CurrentPacket )
274 {
275 ISRLocals.currentLength++;
276 RxBuffer.Data[RxBuffer.IOAccess] = ISRLocals.tempData;
277 }
278 else
279 {
280 /*
281 * We have reached end of buffer.
282 * Discard this packet by restoring IOAccess to begining
283 * of current packet.
284 */
285 RxBuffer.IOAccess = ISRLocals.currentPacket;
286 ISRLocals.smSLIP = SM_SLIP_SOF;
287 ISRLocals.Flags.bits.bIsPacketDone = FALSE;
288 }
289
290 }
291
292 if ( ISRLocals.Flags.bits.bIsPacketDone )
293 {
294 ISRLocals.Flags.bits.bIsPacketDone = FALSE;
295
296 /*
297 * Create link to next packet.
298 */
299 RxBuffer.Data[ISRLocals.currentPacket] = RxBuffer.IOAccess;
300 RxBuffer.PacketCount++;
301
302 /*
303 * Start waiting for another packet.
304 */
305 ISRLocals.smSLIP = SM_SLIP_SOF;
306 }
307 }
308
309 if ( PIR1bits.TXIF && PIE1bits.TXIE )
310 {
311 /*
312 * If there is any data, transmit it.
313 */
314 if ( TxBuffer.Length )
315 {
316 ISRLocals.tempData = TxBuffer.Data[TxBuffer.IOAccess];
317 if ( ISRLocals.tempData == END )
318 {
319 ISRLocals.tempData = ESC;
320 TxBuffer.Data[TxBuffer.IOAccess] = ESC_END;
321 }
322 else if ( ISRLocals.tempData == ESC )
323 {
324 ISRLocals.tempData = ESC;
325 TxBuffer.Data[TxBuffer.IOAccess] = ESC_ESC;
326 }
327 else
328 {
329 TxBuffer.Length--;
330 TxBuffer.IOAccess++;
331 }
332 TXREG = ISRLocals.tempData;
333 }
334 else
335 {
336 /*
337 * Else, disable transmit interrupt.
338 */
339 PIE1bits.TXIE = 0;
340
341 if ( TxBuffer.Flags.bits.bIsModemString )
342 TxBuffer.Flags.bits.bIsModemString = FALSE;
343 else
344 TXREG = END;
345
346 }
347 }
348 }
349
350 void MACInit(void)
351 {
352 MACDiscardTx(0);
353
354 /*
355 * Initialize ISR variables.
356 */
357 ISRLocals.smSLIP = SM_SLIP_SOF;
358 ISRLocals.Flags.byte = 0;
359
360 RxBuffer.CurrentPacket = 0;
361 RxBuffer.PacketCount = 0;
362 RxBuffer.CallerAccess = 0;
363 RxBuffer.IOAccess = 0;
364
365 bIsRxActive = FALSE;
366
367 /*
368 * Clear receive interrupt flag.
369 */
370 PIR1bits.RCIF = 0;
371
372 /*
373 * Enable receive interrupt.
374 * Do not enable transmit interrupt yet. Enable it only when
375 * there is something to transmit
376 */
377 PIE1bits.RCIE = 1;
378 PIE1bits.TXIE = 0;
379
380 /*
381 * Configure USART for Asynch, 8-bit mode.
382 */
383 #if defined(USART_USE_BRGH_LOW)
384 TXSTA = 0b00100000;
385 #else
386 TXSTA = 0b00100100;
387 #endif
388
389 RCSTA = 0b10010000;
390 SPBRG = SPBRG_VAL;
391
392 /*
393 * Enable global and peripheral interrupts.
394 */
395 INTCONbits.GIEH = 1;
396 INTCONbits.GIEL = 1;
397
398 }
399
400 BOOL MACIsTxReady(BOOL HighPriority)
401 {
402 return ( (TxBuffer.Length < MAX_SLIP_BUFFER_SIZE) && !PIE1bits.TXIE);
403 }
404
405 BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
406 {
407 /*
408 * This marks that all future accesses to MACGet and MACPut
409 * be applied to Receive buffer.
410 */
411 bIsRxActive = TRUE;
412
413 if ( RxBuffer.PacketCount )
414 {
415
416 /*
417 * Set up packet access index.
418 */
419 RxBuffer.CallerAccess = RxBuffer.CurrentPacket;
420
421 RxBuffer.CallerAccess++;
422 if ( RxBuffer.CallerAccess >= MAX_SLIP_BUFFER_SIZE )
423 RxBuffer.CallerAccess = 0;
424
425
426 /*
427 * Handle modem commands differently.
428 */
429 if ( RxBuffer.Data[RxBuffer.CallerAccess] == 'A' )
430 {
431 /*
432 * Once a modem command is detected, we are not interested
433 * in detail.
434 */
435 MACDiscardRx();
436
437 /*
438 * Mark TxBuffer for Modem String.
439 * This will make sure that Transmit ISR does nottransmit END
440 * at the end.
441 */
442 TxBuffer.Flags.bits.bIsModemString = TRUE;
443
444 /*
445 * Since this special handling does not follow standard
446 * SLIP buffer logic, we will setup all required variables
447 * manually.
448 */
449 TxBuffer.Length = 4;
450 TxBuffer.CallerAccess = 0;
451
452 /*
453 * Remember to use transmit buffer for MACPut
454 */
455 bIsRxActive = FALSE;
456
457 /*
458 * Now load modem response.
459 */
460 MACPut('O');
461 MACPut('K');
462 MACPut('\r');
463 MACPut('\n');
464
465 /*
466 * Transmit it.
467 */
468 MACFlush();
469 }
470 else
471 {
472 /*
473 * This was not a modem command.
474 * It must be IP packet. Mark it accordingly and return.
475 */
476 *type = MAC_IP;
477
478 return TRUE;
479 }
480 }
481 return FALSE;
482 }
483
484 BYTE MACGet(void)
485 {
486 BYTE c;
487
488 /*
489 * Depending on what buffer is active, act accordingly.
490 */
491 if ( bIsRxActive )
492 {
493 c = RxBuffer.Data[RxBuffer.CallerAccess++];
494 if ( RxBuffer.CallerAccess >= MAX_SLIP_BUFFER_SIZE )
495 RxBuffer.CallerAccess = 0;
496 }
497 else
498 {
499 /*
500 * TxBuffer.Data contains data bytes only. There is no link byte.
501 */
502 c = TxBuffer.Data[TxBuffer.CallerAccess++];
503 }
504
505 return c;
506 }
507
508 WORD MACGetArray(BYTE *val, WORD len)
509 {
510 /*
511 * This function does not verify requested bytes against available
512 * bytes in current packet. Higher level logic must always validate
513 * packet and fetch data according to packet header.
514 */
515
516 while( len-- )
517 *val++ = MACGet();
518 return len;
519 }
520
521 void MACDiscardRx(void)
522 {
523 PIE1bits.RCIE = 0;
524
525 if ( RxBuffer.PacketCount )
526 {
527 /*
528 * Once a packet is discarded, current packet becomes next one.
529 */
530 RxBuffer.CurrentPacket = RxBuffer.Data[RxBuffer.CurrentPacket];
531
532 RxBuffer.PacketCount--;
533 }
534
535 PIE1bits.RCIE = 1;
536 }
537
538 void MACPutHeader(MAC_ADDR *remote,
539 BYTE type,
540 WORD dataLen)
541 {
542 TxBuffer.Length = dataLen;
543 TxBuffer.CallerAccess = 0;
544 bIsRxActive = FALSE;
545 }
546
547 void MACPut(BYTE val)
548 {
549 if ( bIsRxActive )
550 {
551 RxBuffer.Data[RxBuffer.CallerAccess++] = val;
552 if ( RxBuffer.CallerAccess >= MAX_SLIP_BUFFER_SIZE )
553 RxBuffer.CallerAccess = 0;
554 }
555 else
556 {
557 TxBuffer.Data[TxBuffer.CallerAccess++] = val;
558 }
559 }
560
561 void MACPutArray(BYTE *val, WORD len)
562 {
563 while( len-- )
564 MACPut(*val++);
565 }
566
567
568 void MACFlush(void)
569 {
570 TxBuffer.CallerAccess = 0;
571 TxBuffer.IOAccess = 0;
572
573 if ( !TxBuffer.Flags.bits.bIsModemString )
574 TXREG = END;
575
576 PIE1bits.TXIE = 1;
577 }
578
579 void MACDiscardTx(BUFFER buffer)
580 {
581 /*
582 * If there is no transmission in progress,
583 * discard current buffer.
584 * This is different than ethernet controller where
585 * discarding transmit buffer does not affect
586 * transmission that is already in progress.
587 */
588 if ( !PIE1bits.TXIE )
589 {
590 TxBuffer.Length = 0;
591 TxBuffer.CallerAccess = 0;
592 TxBuffer.IOAccess = 0;
593 TxBuffer.Flags.byte = 0;
594 }
595 }
596
597 void MACSetRxBuffer(WORD offset)
598 {
599 /*
600 * Set absolute offset.
601 */
602 offset += RxBuffer.CurrentPacket;
603
604 /*
605 * Skip "next packet" byte.
606 */
607 offset++;
608
609 /*
610 * Wrap the offset if necessary.
611 */
612 if ( offset >= (BYTE)(MAX_SLIP_BUFFER_SIZE-1) )
613 RxBuffer.CallerAccess = (BYTE)(offset - (BYTE)MAX_SLIP_BUFFER_SIZE);
614 else
615 RxBuffer.CallerAccess = (BYTE)offset;
616
617 bIsRxActive = TRUE;
618 }
619
620 void MACSetTxBuffer(BUFFER buffer, WORD offset)
621 {
622 TxBuffer.CallerAccess = offset;
623 bIsRxActive = FALSE;
624 }
625
626 void MACReserveTxBuffer(BUFFER buffer)
627 {
628 }
629
630 WORD MACGetFreeRxSize(void)
631 {
632 BYTE temp;
633
634 PIE1bits.RCIE = 0;
635 temp = RxBuffer.IOAccess;
636 PIE1bits.RCIE = 1;
637
638 if ( RxBuffer.PacketCount )
639 {
640 if( temp > RxBuffer.CurrentPacket )
641 return ((MAX_SLIP_BUFFER_SIZE -temp) + RxBuffer.CurrentPacket);
642 else
643 return (RxBuffer.CurrentPacket - temp);
644 }
645 else
646 return (MAX_SLIP_BUFFER_SIZE-2);
647 }
648
649 BUFFER MACGetTxBuffer(BOOL HighPriority)
650 {
651 return 0;
652 }
653
654
655 #endif //#if defined(STACK_USE_SLIP)

  ViewVC Help
Powered by ViewVC 1.1.20