Rev Author Line No. Line
1661 kaklik 1 /********************************************************************
2 FileName: main.c
3 Dependencies: See INCLUDES section
4 Processor: PIC18 or PIC24 USB Microcontrollers
5 Hardware: The code is natively intended to be used on the following
6 hardware platforms: PICDEM™ FS USB Demo Board,
7 PIC18F87J50 FS USB Plug-In Module, or
8 Explorer 16 + PIC24 USB PIM. The firmware may be
9 modified for use on other USB platforms by editing the
10 HardwareProfile.h file.
11 Complier: Microchip C18 (for PIC18) or C30 (for PIC24)
12 Company: Microchip Technology, Inc.
13  
14 Software License Agreement:
15  
16 The software supplied herewith by Microchip Technology Incorporated
17 (the “Company”) for its PIC® Microcontroller is intended and
18 supplied to you, the Company’s customer, for use solely and
19 exclusively on Microchip PIC Microcontroller products. The
20 software is owned by the Company and/or its supplier, and is
21 protected under applicable copyright laws. All rights are reserved.
22 Any use in violation of the foregoing restrictions may subject the
23 user to criminal sanctions under applicable laws, as well as to
24 civil liability for the breach of the terms and conditions of this
25 license.
26  
27 THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
28 WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
29 TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
30 PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
31 IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
32 CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
33  
34 ********************************************************************
35 File Description:
36  
37 Change History:
38 Rev Date Description
39 1.0 11/19/2004 Initial release
40 2.1 02/26/2007 Updated for simplicity and to use common
41 coding style
42 ********************************************************************/
43  
44 /** INCLUDES *******************************************************/
45 #include "USB/usb.h"
46 #include "USB/usb_function_generic.h"
47 #include "user.h" // Modifiable
48 #include "HardwareProfile.h"
49  
50 /** CONFIGURATION **************************************************/
51 #if defined(PICDEM_FS_USB) // Configuration bits for PICDEM FS USB Demo Board (based on PIC18F4550)
52 #pragma config PLLDIV = 5 // (20 MHz crystal on PICDEM FS USB board)
53 #pragma config CPUDIV = OSC1_PLL2
54 #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
55 #pragma config FOSC = HSPLL_HS
56 #pragma config FCMEN = OFF
57 #pragma config IESO = OFF
58 #pragma config PWRT = OFF
59 #pragma config BOR = ON
60 #pragma config BORV = 3
61 #pragma config VREGEN = ON //USB Voltage Regulator
62 #pragma config WDT = OFF
63 #pragma config WDTPS = 32768
64 #pragma config MCLRE = ON
65 #pragma config LPT1OSC = OFF
66 #pragma config PBADEN = OFF
67 // #pragma config CCP2MX = ON
68 #pragma config STVREN = ON
69 #pragma config LVP = OFF
70 // #pragma config ICPRT = OFF // Dedicated In-Circuit Debug/Programming
71 #pragma config XINST = OFF // Extended Instruction Set
72 #pragma config CP0 = OFF
73 #pragma config CP1 = OFF
74 // #pragma config CP2 = OFF
75 // #pragma config CP3 = OFF
76 #pragma config CPB = OFF
77 // #pragma config CPD = OFF
78 #pragma config WRT0 = OFF
79 #pragma config WRT1 = OFF
80 // #pragma config WRT2 = OFF
81 // #pragma config WRT3 = OFF
82 #pragma config WRTB = OFF // Boot Block Write Protection
83 #pragma config WRTC = OFF
84 // #pragma config WRTD = OFF
85 #pragma config EBTR0 = OFF
86 #pragma config EBTR1 = OFF
87 // #pragma config EBTR2 = OFF
88 // #pragma config EBTR3 = OFF
89 #pragma config EBTRB = OFF
90  
91 #elif defined(PIC18F87J50_PIM) // Configuration bits for PIC18F87J50 FS USB Plug-In Module board
92 #pragma config XINST = OFF // Extended instruction set
93 #pragma config STVREN = ON // Stack overflow reset
94 #pragma config PLLDIV = 3 // (12 MHz crystal used on this board)
95 #pragma config WDTEN = OFF // Watch Dog Timer (WDT)
96 #pragma config CP0 = OFF // Code protect
97 #pragma config CPUDIV = OSC1 // OSC1 = divide by 1 mode
98 #pragma config IESO = OFF // Internal External (clock) Switchover
99 #pragma config FCMEN = OFF // Fail Safe Clock Monitor
100 #pragma config FOSC = HSPLL // Firmware must also set OSCTUNE<PLLEN> to start PLL!
101 #pragma config WDTPS = 32768
102 // #pragma config WAIT = OFF // Commented choices are
103 // #pragma config BW = 16 // only available on the
104 // #pragma config MODE = MM // 80 pin devices in the
105 // #pragma config EASHFT = OFF // family.
106 #pragma config MSSPMSK = MSK5
107 // #pragma config PMPMX = DEFAULT
108 // #pragma config ECCPMX = DEFAULT
109 #pragma config CCP2MX = DEFAULT
110  
111 #elif defined(PIC18F46J50_PIM) || defined(PIC18F_STARTER_KIT_1)
112 #pragma config WDTEN = OFF //WDT disabled (enabled by SWDTEN bit)
113 #pragma config PLLDIV = 3 //Divide by 3 (12 MHz oscillator input)
114 #pragma config STVREN = ON //stack overflow/underflow reset enabled
115 #pragma config XINST = OFF //Extended instruction set disabled
116 #pragma config CPUDIV = OSC1 //No CPU system clock divide
117 #pragma config CP0 = OFF //Program memory is not code-protected
118 #pragma config OSC = HSPLL //HS oscillator, PLL enabled, HSPLL used by USB
119 #pragma config T1DIG = ON //Sec Osc clock source may be selected
120 #pragma config LPT1OSC = OFF //high power Timer1 mode
121 #pragma config FCMEN = OFF //Fail-Safe Clock Monitor disabled
122 #pragma config IESO = OFF //Two-Speed Start-up disabled
123 #pragma config WDTPS = 32768 //1:32768
124 #pragma config DSWDTOSC = INTOSCREF //DSWDT uses INTOSC/INTRC as clock
125 #pragma config RTCOSC = T1OSCREF //RTCC uses T1OSC/T1CKI as clock
126 #pragma config DSBOREN = OFF //Zero-Power BOR disabled in Deep Sleep
127 #pragma config DSWDTEN = OFF //Disabled
128 #pragma config DSWDTPS = 8192 //1:8,192 (8.5 seconds)
129 #pragma config IOL1WAY = OFF //IOLOCK bit can be set and cleared
130 #pragma config MSSP7B_EN = MSK7 //7 Bit address masking
131 #pragma config WPFP = PAGE_1 //Write Protect Program Flash Page 0
132 #pragma config WPEND = PAGE_0 //Start protection at page 0
133 #pragma config WPCFG = OFF //Write/Erase last page protect Disabled
134 #pragma config WPDIS = OFF //WPFP[5:0], WPEND, and WPCFG bits ignored
135  
136 #elif defined(LOW_PIN_COUNT_USB_DEVELOPMENT_KIT)
137 // PIC18F14K50
138 #pragma config CPUDIV = NOCLKDIV
139 #pragma config USBDIV = OFF
140 #pragma config FOSC = HS
141 #pragma config PLLEN = ON
142 #pragma config FCMEN = OFF
143 #pragma config IESO = OFF
144 #pragma config PWRTEN = OFF
145 #pragma config BOREN = OFF
146 #pragma config BORV = 30
147 #pragma config WDTEN = OFF
148 #pragma config WDTPS = 32768
149 #pragma config MCLRE = OFF
150 #pragma config HFOFST = OFF
151 #pragma config STVREN = ON
152 #pragma config LVP = OFF
153 #pragma config XINST = OFF
154 #pragma config BBSIZ = OFF
155 #pragma config CP0 = OFF
156 #pragma config CP1 = OFF
157 #pragma config CPB = OFF
158 #pragma config WRT0 = OFF
159 #pragma config WRT1 = OFF
160 #pragma config WRTB = OFF
161 #pragma config WRTC = OFF
162 #pragma config EBTR0 = OFF
163 #pragma config EBTR1 = OFF
164 #pragma config EBTRB = OFF
165  
166 #elif defined(EXPLORER_16)
167 #ifdef __PIC24FJ256GB110__ //Defined by MPLAB when using 24FJ256GB110 device
168 _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
169 _CONFIG2( 0xF7FF & IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_HS & FNOSC_PRIPLL & PLLDIV_DIV2 & IOL1WAY_ON)
170 #elif defined(__PIC24FJ64GB004__)
171 _CONFIG1(WDTPS_PS1 & FWPSA_PR32 & WINDIS_OFF & FWDTEN_OFF & ICS_PGx1 & GWRP_OFF & GCP_OFF & JTAGEN_OFF)
172 _CONFIG2(POSCMOD_HS & I2C1SEL_PRI & IOL1WAY_OFF & OSCIOFNC_ON & FCKSM_CSDCMD & FNOSC_PRIPLL & PLL96MHZ_ON & PLLDIV_DIV2 & IESO_ON)
173 _CONFIG3(WPFP_WPFP0 & SOSCSEL_SOSC & WUTSEL_LEG & WPDIS_WPDIS & WPCFG_WPCFGDIS & WPEND_WPENDMEM)
174 _CONFIG4(DSWDTPS_DSWDTPS3 & DSWDTOSC_LPRC & RTCOSC_SOSC & DSBOREN_OFF & DSWDTEN_OFF)
175 #elif defined(__32MX460F512L__) || defined(__32MX795F512L__)
176 #pragma config UPLLEN = ON // USB PLL Enabled
177 #pragma config FPLLMUL = MUL_15 // PLL Multiplier
178 #pragma config UPLLIDIV = DIV_2 // USB PLL Input Divider
179 #pragma config FPLLIDIV = DIV_2 // PLL Input Divider
180 #pragma config FPLLODIV = DIV_1 // PLL Output Divider
181 #pragma config FPBDIV = DIV_1 // Peripheral Clock divisor
182 #pragma config FWDTEN = OFF // Watchdog Timer
183 #pragma config WDTPS = PS1 // Watchdog Timer Postscale
184 #pragma config FCKSM = CSDCMD // Clock Switching & Fail Safe Clock Monitor
185 #pragma config OSCIOFNC = OFF // CLKO Enable
186 #pragma config POSCMOD = HS // Primary Oscillator
187 #pragma config IESO = OFF // Internal/External Switch-over
188 #pragma config FSOSCEN = OFF // Secondary Oscillator Enable (KLO was off)
189 #pragma config FNOSC = PRIPLL // Oscillator Selection
190 #pragma config CP = OFF // Code Protect
191 #pragma config BWP = OFF // Boot Flash Write Protect
192 #pragma config PWP = OFF // Program Flash Write Protect
193 #pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select
194 #pragma config DEBUG = ON // Background Debugger Enable
195 #else
196 #error No hardware board defined, see "HardwareProfile.h" and __FILE__
197 #endif
198 #elif defined(PIC24F_STARTER_KIT)
199 _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
200 _CONFIG2( 0xF7FF & IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_HS & FNOSC_PRIPLL & PLLDIV_DIV3 & IOL1WAY_ON)
201 #elif defined(PIC24FJ256DA210_DEV_BOARD)
202 //_CONFIG1(FWDTEN_OFF & ICS_PGx2 & COE_OFF & GWRP_OFF & GCP_OFF & JTAGEN_OFF)
203 //_CONFIG2(POSCMOD_HS & IOL1WAY_ON & OSCIOFNC_ON & FCKSM_CSDCMD & FNOSC_PRIPLL & PLL96MHZ_ON & PLLDIV_DIV2 & IESO_OFF)
204 #elif defined(PIC32_USB_STARTER_KIT)
205 #pragma config UPLLEN = ON // USB PLL Enabled
206 #pragma config FPLLMUL = MUL_15 // PLL Multiplier
207 #pragma config UPLLIDIV = DIV_2 // USB PLL Input Divider
208 #pragma config FPLLIDIV = DIV_2 // PLL Input Divider
209 #pragma config FPLLODIV = DIV_1 // PLL Output Divider
210 #pragma config FPBDIV = DIV_1 // Peripheral Clock divisor
211 #pragma config FWDTEN = OFF // Watchdog Timer
212 #pragma config WDTPS = PS1 // Watchdog Timer Postscale
213 #pragma config FCKSM = CSDCMD // Clock Switching & Fail Safe Clock Monitor
214 #pragma config OSCIOFNC = OFF // CLKO Enable
215 #pragma config POSCMOD = HS // Primary Oscillator
216 #pragma config IESO = OFF // Internal/External Switch-over
217 #pragma config FSOSCEN = OFF // Secondary Oscillator Enable (KLO was off)
218 #pragma config FNOSC = PRIPLL // Oscillator Selection
219 #pragma config CP = OFF // Code Protect
220 #pragma config BWP = OFF // Boot Flash Write Protect
221 #pragma config PWP = OFF // Program Flash Write Protect
222 #pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select
223 #pragma config DEBUG = ON // Background Debugger Enable
1691 kaklik 224  
1661 kaklik 225 #elif defined(UBW)
1691 kaklik 226 #pragma config PLLDIV = 5 // (20 MHz input)
227 #pragma config CPUDIV = OSC1_PLL2
228 #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
229 #pragma config FOSC = HSPLL_HS
230 #pragma config FCMEN = OFF
231 #pragma config IESO = OFF
232 #pragma config PWRT = OFF
233 #pragma config BOR = ON
234 #pragma config BORV = 3
235 #pragma config VREGEN = ON
236 #pragma config WDT = OFF
237 #pragma config WDTPS = 32768
238 #pragma config MCLRE = ON
239 #pragma config LPT1OSC = OFF
240 #pragma config PBADEN = OFF
241 #pragma config CCP2MX = ON
242 #pragma config STVREN = ON
243 #pragma config LVP = OFF
244 //#pragma config ICPRT = OFF // Dedicated In-Circuit Debug/Programming
245 #pragma config XINST = OFF // Extended Instruction Set
246 #pragma config CP0 = OFF
247 #pragma config CP1 = OFF
248 #pragma config CP2 = OFF
249 //#pragma config CP3 = OFF
250 #pragma config CPB = OFF
251 #pragma config CPD = OFF
252 #pragma config WRT0 = OFF
253 #pragma config WRT1 = OFF
254 #pragma config WRT2 = OFF
255 //#pragma config WRT3 = OFF
256 #pragma config WRTB = ON // Boot Block Write Protection
257 #pragma config WRTC = OFF
258 #pragma config WRTD = OFF
259 #pragma config EBTR0 = OFF
260 #pragma config EBTR1 = OFF
261 #pragma config EBTR2 = OFF
262 //#pragma config EBTR3 = OFF
263 #pragma config EBTRB = OFF
264  
1661 kaklik 265 #elif defined(UBW32)
266 #else
267 #error No hardware board defined, see "HardwareProfile.h" and __FILE__
268 #endif
269  
270  
271  
272 /** VARIABLES ******************************************************/
273 #pragma udata
274  
275 /** PRIVATE PROTOTYPES *********************************************/
276 static void InitializeSystem(void);
277 void USBDeviceTasks(void);
278 void YourHighPriorityISRCode(void);
279 void YourLowPriorityISRCode(void);
280  
281  
282 /** VECTOR REMAPPING ***********************************************/
283 #if defined(__18CXX)
284 //On PIC18 devices, addresses 0x00, 0x08, and 0x18 are used for
285 //the reset, high priority interrupt, and low priority interrupt
286 //vectors. However, the current Microchip USB bootloader
287 //examples are intended to occupy addresses 0x00-0x7FF or
288 //0x00-0xFFF depending on which bootloader is used. Therefore,
289 //the bootloader code remaps these vectors to new locations
290 //as indicated below. This remapping is only necessary if you
291 //wish to program the hex file generated from this project with
292 //the USB bootloader. If no bootloader is used, edit the
293 //usb_config.h file and comment out the following defines:
294 //#define PROGRAMMABLE_WITH_USB_HID_BOOTLOADER
295 //#define PROGRAMMABLE_WITH_USB_LEGACY_CUSTOM_CLASS_BOOTLOADER
296  
297 #if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)
298 #define REMAPPED_RESET_VECTOR_ADDRESS 0x1000
299 #define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x1008
300 #define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x1018
301 #elif defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER)
302 #define REMAPPED_RESET_VECTOR_ADDRESS 0x800
303 #define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x808
304 #define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x818
305 #else
306 #define REMAPPED_RESET_VECTOR_ADDRESS 0x00
307 #define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x08
308 #define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x18
309 #endif
310  
311 #if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER)
312 extern void _startup (void); // See c018i.c in your C18 compiler dir
313 #pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESS
314 void _reset (void)
315 {
316 _asm goto _startup _endasm
317 }
318 #endif
319 #pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS
320 void Remapped_High_ISR (void)
321 {
322 _asm goto YourHighPriorityISRCode _endasm
323 }
324 #pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS
325 void Remapped_Low_ISR (void)
326 {
327 _asm goto YourLowPriorityISRCode _endasm
328 }
329  
330 #if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_MCHPUSB_BOOTLOADER)
331 //Note: If this project is built while one of the bootloaders has
332 //been defined, but then the output hex file is not programmed with
333 //the bootloader, addresses 0x08 and 0x18 would end up programmed with 0xFFFF.
334 //As a result, if an actual interrupt was enabled and occured, the PC would jump
335 //to 0x08 (or 0x18) and would begin executing "0xFFFF" (unprogrammed space). This
336 //executes as nop instructions, but the PC would eventually reach the REMAPPED_RESET_VECTOR_ADDRESS
337 //(0x1000 or 0x800, depending upon bootloader), and would execute the "goto _startup". This
338 //would effective reset the application.
339  
340 //To fix this situation, we should always deliberately place a
341 //"goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS" at address 0x08, and a
342 //"goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS" at address 0x18. When the output
343 //hex file of this project is programmed with the bootloader, these sections do not
344 //get bootloaded (as they overlap the bootloader space). If the output hex file is not
345 //programmed using the bootloader, then the below goto instructions do get programmed,
346 //and the hex file still works like normal. The below section is only required to fix this
347 //scenario.
348 #pragma code HIGH_INTERRUPT_VECTOR = 0x08
349 void High_ISR (void)
350 {
351 _asm goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS _endasm
352 }
353 #pragma code LOW_INTERRUPT_VECTOR = 0x18
354 void Low_ISR (void)
355 {
356 _asm goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS _endasm
357 }
358 #endif //end of "#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)||defined(PROGRAMMABLE_WITH_USB_LEGACY_CUSTOM_CLASS_BOOTLOADER)"
359  
360 #pragma code
361  
362  
363 //These are your actual interrupt handling routines.
364 #pragma interrupt YourHighPriorityISRCode
365 void YourHighPriorityISRCode()
366 {
367 //Check which interrupt flag caused the interrupt.
368 //Service the interrupt
369 //Clear the interrupt flag
370 //Etc.
371 #if defined(USB_INTERRUPT)
372 USBDeviceTasks();
373 #endif
374  
375 } //This return will be a "retfie fast", since this is in a #pragma interrupt section
376 #pragma interruptlow YourLowPriorityISRCode
377 void YourLowPriorityISRCode()
378 {
379 //Check which interrupt flag caused the interrupt.
380 //Service the interrupt
381 //Clear the interrupt flag
382 //Etc.
383  
384 } //This return will be a "retfie", since this is in a #pragma interruptlow section
385  
386 #elif defined(__C30__)
387 #if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)
388 /*
389 * ISR JUMP TABLE
390 *
391 * It is necessary to define jump table as a function because C30 will
392 * not store 24-bit wide values in program memory as variables.
393 *
394 * This function should be stored at an address where the goto instructions
395 * line up with the remapped vectors from the bootloader's linker script.
396 *
397 * For more information about how to remap the interrupt vectors,
398 * please refer to AN1157. An example is provided below for the T2
399 * interrupt with a bootloader ending at address 0x1400
400 */
401 // void __attribute__ ((address(0x1404))) ISRTable(){
402 //
403 // asm("reset"); //reset instruction to prevent runaway code
404 // asm("goto %0"::"i"(&_T2Interrupt)); //T2Interrupt's address
405 // }
406 #endif
407 #endif
408  
409  
410  
411  
412 /** DECLARATIONS ***************************************************/
413 #pragma code
414  
415 /******************************************************************************
416 * Function: void main(void)
417 *
418 * PreCondition: None
419 *
420 * Input: None
421 *
422 * Output: None
423 *
424 * Side Effects: None
425 *
426 * Overview: Main program entry point.
427 *
428 * Note: None
429 *******************************************************************/
430  
431 #if defined(__18CXX)
432 void main(void)
433 #else
434 int main(void)
435 #endif
436 {
437 InitializeSystem();
438  
439 #if defined(USB_INTERRUPT)
440 USBDeviceAttach();
441 #endif
442  
443 while(1)
444 {
445 #if defined(USB_POLLING)
446 // Check bus status and service USB interrupts.
447 USBDeviceTasks(); // Interrupt or polling method. If using polling, must call
448 // this function periodically. This function will take care
449 // of processing and responding to SETUP transactions
450 // (such as during the enumeration process when you first
451 // plug in). USB hosts require that USB devices should accept
452 // and process SETUP packets in a timely fashion. Therefore,
453 // when using polling, this function should be called
454 // frequently (such as once about every 100 microseconds) at any
455 // time that a SETUP packet might reasonably be expected to
456 // be sent by the host to your device. In most cases, the
457 // USBDeviceTasks() function does not take very long to
458 // execute (~50 instruction cycles) before it returns.
459 #endif
460  
461  
462 // Application-specific tasks.
463 // Application related code may be added here, or in the ProcessIO() function.
464 ProcessIO();
465 }//end while
466 }//end main
467  
468  
469 /********************************************************************
470 * Function: static void InitializeSystem(void)
471 *
472 * PreCondition: None
473 *
474 * Input: None
475 *
476 * Output: None
477 *
478 * Side Effects: None
479 *
480 * Overview: InitializeSystem is a centralize initialization
481 * routine. All required USB initialization routines
482 * are called from here.
483 *
484 * User application initialization routine should
485 * also be called from here.
486 *
487 * Note: None
488 *******************************************************************/
489 static void InitializeSystem(void)
490 {
491 #if (defined(__18CXX) & !defined(PIC18F87J50_PIM))
492 ADCON1 |= 0x0F; // Default all pins to digital
493 #elif defined(__C30__)
494 #if defined(PIC24FJ256DA210_DEV_BOARD)
495 ANSA = 0x0000;
496 ANSB = 0x0000;
497 ANSC = 0x0000;
498 ANSD = 0x0000;
499 ANSE = 0x0000;
500 ANSF = 0x0000;
501 ANSG = 0x0000;
502 #else
503 AD1PCFGL = 0xFFFF;
504 #endif
505 #elif defined(__C32__)
506 AD1PCFG = 0xFFFF;
507 #endif
508  
509 #if defined(PIC18F87J50_PIM) || defined(PIC18F46J50_PIM) || defined(PIC18F_STARTER_KIT_1)
510 //On the PIC18F87J50 Family of USB microcontrollers, the PLL will not power up and be enabled
511 //by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL).
512 //This allows the device to power up at a lower initial operating frequency, which can be
513 //advantageous when powered from a source which is not gauranteed to be adequate for 48MHz
514 //operation. On these devices, user firmware needs to manually set the OSCTUNE<PLLEN> bit to
515 //power up the PLL.
516 {
517 unsigned int pll_startup_counter = 600;
518 OSCTUNEbits.PLLEN = 1; //Enable the PLL and wait 2+ms until the PLL locks before enabling USB module
519 while(pll_startup_counter--);
520 }
521 //Device switches over automatically to PLL output after PLL is locked and ready.
522 #endif
523  
524 #if defined(PIC18F87J50_PIM)
525 //Configure all I/O pins to use digital input buffers. The PIC18F87J50 Family devices
526 //use the ANCONx registers to control this, which is different from other devices which
527 //use the ADCON1 register for this purpose.
528 WDTCONbits.ADSHR = 1; // Select alternate SFR location to access ANCONx registers
529 ANCON0 = 0xFF; // Default all pins to digital
530 ANCON1 = 0xFF; // Default all pins to digital
531 WDTCONbits.ADSHR = 0; // Select normal SFR locations
532 #endif
533  
534 #if defined(PIC18F46J50_PIM) || defined(PIC18F_STARTER_KIT_1)
535 //Configure all I/O pins to use digital input buffers.
536 ANCON0 = 0x7F; // all pins to digital except AN7
537 ANCON1 = 0xBF; // Default all pins to digital. Bandgap on.
538 #endif
539  
540 #if defined(PIC24FJ64GB004_PIM) || defined(PIC24FJ256DA210_DEV_BOARD)
541 //On the PIC24FJ64GB004 Family of USB microcontrollers, the PLL will not power up and be enabled
542 //by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL).
543 //This allows the device to power up at a lower initial operating frequency, which can be
544 //advantageous when powered from a source which is not gauranteed to be adequate for 32MHz
545 //operation. On these devices, user firmware needs to manually set the CLKDIV<PLLEN> bit to
546 //power up the PLL.
547 {
548 unsigned int pll_startup_counter = 600;
549 CLKDIVbits.PLLEN = 1;
550 while(pll_startup_counter--);
551 }
552  
553 //Device switches over automatically to PLL output after PLL is locked and ready.
554 #endif
555  
556  
557 // The USB specifications require that USB peripheral devices must never source
558 // current onto the Vbus pin. Additionally, USB peripherals should not source
559 // current on D+ or D- when the host/hub is not actively powering the Vbus line.
560 // When designing a self powered (as opposed to bus powered) USB peripheral
561 // device, the firmware should make sure not to turn on the USB module and D+
562 // or D- pull up resistor unless Vbus is actively powered. Therefore, the
563 // firmware needs some means to detect when Vbus is being powered by the host.
564 // A 5V tolerant I/O pin can be connected to Vbus (through a resistor), and
565 // can be used to detect when Vbus is high (host actively powering), or low
566 // (host is shut down or otherwise not supplying power). The USB firmware
567 // can then periodically poll this I/O pin to know when it is okay to turn on
568 // the USB module/D+/D- pull up resistor. When designing a purely bus powered
569 // peripheral device, it is not possible to source current on D+ or D- when the
570 // host is not actively providing power on Vbus. Therefore, implementing this
571 // bus sense feature is optional. This firmware can be made to use this bus
572 // sense feature by making sure "USE_USB_BUS_SENSE_IO" has been defined in the
573 // HardwareProfile.h file.
574 #if defined(USE_USB_BUS_SENSE_IO)
575 tris_usb_bus_sense = INPUT_PIN; // See HardwareProfile.h
576 #endif
577  
578 // If the host PC sends a GetStatus (device) request, the firmware must respond
579 // and let the host know if the USB peripheral device is currently bus powered
580 // or self powered. See chapter 9 in the official USB specifications for details
581 // regarding this request. If the peripheral device is capable of being both
582 // self and bus powered, it should not return a hard coded value for this request.
583 // Instead, firmware should check if it is currently self or bus powered, and
584 // respond accordingly. If the hardware has been configured like demonstrated
585 // on the PICDEM FS USB Demo Board, an I/O pin can be polled to determine the
586 // currently selected power source. On the PICDEM FS USB Demo Board, "RA2"
587 // is used for this purpose. If using this feature, make sure "USE_SELF_POWER_SENSE_IO"
588 // has been defined in HardwareProfile - (platform).h, and that an appropriate I/O pin
589 // has been mapped to it.
590 #if defined(USE_SELF_POWER_SENSE_IO)
591 tris_self_power = INPUT_PIN; // See HardwareProfile
592 #endif
593  
594 UserInit();
595  
596 USBDeviceInit(); //usb_device.c. Initializes USB module SFRs and firmware
597 //variables to known states.
598 }//end InitializeSystem
599  
600 // ******************************************************************************************************
601 // ************** USB Callback Functions ****************************************************************
602 // ******************************************************************************************************
603 // The USB firmware stack will call the callback functions USBCBxxx() in response to certain USB related
604 // events. For example, if the host PC is powering down, it will stop sending out Start of Frame (SOF)
605 // packets to your device. In response to this, all USB devices are supposed to decrease their power
606 // consumption from the USB Vbus to <2.5mA each. The USB module detects this condition (which according
607 // to the USB specifications is 3+ms of no bus activity/SOF packets) and then calls the USBCBSuspend()
608 // function. You should modify these callback functions to take appropriate actions for each of these
609 // conditions. For example, in the USBCBSuspend(), you may wish to add code that will decrease power
610 // consumption from Vbus to <2.5mA (such as by clock switching, turning off LEDs, putting the
611 // microcontroller to sleep, etc.). Then, in the USBCBWakeFromSuspend() function, you may then wish to
612 // add code that undoes the power saving things done in the USBCBSuspend() function.
613  
614 // The USBCBSendResume() function is special, in that the USB stack will not automatically call this
615 // function. This function is meant to be called from the application firmware instead. See the
616 // additional comments near the function.
617  
618 /******************************************************************************
619 * Function: void USBCBSuspend(void)
620 *
621 * PreCondition: None
622 *
623 * Input: None
624 *
625 * Output: None
626 *
627 * Side Effects: None
628 *
629 * Overview: Call back that is invoked when a USB suspend is detected
630 *
631 * Note: None
632 *****************************************************************************/
633 void USBCBSuspend(void)
634 {
635 //Example power saving code. Insert appropriate code here for the desired
636 //application behavior. If the microcontroller will be put to sleep, a
637 //process similar to that shown below may be used:
638  
639 //ConfigureIOPinsForLowPower();
640 //SaveStateOfAllInterruptEnableBits();
641 //DisableAllInterruptEnableBits();
642 //EnableOnlyTheInterruptsWhichWillBeUsedToWakeTheMicro(); //should enable at least USBActivityIF as a wake source
643 //Sleep();
644 //RestoreStateOfAllPreviouslySavedInterruptEnableBits(); //Preferrably, this should be done in the USBCBWakeFromSuspend() function instead.
645 //RestoreIOPinsToNormal(); //Preferrably, this should be done in the USBCBWakeFromSuspend() function instead.
646  
647 //IMPORTANT NOTE: Do not clear the USBActivityIF (ACTVIF) bit here. This bit is
648 //cleared inside the usb_device.c file. Clearing USBActivityIF here will cause
649 //things to not work as intended.
650  
651  
652 #if defined(__C30__)
653 #if 0
654 U1EIR = 0xFFFF;
655 U1IR = 0xFFFF;
656 U1OTGIR = 0xFFFF;
657 IFS5bits.USB1IF = 0;
658 IEC5bits.USB1IE = 1;
659 U1OTGIEbits.ACTVIE = 1;
660 U1OTGIRbits.ACTVIF = 1;
661 Sleep();
662 #endif
663 #endif
664 }
665  
666  
667 /******************************************************************************
668 * Function: void _USB1Interrupt(void)
669 *
670 * PreCondition: None
671 *
672 * Input: None
673 *
674 * Output: None
675 *
676 * Side Effects: None
677 *
678 * Overview: This function is called when the USB interrupt bit is set
679 * In this example the interrupt is only used when the device
680 * goes to sleep when it receives a USB suspend command
681 *
682 * Note: None
683 *****************************************************************************/
684 #if 0
685 void __attribute__ ((interrupt)) _USB1Interrupt(void)
686 {
687 #if !defined(self_powered)
688 if(U1OTGIRbits.ACTVIF)
689 {
690 IEC5bits.USB1IE = 0;
691 U1OTGIEbits.ACTVIE = 0;
692 IFS5bits.USB1IF = 0;
693  
694 //USBClearInterruptFlag(USBActivityIFReg,USBActivityIFBitNum);
695 USBClearInterruptFlag(USBIdleIFReg,USBIdleIFBitNum);
696 //USBSuspendControl = 0;
697 }
698 #endif
699 }
700 #endif
701  
702 /******************************************************************************
703 * Function: void USBCBWakeFromSuspend(void)
704 *
705 * PreCondition: None
706 *
707 * Input: None
708 *
709 * Output: None
710 *
711 * Side Effects: None
712 *
713 * Overview: The host may put USB peripheral devices in low power
714 * suspend mode (by "sending" 3+ms of idle). Once in suspend
715 * mode, the host may wake the device back up by sending non-
716 * idle state signalling.
717 *
718 * This call back is invoked when a wakeup from USB suspend
719 * is detected.
720 *
721 * Note: None
722 *****************************************************************************/
723 void USBCBWakeFromSuspend(void)
724 {
725 // If clock switching or other power savings measures were taken when
726 // executing the USBCBSuspend() function, now would be a good time to
727 // switch back to normal full power run mode conditions. The host allows
728 // a few milliseconds of wakeup time, after which the device must be
729 // fully back to normal, and capable of receiving and processing USB
730 // packets. In order to do this, the USB module must receive proper
731 // clocking (IE: 48MHz clock must be available to SIE for full speed USB
732 // operation).
733 }
734  
735 /********************************************************************
736 * Function: void USBCB_SOF_Handler(void)
737 *
738 * PreCondition: None
739 *
740 * Input: None
741 *
742 * Output: None
743 *
744 * Side Effects: None
745 *
746 * Overview: The USB host sends out a SOF packet to full-speed
747 * devices every 1 ms. This interrupt may be useful
748 * for isochronous pipes. End designers should
749 * implement callback routine as necessary.
750 *
751 * Note: None
752 *******************************************************************/
753 void USBCB_SOF_Handler(void)
754 {
755 // No need to clear UIRbits.SOFIF to 0 here.
756 // Callback caller is already doing that.
757 }
758  
759 /*******************************************************************
760 * Function: void USBCBErrorHandler(void)
761 *
762 * PreCondition: None
763 *
764 * Input: None
765 *
766 * Output: None
767 *
768 * Side Effects: None
769 *
770 * Overview: The purpose of this callback is mainly for
771 * debugging during development. Check UEIR to see
772 * which error causes the interrupt.
773 *
774 * Note: None
775 *******************************************************************/
776 void USBCBErrorHandler(void)
777 {
778 // No need to clear UEIR to 0 here.
779 // Callback caller is already doing that.
780  
781 // Typically, user firmware does not need to do anything special
782 // if a USB error occurs. For example, if the host sends an OUT
783 // packet to your device, but the packet gets corrupted (ex:
784 // because of a bad connection, or the user unplugs the
785 // USB cable during the transmission) this will typically set
786 // one or more USB error interrupt flags. Nothing specific
787 // needs to be done however, since the SIE will automatically
788 // send a "NAK" packet to the host. In response to this, the
789 // host will normally retry to send the packet again, and no
790 // data loss occurs. The system will typically recover
791 // automatically, without the need for application firmware
792 // intervention.
793  
794 // Nevertheless, this callback function is provided, such as
795 // for debugging purposes.
796 }
797  
798  
799 /*******************************************************************
800 * Function: void USBCBCheckOtherReq(void)
801 *
802 * PreCondition: None
803 *
804 * Input: None
805 *
806 * Output: None
807 *
808 * Side Effects: None
809 *
810 * Overview: When SETUP packets arrive from the host, some
811 * firmware must process the request and respond
812 * appropriately to fulfill the request. Some of
813 * the SETUP packets will be for standard
814 * USB "chapter 9" (as in, fulfilling chapter 9 of
815 * the official USB specifications) requests, while
816 * others may be specific to the USB device class
817 * that is being implemented. For example, a HID
818 * class device needs to be able to respond to
819 * "GET REPORT" type of requests. This
820 * is not a standard USB chapter 9 request, and
821 * therefore not handled by usb_device.c. Instead
822 * this request should be handled by class specific
823 * firmware, such as that contained in usb_function_hid.c.
824 *
825 * Note: None
826 *****************************************************************************/
827 void USBCBCheckOtherReq(void)
828 {
829 USBCheckUBWRequest();
830 }//end
831  
832  
833 /*******************************************************************
834 * Function: void USBCBStdSetDscHandler(void)
835 *
836 * PreCondition: None
837 *
838 * Input: None
839 *
840 * Output: None
841 *
842 * Side Effects: None
843 *
844 * Overview: The USBCBStdSetDscHandler() callback function is
845 * called when a SETUP, bRequest: SET_DESCRIPTOR request
846 * arrives. Typically SET_DESCRIPTOR requests are
847 * not used in most applications, and it is
848 * optional to support this type of request.
849 *
850 * Note: None
851 *****************************************************************************/
852 void USBCBStdSetDscHandler(void)
853 {
854 // Must claim session ownership if supporting this request
855 }//end
856  
857  
858 /******************************************************************************
859 * Function: void USBCBInitEP(void)
860 *
861 * PreCondition: None
862 *
863 * Input: None
864 *
865 * Output: None
866 *
867 * Side Effects: None
868 *
869 * Overview: This function is called when the device becomes
870 * initialized, which occurs after the host sends a
871 * SET_CONFIGURATION (wValue not = 0) request. This
872 * callback function should initialize the endpoints
873 * for the device's usage according to the current
874 * configuration.
875 *
876 * Note: None
877 *****************************************************************************/
878 void USBCBInitEP(void)
879 {
880 }
881  
882 /********************************************************************
883 * Function: void USBCBSendResume(void)
884 *
885 * PreCondition: None
886 *
887 * Input: None
888 *
889 * Output: None
890 *
891 * Side Effects: None
892 *
893 * Overview: The USB specifications allow some types of USB
894 * peripheral devices to wake up a host PC (such
895 * as if it is in a low power suspend to RAM state).
896 * This can be a very useful feature in some
897 * USB applications, such as an Infrared remote
898 * control receiver. If a user presses the "power"
899 * button on a remote control, it is nice that the
900 * IR receiver can detect this signalling, and then
901 * send a USB "command" to the PC to wake up.
902 *
903 * The USBCBSendResume() "callback" function is used
904 * to send this special USB signalling which wakes
905 * up the PC. This function may be called by
906 * application firmware to wake up the PC. This
907 * function should only be called when:
908 *
909 * 1. The USB driver used on the host PC supports
910 * the remote wakeup capability.
911 * 2. The USB configuration descriptor indicates
912 * the device is remote wakeup capable in the
913 * bmAttributes field.
914 * 3. The USB host PC is currently sleeping,
915 * and has previously sent your device a SET
916 * FEATURE setup packet which "armed" the
917 * remote wakeup capability.
918 *
919 * This callback should send a RESUME signal that
920 * has the period of 1-15ms.
921 *
922 * Note: Interrupt vs. Polling
923 * -Primary clock
924 * -Secondary clock ***** MAKE NOTES ABOUT THIS *******
925 * > Can switch to primary first by calling USBCBWakeFromSuspend()
926  
927 * The modifiable section in this routine should be changed
928 * to meet the application needs. Current implementation
929 * temporary blocks other functions from executing for a
930 * period of 1-13 ms depending on the core frequency.
931 *
932 * According to USB 2.0 specification section 7.1.7.7,
933 * "The remote wakeup device must hold the resume signaling
934 * for at lest 1 ms but for no more than 15 ms."
935 * The idea here is to use a delay counter loop, using a
936 * common value that would work over a wide range of core
937 * frequencies.
938 * That value selected is 1800. See table below:
939 * ==========================================================
940 * Core Freq(MHz) MIP RESUME Signal Period (ms)
941 * ==========================================================
942 * 48 12 1.05
943 * 4 1 12.6
944 * ==========================================================
945 * * These timing could be incorrect when using code
946 * optimization or extended instruction mode,
947 * or when having other interrupts enabled.
948 * Make sure to verify using the MPLAB SIM's Stopwatch
949 * and verify the actual signal on an oscilloscope.
950 *******************************************************************/
951 void USBCBSendResume(void)
952 {
953 static WORD delay_count;
954  
955 USBResumeControl = 1; // Start RESUME signaling
956  
957 delay_count = 1800U; // Set RESUME line for 1-13 ms
958 do
959 {
960 delay_count--;
961 }while(delay_count);
962 USBResumeControl = 0;
963 }
964  
965  
966 /*******************************************************************
967 * Function: BOOL USER_USB_CALLBACK_EVENT_HANDLER(
968 * USB_EVENT event, void *pdata, WORD size)
969 *
970 * PreCondition: None
971 *
972 * Input: USB_EVENT event - the type of event
973 * void *pdata - pointer to the event data
974 * WORD size - size of the event data
975 *
976 * Output: None
977 *
978 * Side Effects: None
979 *
980 * Overview: This function is called from the USB stack to
981 * notify a user application that a USB event
982 * occured. This callback is in interrupt context
983 * when the USB_INTERRUPT option is selected.
984 *
985 * Note: None
986 *******************************************************************/
987 BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size)
988 {
989 switch(event)
990 {
991 case EVENT_CONFIGURED:
992 USBCBInitEP();
993 break;
994 case EVENT_SET_DESCRIPTOR:
995 USBCBStdSetDscHandler();
996 break;
997 case EVENT_EP0_REQUEST:
998 USBCBCheckOtherReq();
999 break;
1000 case EVENT_SOF:
1001 USBCB_SOF_Handler();
1002 break;
1003 case EVENT_SUSPEND:
1004 USBCBSuspend();
1005 break;
1006 case EVENT_RESUME:
1007 USBCBWakeFromSuspend();
1008 break;
1009 case EVENT_BUS_ERROR:
1010 USBCBErrorHandler();
1011 break;
1012 case EVENT_TRANSFER:
1013 Nop();
1014 break;
1015 default:
1016 break;
1017 }
1018 return TRUE;
1019 }
1020 /** EOF main.c ***************************************************************/