/[H8]/trunk/docs/MCHPStack2.20/Source/slip.c
ViewVC logotype

Contents of /trunk/docs/MCHPStack2.20/Source/slip.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20