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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (hide annotations) (download)
Thu Apr 19 09:01:15 2007 UTC (17 years, 2 months ago) by hedin
File MIME type: text/plain
File size: 17258 byte(s)
added the TCP/IP stack, source code.
1 hedin 15 /*********************************************************************
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