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) |
Powered by WebSVN v2.8.3