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

Contents of /trunk/docs/MCHPStack2.20/Source/TFTPcDemo.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue May 1 08:17:39 2007 UTC (17 years, 1 month ago) by hedin
File MIME type: text/plain
File size: 34475 byte(s)
Removed tcpip stack 4.02 and added tcpip stack 2.20.
1 /*********************************************************************
2 *
3 * TFTP Client Demo App for Microchip TCP/IP Stack
4 *
5 *********************************************************************
6 * FileName: TFTPcDemo.c
7 * Dependencies: tftpc.h
8 * stacktsk.h
9 * xlcd.h
10 * tick.h
11 * Processor: PIC18
12 * Complier: MCC18 v1.00.50 or higher
13 * HITECH PICC-18 V8.10PL1 or higher
14 * Company: Microchip Technology, Inc.
15 *
16 * Software License Agreement
17 *
18 * The software supplied herewith by Microchip Technology Incorporated
19 * (the “Company”) for its PICmicro® Microcontroller is intended and
20 * supplied to you, the Company’s customer, for use solely and
21 * exclusively on Microchip PICmicro Microcontroller products. The
22 * software is owned by the Company and/or its supplier, and is
23 * protected under applicable copyright laws. All rights are reserved.
24 * Any use in violation of the foregoing restrictions may subject the
25 * user to criminal sanctions under applicable laws, as well as to
26 * civil liability for the breach of the terms and conditions of this
27 * license.
28 *
29 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
30 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
31 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
32 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
33 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
34 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
35 *
36 * Author Date Comment
37 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38 * Nilesh Rajbharti 8/7/03 Original (Rev 1.0)
39 *
40 *
41 * This demo application demonstartes Microchip TFTP client module usage
42 * See TFTPDemo(), TFTPWrite() and TFTPRead() for actual implementation.
43 *
44 * This application monitors RB5 switch. On first push it
45 * writes 'tftpwr.bin' file to server. tftpwr.bin file is made up of
46 * first 16KB of program memory.
47 * On second push, it reads 'tftprd.txt' file from server.
48 *
49 * Server IP address is set in "Board Setup" mode using Hyperterminal.
50 *
51 * It displays rotating '-' to indicate command in progress.
52 * 'Y' to indicate success
53 * 'N' for failure
54 * 'T' for timeout
55 * 'E' for error.
56 *
57 *
58 * If running this applicaton on PICDEM.net use
59 * HS Oscillator
60 * Debug disabled
61 * Low Voltage Disabled
62 * Watchdog timer disabled
63 ********************************************************************/
64 /*
65 * Following define uniquely deines this file as main
66 * entry/application In whole project, there should only be one such
67 * definition and application file must define AppConfig variable as
68 * described below.
69 */
70 #define THIS_IS_STACK_APPLICATION
71
72 #include "stacktsk.h"
73 #include "dhcp.h"
74 #include "tftpc.h"
75 #include "xlcd.h"
76 #include "tick.h"
77 #include "xeeprom.h"
78 #include "delay.h"
79
80 #define BAUD_RATE (19200) // bps
81
82
83 // All TFTP command statuts display will be done on first line of LCD.
84 #define TFTP_COMMAND_DISPLAY_LINE 0
85
86 // Result will be displayed at y = 15.
87 #define TFTP_COMMAND_RESULT_POSITION 15
88
89
90 #define STARTUP_MSG "MpStack 2.20.02+"
91
92 ROM char StartupMsg[] = STARTUP_MSG;
93
94 #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
95 ROM char DHCPMsg[] = "DHCP/Gleaning...";
96 #endif
97
98 ROM char SetupMsg[] = "Board Setup...";
99
100 // 1234567890123456
101 ROM char blankLCDLine[] = " ";
102
103 // Name of TFTP Put file
104 static char tftpFilePutName[] = "tftpwr.bin";
105
106 // Name of TFTP Get file
107 static char tftpFileGetName[] = "tftprd.txt";
108
109 // Strings to display on appropriate command.
110 ROM char tftpPutString[] = "PUT";
111 ROM char tftpGetString[] = "GET";
112
113
114 #define USART_USE_BRGH_LOW
115 #if defined(USART_USE_BRGH_LOW)
116 #define SPBRG_VAL ( ((CLOCK_FREQ/BAUD_RATE)/64) - 1)
117 #else
118 #define SPBRG_VAL ( ((CLOCK_FREQ/BAUD_RATE)/16) - 1)
119 #endif
120
121 #if SPBRG_VAL > 255
122 #error "Calculated SPBRG value is out of range for currnet CLOCK_FREQ."
123 #endif
124
125
126 /*
127 * This is used by other stack elements.
128 * Main application must define this and initialize it with
129 * proper values.
130 */
131 APP_CONFIG AppConfig;
132
133
134 BYTE myDHCPBindCount = 0;
135 #if defined(STACK_USE_DHCP)
136 extern BYTE DHCPBindCount;
137 #else
138 /*
139 * If DHCP is not enabled, force DHCP update.
140 */
141 BYTE DHCPBindCount = 1;
142 #endif
143
144
145 // This demo application issues PUT on first push of RB5
146 // GET on second push.
147 static union
148 {
149 struct
150 {
151 unsigned int bFirstPush : 1;
152 } bits;
153 BYTE Val;
154 } tftpDemoFlag;
155
156
157
158 #if defined(MCHP_C18) && defined(__18F8720)
159 #define TXSTAbits TXSTA1bits
160 #define TXREG TXREG1
161 #define TXSTA TXSTA1
162 #define RCSTA RCSTA1
163 #define SPBRG SPBRG1
164 #define RCREG RCREG1
165 #endif
166
167
168 /*
169 * Set configuration fuses for HITECH compiler.
170 * For MCC18 compiler, separately linked config.asm file
171 * will set the correct fuses.
172 */
173 #if defined(HITECH_C18)
174 __CONFIG(1, UNPROTECT & HS);
175 __CONFIG(2, PWRTEN & BORDIS & WDTDIS);
176 #endif
177
178
179 /*
180 * Private helper functions.
181 * These may or may not be present in all applications.
182 */
183 static void InitAppConfig(void);
184 static void InitializeBoard(void);
185 static void DisplayIPValue(IP_ADDR *IPVal, BOOL bToLCD);
186 static void SetConfig(void);
187 static void SaveAppConfig(void);
188 static void USARTPut(BYTE c);
189 static void USARTPutString(BYTE *s);
190
191 static BOOL TFTPRead(void);
192 static BOOL TFTPWrite(void);
193 static void TFTPDemo(void);
194
195
196
197 #define USARTIsGetReady() (PIR1_RCIF)
198 #define USARTGet() (RCREG)
199
200
201 void main(void)
202 {
203 // Tick to blink SYSTEM led.
204 static TICK t = 0;
205
206 // Remember that next RB5 push is the first one.
207 tftpDemoFlag.bits.bFirstPush = TRUE;
208
209 /*
210 * Initialize any application specific hardware.
211 */
212 InitializeBoard();
213
214 /*
215 * Since we are not using MPFS, initialize XEEPROM directly.
216 * If MPFS was used, calling MPFSInit() would automatically
217 * initialize XEEPROM.
218 */
219 XEEInit(EE_BAUD(CLOCK_FREQ, 400000));
220
221 /*
222 * Initialize all stack related components.
223 * Following steps must be performed for all applications using
224 * PICmicro TCP/IP Stack.
225 */
226 TickInit();
227
228 /*
229 * Initialize Stack and application related NV variables.
230 */
231 InitAppConfig();
232
233
234
235 /*
236 * This implementation, initiates Board setup process if RB5
237 * is detected low on startup.
238 */
239 if ( PORTB_RB5 == 0 )
240 {
241 XLCDGoto(1, 0);
242 XLCDPutROMString(SetupMsg);
243
244 SetConfig();
245 }
246
247 StackInit();
248
249 #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
250 if ( AppConfig.Flags.bIsDHCPEnabled )
251 {
252 XLCDGoto(1, 0);
253 XLCDPutROMString(DHCPMsg);
254 }
255 else
256 {
257 /*
258 * Force IP address display update.
259 */
260 myDHCPBindCount = 1;
261 #if defined(STACK_USE_DHCP)
262 DHCPDisable();
263 #endif
264 }
265 #endif
266
267
268 /*
269 * Once all items are initialized, go into infinite loop and let
270 * stack items execute their tasks.
271 * If application needs to perform its own task, it should be
272 * done at the end of while loop.
273 * Note that this is a "co-operative mult-tasking" mechanism
274 * where every task performs its tasks (whether all in one shot
275 * or part of it) and returns so that other tasks can do their
276 * job.
277 * If a task needs very long time to do its job, it must broken
278 * down into smaller pieces so that other tasks can have CPU time.
279 */
280 while(1)
281 {
282 /*
283 * Blink SYSTEM LED every second.
284 */
285 if ( TickGetDiff(TickGet(), t) >= TICK_SECOND/2 )
286 {
287 t = TickGet();
288 LATA4 ^= 1;
289 }
290
291 /*
292 * This task performs normal stack task including checking
293 * for incoming packet, type of packet and calling
294 * appropriate stack entity to process it.
295 */
296 StackTask();
297
298 /*
299 * For DHCP information, display how many times we have renewed the IP
300 * configuration since last reset.
301 */
302 if ( DHCPBindCount != myDHCPBindCount )
303 {
304 DisplayIPValue(&AppConfig.MyIPAddr, TRUE);
305 myDHCPBindCount = DHCPBindCount;
306
307 if ( AppConfig.Flags.bIsDHCPEnabled )
308 {
309 XLCDGoto(1, 14);
310 if ( myDHCPBindCount < 0x0a )
311 XLCDPut(myDHCPBindCount + '0');
312 else
313 XLCDPut(myDHCPBindCount + 'A');
314 }
315 }
316
317
318 /*
319 * This demo applicaton, monitors RB5 switch on-board PICDEM.net board.
320 * On first push, it uses TFTP PUT to send a file named "put.txt".
321 * On second push, it gets same "put.txt" file from server.
322 *
323 * Wait until IP address is assigned to this board.
324 */
325 if ( !stackFlags.bits.bInConfigMode )
326 TFTPDemo();
327
328 }
329 }
330
331
332 static void TFTPDemo(void)
333 {
334 static enum
335 {
336 SM_TFTP_DEMO_IDLE,
337 SM_TFTP_DEMO_WAIT,
338 SM_TFTP_DEMO_READY,
339 SM_TFTP_DEMO_WRITE,
340 SM_TFTP_DEMO_READ,
341 SM_TFTP_DEMO_CYCLE
342 } smTFTPDemo = SM_TFTP_DEMO_IDLE;
343 TFTP_RESULT result;
344
345 // Display rotating '-' while we execute command.
346 if ( smTFTPDemo == SM_TFTP_DEMO_WRITE ||
347 smTFTPDemo == SM_TFTP_DEMO_READ )
348 {
349 static char displayChar[] = { '-', '\\', '|', '/' };
350 static char i = 0;
351 static TICK lastTick = 0;
352
353 if ( TickGetDiff(TickGet(), lastTick) >= TICK_SECOND/2 )
354 {
355 XLCDGoto(TFTP_COMMAND_DISPLAY_LINE, TFTP_COMMAND_RESULT_POSITION);
356 XLCDPut(displayChar[i++]);
357 if ( i == 4 )
358 i = 0;
359
360 lastTick = TickGet();
361 }
362 }
363
364
365 // Main state machine for demo.
366 switch(smTFTPDemo)
367 {
368 case SM_TFTP_DEMO_IDLE:
369 // On startup, we try to resolve TFTP server IP address.
370 // Application may decide to do this when actual TFTP operation is required
371 // This is completely application dependent.
372 // By doing it here, we can reuse ARP on subsequent TFTP operation
373 TFTPOpen(&AppConfig.TFTPServerAddr);
374
375 // Now we must wait for ARP to get resolved.
376 smTFTPDemo = SM_TFTP_DEMO_WAIT;
377 break;
378
379 case SM_TFTP_DEMO_WAIT:
380 // Check to see if connection was established.
381 result = TFTPIsOpened();
382 if ( result == TFTP_OK )
383 // ARP is resolved and UDP port is opened.
384 // Now we are ready for future TFTP commands.
385 smTFTPDemo = SM_TFTP_DEMO_READY;
386
387 else if ( result == TFTP_TIMEOUT )
388 // Timeout has occured.
389 // Application may decide to count attempts and give-up after
390 // so many retries or as in this case, continue to try forever.
391 // We must have resolved server IP address or else nothing
392 // can be done.
393 smTFTPDemo = SM_TFTP_DEMO_IDLE;
394 break;
395
396 case SM_TFTP_DEMO_READY:
397 // Scan for RB5 switch.
398 if ( PORTB_RB5 == 0 )
399 {
400 // RB5 was pushed. Decide if this is first push or second push
401 // and perform appropriate command.
402
403 // Blank out TFTP command display line in LCD.
404 XLCDGoto(TFTP_COMMAND_DISPLAY_LINE, 0);
405 XLCDPutROMString(blankLCDLine);
406 XLCDGoto(TFTP_COMMAND_DISPLAY_LINE, 0);
407
408 if ( tftpDemoFlag.bits.bFirstPush )
409 {
410 // For first push, perform PUT operation.
411 XLCDPutROMString(tftpPutString);
412 smTFTPDemo = SM_TFTP_DEMO_WRITE;
413 }
414
415 else
416 {
417 // On second push, perform GET operation.
418 XLCDPutROMString(tftpGetString);
419 smTFTPDemo = SM_TFTP_DEMO_READ;
420 }
421
422 }
423 break;
424
425 case SM_TFTP_DEMO_WRITE:
426 // Perform actual operation. This may take
427 // some time depending on file size and network condition.
428 // This function returns FALSE if has not finished or TRUE
429 // when it is finished - successful or failed.
430 if ( TFTPWrite() )
431 // Upon completion, we go back to monitoring switch.
432 smTFTPDemo = SM_TFTP_DEMO_CYCLE;
433 break;
434
435 case SM_TFTP_DEMO_READ:
436 // This function too may take time to finish.
437 if ( TFTPRead() )
438 // Read has finished, go back to monitoring switch.
439 smTFTPDemo = SM_TFTP_DEMO_CYCLE;
440 break;
441
442 case SM_TFTP_DEMO_CYCLE:
443 // Wait for switch to be released.
444 if ( PORTB_RB5 == 1 )
445 {
446 // Remember what push this is.
447 tftpDemoFlag.bits.bFirstPush = !tftpDemoFlag.bits.bFirstPush;
448
449 // And go back to monitoring...
450 smTFTPDemo = SM_TFTP_DEMO_READY;
451 }
452 break;
453 }
454 }
455
456
457 // This is template function to perform TFTP Put operation.
458 // Most application should be able to take code from this function and
459 // perform TFTP Put operation.
460 // Remove/Enhance LCD related code as per your requirements.
461 //
462 // This function simply writes first 16KB of program memory to
463 // tftpwr.bin file.
464 static BOOL TFTPWrite(void)
465 {
466 BYTE v;
467 BOOL lbReturn;
468 TFTP_RESULT result;
469
470 // State machine state.
471 static enum
472 {
473 SM_TFTP_PUT_IDLE,
474 SM_TFTP_PUT_OPEN_FILE,
475 SM_TFTP_PUT_OPEN_FILE_WAIT,
476 SM_TFTP_PUT_DATA,
477 SM_TFTP_PUT_CLOSE_FILE_WAIT
478 } smTFTPPut = SM_TFTP_PUT_OPEN_FILE;
479
480 // Since we are writing a file, we must be prepared to resend
481 // last data block. these pointer will keep track of data block
482 static ROM BYTE *retryPtr;
483 static ROM BYTE *currentPtr;
484 BOOL lbIsBeginingOfBlock;
485
486 lbReturn = FALSE;
487
488 lbIsBeginingOfBlock = TRUE;
489
490 switch(smTFTPPut)
491 {
492 // Since this demo application has already opened TFTPOpen on startup, we
493 // do not need to do again. If application will be communicating with
494 // several TFTP servers, it would need to close and open connection with
495 // different servers. In that case for every TFTP operation, it must
496 // perform TFTPOpen and related sequence.
497 //
498 // In this case, we will simply start opening file.
499 #if 0
500 case SM_TFTP_PUT_IDLE:
501 TFTPOpen(&AppConfig.TFTPServerAddr);
502 smTFTPPut = SM_TFTP_PUT_WAIT;
503 break;
504
505 case SM_TFTP_PUT_WAIT:
506 result = TFTPIsOpened();
507 if ( result == TFTP_OK )
508 smTFTPPut = SM_TFTP_PUT_OPEN_FILE;
509
510 else if ( result == TFTP_RETRY )
511 smTFTPPut = SM_TFTP_PUT_IDLE;
512
513 break;
514 #endif
515 case SM_TFTP_PUT_OPEN_FILE:
516 // Make sure that it is okay to send file open request.
517 if ( TFTPIsFileOpenReady() )
518 {
519 // Initialize file data pointer.
520 currentPtr = (ROM BYTE*)0x0;
521 retryPtr = (ROM BYTE*)0x0;
522
523 // Issue file open request for WRITE access.
524 TFTPOpenFile(tftpFilePutName, TFTP_FILE_MODE_WRITE);
525
526 // Wait for it get accepted.
527 smTFTPPut = SM_TFTP_PUT_OPEN_FILE_WAIT;
528 }
529 break;
530
531 case SM_TFTP_PUT_OPEN_FILE_WAIT:
532 // Is file opened? or can we write to the file?
533 result = TFTPIsFileOpened();
534 if ( result == TFTP_OK )
535 // Yes. Start writing data.
536 smTFTPPut = SM_TFTP_PUT_DATA;
537
538 else if ( result == TFTP_RETRY )
539 // Somehow previous request for file open was not
540 // received by server or server simly did not
541 // respond. Try again...
542 smTFTPPut = SM_TFTP_PUT_OPEN_FILE;
543
544 break;
545
546
547 case SM_TFTP_PUT_DATA:
548 // Once it is okay to write data, as per TFTP spec.
549 // we can write up to 512 bytes of data in one block.
550 // Stay in loop and send all 512 bytes of data in one shot.
551 while(1)
552 {
553 // Must make sure that it is okay to put any more data.
554 // If block is fulled, this function will return TFTP_NOT_READY
555 // and we must wait.
556 result = TFTPIsPutReady();
557 if( result == TFTP_OK )
558 {
559 // If this is very first block put, remember retry pointer
560 // so that in case we need to retry it, we can simply
561 // reset the pointer and supply retry data.
562 if ( lbIsBeginingOfBlock )
563 {
564 lbIsBeginingOfBlock = FALSE;
565 retryPtr = currentPtr;
566 }
567
568 // Get data byte that we want to write.
569 v = *currentPtr++;
570
571 // Check for end of data.
572 if ( currentPtr >= (ROM BYTE*)0x3FFFL )
573 {
574 // If end of data is reached, initiated FileClose.
575 TFTPCloseFile();
576
577 // Wait for file to get closed.
578 smTFTPPut = SM_TFTP_PUT_CLOSE_FILE_WAIT;
579 break;
580 }
581 else
582 // or else put it in block.
583 TFTPPut(v);
584
585 }
586
587 else if ( result == TFTP_RETRY )
588 {
589 // Retry last block.
590 currentPtr = retryPtr;
591 break;
592 }
593
594 else
595 // For all other returns, break out of this loop and
596 // let common logic at the end of function handle it.
597 break;
598
599 }
600 break;
601
602 case SM_TFTP_PUT_CLOSE_FILE_WAIT:
603 // Is file close request compelte?
604 result = TFTPIsFileClosed();
605 if ( result == TFTP_OK )
606 // Yes, Remember to return TRUE.
607 lbReturn = TRUE;
608
609 else if ( result == TFTP_RETRY )
610 {
611 // No. We need to retry.
612 // In this case, we need to send last data block again.
613 // and redo file close sequence.
614 currentPtr = retryPtr;
615
616 // Go back to PUT_DATA state.
617 smTFTPPut = SM_TFTP_PUT_DATA;
618 }
619 break;
620 }
621
622 // Common action to all states.
623 if ( result == TFTP_OK && lbReturn )
624 {
625 // Operation is complete and successful.
626 // For visual indication, display 'Y' on LCD first line.
627 XLCDGoto(TFTP_COMMAND_DISPLAY_LINE, TFTP_COMMAND_RESULT_POSITION);
628 XLCDPut('Y');
629 }
630
631 else if ( result == TFTP_TIMEOUT || result == TFTP_ERROR )
632 {
633 // Either timeout or error has occurred.
634 XLCDGoto(TFTP_COMMAND_DISPLAY_LINE, TFTP_COMMAND_RESULT_POSITION);
635
636 // Display 'T' for timeout
637 if ( result == TFTP_TIMEOUT )
638 XLCDPut('T');
639 else
640 // 'E' for error.
641 XLCDPut('E');
642 lbReturn = TRUE;
643 }
644
645 // If command is complete, reset the state machine.
646 if ( lbReturn )
647 smTFTPPut = SM_TFTP_PUT_OPEN_FILE;
648
649 return lbReturn;
650 }
651
652
653
654 // This is template function to perform TFTP Get operation.
655 // Most application should be able to take code from this function and
656 // perform TFTP Put operation.
657 // Remove/Enhance LCD related code as per your requirements.
658 //
659 // This function trie to read tftprd.txt file from remote server.
660 static BOOL TFTPRead(void)
661 {
662 BYTE v;
663 BOOL lbReturn;
664 TFTP_RESULT result;
665
666 // State machine states.
667 static enum
668 {
669 SM_TFTP_GET_IDLE,
670 SM_TFTP_GET_WAIT,
671 SM_TFTP_GET_OPEN_FILE,
672 SM_TFTP_GET_OPEN_FILE_WAIT,
673 SM_TFTP_GET_DATA
674 } smTFTPGet = SM_TFTP_GET_OPEN_FILE;
675
676
677 lbReturn = FALSE;
678
679 switch(smTFTPGet)
680 {
681 // Since this demo application has already opened TFTPOpen on startup, we
682 // do not need to do again. If application will be communicating with
683 // several TFTP servers, it would need to close and open connection with
684 // different servers. In that case for every TFTP operation, it must
685 // perform TFTPOpen and related sequence.
686 //
687 // In this case, we will simply start opening file.
688 #if 0
689 case SM_TFTP_GET_IDLE:
690 TFTPOpen(&AppConfig.TFTPServerAddr);
691 smTFTPGet = SM_TFTP_GET_WAIT;
692 break;
693
694 case SM_TFTP_GET_WAIT:
695 result = TFTPIsOpened();
696 if ( result == TFTP_OK
697 smTFTPGet = SM_TFTP_GET_OPEN_FILE;
698
699 else if ( result == TFTP_RETRY )
700 smTFTPGet = SM_TFTP_GET_IDLE;
701 break;
702 #endif
703
704 case SM_TFTP_GET_OPEN_FILE:
705 // Is is okay to issue file open?
706 if ( TFTPIsFileOpenReady() )
707 {
708 // Issue file open command.
709 // For read operation, there is no need to data retry. All retries
710 // are done automatically by module.
711 TFTPOpenFile(tftpFileGetName, TFTP_FILE_MODE_READ);
712
713 // Wait for file get opened.
714 smTFTPGet = SM_TFTP_GET_OPEN_FILE_WAIT;
715 }
716 break;
717
718 case SM_TFTP_GET_OPEN_FILE_WAIT:
719 // Is file opened?
720 result = TFTPIsFileOpened();
721 if ( result == TFTP_OK )
722 // Yes. Go and read the first data block.
723 smTFTPGet = SM_TFTP_GET_DATA;
724
725 else if ( result == TFTP_RETRY )
726 {
727 // Somehow fileopen was not acknowledged, try again.
728 smTFTPGet = SM_TFTP_GET_OPEN_FILE;
729 break;
730 }
731 else
732 break;
733
734 case SM_TFTP_GET_DATA:
735 // Once a data block is available, application may read up to 512 bytes
736 // of data. Read up to 512 bytes in one shot.
737 while(1)
738 {
739 // Make sure that it is okay to call TFTPGet. If all 512 bytes are
740 // read or if there is no more data byte, this function will return
741 // TFTP_NOT_READY.
742 result = TFTPIsGetReady();
743 if ( result == TFTP_OK )
744 {
745 // Fetch data byte.
746 // In this demo, it is simply ignored.
747 v = TFTPGet();
748
749 // One may output it so another port - for example UART.
750 //USARTPut(v);
751 }
752 else
753 break;
754 }
755 break;
756 }
757
758 // Common logic for all states.
759 if ( result == TFTP_END_OF_FILE )
760 {
761 // If end of file is reached, display it.
762 lbReturn = TRUE;
763 XLCDGoto(TFTP_COMMAND_DISPLAY_LINE, TFTP_COMMAND_RESULT_POSITION);
764 XLCDPut('Y');
765 }
766
767 else if ( result == TFTP_TIMEOUT || result == TFTP_ERROR )
768 {
769 lbReturn = TRUE;
770 XLCDGoto(TFTP_COMMAND_DISPLAY_LINE, TFTP_COMMAND_RESULT_POSITION);
771
772 // For timeout, display 'T'
773 if ( result == TFTP_TIMEOUT )
774 XLCDPut('T');
775 else
776 // an for error, display 'E'
777 XLCDPut('E');
778 }
779
780 // On completion of command, reset the state machine.
781 if ( lbReturn )
782 smTFTPGet = SM_TFTP_GET_OPEN_FILE;
783
784 return lbReturn;
785 }
786
787
788
789
790
791
792
793 #if defined(MCHP_C18)
794 #pragma interrupt HighISR save=section(".tmpdata")
795 void HighISR(void)
796 #elif defined(HITECH_C18)
797 #if defined(STACK_USE_SLIP)
798 extern void MACISR(void);
799 #endif
800 void interrupt HighISR(void)
801 #endif
802 {
803 TickUpdate();
804
805 #if defined(STACK_USE_SLIP)
806 MACISR();
807 #endif
808 }
809
810 #if defined(MCHP_C18)
811 #pragma code highVector=0x08
812 void HighVector (void)
813 {
814 _asm goto HighISR _endasm
815 }
816 #pragma code /* return to default code section */
817 #endif
818
819
820
821
822 static void DisplayIPValue(IP_ADDR *IPVal, BOOL bToLCD)
823 {
824 char IPDigit[8];
825
826 if ( bToLCD )
827 {
828 /*
829 * Erase second line.
830 */
831 XLCDGoto(1, 0);
832 XLCDPutROMString(blankLCDLine);
833
834 }
835
836 /*
837 * Rewrite the second line.
838 */
839 XLCDGoto(1, 0);
840
841 itoa(IPVal->v[0], IPDigit);
842 if ( bToLCD )
843 {
844 XLCDPutString(IPDigit);
845 XLCDPut('.');
846 }
847 else
848 {
849 USARTPutString((BYTE*)IPDigit);
850 USARTPut('.');
851 }
852
853 itoa(IPVal->v[1], IPDigit);
854 if ( bToLCD )
855 {
856 XLCDPutString(IPDigit);
857 XLCDPut('.');
858 }
859 else
860 {
861 USARTPutString((BYTE*)IPDigit);
862 USARTPut('.');
863 }
864
865 itoa(IPVal->v[2], IPDigit);
866 if ( bToLCD )
867 {
868 XLCDPutString(IPDigit);
869 XLCDPut('.');
870 }
871 else
872 {
873 USARTPutString((BYTE*)IPDigit);
874 USARTPut('.');
875 }
876
877 itoa(IPVal->v[3], IPDigit);
878 if ( bToLCD )
879 XLCDPutString(IPDigit);
880 else
881 USARTPutString((BYTE*)IPDigit);
882 }
883
884 /*********************************************************************
885 * Function: void InitializeBoard(void)
886 *
887 * PreCondition: None
888 *
889 * Input: None
890 *
891 * Output: None
892 *
893 * Side Effects: None
894 *
895 * Overview: Initialize board specific hardware.
896 *
897 * Note: None
898 ********************************************************************/
899 static void InitializeBoard(void)
900 {
901 /*
902 * Setup for PORTA.RA0 as analog input while rests
903 * as digital i/o lines.
904 */
905 ADCON1 = 0b10001110; // RA0 as analog input, Right justified
906 TRISA = 0x03;
907
908 /*
909 * LCD is enabled using RA5.
910 */
911 PORTA_RA5 = 0; // Disable LCD.
912
913 /*
914 * Turn off the LED's.
915 */
916 LATA2 = 1;
917 LATA3 = 1;
918
919 /*
920 * External data EEPROM needs pull-ups, so enable internal
921 * pull-ups.
922 */
923 INTCON2_RBPU = 0;
924
925 XLCDInit();
926 XLCDGoto(0, 0);
927 XLCDPutROMString(StartupMsg);
928
929
930 TXSTA = 0b00100000; // Low BRG speed
931 RCSTA = 0b10010000;
932 SPBRG = SPBRG_VAL;
933
934 T0CON = 0;
935 INTCON_GIEH = 1;
936 INTCON_GIEL = 1;
937
938 }
939
940 /*********************************************************************
941 * Function: void InitAppConfig(void)
942 *
943 * PreCondition: MPFSInit() is already called.
944 *
945 * Input: None
946 *
947 * Output: Write/Read non-volatile config variables.
948 *
949 * Side Effects: None
950 *
951 * Overview: None
952 *
953 * Note: None
954 ********************************************************************/
955 static void InitAppConfig(void)
956 {
957 #if defined(MPFS_USE_EEPROM)
958 BYTE c;
959 BYTE *p;
960 #endif
961
962 /*
963 * Load default configuration into RAM.
964 */
965 AppConfig.MyIPAddr.v[0] = MY_DEFAULT_IP_ADDR_BYTE1;
966 AppConfig.MyIPAddr.v[1] = MY_DEFAULT_IP_ADDR_BYTE2;
967 AppConfig.MyIPAddr.v[2] = MY_DEFAULT_IP_ADDR_BYTE3;
968 AppConfig.MyIPAddr.v[3] = MY_DEFAULT_IP_ADDR_BYTE4;
969
970 AppConfig.MyMask.v[0] = MY_DEFAULT_MASK_BYTE1;
971 AppConfig.MyMask.v[1] = MY_DEFAULT_MASK_BYTE2;
972 AppConfig.MyMask.v[2] = MY_DEFAULT_MASK_BYTE3;
973 AppConfig.MyMask.v[3] = MY_DEFAULT_MASK_BYTE4;
974
975 AppConfig.MyGateway.v[0] = MY_DEFAULT_GATE_BYTE1;
976 AppConfig.MyGateway.v[1] = MY_DEFAULT_GATE_BYTE2;
977 AppConfig.MyGateway.v[2] = MY_DEFAULT_GATE_BYTE3;
978 AppConfig.MyGateway.v[3] = MY_DEFAULT_GATE_BYTE4;
979
980 AppConfig.MyMACAddr.v[0] = MY_DEFAULT_MAC_BYTE1;
981 AppConfig.MyMACAddr.v[1] = MY_DEFAULT_MAC_BYTE2;
982 AppConfig.MyMACAddr.v[2] = MY_DEFAULT_MAC_BYTE3;
983 AppConfig.MyMACAddr.v[3] = MY_DEFAULT_MAC_BYTE4;
984 AppConfig.MyMACAddr.v[4] = MY_DEFAULT_MAC_BYTE5;
985 AppConfig.MyMACAddr.v[5] = MY_DEFAULT_MAC_BYTE6;
986
987 #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
988 AppConfig.Flags.bIsDHCPEnabled = TRUE;
989 #else
990 AppConfig.Flags.bIsDHCPEnabled = FALSE;
991 #endif
992
993 #if defined(MPFS_USE_EEPROM)
994 p = (BYTE*)&AppConfig;
995
996
997 XEEBeginRead(EEPROM_CONTROL, 0x00);
998 c = XEERead();
999 XEEEndRead();
1000
1001 /*
1002 * When a record is saved, first byte is written as 0x55 to indicate
1003 * that a valid record was saved.
1004 */
1005 if ( c == 0x55 )
1006 {
1007 XEEBeginRead(EEPROM_CONTROL, 0x01);
1008 for ( c = 0; c < sizeof(AppConfig); c++ )
1009 *p++ = XEERead();
1010 XEEEndRead();
1011 }
1012 else
1013 SaveAppConfig();
1014 #endif
1015 }
1016
1017 #if defined(MPFS_USE_EEPROM)
1018 static void SaveAppConfig(void)
1019 {
1020 BYTE c;
1021 BYTE *p;
1022
1023 p = (BYTE*)&AppConfig;
1024 XEEBeginWrite(EEPROM_CONTROL, 0x00);
1025 XEEWrite(0x55);
1026 for ( c = 0; c < sizeof(AppConfig); c++ )
1027 {
1028 XEEWrite(*p++);
1029 }
1030
1031 XEEEndWrite();
1032 }
1033 #endif
1034
1035
1036 ROM char menu[] =
1037 "\r\n\r\n\r\MCHPStack TFTP Client Demo 1.0 ("STARTUP_MSG", " __DATE__ ")\r\n\r\n"
1038
1039 "\t1: Change Board serial number.\r\n"
1040 "\t2: Change default IP address.\r\n"
1041 "\t3: Change default gateway address.\r\n"
1042 "\t4: Change default subnet mask.\r\n"
1043 "\t5: Enable DHCP & IP Gleaning.\r\n"
1044 "\t6: Disable DHCP & IP Gleaning.\r\n"
1045 "\t7: Set TFTP Server IP address:\r\n"
1046 "\t8: Save & Quit.\r\n"
1047 "\r\n"
1048 "Enter a menu choice (1-8): ";
1049
1050 typedef enum _MENU_CMD
1051 {
1052 MENU_CMD_SERIAL_NUMBER = '1',
1053 MENU_CMD_IP_ADDRESS,
1054 MENU_CMD_GATEWAY_ADDRESS,
1055 MENU_CMD_SUBNET_MASK,
1056 MENU_CMD_ENABLE_AUTO_CONFIG,
1057 MENU_CMD_DISABLE_AUTO_CONFIG,
1058 MENU_CMD_TFTP_SERVER_ADDRESS,
1059 MENU_CMD_QUIT,
1060 MENU_CMD_INVALID
1061 } MENU_CMD;
1062
1063 ROM char* menuCommandPrompt[] =
1064 {
1065 "\r\nSerial Number (",
1066 "\r\nDefault IP Address (",
1067 "\r\nDefault Gateway Address (",
1068 "\r\nDefault Subnet Mask (",
1069 "\r\nDHCP & IP Gleaning enabled.\r\n",
1070 "\r\nDHCP & IP Gleaning disabled.\r\n",
1071 "\r\nTFTP Serer IP Address (",
1072 "\r\nNow running application..."
1073 };
1074
1075 ROM char InvalidInputMsg[] = "\r\nInvalid input received - Input ignored.\r\n"
1076 "Press any key to continue...\r\n";
1077
1078 void USARTPutROMString(ROM char* str)
1079 {
1080 BYTE v;
1081
1082 while( v = *str++ )
1083 USARTPut(v);
1084 }
1085
1086
1087 BYTE USARTGetString(char *buffer, BYTE bufferLen)
1088 {
1089 BYTE v;
1090 BYTE count;
1091
1092 count = 0;
1093 do
1094 {
1095 while( !USARTIsGetReady() );
1096
1097 v = USARTGet();
1098
1099 if ( v == '\r' || v == '\n' )
1100 break;
1101
1102 count++;
1103 *buffer++ = v;
1104 *buffer = '\0';
1105 if ( bufferLen-- == 0 )
1106 break;
1107 } while(1);
1108 return count;
1109 }
1110
1111 BOOL StringToIPAddress(char *str, IP_ADDR *buffer)
1112 {
1113 BYTE v;
1114 char *temp;
1115 BYTE byteIndex;
1116
1117 temp = str;
1118 byteIndex = 0;
1119
1120 while( v = *str )
1121 {
1122 if ( v == '.' )
1123 {
1124 *str++ = '\0';
1125 buffer->v[byteIndex++] = atoi(temp);
1126 temp = str;
1127 }
1128 else if ( v < '0' || v > '9' )
1129 return FALSE;
1130
1131 str++;
1132 }
1133
1134 buffer->v[byteIndex] = atoi(temp);
1135
1136 return (byteIndex == 3);
1137 }
1138
1139
1140
1141 MENU_CMD GetMenuChoice(void)
1142 {
1143 BYTE c;
1144
1145 while ( !USARTIsGetReady() );
1146
1147 c = USARTGet();
1148
1149 if ( c >= '1' && c < MENU_CMD_INVALID )
1150 return c;
1151 else
1152 return MENU_CMD_INVALID;
1153 }
1154
1155 #define MAX_USER_RESPONSE_LEN (20)
1156 void ExecuteMenuChoice(MENU_CMD choice)
1157 {
1158 char response[MAX_USER_RESPONSE_LEN];
1159 IP_ADDR tempIPValue;
1160 IP_ADDR *destIPValue;
1161
1162 USARTPut('\r');
1163 USARTPut('\n');
1164 USARTPutROMString(menuCommandPrompt[choice-'0'-1]);
1165
1166 switch(choice)
1167 {
1168 case MENU_CMD_SERIAL_NUMBER:
1169 itoa(AppConfig.SerialNumber.Val, response);
1170 USARTPutString((BYTE*)response);
1171 USARTPut(')');
1172 USARTPut(':');
1173 USARTPut(' ');
1174
1175 if ( USARTGetString(response, sizeof(response)) )
1176 {
1177 AppConfig.SerialNumber.Val = atoi(response);
1178
1179 AppConfig.MyMACAddr.v[4] = AppConfig.SerialNumber.v[1];
1180 AppConfig.MyMACAddr.v[5] = AppConfig.SerialNumber.v[0];
1181 }
1182 else
1183 goto HandleInvalidInput;
1184
1185 break;
1186
1187 case MENU_CMD_IP_ADDRESS:
1188 destIPValue = &AppConfig.MyIPAddr;
1189 goto ReadIPConfig;
1190
1191 case MENU_CMD_GATEWAY_ADDRESS:
1192 destIPValue = &AppConfig.MyGateway;
1193 goto ReadIPConfig;
1194
1195 case MENU_CMD_SUBNET_MASK:
1196 destIPValue = &AppConfig.MyMask;
1197
1198 ReadIPConfig:
1199 DisplayIPValue(destIPValue, FALSE);
1200 USARTPut(')');
1201 USARTPut(':');
1202 USARTPut(' ');
1203
1204 USARTGetString(response, sizeof(response));
1205
1206 if ( !StringToIPAddress(response, &tempIPValue) )
1207 {
1208 HandleInvalidInput:
1209 USARTPutROMString(InvalidInputMsg);
1210 while( !USARTIsGetReady() );
1211 USARTGet();
1212 }
1213 else
1214 {
1215 destIPValue->Val = tempIPValue.Val;
1216 }
1217 break;
1218
1219
1220 case MENU_CMD_ENABLE_AUTO_CONFIG:
1221 AppConfig.Flags.bIsDHCPEnabled = TRUE;
1222 break;
1223
1224 case MENU_CMD_DISABLE_AUTO_CONFIG:
1225 AppConfig.Flags.bIsDHCPEnabled = FALSE;
1226 break;
1227
1228 case MENU_CMD_TFTP_SERVER_ADDRESS:
1229 destIPValue = &AppConfig.TFTPServerAddr;
1230 goto ReadIPConfig;
1231
1232 case MENU_CMD_QUIT:
1233 SaveAppConfig();
1234 break;
1235 }
1236 }
1237
1238
1239
1240
1241 static void SetConfig(void)
1242 {
1243 MENU_CMD choice;
1244
1245 do
1246 {
1247 USARTPutROMString(menu);
1248 choice = GetMenuChoice();
1249 if ( choice != MENU_CMD_INVALID )
1250 ExecuteMenuChoice(choice);
1251 } while(choice != MENU_CMD_QUIT);
1252
1253 }
1254
1255
1256 static void USARTPut(BYTE c)
1257 {
1258 while( !TXSTA_TRMT);
1259 TXREG = c;
1260 }
1261
1262 static void USARTPutString(BYTE *s)
1263 {
1264 BYTE c;
1265
1266 while( (c = *s++) )
1267 USARTPut(c);
1268 }
1269
1270 void XLCDDelay15ms(void)
1271 {
1272 DelayMs(15);
1273 }
1274 void XLCDDelay4ms(void)
1275 {
1276 DelayMs(4);
1277 }
1278
1279 void XLCDDelay100us(void)
1280 {
1281 INTCON_GIEH = 0;
1282 Delay10us(1);
1283 INTCON_GIEH = 1;
1284 }

  ViewVC Help
Powered by ViewVC 1.1.20