/[H8]/trunk/PIC/Demo trimmet/udp.c
ViewVC logotype

Contents of /trunk/PIC/Demo trimmet/udp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 91 - (show annotations) (download)
Tue May 8 09:37:15 2007 UTC (17 years ago) by hedin
File MIME type: text/plain
File size: 18322 byte(s)
added tcp/ip stack demo, trimmed.
1 /*********************************************************************
2 *
3 * UDP Module for Microchip TCP/IP Stack
4 *
5 *********************************************************************
6 * FileName: UDP.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 * HiTech PICC18 Compiler Options excluding device selection:
36 * -FAKELOCAL -G -O -Zg -E -C
37 *
38 * Author Date Comment
39 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40 * Nilesh Rajbharti 3/19/01 Original (Rev 1.0)
41 * Nilesh Rajbharti 2/26/03 Fixed UDPGet and UDPProcess bugs
42 * as discovered and fixed by John Owen
43 * of Powerwave.
44 * 1. UDPGet would return FALSE on last good byte
45 * 2. UDPProcess was incorrectly calculating length.
46 * Nilesh Rajbharti 5/19/03 Added bFirstRead flag similar to TCP
47 * to detect very first UDPGet and
48 * reset MAC Rx pointer to begining of
49 * UDP data area. This would ensure that
50 * if UDP socket has pending Rx data and
51 * another module resets MAC Rx pointer,
52 * next UDP socket Get would get correct
53 * data.
54 * Robert Sloan (RSS) 5/29/03 Improved FindMatchingSocket()
55 ********************************************************************/
56
57 #define THIS_IS_UDP_MODULE
58
59 #include <string.h>
60
61 #include "stacktsk.h"
62 #include "helpers.h"
63 #include "mac.h"
64 #include "ip.h"
65 #include "udp.h"
66
67 #if !defined(STACK_USE_UDP)
68 #error UDP module is not enabled.
69 #error If you do not want UDP module, remove this file from your
70 #error project to reduce your code size.
71 #error If you do want UDP module, make sure that STACK_USE_UDP
72 #error is defined in StackTsk.h file.
73 #endif
74
75 UDP_SOCKET_INFO UDPSocketInfo[MAX_UDP_SOCKETS];
76 UDP_SOCKET activeUDPSocket;
77
78 static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h, NODE_INFO *remoteNode);
79
80
81 /*********************************************************************
82 * Function: void UDPInit(void)
83 *
84 * PreCondition: None
85 *
86 * Input: None
87 *
88 * Output: None
89 *
90 * Side Effects: None
91 *
92 * Overview: Initializes internal variables.
93 *
94 * Note:
95 ********************************************************************/
96 void UDPInit(void)
97 {
98 UDP_SOCKET s;
99
100 for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
101 {
102 UDPSocketInfo[s].localPort = INVALID_UDP_PORT;
103 UDPSocketInfo[s].Flags.bFirstRead = FALSE;
104 }
105 }
106
107 /*********************************************************************
108 * Function: UDP_SOCKET UDPOpen(UDP_PORT localPort,
109 * NODE_INFO *remoteNode,
110 * UDP_PORT remotePort)
111 *
112 * PreCondition: UDPInit() is already called
113 *
114 * Input: remoteNode - Remote Node info such as MAC and IP
115 * address
116 * If NULL, broadcast node address is set.
117 * remotePort - Remote Port to which to talk to
118 * If INVALID_UDP_SOCKET, localPort is
119 * opened for Listen.
120 * localPort - A valid port number.
121 *
122 * Output: A valid UDP socket that is to be used for
123 * subsequent UDP communications.
124 *
125 * Side Effects: None
126 *
127 * Overview: A UDP packet header is assembled and loaded into
128 * UDP transmit buffer.
129 *
130 * Note: This call must always have valid localPort
131 * value.
132 ********************************************************************/
133 UDP_SOCKET UDPOpen(UDP_PORT localPort,
134 NODE_INFO *remoteNode,
135 UDP_PORT remotePort)
136 {
137 UDP_SOCKET s;
138 UDP_SOCKET_INFO *p;
139
140
141 p = UDPSocketInfo;
142 for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
143 {
144 if ( p->localPort == INVALID_UDP_PORT )
145 {
146 p->localPort = localPort;
147
148 /*
149 * If remoteNode is supplied, remember it.
150 */
151 if ( remoteNode )
152 {
153 memcpy((void*)&p->remoteNode,
154 (const void*)remoteNode,
155 sizeof(p->remoteNode));
156 }
157 /* else Set broadcast address - TO BE DONE */
158
159
160 p->remotePort = remotePort;
161 p->TxCount = 0;
162 p->RxCount = 0;
163
164 /*
165 * Mark this socket as active.
166 * Once an active socket is set, subsequent operation can be
167 * done without explicitely supply socket identifier.
168 */
169 activeUDPSocket = s;
170 return s;
171 }
172 p++;
173 }
174
175 return (UDP_SOCKET)INVALID_UDP_SOCKET;
176 }
177
178
179
180
181 /*********************************************************************
182 * Function: void UDPClose(UDP_SOCKET s)
183 *
184 * PreCondition: UDPOpen() is already called
185 *
186 * Input: s - Socket that is to be closed.
187 *
188 * Output: None
189 *
190 * Side Effects: None
191 *
192 * Overview: Given socket is marked as available for future
193 * new communcations.
194 *
195 * Note: This function does not affect previous
196 * active UDP socket designation.
197 ********************************************************************/
198 void UDPClose(UDP_SOCKET s)
199 {
200 UDPSocketInfo[s].localPort = INVALID_UDP_PORT;
201 }
202
203
204 /*********************************************************************
205 * Function: BOOL UDPPut(BYTE v)
206 *
207 * PreCondition: UDPIsPutReady() == TRUE with desired UDP socket
208 * that is to be loaded.
209 *
210 * Input: v - Data byte to loaded into transmit buffer
211 *
212 * Output: TRUE if transmit buffer is still ready to accept
213 * more data bytes
214 *
215 * FALSE if transmit buffer can no longer accept
216 * any more data byte.
217 *
218 * Side Effects: None
219 *
220 * Overview: Given data byte is put into UDP transmit buffer
221 * and active UDP socket buffer length is incremented
222 * by one.
223 * If buffer has become full, FALSE is returned.
224 * Or else TRUE is returned.
225 *
226 * Note: This function loads data into an active UDP socket
227 * as determined by previous call to UDPIsPutReady()
228 ********************************************************************/
229 BOOL UDPPut(BYTE v)
230 {
231 UDP_SOCKET_INFO *p;
232 WORD temp;
233
234 p = &UDPSocketInfo[activeUDPSocket];
235
236 if ( p->TxCount == 0 )
237 {
238 /*
239 * This is the very first byte that is loaded in UDP buffer.
240 * Remember what transmit buffer we are loading, and
241 * start loading this and next bytes in data area of UDP
242 * packet.
243 */
244 p->TxBuffer = MACGetTxBuffer();
245
246 IPSetTxBuffer(p->TxBuffer, sizeof(UDP_HEADER));
247
248 p->TxOffset = 0;
249 }
250
251 /*
252 * Load it.
253 */
254 MACPut(v);
255
256 if ( p->TxOffset++ >= p->TxCount )
257 p->TxCount++;
258
259 #if 0
260 /*
261 * Keep track of number of bytes loaded.
262 * If total bytes fill up buffer, transmit it.
263 */
264 p->TxCount++;
265 #endif
266
267 #define SIZEOF_MAC_HEADER (14)
268
269 /*
270 * Depending on what communication media is used, allowable UDP
271 * data length will vary.
272 */
273 #if !defined(STACK_USE_SLIP)
274 #define MAX_UDP_DATA (MAC_TX_BUFFER_SIZE - SIZEOF_MAC_HEADER - sizeof(IP_HEADER) - sizeof(UDP_HEADER))
275 #else
276 #define MAX_UDP_DATA (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER) )
277 #endif
278
279 temp = p->TxCount;
280 if ( temp >= MAX_UDP_DATA )
281 {
282 UDPFlush();
283 }
284 #undef MAX_UDP_DATA
285
286 return TRUE;
287 }
288
289
290 /*********************************************************************
291 * Function: BOOL UDPFlush(void)
292 *
293 * PreCondition: UDPPut() is already called and desired UDP socket
294 * is set as an active socket by calling
295 * UDPIsPutReady().
296 *
297 * Input: None
298 *
299 * Output: All and any data associated with active UDP socket
300 * buffer is marked as ready for transmission.
301 *
302 * Side Effects: None
303 *
304 * Overview: None
305 *
306 * Note: This function transmit all data from
307 * an active UDP socket.
308 ********************************************************************/
309 void UDPFlush(void)
310 {
311 UDP_HEADER h;
312 UDP_SOCKET_INFO *p;
313
314 /*
315 * When using SLIP (USART), packet transmission takes some time
316 * and hence before sending another packet, we must make sure
317 * that, last packet is transmitted.
318 * When using ethernet controller, transmission occurs very fast
319 * and by the time next packet is transmitted, previous is
320 * transmitted and we do not need to check for last packet.
321 */
322 //while( !IPIsTxReady() );
323
324 p = &UDPSocketInfo[activeUDPSocket];
325
326 h.SourcePort = swaps(p->localPort);
327 h.DestinationPort = swaps(p->remotePort);
328 h.Length = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER));
329 // Do not swap h.Length yet. It is needed in IPPutHeader.
330 h.Checksum = 0x00;
331
332 IPSetTxBuffer(p->TxBuffer, 0);
333
334 /*
335 * Load IP header.
336 */
337 IPPutHeader( &p->remoteNode,
338 IP_PROT_UDP,
339 h.Length );
340
341
342 // Now swap h.Length.
343 h.Length = swaps(h.Length);
344
345 /*
346 * Now load UDP header.
347 */
348 IPPutArray((BYTE*)&h, sizeof(h));
349
350 /*
351 * Update checksum.
352 * TO BE IMPLEMENTED
353 */
354
355 MACFlush();
356
357 p->TxBuffer = INVALID_BUFFER;
358 p->TxCount = 0;
359
360 }
361
362
363
364 /*********************************************************************
365 * Function: BOOL UDPIsGetReady(UDP_SOCKET s)
366 *
367 * PreCondition: UDPInit() is already called.
368 *
369 * Input: A valid UDP socket that is already "Listen"ed on
370 * or opened.
371 *
372 * Output: TRUE if given port contains any data.
373 * FALSE if given port does not contain any data.
374 *
375 * Side Effects: Given socket is set as an active UDP Socket.
376 *
377 * Overview: None
378 *
379 * Note: This function automatically sets supplied socket
380 * as an active socket. Caller need not call
381 * explicit function UDPSetActiveSocket(). All
382 * subsequent calls will us this socket as an
383 * active socket.
384 ********************************************************************/
385 BOOL UDPIsGetReady(UDP_SOCKET s)
386 {
387 activeUDPSocket = s;
388 return ( UDPSocketInfo[activeUDPSocket].RxCount > 0 );
389 }
390
391 /*********************************************************************
392 * Function: BOOL UDPGet(BYTE *v)
393 *
394 * PreCondition: UDPInit() is already called AND
395 * UDPIsGetReady(s) == TRUE
396 *
397 * Input: v - Buffer to receive UDP data byte
398 *
399 * Output: TRUE if a data byte was read
400 * FALSE if no data byte was read or available
401 *
402 * Side Effects: None
403 *
404 * Overview: None
405 *
406 * Note: This function fetches data from an active UDP
407 * socket as set by UDPIsGetReady() call.
408 ********************************************************************/
409 BOOL UDPGet(BYTE *v)
410 {
411 /*
412 * CALLER MUST MAKE SURE THAT THERE IS ENOUGH DATA BYTE IN BUFFER
413 * BEFORE CALLING THIS FUNCTION.
414 * USE UDPIsGetReady() TO CONFIRM.
415 */
416 if ( UDPSocketInfo[activeUDPSocket].RxCount == 0 )
417 return FALSE;
418
419 // If if this very first read to packet, set MAC Rx Pointer to
420 // beginig of UDP data area.
421 if ( UDPSocketInfo[activeUDPSocket].Flags.bFirstRead )
422 {
423 UDPSocketInfo[activeUDPSocket].Flags.bFirstRead = FALSE;
424 UDPSetRxBuffer(0);
425 }
426
427 *v = MACGet();
428
429 UDPSocketInfo[activeUDPSocket].RxCount--;
430
431 if ( UDPSocketInfo[activeUDPSocket].RxCount == 0 )
432 {
433 MACDiscardRx();
434 }
435
436 return TRUE;
437 }
438
439
440 /*********************************************************************
441 * Function: void UDPDiscard(void)
442 *
443 * PreCondition: UDPInit() is already called AND
444 * UDPIsGetReady() == TRUE with desired UDP socket.
445 *
446 * Input: None
447 *
448 * Output: None
449 *
450 * Side Effects: None
451 *
452 * Overview: None
453 *
454 * Note: This function discards an active UDP socket content.
455 ********************************************************************/
456 void UDPDiscard(void)
457 {
458 if ( UDPSocketInfo[activeUDPSocket].RxCount )
459 MACDiscardRx();
460
461 UDPSocketInfo[activeUDPSocket].RxCount = 0;
462 }
463
464
465
466 /*********************************************************************
467 * Function: BOOL UDPProcess(NODE_INFO* remoteNode,
468 * WORD len)
469 *
470 * PreCondition: UDPInit() is already called AND
471 * UDP segment is ready in MAC buffer
472 *
473 * Input: remoteNode - Remote node info
474 * len - Total length of UDP semgent.
475 *
476 * Output: TRUE if this function has completed its task
477 * FALSE otherwise
478 *
479 * Side Effects: None
480 *
481 * Overview: None
482 *
483 * Note: None
484 ********************************************************************/
485 BOOL UDPProcess(NODE_INFO *remoteNode, WORD len)
486 {
487 UDP_HEADER h;
488 UDP_SOCKET s;
489
490 /*
491 * Retrieve UDP header.
492 */
493 MACGetArray((BYTE*)&h, sizeof(h));
494
495 h.SourcePort = swaps(h.SourcePort);
496 h.DestinationPort = swaps(h.DestinationPort);
497 h.Length = swaps(h.Length) - sizeof(UDP_HEADER);;
498 h.Checksum = swaps(h.Checksum);
499
500 s = FindMatchingSocket(&h, remoteNode);
501 if ( s == INVALID_UDP_SOCKET )
502 {
503 /*
504 * If there is no matching socket, There is no one to handle
505 * this data. Discard it.
506 */
507 MACDiscardRx();
508 }
509 else
510 {
511 UDPSocketInfo[s].RxCount = h.Length;
512 UDPSocketInfo[s].Flags.bFirstRead = TRUE;
513 }
514
515
516 return TRUE;
517 }
518
519
520 /*********************************************************************
521 * Function: UDP_SOCKET FindMatchingSocket(UDP_HEADER *h,
522 * NODE_INFO *remoteNode)
523 *
524 * PreCondition: UDP Segment header has been retrieved from buffer
525 * The IP header has also been retrieved
526 *
527 * Input: remoteNode - Remote node info from IP header
528 * h - header of UDP semgent.
529 *
530 * Output: matching UDP socket or INVALID_UDP_SOCKET
531 *
532 * Side Effects: None
533 *
534 * Overview: None
535 *
536 * Note: None
537 ********************************************************************/
538 #define BROADCAST_ADDRESS (0xffffffffL)
539 static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h, NODE_INFO *remoteNode)
540 {
541 UDP_SOCKET s;
542 UDP_SOCKET partialMatch;
543 UDP_SOCKET_INFO *p;
544
545 partialMatch = INVALID_UDP_SOCKET;
546
547 p = UDPSocketInfo;
548 for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
549 {
550 /*
551 * This packet is said to be matching with current socket
552 * 1. If its destination port matches with our local port.
553 * 2. This socket does not have any data pending.
554 * 3. Packet source IP address matches with socket remote IP address.
555 * OR this socket had transmitted packet with destination address
556 * as broadcast.
557 */
558 if ( p->localPort == h->DestinationPort )
559 {
560 if ( (p->remotePort == h->SourcePort) && (p->RxCount == 0L) )
561 {
562 if ( (p->remoteNode.IPAddr.Val == remoteNode->IPAddr.Val) ||
563 (p->remoteNode.IPAddr.Val == BROADCAST_ADDRESS) )
564 {
565 return s;
566 }
567 }
568
569 partialMatch = s;
570 }
571 p++;
572 }
573
574 if ( partialMatch != INVALID_UDP_SOCKET )
575 {
576 p = &UDPSocketInfo[partialMatch];
577
578 memcpy((void*)&p->remoteNode,
579 (const void*)remoteNode, sizeof(p->remoteNode) );
580
581 p->remotePort = h->SourcePort;
582 }
583 return partialMatch;
584 }
585
586
587

  ViewVC Help
Powered by ViewVC 1.1.20