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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide 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 hedin 62 /*********************************************************************
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