?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*********************************************************************
2 *
3 * UART <-> TCP Bridge Example
4 * Module for Microchip TCP/IP Stack
5 * -Transmits all incoming TCP bytes on a socket out the UART
6 * module, all incoming UART bytes out of the TCP socket.
7 * -Reference: None (hopefully AN833 in the future)
8 *
9 *********************************************************************
10 * FileName: UART2TCPBridge.c
11 * Dependencies: TCP, Hardware UART module, ARP (optional),
12 * DNS (optional)
13 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
14 * Compiler: Microchip C32 v1.05 or higher
15 * Microchip C30 v3.12 or higher
16 * Microchip C18 v3.30 or higher
17 * HI-TECH PICC-18 PRO 9.63PL2 or higher
18 * Company: Microchip Technology, Inc.
19 *
20 * Software License Agreement
21 *
22 * Copyright (C) 2002-2009 Microchip Technology Inc. All rights
23 * reserved.
24 *
25 * Microchip licenses to you the right to use, modify, copy, and
26 * distribute:
27 * (i) the Software when embedded on a Microchip microcontroller or
28 * digital signal controller product ("Device") which is
29 * integrated into Licensee's product; or
30 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
31 * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
32 * used in conjunction with a Microchip ethernet controller for
33 * the sole purpose of interfacing with the ethernet controller.
34 *
35 * You should refer to the license agreement accompanying this
36 * Software for additional information regarding your rights and
37 * obligations.
38 *
39 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
40 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
41 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
42 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
43 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
44 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
45 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
46 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
47 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
48 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
49 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
50 *
51 *
52 * Author Date Comment
53 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
54 * Howard Schlunder 06/12/07 Original
55 ********************************************************************/
56 #define __UART2TCPBRIDGE_C
57  
58 #include "TCPIPConfig.h"
59 #include "HardwareProfile.h"
60  
61  
62 // TCP listen port and UART baud rate settings. Due to a current C18
63 // preprocessor bug (tested on compiler 3.30), the BAUD_RATE definition needs
64 // to be placed above the #if defined(STACK_USE_UART2TCP_BRIDGE) test.
65 // Otherwise, it won't compile when STACK_USE_UART2TCP_BRIDGE is UNdefined.
66 // Also, HardwareProfile.h also needs to be included before the
67 // STACK_USE_UART2TCP_BRIDGE test.
68 #define UART2TCPBRIDGE_PORT 9761
69 #define BAUD_RATE 19200
70  
71  
72 #if defined(STACK_USE_UART2TCP_BRIDGE)
73  
74 #include "TCPIP Stack/TCPIP.h"
75  
76 // Comment this define out if we are the server.
77 // Insert the appropriate address if we are the client.
78 //#define USE_REMOTE_TCP_SERVER "192.168.2.50"
79  
80 // Ring buffers for transfering data to and from the UART ISR:
81 // - (Head pointer == Tail pointer) is defined as an empty FIFO
82 // - (Head pointer == Tail pointer - 1), accounting for wraparound,
83 // is defined as a completely full FIFO. As a result, the max data
84 // in a FIFO is the buffer size - 1.
85 static BYTE vUARTRXFIFO[65];
86 static BYTE vUARTTXFIFO[17];
87 static volatile BYTE *RXHeadPtr = vUARTRXFIFO, *RXTailPtr = vUARTRXFIFO;
88 static volatile BYTE *TXHeadPtr = vUARTTXFIFO, *TXTailPtr = vUARTTXFIFO;
89  
90  
91 /*********************************************************************
92 * Function: void UART2TCPBridgeInit(void)
93 *
94 * PreCondition: None
95 *
96 * Input: None
97 *
98 * Output: None
99 *
100 * Side Effects: None
101 *
102 * Overview: Sets up the UART peripheral for this application
103 *
104 * Note: Uses interrupts
105 ********************************************************************/
106 void UART2TCPBridgeInit(void)
107 {
108 // Initilize UART
109 #if defined(__18CXX)
110 TXSTA = 0x20;
111 RCSTA = 0x90;
112  
113 #define CLOSEST_SPBRG_VALUE ((GetPeripheralClock()+2ul*BAUD_RATE)/BAUD_RATE/4-1)
114 #define BAUD_ACTUAL (GetPeripheralClock()/(CLOSEST_SPBRG_VALUE+1))
115 #if (BAUD_ACTUAL > BAUD_RATE)
116 #define BAUD_ERROR (BAUD_ACTUAL-BAUD_RATE)
117 #else
118 #define BAUD_ERROR (BAUD_RATE-BAUD_ACTUAL)
119 #endif
120 #define BAUD_ERROR_PRECENT ((BAUD_ERROR*100+BAUD_RATE/2)/BAUD_RATE)
121 #if BAUD_ERROR_PRECENT > 2
122 // Use high speed (Fosc/4) 16-bit baud rate generator
123 BAUDCONbits.BRG16 = 1;
124 TXSTAbits.BRGH = 1;
125 SPBRGH = ((GetPeripheralClock()+BAUD_RATE/2)/BAUD_RATE-1)>>8 & 0xFF;
126 SPBRG = ((GetPeripheralClock()+BAUD_RATE/2)/BAUD_RATE-1) & 0xFF;
127 #else
128 // See if we can use the high baud (Fosc/16) 8-bit rate setting
129 #if ((GetPeripheralClock()+2*BAUD_RATE)/BAUD_RATE/4 - 1) <= 255
130 SPBRG = (GetPeripheralClock()+2*BAUD_RATE)/BAUD_RATE/4 - 1;
131 TXSTAbits.BRGH = 1;
132 #else // Use the low baud rate 8-bit setting
133 SPBRG = (GetPeripheralClock()+8*BAUD_RATE)/BAUD_RATE/16 - 1;
134 #endif
135 #endif
136  
137 // Use high priority interrupt
138 IPR1bits.TXIP = 1;
139  
140 #else
141 UARTTX_TRIS = 0;
142 UARTRX_TRIS = 1;
143 UMODE = 0x8000; // Set UARTEN. Note: this must be done before setting UTXEN
144  
145 #if defined(__C30__)
146 USTA = 0x0400; // UTXEN set
147 #define CLOSEST_UBRG_VALUE ((GetPeripheralClock()+8ul*BAUD_RATE)/16/BAUD_RATE-1)
148 #define BAUD_ACTUAL (GetPeripheralClock()/16/(CLOSEST_UBRG_VALUE+1))
149 #else //defined(__C32__)
150 IPC8bits.U2IP = 6; // Priority level 6
151 USTA = 0x00001400; // RXEN set, TXEN set
152 #define CLOSEST_UBRG_VALUE ((GetPeripheralClock()+8ul*BAUD_RATE)/16/BAUD_RATE-1)
153 #define BAUD_ACTUAL (GetPeripheralClock()/16/(CLOSEST_UBRG_VALUE+1))
154 #endif
155  
156 #define BAUD_ERROR ((BAUD_ACTUAL > BAUD_RATE) ? BAUD_ACTUAL-BAUD_RATE : BAUD_RATE-BAUD_ACTUAL)
157 #define BAUD_ERROR_PRECENT ((BAUD_ERROR*100+BAUD_RATE/2)/BAUD_RATE)
158 #if (BAUD_ERROR_PRECENT > 3)
159 #warning UART frequency error is worse than 3%
160 #elif (BAUD_ERROR_PRECENT > 2)
161 #warning UART frequency error is worse than 2%
162 #endif
163  
164 UBRG = CLOSEST_UBRG_VALUE;
165 #endif
166  
167 }
168  
169  
170 /*********************************************************************
171 * Function: void UART2TCPBridgeTask(void)
172 *
173 * PreCondition: Stack is initialized()
174 *
175 * Input: None
176 *
177 * Output: None
178 *
179 * Side Effects: None
180 *
181 * Overview: None
182 *
183 * Note: None
184 ********************************************************************/
185 void UART2TCPBridgeTask(void)
186 {
187 static enum _BridgeState
188 {
189 SM_HOME = 0,
190 SM_SOCKET_OBTAINED
191 } BridgeState = SM_HOME;
192 static TCP_SOCKET MySocket = INVALID_SOCKET;
193 WORD wMaxPut, wMaxGet, w;
194 BYTE *RXHeadPtrShadow, *RXTailPtrShadow;
195 BYTE *TXHeadPtrShadow, *TXTailPtrShadow;
196  
197  
198 switch(BridgeState)
199 {
200 case SM_HOME:
201 #if defined(USE_REMOTE_TCP_SERVER)
202 // Connect a socket to the remote TCP server
203 MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
204 #else
205 MySocket = TCPOpen(0, TCP_OPEN_SERVER, UART2TCPBRIDGE_PORT, TCP_PURPOSE_UART_2_TCP_BRIDGE);
206 #endif
207  
208 // Abort operation if no TCP socket of type TCP_PURPOSE_UART_2_TCP_BRIDGE is available
209 // If this ever happens, you need to go add one to TCPIPConfig.h
210 if(MySocket == INVALID_SOCKET)
211 break;
212  
213 // Eat the first TCPWasReset() response so we don't
214 // infinitely create and reset/destroy client mode sockets
215 TCPWasReset(MySocket);
216  
217 // We have a socket now, advance to the next state
218 BridgeState = SM_SOCKET_OBTAINED;
219 break;
220  
221 case SM_SOCKET_OBTAINED:
222 // Reset all buffers if the connection was lost
223 if(TCPWasReset(MySocket))
224 {
225 // Optionally discard anything in the UART FIFOs
226 //RXHeadPtr = vUARTRXFIFO;
227 //RXTailPtr = vUARTRXFIFO;
228 //TXHeadPtr = vUARTTXFIFO;
229 //TXTailPtr = vUARTTXFIFO;
230  
231 // If we were a client socket, close the socket and attempt to reconnect
232 #if defined(USE_REMOTE_TCP_SERVER)
233 TCPDisconnect(MySocket);
234 MySocket = INVALID_SOCKET;
235 BridgeState = SM_HOME;
236 break;
237 #endif
238 }
239  
240 // Don't do anything if nobody is connected to us
241 if(!TCPIsConnected(MySocket))
242 break;
243  
244  
245 // Make sure to clear UART errors so they don't block all future operations
246 #if defined(__18CXX)
247 if(RCSTAbits.OERR)
248 {
249 RCSTAbits.CREN = 0;
250 RCSTAbits.CREN = 1;
251 LED1_IO ^= 1;
252 }
253 if(RCSTAbits.FERR)
254 {
255 BYTE dummy = RCREG;
256 LED2_IO ^= 1;
257 }
258 #else
259 if(U2STAbits.OERR)
260 U2STAbits.OERR = 0;
261 #endif
262  
263  
264 // Read FIFO pointers into a local shadow copy. Some pointers are volatile
265 // (modified in the ISR), so we must do this safely by disabling interrupts
266 RXTailPtrShadow = (BYTE*)RXTailPtr;
267 TXHeadPtrShadow = (BYTE*)TXHeadPtr;
268 #if defined(__18CXX)
269 PIE1bits.RCIE = 0;
270 PIE1bits.TXIE = 0;
271 #else
272 IEC1bits.U2RXIE = 0;
273 IEC1bits.U2TXIE = 0;
274 #endif
275 RXHeadPtrShadow = (BYTE*)RXHeadPtr;
276 TXTailPtrShadow = (BYTE*)TXTailPtr;
277 #if defined(__18CXX)
278 PIE1bits.RCIE = 1;
279 if(TXHeadPtrShadow != TXTailPtrShadow)
280 PIE1bits.TXIE = 1;
281 #else
282 IEC1bits.U2RXIE = 1;
283 if(TXHeadPtrShadow != TXTailPtrShadow)
284 IEC1bits.U2TXIE = 1;
285 #endif
286  
287 //
288 // Transmit pending data that has been placed into the UART RX FIFO (in the ISR)
289 //
290 wMaxPut = TCPIsPutReady(MySocket); // Get TCP TX FIFO space
291 wMaxGet = RXHeadPtrShadow - RXTailPtrShadow; // Get UART RX FIFO byte count
292 if(RXHeadPtrShadow < RXTailPtrShadow)
293 wMaxGet += sizeof(vUARTRXFIFO);
294 if(wMaxPut > wMaxGet) // Calculate the lesser of the two
295 wMaxPut = wMaxGet;
296 if(wMaxPut) // See if we can transfer anything
297 {
298 // Transfer the data over. Note that a two part put
299 // may be needed if the data spans the vUARTRXFIFO
300 // end to start address.
301 w = vUARTRXFIFO + sizeof(vUARTRXFIFO) - RXTailPtrShadow;
302 if(wMaxPut >= w)
303 {
304 TCPPutArray(MySocket, RXTailPtrShadow, w);
305 RXTailPtrShadow = vUARTRXFIFO;
306 wMaxPut -= w;
307 }
308 TCPPutArray(MySocket, RXTailPtrShadow, wMaxPut);
309 RXTailPtrShadow += wMaxPut;
310  
311 // No flush. The stack will automatically flush and do
312 // transmit coallescing to minimize the number of TCP
313 // packets that get sent. If you explicitly call TCPFlush()
314 // here, latency will go down, but so will max throughput
315 // and bandwidth efficiency.
316 }
317  
318 //
319 // Transfer received TCP data into the UART TX FIFO for future transmission (in the ISR)
320 //
321 wMaxGet = TCPIsGetReady(MySocket); // Get TCP RX FIFO byte count
322 wMaxPut = TXTailPtrShadow - TXHeadPtrShadow - 1;// Get UART TX FIFO free space
323 if(TXHeadPtrShadow >= TXTailPtrShadow)
324 wMaxPut += sizeof(vUARTTXFIFO);
325 if(wMaxPut > wMaxGet) // Calculate the lesser of the two
326 wMaxPut = wMaxGet;
327 if(wMaxPut) // See if we can transfer anything
328 {
329 // Transfer the data over. Note that a two part put
330 // may be needed if the data spans the vUARTTXFIFO
331 // end to start address.
332 w = vUARTTXFIFO + sizeof(vUARTTXFIFO) - TXHeadPtrShadow;
333 if(wMaxPut >= w)
334 {
335 TCPGetArray(MySocket, TXHeadPtrShadow, w);
336 TXHeadPtrShadow = vUARTTXFIFO;
337 wMaxPut -= w;
338 }
339 TCPGetArray(MySocket, TXHeadPtrShadow, wMaxPut);
340 TXHeadPtrShadow += wMaxPut;
341 }
342  
343 // Write local shadowed FIFO pointers into the volatile FIFO pointers.
344 #if defined(__18CXX)
345 PIE1bits.RCIE = 0;
346 PIE1bits.TXIE = 0;
347 #else
348 IEC1bits.U2RXIE = 0;
349 IEC1bits.U2TXIE = 0;
350 #endif
351 RXTailPtr = (volatile BYTE*)RXTailPtrShadow;
352 TXHeadPtr = (volatile BYTE*)TXHeadPtrShadow;
353 #if defined(__18CXX)
354 PIE1bits.RCIE = 1;
355 if(TXHeadPtrShadow != TXTailPtrShadow)
356 PIE1bits.TXIE = 1;
357 #else
358 IEC1bits.U2RXIE = 1;
359 if(TXHeadPtrShadow != TXTailPtrShadow)
360 IEC1bits.U2TXIE = 1;
361 #endif
362  
363 break;
364 }
365 }
366  
367  
368 #if defined(__18CXX)
369 /*********************************************************************
370 * Function: void UART2TCPBridgeISR(void)
371 *
372 * PreCondition: UART interrupt has occured
373 *
374 * Input: None
375 *
376 * Output: None
377 *
378 * Side Effects: None
379 *
380 * Overview: None
381 *
382 * Note: This function is supposed to be called in the ISR
383 * context.
384 ********************************************************************/
385 void UART2TCPBridgeISR(void)
386 {
387 // NOTE: All local variables used here should be declared static
388 static BYTE i;
389  
390 // Store a received byte, if pending, if possible
391 if(PIR1bits.RCIF)
392 {
393 // Get the byte
394 i = RCREG;
395  
396 // Clear the interrupt flag so we don't keep entering this ISR
397 PIR1bits.RCIF = 0;
398  
399 // Copy the byte into the local FIFO, if it won't cause an overflow
400 if(RXHeadPtr != RXTailPtr - 1)
401 {
402 if((RXHeadPtr != vUARTRXFIFO + sizeof(vUARTRXFIFO)) || (RXTailPtr != vUARTRXFIFO))
403 {
404 *RXHeadPtr++ = i;
405 if(RXHeadPtr >= vUARTRXFIFO + sizeof(vUARTRXFIFO))
406 RXHeadPtr = (volatile BYTE*)vUARTRXFIFO;
407 }
408 }
409 }
410  
411 // Transmit a byte, if pending, if possible
412 if(PIR1bits.TXIF)
413 {
414 if(TXHeadPtr != TXTailPtr)
415 {
416 TXREG = *TXTailPtr++;
417 if(TXTailPtr >= vUARTTXFIFO + sizeof(vUARTTXFIFO))
418 TXTailPtr = (volatile BYTE*)vUARTTXFIFO;
419 }
420 else // Disable the TX interrupt if we are done so that we don't keep entering this ISR
421 {
422 PIE1bits.TXIE = 0;
423 }
424 }
425 }
426  
427 #else
428 /*********************************************************************
429 * Function: void _ISR _U2RXInterrupt(void)
430 *
431 * PreCondition: None
432 *
433 * Input: None
434 *
435 * Output: None
436 *
437 * Side Effects: None
438 *
439 * Overview: Copies bytes to and from the local UART TX and
440 * RX FIFOs
441 *
442 * Note: None
443 ********************************************************************/
444 #if __C30_VERSION__ >= 300
445 void _ISR __attribute__((__no_auto_psv__)) _U2RXInterrupt(void)
446 #elif defined(__C30__)
447 void _ISR _U2RXInterrupt(void)
448 #else
449 void _U2RXInterrupt(void)
450 #endif
451 {
452 BYTE i;
453  
454 // Store a received byte, if pending, if possible
455 // Get the byte
456 i = U2RXREG;
457  
458 // Clear the interrupt flag so we don't keep entering this ISR
459 IFS1bits.U2RXIF = 0;
460  
461 // Copy the byte into the local FIFO, if it won't cause an overflow
462 if(RXHeadPtr != RXTailPtr - 1)
463 {
464 if((RXHeadPtr != vUARTRXFIFO + sizeof(vUARTRXFIFO)) || (RXTailPtr != vUARTRXFIFO))
465 {
466 *RXHeadPtr++ = i;
467 if(RXHeadPtr >= vUARTRXFIFO + sizeof(vUARTRXFIFO))
468 RXHeadPtr = vUARTRXFIFO;
469 }
470 }
471 }
472 /*********************************************************************
473 * Function: void _ISR _U2TXInterrupt(void)
474 *
475 * PreCondition: None
476 *
477 * Input: None
478 *
479 * Output: None
480 *
481 * Side Effects: None
482 *
483 * Overview: Copies bytes to and from the local UART TX and
484 * RX FIFOs
485 *
486 * Note: None
487 ********************************************************************/
488 #if __C30_VERSION__ >= 300
489 void _ISR __attribute__((__no_auto_psv__)) _U2TXInterrupt(void)
490 #elif defined(__C30__)
491 void _ISR _U2TXInterrupt(void)
492 #else
493 void _U2TXInterrupt(void)
494 #endif
495 {
496 // Transmit a byte, if pending, if possible
497 if(TXHeadPtr != TXTailPtr)
498 {
499 // Clear the TX interrupt flag before transmitting again
500 IFS1bits.U2TXIF = 0;
501  
502 U2TXREG = *TXTailPtr++;
503 if(TXTailPtr >= vUARTTXFIFO + sizeof(vUARTTXFIFO))
504 TXTailPtr = vUARTTXFIFO;
505 }
506 else // Disable the TX interrupt if we are done so that we don't keep entering this ISR
507 {
508 IEC1bits.U2TXIE = 0;
509 }
510 }
511  
512  
513 #if defined(__C32__)
514 void __attribute((interrupt(ipl6), vector(_UART2_VECTOR), nomips16)) U2Interrupt(void)
515 {
516 if(IFS1bits.U2RXIF)
517 _U2RXInterrupt();
518 if(IEC1bits.U2TXIE)
519 {
520 if(IFS1bits.U2TXIF)
521 _U2TXInterrupt();
522 }
523 }
524 #endif
525  
526 #endif // end of ISRs
527  
528  
529 #endif //#if defined(STACK_USE_UART2TCP_BRIDGE)
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3