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

Annotation of /trunk/docs/MCHPStack2.20/Source/TFTPcDemo.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: 34475 byte(s)
Removed tcpip stack 4.02 and added tcpip stack 2.20.
1 hedin 62 /*********************************************************************
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