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

Contents of /trunk/docs/MCHPStack2.20/Source/DemoSNMPAgent.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: 35610 byte(s)
Removed tcpip stack 4.02 and added tcpip stack 2.20.
1 /*********************************************************************
2 *
3 * Example SNMP Agent Application using Microchip TCP/IP Stack
4 *
5 *********************************************************************
6 * FileName: DemoSNMPAgent.c
7 * Dependencies: string.H
8 * usart.h
9 * StackTsk.h
10 * Tick.h
11 * http.h
12 * MPFS.h
13 * Processor: PIC18
14 * Complier: MCC18 v1.00.50 or higher
15 * HITECH PICC-18 V8.10PL1 or higher
16 * Company: Microchip Technology, Inc.
17 *
18 * Software License Agreement
19 *
20 * The software supplied herewith by Microchip Technology Incorporated
21 * (the “Company”) for its PICmicro® Microcontroller is intended and
22 * supplied to you, the Company’s customer, for use solely and
23 * exclusively on Microchip PICmicro Microcontroller products. The
24 * software is owned by the Company and/or its supplier, and is
25 * protected under applicable copyright laws. All rights are reserved.
26 * Any use in violation of the foregoing restrictions may subject the
27 * user to criminal sanctions under applicable laws, as well as to
28 * civil liability for the breach of the terms and conditions of this
29 * license.
30 *
31 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
32 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
33 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
34 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
35 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
36 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
37 *
38 *
39 * HiTech PICC18 Compiler Options excluding device selection:
40 * -FAKELOCAL -G -O -Zg -E -C
41 *
42 *
43 *
44 *
45 * Author Date Comment
46 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
47 * Nilesh Rajbharti 5/23/03 Original (Rev. 1.0)
48 ********************************************************************/
49 /*
50 * Following define uniquely deines this file as main
51 * entry/application In whole project, there should only be one such
52 * definition and application file must define AppConfig variable as
53 * described below.
54 */
55 #define THIS_IS_STACK_APPLICATION
56
57 #define BAUD_RATE (19200) // bps
58
59 #define USART_USE_BRGH_LOW
60 #if defined(USART_USE_BRGH_LOW)
61 #define SPBRG_VAL ( ((CLOCK_FREQ/BAUD_RATE)/64) - 1)
62 #else
63 #define SPBRG_VAL ( ((CLOCK_FREQ/BAUD_RATE)/16) - 1)
64 #endif
65
66 #if SPBRG_VAL > 255
67 #error "Calculated SPBRG value is out of range for currnet CLOCK_FREQ."
68 #endif
69
70
71
72 #include <string.h>
73
74 /*
75 * These headers must be included for required defs.
76 */
77 #include "stacktsk.h"
78 #include "tick.h"
79 #include "snmp.h"
80 #include "mib.h"
81 #include "icmp.h"
82 #include "delay.h"
83 #include "mpfs.h"
84 #include "xlcd.h"
85
86 #if defined(STACK_USE_DHCP)
87 #include "dhcp.h"
88 #endif
89
90
91 #if defined(MPFS_USE_EEPROM)
92 #include "xeeprom.h"
93 #endif
94
95 #define DEMO_SNMP_MSG "DemoSNMP 1.0"
96 ROM char StartupMsg[] = DEMO_SNMP_MSG;
97
98 #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
99 ROM char DHCPMsg[] = "DHCP/Gleaning...";
100 #endif
101
102 ROM char SetupMsg[] = "Board Setup...";
103
104 /*
105 * These are hardware I/O labels to ease access.
106 */
107 #define SW_S3 PORTB_RB5
108 #define LED_D5_CONTROL LATA2
109 #define LED_D6_CONTROL LATA3
110
111 /*
112 * Analog pots.
113 */
114 static WORD_VAL AN0Value;
115 static WORD_VAL AN1Value;
116
117
118 /*
119 * LCD Display
120 */
121 #define LCD_DISPLAY_LEN (16)
122 char LCDDisplayString[LCD_DISPLAY_LEN] = DEMO_SNMP_MSG;
123 BYTE LCDDisplayStringLen = sizeof(DEMO_SNMP_MSG)-1;
124
125 /*
126 * Trap information.
127 * This table maintains list of intereseted receivers
128 * who should receive notifications when some interesting
129 * event occurs.
130 */
131 #define TRAP_TABLE_SIZE (2)
132 #define MAX_COMMUNITY_LEN (8)
133 typedef struct _TRAP_INFO
134 {
135 BYTE Size;
136 struct
137 {
138 BYTE communityLen;
139 char community[MAX_COMMUNITY_LEN];
140 IP_ADDR IPAddress;
141 struct
142 {
143 unsigned int bEnabled : 1;
144 } Flags;
145 } table[TRAP_TABLE_SIZE];
146 } TRAP_INFO;
147
148 /*
149 * Initialize trap table with no entries.
150 */
151 TRAP_INFO trapInfo = { TRAP_TABLE_SIZE };
152
153 // 1234567890123456
154 ROM char blankLCDLine[] = " ";
155
156
157
158 /*
159 * This is used by other stack elements.
160 * Main application must define this and initialize it with
161 * proper values.
162 */
163 APP_CONFIG AppConfig;
164
165 BYTE myDHCPBindCount = 0;
166 #if defined(STACK_USE_DHCP)
167 extern BYTE DHCPBindCount;
168 #else
169 /*
170 * If DHCP is not enabled, force DHCP update.
171 */
172 BYTE DHCPBindCount = 1;
173 #endif
174
175
176 /*
177 * Set configuration fuses for HITECH compiler.
178 * For MCC18 compiler, separately linked config.asm file
179 * will set the correct fuses.
180 */
181 #if defined(HITECH_C18)
182 __CONFIG(1, UNPROTECT & HS);
183 __CONFIG(2, PWRTEN & BORDIS & WDTDIS);
184 #endif
185
186 /*
187 * Private helper functions.
188 * These may or may not be present in all applications.
189 */
190 static void InitAppConfig(void);
191
192 static void InitializeBoard(void);
193 static void ProcessIO(void);
194
195 void NotifyRemoteUser(void);
196 static void DisplayIPValue(IP_ADDR *IPVal, BOOL bToLCD);
197 static void SetConfig(void);
198
199
200 #if defined(MPFS_USE_EEPROM)
201 static BOOL DownloadMPFS(void);
202 static void SaveAppConfig(void);
203 #endif
204
205 #if defined(MCHP_C18)
206 #pragma interrupt HighISR save=section(".tmpdata")
207 void HighISR(void)
208 #elif defined(HITECH_C18)
209 #if defined(STACK_USE_SLIP)
210 extern void MACISR(void);
211 #endif
212 void interrupt HighISR(void)
213 #endif
214 {
215 TickUpdate();
216
217 #if defined(STACK_USE_SLIP)
218 MACISR();
219 #endif
220 }
221
222 #if defined(MCHP_C18)
223 #pragma code highVector=0x08
224 void HighVector (void)
225 {
226 _asm goto HighISR _endasm
227 }
228 #pragma code /* return to default code section */
229 #endif
230
231 static BOOL SendNotification(BYTE receiverIndex, SNMP_ID var, SNMP_VAL val);
232
233 static void USARTPut(BYTE c)
234 {
235 while( !TXSTA_TRMT);
236 TXREG = c;
237 }
238
239 static void USARTPutString(BYTE *s)
240 {
241 BYTE c;
242
243 while( (c = *s++) )
244 USARTPut(c);
245 }
246
247 #define USARTIsGetReady() (PIR1_RCIF)
248 #define USARTGet() (RCREG)
249
250
251
252 /*
253 * Main entry point.
254 */
255 void main(void)
256 {
257 static TICK t = 0;
258
259 /*
260 * Initialize any application specific hardware.
261 */
262 InitializeBoard();
263
264 /*
265 * Initialize all stack related components.
266 * Following steps must be performed for all applications using
267 * PICmicro TCP/IP Stack.
268 */
269 TickInit();
270
271 /*
272 * Following steps must be performed for all applications using
273 * PICmicro TCP/IP Stack.
274 */
275 MPFSInit();
276
277
278 /*
279 * Initialize Stack and application related NV variables.
280 */
281 InitAppConfig();
282
283
284 /*
285 * Depending on whether internal program memor is used or external
286 * EEPROM is used, keep/remove these block.
287 */
288
289 /*
290 * This implementation, initiates Board setup process if RB5
291 * is detected low on startup.
292 */
293 if ( PORTB_RB5 == 0 )
294 {
295 XLCDGoto(1, 0);
296 XLCDPutROMString(SetupMsg);
297
298 SetConfig();
299 }
300
301 StackInit();
302
303 SNMPInit();
304
305
306 #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
307 if ( AppConfig.Flags.bIsDHCPEnabled )
308 {
309 XLCDGoto(1, 0);
310 XLCDPutROMString(DHCPMsg);
311 }
312 else
313 {
314 /*
315 * Force IP address display update.
316 */
317 myDHCPBindCount = 1;
318 #if defined(STACK_USE_DHCP)
319 DHCPDisable();
320 #endif
321 }
322 #endif
323
324
325
326 /*
327 * Once all items are initialized, go into infinite loop and let
328 * stack items execute their tasks.
329 * If application needs to perform its own task, it should be
330 * done at the end of while loop.
331 * Note that this is a "co-operative mult-tasking" mechanism
332 * where every task performs its tasks (whether all in one shot
333 * or part of it) and returns so that other tasks can do their
334 * job.
335 * If a task needs very long time to do its job, it must broken
336 * down into smaller pieces so that other tasks can have CPU time.
337 */
338 while(1)
339 {
340 /*
341 * Blink SYSTEM LED every second.
342 */
343 if ( TickGetDiff(TickGet(), t) >= TICK_SECOND/2 )
344 {
345 t = TickGet();
346 LATA4 ^= 1;
347 }
348
349 /*
350 * This task performs normal stack task including checking
351 * for incoming packet, type of packet and calling
352 * appropriate stack entity to process it.
353 */
354 StackTask();
355
356 /*
357 * This task performs common SNMP Agent tasks. When
358 * a request is received and processed,
359 * it callbacks to application.
360 */
361 SNMPTask();
362
363 /*
364 * More Microchip Stack tasks may be added as required.
365 */
366
367 /*
368 * Add your application speicifc tasks here.
369 * This task monitors I/O and notifies remote NMS
370 * if configured to do so.
371 */
372 ProcessIO();
373
374
375 /*
376 * For DHCP information, display how many times we have renewed the IP
377 * configuration since last reset.
378 */
379 if ( DHCPBindCount != myDHCPBindCount )
380 {
381 DisplayIPValue(&AppConfig.MyIPAddr, TRUE);
382 myDHCPBindCount = DHCPBindCount;
383
384 if ( AppConfig.Flags.bIsDHCPEnabled )
385 {
386 XLCDGoto(1, 14);
387 if ( myDHCPBindCount < 0x0a )
388 XLCDPut(myDHCPBindCount + '0');
389 else
390 XLCDPut(myDHCPBindCount + 'A');
391 }
392 }
393
394 }
395 }
396
397
398 static BOOL SendNotification(BYTE receiverIndex, SNMP_ID var, SNMP_VAL val)
399 {
400 static enum { SM_PREPARE, SM_NOTIFY_WAIT } smState = SM_PREPARE;
401 IP_ADDR IPAddress;
402
403 // Convert local to network order.
404 IPAddress.v[0] = trapInfo.table[receiverIndex].IPAddress.v[3];
405 IPAddress.v[1] = trapInfo.table[receiverIndex].IPAddress.v[2];
406 IPAddress.v[2] = trapInfo.table[receiverIndex].IPAddress.v[1];
407 IPAddress.v[3] = trapInfo.table[receiverIndex].IPAddress.v[0];
408
409 switch(smState)
410 {
411 case SM_PREPARE:
412 SNMPNotifyPrepare(&IPAddress,
413 trapInfo.table[receiverIndex].community,
414 trapInfo.table[receiverIndex].communityLen,
415 MICROCHIP, // Agent ID Var
416 6, // Notification code
417 (DWORD)TickGet());
418 smState = SM_NOTIFY_WAIT;
419
420 break;
421
422 case SM_NOTIFY_WAIT:
423 if ( SNMPIsNotifyReady(&IPAddress) )
424 {
425 smState = SM_PREPARE;
426 SNMPNotify(var, val, 0);
427 return TRUE;
428 }
429 }
430 return FALSE;
431 }
432
433 BOOL SNMPValidate(SNMP_ACTION SNMPAction, char* community)
434 {
435 return TRUE;
436 }
437
438
439
440 // Only dynamic variables with ASCII_STRING or OCTET_STRING data type
441 // needs to be handled.
442 BOOL SNMPIsValidSetLen(SNMP_ID var, BYTE len)
443 {
444 switch(var)
445 {
446 case TRAP_COMMUNITY:
447 if ( len < MAX_COMMUNITY_LEN+1 )
448 return TRUE;
449 break;
450
451 case LCD_DISPLAY:
452 if ( len < LCD_DISPLAY_LEN+1 )
453 return TRUE;
454 break;
455 }
456 return FALSE;
457 }
458
459
460 // Only dynamic read-write variables needs to be handled.
461 BOOL SNMPSetVar(SNMP_ID var, SNMP_INDEX index, BYTE ref, SNMP_VAL val)
462 {
463 switch(var)
464 {
465 case LED_D5:
466 LED_D5_CONTROL = val.byte;
467 return TRUE;
468
469 case LED_D6:
470 LED_D6_CONTROL = val.byte;
471 return TRUE;
472
473 case TRAP_RECEIVER_IP:
474 // Make sure that index is within our range.
475 if ( index < trapInfo.Size )
476 {
477 // This is just an update to an existing entry.
478 trapInfo.table[index].IPAddress.Val = val.dword;
479 return TRUE;
480 }
481 else if ( index < TRAP_TABLE_SIZE )
482 {
483 // This is an addition to table.
484 trapInfo.table[index].IPAddress.Val = val.dword;
485 trapInfo.table[index].communityLen = 0;
486 trapInfo.Size++;
487 return TRUE;
488 }
489 break;
490
491 case TRAP_RECEIVER_ENABLED:
492 // Make sure that index is within our range.
493 if ( index < trapInfo.Size )
494 {
495 // Value of '1' means Enabled".
496 if ( val.byte == 1 )
497 trapInfo.table[index].Flags.bEnabled = 1;
498 // Value of '0' means "Disabled.
499 else if ( val.byte == 0 )
500 trapInfo.table[index].Flags.bEnabled = 0;
501 else
502 // This is unknown value.
503 return FALSE;
504 return TRUE;
505 }
506 // Given index is more than our current table size.
507 // If it is within our range, treat it as an addition to table.
508 else if ( index < TRAP_TABLE_SIZE )
509 {
510 // Treat this as an addition to table.
511 trapInfo.Size++;
512 trapInfo.table[index].communityLen = 0;
513 }
514
515 break;
516
517 case TRAP_COMMUNITY:
518 // Since this is a ASCII_STRING data type, SNMP will call with
519 // SNMP_END_OF_VAR to indicate no more bytes.
520 // Use this information to determine if we just added new row
521 // or updated an existing one.
522 if ( ref == SNMP_END_OF_VAR )
523 {
524 // Index equal to table size means that we have new row.
525 if ( index == trapInfo.Size )
526 trapInfo.Size++;
527
528 // Length of string is one more than index.
529 trapInfo.table[index].communityLen++;
530
531 return TRUE;
532 }
533
534 // Make sure that index is within our range.
535 if ( index < trapInfo.Size )
536 {
537 // Copy given value into local buffer.
538 trapInfo.table[index].community[ref] = val.byte;
539 // Keep track of length too.
540 // This may not be NULL terminate string.
541 trapInfo.table[index].communityLen = (BYTE)ref;
542 return TRUE;
543 }
544 break;
545
546 case LCD_DISPLAY:
547 // Copy all bytes until all bytes are transferred
548 if ( ref != SNMP_END_OF_VAR )
549 {
550 LCDDisplayString[ref] = val.byte;
551 LCDDisplayStringLen++;
552 }
553 else
554 {
555 XLCDGoto(0, 0);
556 XLCDPutROMString(blankLCDLine);
557 XLCDGoto(0, 0);
558 XLCDPutString(LCDDisplayString);
559 }
560
561 return TRUE;
562
563 }
564
565 return FALSE;
566 }
567
568 // Only sequence index needs to be handled in this function.
569 BOOL SNMPGetNextIndex(SNMP_ID var, SNMP_INDEX *index)
570 {
571 SNMP_INDEX tempIndex;
572
573 tempIndex = *index;
574
575 switch(var)
576 {
577 case TRAP_RECEIVER_ID:
578 // There is no next possible index if table itself is empty.
579 if ( trapInfo.Size == 0 )
580 return FALSE;
581
582 // INDEX_INVALID means start with first index.
583 if ( tempIndex == SNMP_INDEX_INVALID )
584 {
585 *index = 0;
586 return TRUE;
587 }
588 else if ( tempIndex < (trapInfo.Size-1) )
589 {
590 *index = tempIndex+1;
591 return TRUE;
592 }
593 break;
594 }
595 return FALSE;
596 }
597
598
599 BOOL SNMPGetVar(SNMP_ID var, SNMP_INDEX index, BYTE *ref, SNMP_VAL* val)
600 {
601 BYTE myRef;
602
603 myRef = *ref;
604
605 switch(var)
606 {
607 case SYS_UP_TIME:
608 val->dword = TickGet();
609 return TRUE;
610
611 case LED_D5:
612 val->byte = LED_D5_CONTROL;
613 return TRUE;
614
615 case LED_D6:
616 val->byte = LED_D6_CONTROL;
617 return TRUE;
618
619 case PUSH_BUTTON:
620 // There is only one button - meaning only index of 0 is allowed.
621 val->byte = SW_S3;
622 return TRUE;
623
624 case ANALOG_POT0:
625 val->word = AN0Value.Val;
626 return TRUE;
627
628 case ANALOG_POT1:
629 val->word = AN1Value.Val;
630 return TRUE;
631
632 case TRAP_RECEIVER_ID:
633 if ( index < trapInfo.Size )
634 {
635 val->byte = index;
636 return TRUE;
637 }
638 break;
639
640 case TRAP_RECEIVER_ENABLED:
641 if ( index < trapInfo.Size )
642 {
643 val->byte = trapInfo.table[index].Flags.bEnabled;
644 return TRUE;
645 }
646 break;
647
648 case TRAP_RECEIVER_IP:
649 if ( index < trapInfo.Size )
650 {
651 val->dword = trapInfo.table[index].IPAddress.Val;
652 return TRUE;
653 }
654 break;
655
656 case TRAP_COMMUNITY:
657 if ( index < trapInfo.Size )
658 {
659 if ( trapInfo.table[index].communityLen == 0 )
660 *ref = SNMP_END_OF_VAR;
661 else
662 {
663 val->byte = trapInfo.table[index].community[myRef];
664
665 myRef++;
666
667 if ( myRef == trapInfo.table[index].communityLen )
668 *ref = SNMP_END_OF_VAR;
669 else
670 *ref = myRef;
671 }
672 return TRUE;
673 }
674 break;
675
676 case LCD_DISPLAY:
677 if ( LCDDisplayStringLen == 0 )
678 myRef = SNMP_END_OF_VAR;
679 else
680 {
681 val->byte = LCDDisplayString[myRef++];
682 if ( myRef == LCDDisplayStringLen )
683 myRef = SNMP_END_OF_VAR;
684 }
685
686 *ref = myRef;
687 return TRUE;
688
689 }
690
691 return FALSE;
692 }
693
694
695
696 static void DisplayIPValue(IP_ADDR *IPVal, BOOL bToLCD)
697 {
698 char IPDigit[8];
699
700 if ( bToLCD )
701 {
702 /*
703 * Erase second line.
704 */
705 XLCDGoto(1, 0);
706 XLCDPutROMString(blankLCDLine);
707
708 }
709
710 /*
711 * Rewrite the second line.
712 */
713 XLCDGoto(1, 0);
714
715 itoa(IPVal->v[0], IPDigit);
716 if ( bToLCD )
717 {
718 XLCDPutString(IPDigit);
719 XLCDPut('.');
720 }
721 else
722 {
723 USARTPutString((BYTE*)IPDigit);
724 USARTPut('.');
725 }
726
727 itoa(IPVal->v[1], IPDigit);
728 if ( bToLCD )
729 {
730 XLCDPutString(IPDigit);
731 XLCDPut('.');
732 }
733 else
734 {
735 USARTPutString((BYTE*)IPDigit);
736 USARTPut('.');
737 }
738
739 itoa(IPVal->v[2], IPDigit);
740 if ( bToLCD )
741 {
742 XLCDPutString(IPDigit);
743 XLCDPut('.');
744 }
745 else
746 {
747 USARTPutString((BYTE*)IPDigit);
748 USARTPut('.');
749 }
750
751 itoa(IPVal->v[3], IPDigit);
752 if ( bToLCD )
753 XLCDPutString(IPDigit);
754 else
755 USARTPutString((BYTE*)IPDigit);
756 }
757
758
759
760 static void ProcessIO(void)
761 {
762 static BOOL lbNotify = FALSE;
763 static BYTE i = 0;
764 SNMP_VAL val;
765
766 if ( PORTB_RB5 == 0 && !lbNotify )
767 lbNotify = TRUE;
768
769 if ( i == trapInfo.Size )
770 {
771 i = 0;
772 lbNotify = FALSE;
773 }
774
775 if ( lbNotify )
776 {
777 if ( trapInfo.table[i].Flags.bEnabled )
778 {
779 val.byte = 0;
780 if ( SendNotification(i, PUSH_BUTTON, val) )
781 i++;
782 }
783 else
784 i++;
785 }
786
787 /*
788 * Select AN0 channel, Fosc/32 clock
789 */
790 ADCON0 = 0b10000001;
791
792 /*
793 * Wait for acquisition time.
794 * Here, rather than waiting for exact time, a simple wait is
795 * used. Real applications requiring high accuracy should
796 * calculate exact acquisition time and wait accordingly.
797 */
798 AN0Value.v[0] = 100;
799 while( AN0Value.v[0]-- );
800
801 /*
802 * First convert AN0 channel.
803 * AN0 is already setup as an analog input.
804 */
805 ADCON0_GO = 1;
806
807 /*
808 * Wait until conversion is done.
809 */
810 while( ADCON0_GO );
811
812 /*
813 * Save the result.
814 */
815 AN0Value.v[0] = ADRESL;
816 AN0Value.v[1] = ADRESH;
817
818 /*
819 * Now, convert AN1 channel.
820 *
821 * In PICDEM.net board, RA2 thru RA7 should be digital or else
822 * LED, LCD and NIC would not operate correctly.
823 * Since there is no mode where only AN0 and AN1 be analog inputs
824 * while rests are digial pins, we will temperoraily switch
825 * select a mode where RA2 becomes analog input while we do
826 * conversion of RA1. Once conversion is done, we will convert
827 * RA2 back to digital pin.
828 */
829 ADCON1 = 0b10000100;
830
831 /*
832 * Select AN1 channel.
833 */
834 ADCON0 = 0b10001001;
835
836 /*
837 * Wait for acquisition time.
838 * Here, rather than waiting for exact time, a simple wait is
839 * used. Real applications requiring high accuracy should
840 * calculate exact acquisition time and wait accordingly.
841 */
842 AN1Value.v[0] = 100;
843 while( AN1Value.v[0]-- );
844
845 /*
846 * Start the conversion.
847 */
848 ADCON0_GO = 1;
849
850 /*
851 * Wait until it is done.
852 */
853 while( ADCON0_GO );
854
855 /*
856 * Save the result.
857 */
858 AN1Value.v[0] = ADRESL;
859 AN1Value.v[1] = ADRESH;
860
861 /*
862 * Reset RA2 pin back to digital output.
863 */
864 ADCON1 = 0b10001110; // RA0 as analog input.
865
866 }
867
868 /*********************************************************************
869 * Function: void InitializeBoard(void)
870 *
871 * PreCondition: None
872 *
873 * Input: None
874 *
875 * Output: None
876 *
877 * Side Effects: None
878 *
879 * Overview: Initialize board specific hardware.
880 *
881 * Note: None
882 ********************************************************************/
883 static void InitializeBoard(void)
884 {
885 /*
886 * Setup for PORTA.RA0 as analog input while rests
887 * as digital i/o lines.
888 */
889 ADCON1 = 0b10001110; // RA0 as analog input, Right justified
890 TRISA = 0x03;
891
892 /*
893 * LCD is enabled using RA5.
894 */
895 PORTA_RA5 = 0; // Disable LCD.
896
897 /*
898 * Turn off the LED's.
899 */
900 LATA2 = 1;
901 LATA3 = 1;
902
903 /*
904 * External data EEPROM needs pull-ups, so enable internal
905 * pull-ups.
906 */
907 INTCON2_RBPU = 0;
908
909 XLCDInit();
910 XLCDGoto(0, 0);
911 XLCDPutROMString(StartupMsg);
912
913
914 TXSTA = 0b00100000; // Low BRG speed
915 RCSTA = 0b10010000;
916 SPBRG = SPBRG_VAL;
917
918 T0CON = 0;
919 INTCON_GIEH = 1;
920 INTCON_GIEL = 1;
921
922 }
923
924 /*********************************************************************
925 * Function: void InitAppConfig(void)
926 *
927 * PreCondition: MPFSInit() is already called.
928 *
929 * Input: None
930 *
931 * Output: Write/Read non-volatile config variables.
932 *
933 * Side Effects: None
934 *
935 * Overview: None
936 *
937 * Note: None
938 ********************************************************************/
939 static void InitAppConfig(void)
940 {
941 #if defined(MPFS_USE_EEPROM)
942 BYTE c;
943 BYTE *p;
944 #endif
945
946 /*
947 * Load default configuration into RAM.
948 */
949 AppConfig.MyIPAddr.v[0] = MY_DEFAULT_IP_ADDR_BYTE1;
950 AppConfig.MyIPAddr.v[1] = MY_DEFAULT_IP_ADDR_BYTE2;
951 AppConfig.MyIPAddr.v[2] = MY_DEFAULT_IP_ADDR_BYTE3;
952 AppConfig.MyIPAddr.v[3] = MY_DEFAULT_IP_ADDR_BYTE4;
953
954 AppConfig.MyMask.v[0] = MY_DEFAULT_MASK_BYTE1;
955 AppConfig.MyMask.v[1] = MY_DEFAULT_MASK_BYTE2;
956 AppConfig.MyMask.v[2] = MY_DEFAULT_MASK_BYTE3;
957 AppConfig.MyMask.v[3] = MY_DEFAULT_MASK_BYTE4;
958
959 AppConfig.MyGateway.v[0] = MY_DEFAULT_GATE_BYTE1;
960 AppConfig.MyGateway.v[1] = MY_DEFAULT_GATE_BYTE2;
961 AppConfig.MyGateway.v[2] = MY_DEFAULT_GATE_BYTE3;
962 AppConfig.MyGateway.v[3] = MY_DEFAULT_GATE_BYTE4;
963
964 AppConfig.MyMACAddr.v[0] = MY_DEFAULT_MAC_BYTE1;
965 AppConfig.MyMACAddr.v[1] = MY_DEFAULT_MAC_BYTE2;
966 AppConfig.MyMACAddr.v[2] = MY_DEFAULT_MAC_BYTE3;
967 AppConfig.MyMACAddr.v[3] = MY_DEFAULT_MAC_BYTE4;
968 AppConfig.MyMACAddr.v[4] = MY_DEFAULT_MAC_BYTE5;
969 AppConfig.MyMACAddr.v[5] = MY_DEFAULT_MAC_BYTE6;
970
971 #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
972 AppConfig.Flags.bIsDHCPEnabled = TRUE;
973 #else
974 AppConfig.Flags.bIsDHCPEnabled = FALSE;
975 #endif
976
977 #if defined(MPFS_USE_EEPROM)
978 p = (BYTE*)&AppConfig;
979
980
981 XEEBeginRead(EEPROM_CONTROL, 0x00);
982 c = XEERead();
983 XEEEndRead();
984
985 /*
986 * When a record is saved, first byte is written as 0x55 to indicate
987 * that a valid record was saved.
988 */
989 if ( c == 0x55 )
990 {
991 XEEBeginRead(EEPROM_CONTROL, 0x01);
992 for ( c = 0; c < sizeof(AppConfig); c++ )
993 *p++ = XEERead();
994 XEEEndRead();
995 }
996 else
997 SaveAppConfig();
998 #endif
999 }
1000
1001 #if defined(MPFS_USE_EEPROM)
1002 static void SaveAppConfig(void)
1003 {
1004 BYTE c;
1005 BYTE *p;
1006
1007 p = (BYTE*)&AppConfig;
1008 XEEBeginWrite(EEPROM_CONTROL, 0x00);
1009 XEEWrite(0x55);
1010 for ( c = 0; c < sizeof(AppConfig); c++ )
1011 {
1012 XEEWrite(*p++);
1013 }
1014
1015 XEEEndWrite();
1016 }
1017 #endif
1018
1019 ROM char menu[] =
1020 "\r\n\r\n\r\MCHPStack SNMP Agent Demo Application 1.0 (Microchip TCP/IP Stack 2.20+ " __DATE__ ")\r\n\r\n"
1021
1022 "\t1: Change Board serial number.\r\n"
1023 "\t2: Change default IP address.\r\n"
1024 "\t3: Change default gateway address.\r\n"
1025 "\t4: Change default subnet mask.\r\n"
1026 "\t5: Enable DHCP & IP Gleaning.\r\n"
1027 "\t6: Disable DHCP & IP Gleaning.\r\n"
1028 "\t7: Download MPFS image.\r\n"
1029 "\t8: Save & Quit.\r\n"
1030 "\r\n"
1031 "Enter a menu choice (1-8): ";
1032
1033 typedef enum _MENU_CMD
1034 {
1035 MENU_CMD_SERIAL_NUMBER = '1',
1036 MENU_CMD_IP_ADDRESS,
1037 MENU_CMD_GATEWAY_ADDRESS,
1038 MENU_CMD_SUBNET_MASK,
1039 MENU_CMD_ENABLE_AUTO_CONFIG,
1040 MENU_CMD_DISABLE_AUTO_CONFIG,
1041 MENU_CMD_DOWNLOAD_MPFS,
1042 MENU_CMD_QUIT,
1043 MENU_CMD_INVALID
1044 } MENU_CMD;
1045
1046 ROM char* menuCommandPrompt[] =
1047 {
1048 "\r\nSerial Number (",
1049 "\r\nDefault IP Address (",
1050 "\r\nDefault Gateway Address (",
1051 "\r\nDefault Subnet Mask (",
1052 "\r\nDHCP & IP Gleaning enabled.\r\n",
1053 "\r\nDHCP & IP Gleaning disabled.\r\n",
1054 "\r\nReady to download MPFS image - Use Xmodem protocol.\r\n",
1055 "\r\nNow running application..."
1056 };
1057
1058 ROM char InvalidInputMsg[] = "\r\nInvalid input received - Input ignored.\r\n"
1059 "Press any key to continue...\r\n";
1060
1061 void USARTPutROMString(ROM char* str)
1062 {
1063 BYTE v;
1064
1065 while( v = *str++ )
1066 USARTPut(v);
1067 }
1068
1069
1070 BYTE USARTGetString(char *buffer, BYTE bufferLen)
1071 {
1072 BYTE v;
1073 BYTE count;
1074
1075 count = 0;
1076 do
1077 {
1078 while( !USARTIsGetReady() );
1079
1080 v = USARTGet();
1081
1082 if ( v == '\r' || v == '\n' )
1083 break;
1084
1085 count++;
1086 *buffer++ = v;
1087 *buffer = '\0';
1088 if ( bufferLen-- == 0 )
1089 break;
1090 } while(1);
1091 return count;
1092 }
1093
1094 BOOL StringToIPAddress(char *str, IP_ADDR *buffer)
1095 {
1096 BYTE v;
1097 char *temp;
1098 BYTE byteIndex;
1099
1100 temp = str;
1101 byteIndex = 0;
1102
1103 while( v = *str )
1104 {
1105 if ( v == '.' )
1106 {
1107 *str++ = '\0';
1108 buffer->v[byteIndex++] = atoi(temp);
1109 temp = str;
1110 }
1111 else if ( v < '0' || v > '9' )
1112 return FALSE;
1113
1114 str++;
1115 }
1116
1117 buffer->v[byteIndex] = atoi(temp);
1118
1119 return (byteIndex == 3);
1120 }
1121
1122
1123
1124 MENU_CMD GetMenuChoice(void)
1125 {
1126 BYTE c;
1127
1128 while ( !USARTIsGetReady() );
1129
1130 c = USARTGet();
1131
1132 if ( c >= '1' && c < MENU_CMD_INVALID )
1133 return c;
1134 else
1135 return MENU_CMD_INVALID;
1136 }
1137
1138 #define MAX_USER_RESPONSE_LEN (20)
1139 void ExecuteMenuChoice(MENU_CMD choice)
1140 {
1141 char response[MAX_USER_RESPONSE_LEN];
1142 IP_ADDR tempIPValue;
1143 IP_ADDR *destIPValue;
1144
1145 USARTPut('\r');
1146 USARTPut('\n');
1147 USARTPutROMString(menuCommandPrompt[choice-'0'-1]);
1148
1149 switch(choice)
1150 {
1151 case MENU_CMD_SERIAL_NUMBER:
1152 itoa(AppConfig.SerialNumber.Val, response);
1153 USARTPutString((BYTE*)response);
1154 USARTPut(')');
1155 USARTPut(':');
1156 USARTPut(' ');
1157
1158 if ( USARTGetString(response, sizeof(response)) )
1159 {
1160 AppConfig.SerialNumber.Val = atoi(response);
1161
1162 AppConfig.MyMACAddr.v[4] = AppConfig.SerialNumber.v[1];
1163 AppConfig.MyMACAddr.v[5] = AppConfig.SerialNumber.v[0];
1164 }
1165 else
1166 goto HandleInvalidInput;
1167
1168 break;
1169
1170 case MENU_CMD_IP_ADDRESS:
1171 destIPValue = &AppConfig.MyIPAddr;
1172 goto ReadIPConfig;
1173
1174 case MENU_CMD_GATEWAY_ADDRESS:
1175 destIPValue = &AppConfig.MyGateway;
1176 goto ReadIPConfig;
1177
1178 case MENU_CMD_SUBNET_MASK:
1179 destIPValue = &AppConfig.MyMask;
1180
1181 ReadIPConfig:
1182 DisplayIPValue(destIPValue, FALSE);
1183 USARTPut(')');
1184 USARTPut(':');
1185 USARTPut(' ');
1186
1187 USARTGetString(response, sizeof(response));
1188
1189 if ( !StringToIPAddress(response, &tempIPValue) )
1190 {
1191 HandleInvalidInput:
1192 USARTPutROMString(InvalidInputMsg);
1193 while( !USARTIsGetReady() );
1194 USARTGet();
1195 }
1196 else
1197 {
1198 destIPValue->Val = tempIPValue.Val;
1199 }
1200 break;
1201
1202
1203 case MENU_CMD_ENABLE_AUTO_CONFIG:
1204 AppConfig.Flags.bIsDHCPEnabled = TRUE;
1205 break;
1206
1207 case MENU_CMD_DISABLE_AUTO_CONFIG:
1208 AppConfig.Flags.bIsDHCPEnabled = FALSE;
1209 break;
1210
1211 case MENU_CMD_DOWNLOAD_MPFS:
1212 #if defined(MPFS_USE_EEPROM)
1213 DownloadMPFS();
1214 #endif
1215 break;
1216
1217 case MENU_CMD_QUIT:
1218 #if defined(MPFS_USE_EEPROM)
1219 SaveAppConfig();
1220 #endif
1221 break;
1222 }
1223 }
1224
1225
1226
1227
1228 static void SetConfig(void)
1229 {
1230 MENU_CMD choice;
1231
1232 do
1233 {
1234 USARTPutROMString(menu);
1235 choice = GetMenuChoice();
1236 if ( choice != MENU_CMD_INVALID )
1237 ExecuteMenuChoice(choice);
1238 } while(choice != MENU_CMD_QUIT);
1239
1240 }
1241
1242
1243 #if defined(MPFS_USE_EEPROM)
1244
1245 /*********************************************************************
1246 * Function: BOOL DownloadMPFS(void)
1247 *
1248 * PreCondition: MPFSInit() is already called.
1249 *
1250 * Input: None
1251 *
1252 * Output: TRUE if successful
1253 * FALSE otherwise
1254 *
1255 * Side Effects: This function uses 128 bytes of Bank 4 using
1256 * indirect pointer. This requires that no part of
1257 * code is using this block during or before calling
1258 * this function. Once this function is done,
1259 * that block of memory is available for general use.
1260 *
1261 * Overview: This function implements XMODEM protocol to
1262 * be able to receive a binary file from PC
1263 * applications such as HyperTerminal.
1264 *
1265 * Note: In current version, this function does not
1266 * implement user interface to set IP address and
1267 * other informations. User should create their
1268 * own interface to allow user to modify IP
1269 * information.
1270 * Also, this version implements simple user
1271 * action to start file transfer. User may
1272 * evaulate its own requirement and implement
1273 * appropriate start action.
1274 *
1275 ********************************************************************/
1276 #define XMODEM_SOH 0x01
1277 #define XMODEM_EOT 0x04
1278 #define XMODEM_ACK 0x06
1279 #define XMODEM_NAK 0x15
1280 #define XMODEM_CAN 0x18
1281 #define XMODEM_BLOCK_LEN 128
1282
1283 static BOOL DownloadMPFS(void)
1284 {
1285 enum SM_MPFS
1286 {
1287 SM_MPFS_SOH,
1288 SM_MPFS_BLOCK,
1289 SM_MPFS_BLOCK_CMP,
1290 SM_MPFS_DATA,
1291 } state;
1292
1293 BYTE c;
1294 MPFS handle;
1295 BOOL lbDone;
1296 BYTE blockLen;
1297 BYTE lResult;
1298 BYTE tempData[XMODEM_BLOCK_LEN];
1299 TICK lastTick;
1300 TICK currentTick;
1301
1302 state = SM_MPFS_SOH;
1303 lbDone = FALSE;
1304
1305 handle = MPFSFormat();
1306
1307 /*
1308 * Notify the host that we are ready to receive...
1309 */
1310 lastTick = TickGet();
1311 do
1312 {
1313 /*
1314 * Update tick here too - just in case interrupt is not used.
1315 */
1316 TickUpdate();
1317
1318 currentTick = TickGet();
1319 if ( TickGetDiff(currentTick, lastTick) >= (TICK_SECOND/2) )
1320 {
1321 lastTick = TickGet();
1322 USARTPut(XMODEM_NAK);
1323
1324 /*
1325 * Blink LED to indicate that we are waiting for
1326 * host to send the file.
1327 */
1328 LATA2 ^= 1;
1329 }
1330
1331 } while( !USARTIsGetReady() );
1332
1333
1334 while(!lbDone)
1335 {
1336 /*
1337 * Update tick here too - just in case interrupt is not used.
1338 */
1339 TickUpdate();
1340
1341 if ( USARTIsGetReady() )
1342 {
1343 /*
1344 * Toggle LED as we receive the data from host.
1345 */
1346 LATA2 ^= 1;
1347 c = USARTGet();
1348 }
1349 else
1350 {
1351 /*
1352 * Real application should put some timeout to make sure
1353 * that we do not wait forever.
1354 */
1355 continue;
1356 }
1357
1358 switch(state)
1359 {
1360 default:
1361 if ( c == XMODEM_SOH )
1362 {
1363 state = SM_MPFS_BLOCK;
1364 }
1365 else if ( c == XMODEM_EOT )
1366 {
1367 /*
1368 * Turn off LED when we are done.
1369 */
1370 LATA2 = 1;
1371
1372 MPFSClose();
1373 USARTPut(XMODEM_ACK);
1374 lbDone = TRUE;
1375 }
1376 else
1377 USARTPut(XMODEM_NAK);
1378
1379 break;
1380
1381 case SM_MPFS_BLOCK:
1382 /*
1383 * We do not use block information.
1384 */
1385 lResult = XMODEM_ACK;
1386 blockLen = 0;
1387 state = SM_MPFS_BLOCK_CMP;
1388 break;
1389
1390 case SM_MPFS_BLOCK_CMP:
1391 /*
1392 * We do not use 1's comp. block value.
1393 */
1394 state = SM_MPFS_DATA;
1395 break;
1396
1397 case SM_MPFS_DATA:
1398 /*
1399 * Buffer block data until it is over.
1400 */
1401 tempData[blockLen++] = c;
1402 if ( blockLen > XMODEM_BLOCK_LEN )
1403 {
1404 /*
1405 * We have one block data.
1406 * Write it to EEPROM.
1407 */
1408 MPFSPutBegin(handle);
1409
1410 lResult = XMODEM_ACK;
1411 for ( c = 0; c < XMODEM_BLOCK_LEN; c++ )
1412 MPFSPut(tempData[c]);
1413
1414 handle = MPFSPutEnd();
1415
1416 USARTPut(lResult);
1417 state = SM_MPFS_SOH;
1418 }
1419 break;
1420
1421 }
1422
1423 }
1424
1425
1426 /*
1427 * This small wait is required if SLIP is in use.
1428 * If this is not used, PC might misinterpret SLIP
1429 * module communication and never close file transfer
1430 * dialog box.
1431 */
1432 #if defined(STACK_USE_SLIP)
1433 {
1434 BYTE i;
1435 i = 255;
1436 while( i-- );
1437 }
1438 #endif
1439 return TRUE;
1440 }
1441
1442 #endif
1443
1444
1445
1446
1447 void XLCDDelay15ms(void)
1448 {
1449 DelayMs(15);
1450 }
1451 void XLCDDelay4ms(void)
1452 {
1453 DelayMs(4);
1454 }
1455
1456 void XLCDDelay100us(void)
1457 {
1458 INTCON_GIEH = 0;
1459 Delay10us(1);
1460 INTCON_GIEH = 1;
1461 }

  ViewVC Help
Powered by ViewVC 1.1.20