1 //###########################################################################
2 //
3 // FILE:   F2837xD_SysCtrl.c
4 //
5 // TITLE:  F2837xD Device System Control Initialization & Support Functions.
6 //
7 // DESCRIPTION:
8 //
9 //         Example initialization of system resources.
10 //
11 //###########################################################################
12 // $TI Release: F2837xD Support Library v3.05.00.00 $
13 // $Release Date: Tue Jun 26 03:15:23 CDT 2018 $
14 // $Copyright:
15 // Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/
16 //
17 // Redistribution and use in source and binary forms, with or without
18 // modification, are permitted provided that the following conditions
19 // are met:
20 //
21 //   Redistributions of source code must retain the above copyright
22 //   notice, this list of conditions and the following disclaimer.
23 //
24 //   Redistributions in binary form must reproduce the above copyright
25 //   notice, this list of conditions and the following disclaimer in the
26 //   documentation and/or other materials provided with the
27 //   distribution.
28 //
29 //   Neither the name of Texas Instruments Incorporated nor the names of
30 //   its contributors may be used to endorse or promote products derived
31 //   from this software without specific prior written permission.
32 //
33 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
34 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
35 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
36 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
40 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
41 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
43 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 // $
45 //###########################################################################
46 
47 //
48 // Included Files
49 //
50 #include "F2837xD_device.h"
51 #include "F2837xD_Examples.h"
52 #ifdef __cplusplus
53 using std::memcpy;
54 #endif
55 
56 #define STATUS_FAIL          0
57 #define STATUS_SUCCESS       1
58 #define TMR1SYSCLKCTR        0xF0000000
59 #define TMR2INPCLKCTR        0x800
60 
61 //
62 // Functions that will be run from RAM need to be assigned to a different
63 // section.  This section will then be mapped to a load and run address using
64 // the linker cmd file.
65 //
66 //      *IMPORTANT*
67 //
68 //  IF RUNNING FROM FLASH, PLEASE COPY OVER THE SECTION ".TI.ramfunc" FROM
69 //  FLASH TO RAM PRIOR TO CALLING InitSysCtrl(). THIS PREVENTS THE MCU FROM
70 //  THROWING AN EXCEPTION WHEN A CALL TO DELAY_US() IS MADE.
71 //
72 #ifndef __cplusplus
73     #ifdef __TI_COMPILER_VERSION__
74         #if __TI_COMPILER_VERSION__ >= 15009000
75             #pragma CODE_SECTION(InitFlash, ".TI.ramfunc");
76             #pragma CODE_SECTION(FlashOff, ".TI.ramfunc");
77         #else
78             #pragma CODE_SECTION(InitFlash, "ramfuncs");
79             #pragma CODE_SECTION(FlashOff, "ramfuncs");
80         #endif
81     #endif
82 #endif
83 
84 //
85 // InitSysCtrl - Initialization of system resources.
86 //
InitSysCtrl(void)87 void InitSysCtrl(void)
88 {
89     //
90     // Disable the watchdog
91     //
92     DisableDog();
93 
94 #ifdef _FLASH
95     //
96     // Copy time critical code and Flash setup code to RAM. This includes the
97     // following functions: InitFlash()
98     //
99     // The  RamfuncsLoadStart, RamfuncsLoadSize, and RamfuncsRunStart
100     // symbols are created by the linker. Refer to the device .cmd file.
101     //
102     memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
103 
104     //
105     // Call Flash Initialization to setup flash waitstates. This function must
106     // reside in RAM.
107     //
108     InitFlash();
109 #endif
110 
111     //
112     //      *IMPORTANT*
113     //
114     // The Device_cal function, which copies the ADC & oscillator calibration
115     // values from TI reserved OTP into the appropriate trim registers, occurs
116     // automatically in the Boot ROM. If the boot ROM code is bypassed during
117     // the debug process, the following function MUST be called for the ADC and
118     // oscillators to function according to specification. The clocks to the
119     // ADC MUST be enabled before calling this function.
120     //
121     // See the device data manual and/or the ADC Reference Manual for more
122     // information.
123     //
124 #ifdef CPU1
125     EALLOW;
126 
127     //
128     // Enable pull-ups on unbonded IOs as soon as possible to reduce power
129     // consumption.
130     //
131     GPIO_EnableUnbondedIOPullups();
132 
133     CpuSysRegs.PCLKCR13.bit.ADC_A = 1;
134     CpuSysRegs.PCLKCR13.bit.ADC_B = 1;
135     CpuSysRegs.PCLKCR13.bit.ADC_C = 1;
136     CpuSysRegs.PCLKCR13.bit.ADC_D = 1;
137 
138     //
139     // Check if device is trimmed
140     //
141     if(*((Uint16 *)0x5D1B6) == 0x0000){
142         //
143         // Device is not trimmed--apply static calibration values
144         //
145         AnalogSubsysRegs.ANAREFTRIMA.all = 31709;
146         AnalogSubsysRegs.ANAREFTRIMB.all = 31709;
147         AnalogSubsysRegs.ANAREFTRIMC.all = 31709;
148         AnalogSubsysRegs.ANAREFTRIMD.all = 31709;
149     }
150 
151     CpuSysRegs.PCLKCR13.bit.ADC_A = 0;
152     CpuSysRegs.PCLKCR13.bit.ADC_B = 0;
153     CpuSysRegs.PCLKCR13.bit.ADC_C = 0;
154     CpuSysRegs.PCLKCR13.bit.ADC_D = 0;
155     EDIS;
156 
157     //
158     // Initialize the PLL control: SYSPLLMULT and SYSCLKDIVSEL.
159     //
160     // Defined options to be passed as arguments to this function are defined
161     // in F2837xD_Examples.h.
162     //
163     // Note: The internal oscillator CANNOT be used as the PLL source if the
164     // PLLSYSCLK is configured to frequencies above 194 MHz.
165     //
166     //  PLLSYSCLK = (XTAL_OSC) * (IMULT + FMULT) / (PLLSYSCLKDIV)
167     //
168 #ifdef _LAUNCHXL_F28379D
169     InitSysPll(XTAL_OSC,IMULT_40,FMULT_0,PLLCLK_BY_2);
170 #else
171     InitSysPll(XTAL_OSC, IMULT_20, FMULT_0, PLLCLK_BY_2);
172 #endif // _LAUNCHXL_F28379D
173 
174 #endif // CPU1
175 
176     //
177     // Turn on all peripherals
178     //
179     InitPeripheralClocks();
180 }
181 
182 //
183 // InitPeripheralClocks - Initializes the clocks for the peripherals.
184 //
185 // Note: In order to reduce power consumption, turn off the clocks to any
186 // peripheral that is not specified for your part-number or is not used in the
187 // application
188 //
InitPeripheralClocks(void)189 void InitPeripheralClocks(void)
190 {
191     EALLOW;
192 
193     CpuSysRegs.PCLKCR0.bit.CLA1 = 1;
194     CpuSysRegs.PCLKCR0.bit.DMA = 1;
195     CpuSysRegs.PCLKCR0.bit.CPUTIMER0 = 1;
196     CpuSysRegs.PCLKCR0.bit.CPUTIMER1 = 1;
197     CpuSysRegs.PCLKCR0.bit.CPUTIMER2 = 1;
198 
199 #ifdef CPU1
200     CpuSysRegs.PCLKCR0.bit.HRPWM = 1;
201 #endif
202 
203     CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
204 
205 #ifdef CPU1
206     CpuSysRegs.PCLKCR1.bit.EMIF1 = 1;
207     CpuSysRegs.PCLKCR1.bit.EMIF2 = 1;
208 #endif
209 
210     CpuSysRegs.PCLKCR2.bit.EPWM1 = 1;
211     CpuSysRegs.PCLKCR2.bit.EPWM2 = 1;
212     CpuSysRegs.PCLKCR2.bit.EPWM3 = 1;
213     CpuSysRegs.PCLKCR2.bit.EPWM4 = 1;
214     CpuSysRegs.PCLKCR2.bit.EPWM5 = 1;
215     CpuSysRegs.PCLKCR2.bit.EPWM6 = 1;
216     CpuSysRegs.PCLKCR2.bit.EPWM7 = 1;
217     CpuSysRegs.PCLKCR2.bit.EPWM8 = 1;
218     CpuSysRegs.PCLKCR2.bit.EPWM9 = 1;
219     CpuSysRegs.PCLKCR2.bit.EPWM10 = 1;
220     CpuSysRegs.PCLKCR2.bit.EPWM11 = 1;
221     CpuSysRegs.PCLKCR2.bit.EPWM12 = 1;
222 
223     CpuSysRegs.PCLKCR3.bit.ECAP1 = 1;
224     CpuSysRegs.PCLKCR3.bit.ECAP2 = 1;
225     CpuSysRegs.PCLKCR3.bit.ECAP3 = 1;
226     CpuSysRegs.PCLKCR3.bit.ECAP4 = 1;
227     CpuSysRegs.PCLKCR3.bit.ECAP5 = 1;
228     CpuSysRegs.PCLKCR3.bit.ECAP6 = 1;
229 
230     CpuSysRegs.PCLKCR4.bit.EQEP1 = 1;
231     CpuSysRegs.PCLKCR4.bit.EQEP2 = 1;
232     CpuSysRegs.PCLKCR4.bit.EQEP3 = 1;
233 
234     CpuSysRegs.PCLKCR6.bit.SD1 = 1;
235     CpuSysRegs.PCLKCR6.bit.SD2 = 1;
236 
237     CpuSysRegs.PCLKCR7.bit.SCI_A = 1;
238     CpuSysRegs.PCLKCR7.bit.SCI_B = 1;
239     CpuSysRegs.PCLKCR7.bit.SCI_C = 1;
240     CpuSysRegs.PCLKCR7.bit.SCI_D = 1;
241 
242     CpuSysRegs.PCLKCR8.bit.SPI_A = 1;
243     CpuSysRegs.PCLKCR8.bit.SPI_B = 1;
244     CpuSysRegs.PCLKCR8.bit.SPI_C = 1;
245 
246     CpuSysRegs.PCLKCR9.bit.I2C_A = 1;
247     CpuSysRegs.PCLKCR9.bit.I2C_B = 1;
248 
249     CpuSysRegs.PCLKCR10.bit.CAN_A = 1;
250     CpuSysRegs.PCLKCR10.bit.CAN_B = 1;
251 
252     CpuSysRegs.PCLKCR11.bit.McBSP_A = 1;
253     CpuSysRegs.PCLKCR11.bit.McBSP_B = 1;
254 
255 #ifdef CPU1
256     CpuSysRegs.PCLKCR11.bit.USB_A = 1;
257 
258     CpuSysRegs.PCLKCR12.bit.uPP_A = 1;
259 #endif
260 
261     CpuSysRegs.PCLKCR13.bit.ADC_A = 1;
262     CpuSysRegs.PCLKCR13.bit.ADC_B = 1;
263     CpuSysRegs.PCLKCR13.bit.ADC_C = 1;
264     CpuSysRegs.PCLKCR13.bit.ADC_D = 1;
265 
266     CpuSysRegs.PCLKCR14.bit.CMPSS1 = 1;
267     CpuSysRegs.PCLKCR14.bit.CMPSS2 = 1;
268     CpuSysRegs.PCLKCR14.bit.CMPSS3 = 1;
269     CpuSysRegs.PCLKCR14.bit.CMPSS4 = 1;
270     CpuSysRegs.PCLKCR14.bit.CMPSS5 = 1;
271     CpuSysRegs.PCLKCR14.bit.CMPSS6 = 1;
272     CpuSysRegs.PCLKCR14.bit.CMPSS7 = 1;
273     CpuSysRegs.PCLKCR14.bit.CMPSS8 = 1;
274 
275     CpuSysRegs.PCLKCR16.bit.DAC_A = 1;
276     CpuSysRegs.PCLKCR16.bit.DAC_B = 1;
277     CpuSysRegs.PCLKCR16.bit.DAC_C = 1;
278 
279     EDIS;
280 }
281 
282 //
283 // DisablePeripheralClocks - Gates-off all peripheral clocks.
284 //
DisablePeripheralClocks(void)285 void DisablePeripheralClocks(void)
286 {
287     EALLOW;
288 
289     CpuSysRegs.PCLKCR0.all = 0;
290     CpuSysRegs.PCLKCR1.all = 0;
291     CpuSysRegs.PCLKCR2.all = 0;
292     CpuSysRegs.PCLKCR3.all = 0;
293     CpuSysRegs.PCLKCR4.all = 0;
294     CpuSysRegs.PCLKCR6.all = 0;
295     CpuSysRegs.PCLKCR7.all = 0;
296     CpuSysRegs.PCLKCR8.all = 0;
297     CpuSysRegs.PCLKCR9.all = 0;
298     CpuSysRegs.PCLKCR10.all = 0;
299     CpuSysRegs.PCLKCR11.all = 0;
300     CpuSysRegs.PCLKCR12.all = 0;
301     CpuSysRegs.PCLKCR13.all = 0;
302     CpuSysRegs.PCLKCR14.all = 0;
303     CpuSysRegs.PCLKCR16.all = 0;
304 
305     EDIS;
306 }
307 
308 //
309 // InitFlash - This function initializes the Flash Control registers.
310 //
311 //      *CAUTION*
312 // This function MUST be executed out of RAM. Executing it out of OTP/Flash
313 // will yield unpredictable results.
314 //
315 #ifdef __cplusplus
316     #ifdef __TI_COMPILER_VERSION__
317         #if __TI_COMPILER_VERSION__ >= 15009000
318             #pragma CODE_SECTION(".TI.ramfunc");
319         #else
320             #pragma CODE_SECTION("ramfuncs");
321         #endif
322     #endif
323 #endif
InitFlash(void)324 void InitFlash(void)
325 {
326     EALLOW;
327 
328     //
329     // The default value of VREADST is good enough for the flash to power up
330     // properly at the INTOSC frequency. Below VREADST configuration covers up
331     // to the max frequency possible for this device. This is required for
332     // proper flash wake up at the higher frequencies if users put it to sleep
333     // for power saving reason.
334     //
335     Flash0CtrlRegs.FBAC.bit.VREADST = 0x14;
336 
337     //
338     // At reset bank and pump are in sleep. A Flash access will power up the
339     // bank and pump automatically.
340     //
341     // After a Flash access, bank and pump go to low power mode (configurable
342     // in FBFALLBACK/FPAC1 registers) if there is no further access to flash.
343     //
344     // Power up Flash bank and pump. This also sets the fall back mode of
345     // flash and pump as active.
346     //
347     Flash0CtrlRegs.FPAC1.bit.PMPPWR = 0x1;
348     Flash0CtrlRegs.FBFALLBACK.bit.BNKPWR0 = 0x3;
349 
350     //
351     // Disable Cache and prefetch mechanism before changing wait states
352     //
353     Flash0CtrlRegs.FRD_INTF_CTRL.bit.DATA_CACHE_EN = 0;
354     Flash0CtrlRegs.FRD_INTF_CTRL.bit.PREFETCH_EN = 0;
355 
356     //
357     // Set waitstates according to frequency
358     //
359     //      *CAUTION*
360     // Minimum waitstates required for the flash operating at a given CPU rate
361     // must be characterized by TI. Refer to the datasheet for the latest
362     // information.
363     //
364     #if CPU_FRQ_200MHZ
365     Flash0CtrlRegs.FRDCNTL.bit.RWAIT = 0x3;
366     #endif
367 
368     #if CPU_FRQ_150MHZ
369     Flash0CtrlRegs.FRDCNTL.bit.RWAIT = 0x2;
370     #endif
371 
372     #if CPU_FRQ_120MHZ
373     Flash0CtrlRegs.FRDCNTL.bit.RWAIT = 0x2;
374     #endif
375 
376     //
377     // Enable Cache and prefetch mechanism to improve performance of code
378     // executed from Flash.
379     //
380     Flash0CtrlRegs.FRD_INTF_CTRL.bit.DATA_CACHE_EN = 1;
381     Flash0CtrlRegs.FRD_INTF_CTRL.bit.PREFETCH_EN = 1;
382 
383     //
384     // At reset, ECC is enabled. If it is disabled by application software and
385     // if application again wants to enable ECC.
386     //
387     Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0xA;
388 
389     EDIS;
390 
391     //
392     // Force a pipeline flush to ensure that the write to the last register
393     // configured occurs before returning.
394     //
395     __asm(" RPT #7 || NOP");
396 }
397 
398 //
399 // FlashOff - This function powers down the flash
400 //
401 //      *CAUTION*
402 // This function MUST be executed out of RAM. Executing it out of OTP/Flash
403 // will yield unpredictable results. Also you must seize the flash pump in
404 // order to power it down.
405 //
406 #ifdef __cplusplus
407     #ifdef __TI_COMPILER_VERSION__
408         #if __TI_COMPILER_VERSION__ >= 15009000
409             #pragma CODE_SECTION(".TI.ramfunc");
410         #else
411             #pragma CODE_SECTION("ramfuncs");
412         #endif
413     #endif
414 #endif
FlashOff(void)415 void FlashOff(void)
416 {
417     EALLOW;
418 
419     //
420     // Set VREADST to the proper value for the flash banks to power up properly
421     //
422     Flash0CtrlRegs.FBAC.bit.VREADST = 0x14;
423 
424     //
425     // Power down bank
426     //
427     Flash0CtrlRegs.FBFALLBACK.bit.BNKPWR0 = 0;
428 
429     //
430     // Power down pump
431     //
432     Flash0CtrlRegs.FPAC1.bit.PMPPWR = 0;
433 
434     EDIS;
435 }
436 
437 //
438 // SeizeFlashPump - Wait until the flash pump is available. Then take control
439 //                  of it using the flash pump Semaphore.
440 //
SeizeFlashPump(void)441 void SeizeFlashPump(void)
442 {
443     EALLOW;
444     #ifdef CPU1
445         while (FlashPumpSemaphoreRegs.PUMPREQUEST.bit.PUMP_OWNERSHIP != 0x2)
446         {
447             FlashPumpSemaphoreRegs.PUMPREQUEST.all = IPC_PUMP_KEY | 0x2;
448         }
449     #elif defined(CPU2)
450         while (FlashPumpSemaphoreRegs.PUMPREQUEST.bit.PUMP_OWNERSHIP != 0x1)
451         {
452             FlashPumpSemaphoreRegs.PUMPREQUEST.all = IPC_PUMP_KEY | 0x1;
453         }
454     #endif
455     EDIS;
456 }
457 
458 //
459 // ReleaseFlashPump - Release control of the flash pump using the flash pump
460 //                    semaphore.
461 //
ReleaseFlashPump(void)462 void ReleaseFlashPump(void)
463 {
464     EALLOW;
465     FlashPumpSemaphoreRegs.PUMPREQUEST.all = IPC_PUMP_KEY | 0x0;
466     EDIS;
467 }
468 
469 //
470 // ServiceDog - This function resets the watchdog timer.
471 //
472 // Enable this function for using ServiceDog in the application.
473 //
ServiceDog(void)474 void ServiceDog(void)
475 {
476     EALLOW;
477     WdRegs.WDKEY.bit.WDKEY = 0x0055;
478     WdRegs.WDKEY.bit.WDKEY = 0x00AA;
479     EDIS;
480 }
481 
482 //
483 // DisableDog - This function disables the watchdog timer.
484 //
DisableDog(void)485 void DisableDog(void)
486 {
487     volatile Uint16 temp;
488 
489     //
490     // Grab the clock config first so we don't clobber it
491     //
492     EALLOW;
493     temp = WdRegs.WDCR.all & 0x0007;
494     WdRegs.WDCR.all = 0x0068 | temp;
495     EDIS;
496 }
497 
498 #ifdef CPU1
499 //
500 // InitSysPll()
501 // This function initializes the PLL registers.
502 // Note:
503 //  - The internal oscillator CANNOT be used as the PLL source if the
504 //    PLLSYSCLK is configured to frequencies above 194 MHz.
505 //
506 //  - This function uses the Watchdog as a monitor for the PLL. The user
507 //  watchdog settings will be modified and restored upon completion.  Function
508 //  allows for a minimum re lock attempt for 5 tries.  Re lock attempt is carried
509 //  out if either SLIP condition occurs or SYSCLK to Input Clock ratio is off by 10%
510 //
511 //  - This function uses the following resources to support PLL initialization:
512 //          o Watchdog
513 //          o CPU Timer 1
514 //          o CPU Timer 2
515 //
InitSysPll(Uint16 clock_source,Uint16 imult,Uint16 fmult,Uint16 divsel)516 void InitSysPll(Uint16 clock_source, Uint16 imult, Uint16 fmult, Uint16 divsel)
517 {
518     Uint16 SCSR, WDCR, WDWCR, intStatus,  t1TCR, t1TPR, t1TPRH;
519     Uint16 t2TCR, t2TPR, t2TPRH, t2SRC, t2Prescale;
520     Uint32 t1PRD, t2PRD, ctr1;
521     float sysclkToInClkError, mult, div;
522     bool sysclkInvalidFreq=true;
523 
524     if((clock_source == ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL)    &&
525        (imult        == ClkCfgRegs.SYSPLLMULT.bit.IMULT)           &&
526        (fmult        == ClkCfgRegs.SYSPLLMULT.bit.FMULT)           &&
527        (divsel       == ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV))
528     {
529         //
530         // Everything is set as required, so just return
531         //
532         return;
533     }
534 
535     if(clock_source != ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL)
536     {
537         switch (clock_source)
538         {
539             case INT_OSC1:
540                 SysIntOsc1Sel();
541                 break;
542 
543             case INT_OSC2:
544                 SysIntOsc2Sel();
545                 break;
546 
547             case XTAL_OSC:
548                 SysXtalOscSel();
549                 break;
550         }
551     }
552 
553     EALLOW;
554     if(imult != ClkCfgRegs.SYSPLLMULT.bit.IMULT ||
555        fmult != ClkCfgRegs.SYSPLLMULT.bit.FMULT)
556     {
557         Uint16 i;
558 
559         //
560         // This bit is reset only by POR
561         //
562         if(DevCfgRegs.SYSDBGCTL.bit.BIT_0 == 1)
563         {
564             //
565             // The user can optionally insert handler code here. This will only
566             // be executed if a watchdog reset occurred after a failed system
567             // PLL initialization. See your device user's guide for more
568             // information.
569             //
570             // If the application has a watchdog reset handler, this bit should
571             // be checked to determine if the watchdog reset occurred because
572             // of the PLL.
573             //
574             // No action here will continue with retrying the PLL as normal.
575             //
576             // Failed PLL initialization is due to any of the following:
577             //      - No PLL clock
578             //      - SLIP condition
579             //      - Wrong Frequency
580             //
581         }
582 
583         //
584         // Bypass PLL and set dividers to /1
585         //
586         ClkCfgRegs.SYSPLLCTL1.bit.PLLCLKEN = 0;
587         asm(" RPT #20 || NOP");
588         ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV = 0;
589 
590         //
591         // Lock the PLL five times. This helps ensure a successful start.
592         // Five is the minimum recommended number. The user can increase this
593         // number according to allotted system initialization time.
594         //
595         for(i = 0; i < 5; i++)
596         {
597             //
598             // Turn off PLL
599             //
600             ClkCfgRegs.SYSPLLCTL1.bit.PLLEN = 0;
601             asm(" RPT #20 || NOP");
602 
603             //
604             // Write multiplier, which automatically turns on the PLL
605             //
606             ClkCfgRegs.SYSPLLMULT.all = ((fmult << 8U) | imult);
607 
608             //
609             // Wait for the SYSPLL lock counter
610             //
611             while(ClkCfgRegs.SYSPLLSTS.bit.LOCKS != 1)
612             {
613                 //
614                 // Uncomment to service the watchdog
615                 //
616                 // ServiceDog();
617             }
618         }
619     }
620 
621     //
622     // Set divider to produce slower output frequency to limit current increase
623     //
624     if(divsel != PLLCLK_BY_126)
625     {
626          ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV = divsel + 1;
627     }
628     else
629     {
630          ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV = divsel;
631     }
632 
633     //
634     //      *CAUTION*
635     // It is recommended to use the following watchdog code to monitor the PLL
636     // startup sequence. If your application has already cleared the watchdog
637     // SCRS[WDOVERRIDE] bit this cannot be done. It is recommended not to clear
638     // this bit until after the PLL has been initiated.
639     //
640 
641     //
642     // Backup User Watchdog
643     //
644     SCSR = WdRegs.SCSR.all;
645     WDCR = WdRegs.WDCR.all;
646     WDWCR = WdRegs.WDWCR.all;
647 
648     //
649     // Disable windowed functionality, reset counter
650     //
651     EALLOW;
652     WdRegs.WDWCR.all = 0x0;
653     WdRegs.WDKEY.bit.WDKEY = 0x55;
654     WdRegs.WDKEY.bit.WDKEY = 0xAA;
655 
656     //
657     // Disable global interrupts
658     //
659     intStatus = __disable_interrupts();
660 
661     //
662     // Configure for watchdog reset and to run at max frequency
663     //
664     WdRegs.SCSR.all = 0x0;
665     WdRegs.WDCR.all = 0x28;
666 
667     //
668     // This bit is reset only by power-on-reset (POR) and will not be cleared
669     // by a WD reset
670     //
671     DevCfgRegs.SYSDBGCTL.bit.BIT_0 = 1;
672 
673     //
674     // Enable PLLSYSCLK is fed from system PLL clock
675     //
676     ClkCfgRegs.SYSPLLCTL1.bit.PLLCLKEN = 1;
677 
678     //
679     // Delay to ensure system is clocking from PLL prior to clearing status bit
680     //
681     asm(" RPT #20 || NOP");
682 
683     //
684     // Service watchdog
685     //
686     ServiceDog();
687 
688     //
689     // Slip Bit Monitor and SYSCLK Frequency Check using timers
690     // Re-lock routine for SLIP condition or if SYSCLK and CLKSRC timer counts
691     // are off by +/- 10%.
692     // At a minimum, SYSCLK check is performed.  Re lock attempt is carried out
693     // if SLIPS bit is set. This while loop is monitored by watchdog.
694     // In the event that the PLL does not successfully lock, the loop will be
695     // aborted by watchdog reset.
696     //
697     EALLOW;
698     while(sysclkInvalidFreq == true)
699     {
700         if(ClkCfgRegs.SYSPLLSTS.bit.SLIPS == 1)
701         {
702             //
703             // Bypass PLL
704             //
705             ClkCfgRegs.SYSPLLCTL1.bit.PLLCLKEN = 0;
706             asm(" RPT #20 || NOP");
707 
708             //
709             // Turn off PLL
710             //
711             ClkCfgRegs.SYSPLLCTL1.bit.PLLEN = 0;
712             asm(" RPT #20 || NOP");
713 
714             //
715             // Write multipliers, which automatically turns on the PLL
716             //
717             ClkCfgRegs.SYSPLLMULT.all = ((fmult << 8U) | imult);
718 
719             //
720             // Wait for the SYSPLL lock counter to expire
721             //
722             while(ClkCfgRegs.SYSPLLSTS.bit.LOCKS != 1);
723 
724             //
725             // Enable PLLSYSCLK is fed from system PLL clock
726             //
727             ClkCfgRegs.SYSPLLCTL1.bit.PLLCLKEN = 1;
728 
729             //
730             // Delay to ensure system is clocking from PLL
731             //
732             asm(" RPT #20 || NOP");
733         }
734 
735         //
736         // Backup timer1 and timer2 settings
737         //
738         t1TCR = CpuTimer1Regs.TCR.all;
739         t1PRD = CpuTimer1Regs.PRD.all;
740         t1TPR = CpuTimer1Regs.TPR.all;
741         t1TPRH = CpuTimer1Regs.TPRH.all;
742         t2SRC = CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKSRCSEL;
743         t2Prescale = CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKPRESCALE;
744         t2TCR = CpuTimer2Regs.TCR.all;
745         t2PRD = CpuTimer2Regs.PRD.all;
746         t2TPR = CpuTimer2Regs.TPR.all;
747         t2TPRH = CpuTimer2Regs.TPRH.all;
748 
749         //
750         // Set up timers 1 and 2
751         // Configure timer1 to count SYSCLK cycles
752         //
753         CpuTimer1Regs.TCR.bit.TSS = 1;                                    // stop timer1
754         CpuTimer1Regs.PRD.all = TMR1SYSCLKCTR;                            // seed timer1 counter
755         CpuTimer1Regs.TPR.bit.TDDR = 0x0;                                 // sysclock divider
756         CpuTimer1Regs.TCR.bit.TRB = 1;                                    // reload timer with value in PRD
757         CpuTimer1Regs.TCR.bit.TIF = 1;                                    // clear interrupt flag
758         CpuTimer1Regs.TCR.bit.TIE = 1;                                    // enable interrupt
759 
760         //
761         // Configure timer2 to count Input clock cycles
762         //
763         switch(clock_source)
764         {
765             case INT_OSC1:
766                 // Clk Src = INT_OSC1
767                 CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKSRCSEL = 0x1;
768                 break;
769             case INT_OSC2:
770                 // Clk Src = INT_OSC2
771                 CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKSRCSEL = 0x2;
772                 break;
773             case XTAL_OSC:
774                 // Clk Src = XTAL
775                 CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKSRCSEL = 0x3;
776                 break;
777 
778         }
779         CpuTimer2Regs.TCR.bit.TIF = 1;                                    // clear interrupt flag
780         CpuTimer2Regs.TCR.bit.TIE = 1;                                    // enable interrupt
781         CpuTimer2Regs.TCR.bit.TSS = 1;                                    // stop timer2
782         CpuTimer2Regs.PRD.all = TMR2INPCLKCTR;                            // seed timer2 counter
783         CpuTimer2Regs.TPR.bit.TDDR = 0x0;                                 // sysclock divider
784         CpuTimer2Regs.TCR.bit.TRB = 1;                                    // reload timer with value in PRD
785 
786         //
787         // Stop/Start timer counters
788         //
789         CpuTimer1Regs.TCR.bit.TSS = 1;                                    // stop timer1
790         CpuTimer2Regs.TCR.bit.TSS = 1;                                    // stop timer2
791         CpuTimer1Regs.TCR.bit.TRB = 1;                                    // reload timer1 with value in PRD
792         CpuTimer2Regs.TCR.bit.TRB = 1;                                    // reload timer2 with value in PRD
793         CpuTimer2Regs.TCR.bit.TIF = 1;                                    // clear timer2 interrupt flag
794         CpuTimer2Regs.TCR.bit.TSS = 0;                                    // start timer2
795         CpuTimer1Regs.TCR.bit.TSS = 0;                                    // start timer1
796 
797         //
798         // Stop timers if either timer1 or timer2 counters overflow
799         //
800         while((CpuTimer2Regs.TCR.bit.TIF == 0) && (CpuTimer1Regs.TCR.bit.TIF == 0));
801 
802         CpuTimer1Regs.TCR.bit.TSS = 1;                                    // stop timer1
803         CpuTimer2Regs.TCR.bit.TSS = 1;                                    // stop timer2
804 
805         //
806         // Calculate elapsed counts on timer1
807         //
808         ctr1 = TMR1SYSCLKCTR - CpuTimer1Regs.TIM.all;
809 
810         //
811         // Restore timer settings
812         //
813         CpuTimer1Regs.TCR.all = t1TCR;
814         CpuTimer1Regs.PRD.all = t1PRD;
815         CpuTimer1Regs.TPR.all = t1TPR;
816         CpuTimer1Regs.TPRH.all = t1TPRH;
817         CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKSRCSEL = t2SRC;
818         CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKPRESCALE = t2Prescale;
819         CpuTimer2Regs.TCR.all = t2TCR;
820         CpuTimer2Regs.PRD.all = t2PRD;
821         CpuTimer2Regs.TPR.all = t2TPR;
822         CpuTimer2Regs.TPRH.all = t2TPRH;
823 
824         //
825         // Calculate Clock Error:
826         // Error = (mult/div) - (timer1 count/timer2 count)
827         //
828         mult = (float)(imult) + (float)(fmult)/4;
829         div = (float)((!ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV) ? 1 : (ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV << 1));
830 
831         sysclkToInClkError = (mult/div) - ((float)ctr1/(float)TMR2INPCLKCTR);
832 
833         //
834         // sysclkInvalidFreq will be set to true if sysclkToInClkError is off by 10%
835         //
836         sysclkInvalidFreq = ((sysclkToInClkError > 0.10) || (sysclkToInClkError < -0.10));
837     }
838 
839     //
840     // Clear bit
841     //
842     DevCfgRegs.SYSDBGCTL.bit.BIT_0 = 0;
843 
844     //
845     // Restore user watchdog, first resetting counter
846     //
847     WdRegs.WDKEY.bit.WDKEY = 0x55;
848     WdRegs.WDKEY.bit.WDKEY = 0xAA;
849 
850     WDCR |= 0x28;                     // Setup WD key--KEY bits always read 0
851     WdRegs.WDCR.all = WDCR;
852     WdRegs.WDWCR.all = WDWCR;
853     WdRegs.SCSR.all = SCSR & 0xFFFE;  // Mask write to bit 0 (W1toClr)
854 
855     //
856     // Restore state of ST1[INTM]. This was set by the __disable_interrupts()
857     // intrinsic previously.
858     //
859     if(!(intStatus & 0x1))
860     {
861         EINT;
862     }
863 
864     //
865     // Restore state of ST1[DBGM]. This was set by the __disable_interrupts()
866     // intrinsic previously.
867     //
868     if(!(intStatus & 0x2))
869     {
870         asm(" CLRC DBGM");
871     }
872 
873     //
874     // 200 PLLSYSCLK delay to allow voltage regulator to stabilize prior
875     // to increasing entire system clock frequency.
876     //
877     asm(" RPT #200 || NOP");
878 
879     //
880     // Set the divider to user value
881     //
882     ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV = divsel;
883 
884     EDIS;
885 }
886 #endif // CPU1
887 
888 //
889 // InitAuxPll - This function initializes the AUXPLL registers.
890 //
891 // Note: For this function to properly detect PLL startup,
892 // SYSCLK >= 2*AUXPLLCLK after the AUXPLL is selected as the clocking source.
893 //
894 // This function will use CPU Timer 2 to monitor a successful lock of the
895 // AUXPLL.
896 //
InitAuxPll(Uint16 clock_source,Uint16 imult,Uint16 fmult,Uint16 divsel)897 void InitAuxPll(Uint16 clock_source, Uint16 imult, Uint16 fmult, Uint16 divsel)
898 {
899     Uint16 i;
900     Uint16 counter = 0;
901     Uint16 started = 0;
902     Uint16 t2TCR, t2TPR, t2TPRH, t2SRC, t2Prescale, attempts;
903     Uint32 t2PRD;
904 
905     if((clock_source == ClkCfgRegs.CLKSRCCTL2.bit.AUXOSCCLKSRCSEL) &&
906        (imult        == ClkCfgRegs.AUXPLLMULT.bit.IMULT)           &&
907        (fmult        == ClkCfgRegs.AUXPLLMULT.bit.FMULT)           &&
908        (divsel       == ClkCfgRegs.AUXCLKDIVSEL.bit.AUXPLLDIV))
909     {
910         //
911         // Everything is set as required, so just return
912         //
913         return;
914     }
915 
916     switch (clock_source)
917     {
918         case INT_OSC2:
919             AuxIntOsc2Sel();
920             break;
921 
922         case XTAL_OSC:
923             AuxXtalOscSel();
924             break;
925 
926         case AUXCLKIN:
927             AuxAuxClkSel();
928             break;
929     }
930 
931     //
932     // Backup Timer 2 settings
933     //
934     t2SRC = CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKSRCSEL;
935     t2Prescale = CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKPRESCALE;
936     t2TCR = CpuTimer2Regs.TCR.all;
937     t2PRD = CpuTimer2Regs.PRD.all;
938     t2TPR = CpuTimer2Regs.TPR.all;
939     t2TPRH = CpuTimer2Regs.TPRH.all;
940 
941     //
942     // Configure Timer 2 for AUXPLL as source in known configuration
943     //
944     EALLOW;
945     CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKSRCSEL = 0x6;
946     CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKPRESCALE = 0x0;    // Divide by 1
947 
948     CpuTimer2Regs.TCR.bit.TSS = 1;      // Stop timer
949     CpuTimer2Regs.PRD.all = 10;         // Small PRD value to detect overflow
950     CpuTimer2Regs.TPR.all = 0;
951     CpuTimer2Regs.TPRH.all = 0;
952     CpuTimer2Regs.TCR.bit.TIE = 0;      // Disable timer interrupts
953 
954     //
955     // Set AUX Divide by 8 to ensure that AUXPLLCLK <= SYSCLK/2 while using
956     // Timer 2
957     //
958     ClkCfgRegs.AUXCLKDIVSEL.bit.AUXPLLDIV = 0x3;
959     EDIS;
960 
961     while((counter < 5) && (started == 0))
962     {
963         EALLOW;
964         ClkCfgRegs.AUXPLLCTL1.bit.PLLEN = 0;    // Turn off AUXPLL
965         asm(" RPT #20 || NOP");                 // Small delay for power down
966 
967         //
968         // Set integer and fractional multiplier, which automatically turns on
969         // the PLL
970         //
971         ClkCfgRegs.AUXPLLMULT.all = ((fmult << 8U) | imult);
972 
973         //
974         // Enable AUXPLL
975         //
976         ClkCfgRegs.AUXPLLCTL1.bit.PLLEN = 1;
977         EDIS;
978 
979         //
980         // Wait for the AUXPLL lock counter
981         //
982         while(ClkCfgRegs.AUXPLLSTS.bit.LOCKS != 1)
983         {
984             //
985             // Uncomment to service the watchdog
986             //
987             // ServiceDog();
988         }
989 
990         //
991         // Enable AUXPLLCLK to be fed from AUX PLL
992         //
993         EALLOW;
994         ClkCfgRegs.AUXPLLCTL1.bit.PLLCLKEN = 1;
995         asm(" RPT #20 || NOP");
996 
997         //
998         // CPU Timer 2 will now be setup to be clocked from AUXPLLCLK. This is
999         // used to test that the PLL has successfully started.
1000         //
1001         CpuTimer2Regs.TCR.bit.TRB = 1;      // Reload period value
1002         CpuTimer2Regs.TCR.bit.TSS = 0;      // Start Timer
1003 
1004         //
1005         // Check to see timer is counting properly
1006         //
1007         for(i = 0; i < 1000; i++)
1008         {
1009             //
1010             // Check overflow flag
1011             //
1012             if(CpuTimer2Regs.TCR.bit.TIF)
1013             {
1014                 //
1015                 // Clear overflow flag
1016                 //
1017                 CpuTimer2Regs.TCR.bit.TIF = 1;
1018 
1019                 //
1020                 // Set flag to indicate PLL started and break out of for-loop
1021                 //
1022                 started = 1;
1023                 break;
1024             }
1025         }
1026 
1027         //
1028         // Stop timer
1029         //
1030         CpuTimer2Regs.TCR.bit.TSS = 1;
1031         counter++;
1032         EDIS;
1033     }
1034 
1035     if(started == 0)
1036     {
1037         //
1038         // AUX PLL may not have started. Reset multiplier to 0 (bypass PLL).
1039         //
1040         EALLOW;
1041         ClkCfgRegs.AUXPLLMULT.all = 0;
1042         EDIS;
1043 
1044         //
1045         // The user should put some handler code here based on how this
1046         // condition should be handled in their application.
1047         //
1048         asm(" ESTOP0");
1049     }
1050 
1051     //
1052     // Slip Bit Monitor
1053     // Re-lock routine for SLIP condition
1054     //
1055     attempts = 0;
1056     while(ClkCfgRegs.AUXPLLSTS.bit.SLIPS && (attempts < 10))
1057     {
1058         EALLOW;
1059         //
1060         // Bypass AUXPLL
1061         //
1062         ClkCfgRegs.AUXPLLCTL1.bit.PLLCLKEN = 0;
1063         asm(" RPT #20 || NOP");
1064 
1065         //
1066         // Turn off AUXPLL
1067         //
1068         ClkCfgRegs.AUXPLLCTL1.bit.PLLEN = 0;
1069         asm(" RPT #20 || NOP");
1070 
1071         //
1072         // Set integer and fractional multiplier, which automatically turns
1073         // on the PLL
1074         //
1075         ClkCfgRegs.AUXPLLMULT.all = ((fmult << 8U) | imult);
1076 
1077         //
1078         // Wait for the AUXPLL lock counter
1079         //
1080         while(ClkCfgRegs.AUXPLLSTS.bit.LOCKS != 1);
1081 
1082         //
1083         // Enable AUXPLLCLK to be fed from AUXPLL
1084         //
1085         ClkCfgRegs.AUXPLLCTL1.bit.PLLCLKEN = 1;
1086         asm(" RPT #20 || NOP");
1087 
1088         attempts++;
1089         EDIS;
1090     }
1091 
1092     //
1093     // Set divider to desired value
1094     //
1095     EALLOW;
1096     ClkCfgRegs.AUXCLKDIVSEL.bit.AUXPLLDIV = divsel;
1097 
1098     //
1099     // Restore Timer 2 configuration
1100     //
1101     CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKSRCSEL = t2SRC;
1102     CpuSysRegs.TMR2CLKCTL.bit.TMR2CLKPRESCALE = t2Prescale;
1103     CpuTimer2Regs.TCR.all = t2TCR;
1104     CpuTimer2Regs.PRD.all = t2PRD;
1105     CpuTimer2Regs.TPR.all = t2TPR;
1106     CpuTimer2Regs.TPRH.all = t2TPRH;
1107 
1108     //
1109     // Reload period value
1110     //
1111     CpuTimer2Regs.TCR.bit.TRB = 1;
1112     EDIS;
1113 }
1114 
1115 //
1116 // CsmUnlock - This function unlocks the CSM. User must replace 0xFFFF's with
1117 //             current password for the DSP. Returns 1 if unlock is successful.
1118 //
CsmUnlock(void)1119 Uint16 CsmUnlock(void)
1120 {
1121     volatile Uint16 temp;
1122 
1123     //
1124     // Load the key registers with the current password. The 0xFFFF's are dummy
1125     // passwords.  User should replace them with the correct password for the
1126     // DSP.
1127     //
1128     EALLOW;
1129     DcsmZ1Regs.Z1_CSMKEY0 = 0xFFFFFFFF;
1130     DcsmZ1Regs.Z1_CSMKEY1 = 0xFFFFFFFF;
1131     DcsmZ1Regs.Z1_CSMKEY2 = 0xFFFFFFFF;
1132     DcsmZ1Regs.Z1_CSMKEY3 = 0xFFFFFFFF;
1133 
1134     DcsmZ2Regs.Z2_CSMKEY0 = 0xFFFFFFFF;
1135     DcsmZ2Regs.Z2_CSMKEY1 = 0xFFFFFFFF;
1136     DcsmZ2Regs.Z2_CSMKEY2 = 0xFFFFFFFF;
1137     DcsmZ2Regs.Z2_CSMKEY3 = 0xFFFFFFFF;
1138     EDIS;
1139 
1140     return(0);
1141 }
1142 
1143 //
1144 // SysIntOsc1Sel - This function switches to Internal Oscillator 1.
1145 //
SysIntOsc1Sel(void)1146 void SysIntOsc1Sel(void)
1147 {
1148     EALLOW;
1149     ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL = 2;     // Clk Src = INTOSC1
1150     ClkCfgRegs.CLKSRCCTL1.bit.XTALOFF=1;            // Turn off XTALOSC
1151     EDIS;
1152 }
1153 
1154 //
1155 // SysIntOsc2Sel - This function switches to Internal oscillator 2.
1156 //
SysIntOsc2Sel(void)1157 void SysIntOsc2Sel(void)
1158 {
1159     EALLOW;
1160     ClkCfgRegs.CLKSRCCTL1.bit.INTOSC2OFF=0;         // Turn on INTOSC2
1161     ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL = 0;     // Clk Src = INTOSC2
1162     ClkCfgRegs.CLKSRCCTL1.bit.XTALOFF=1;            // Turn off XTALOSC
1163     EDIS;
1164 }
1165 
1166 //
1167 // SysXtalOscSel - This function switches to External CRYSTAL oscillator.
1168 //
SysXtalOscSel(void)1169 void SysXtalOscSel(void)
1170 {
1171     EALLOW;
1172     ClkCfgRegs.CLKSRCCTL1.bit.XTALOFF=0;            // Turn on XTALOSC
1173     ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL = 1;     // Clk Src = XTAL
1174     EDIS;
1175 }
1176 
1177 //
1178 // AuxIntOsc2Sel - This function switches to Internal oscillator 2.
1179 //
AuxIntOsc2Sel(void)1180 void AuxIntOsc2Sel(void)
1181 {
1182     EALLOW;
1183     ClkCfgRegs.CLKSRCCTL1.bit.INTOSC2OFF=0;         // Turn on INTOSC2
1184     ClkCfgRegs.CLKSRCCTL2.bit.AUXOSCCLKSRCSEL = 0;  // Clk Src = INTOSC2
1185     EDIS;
1186 }
1187 
1188 //
1189 // AuxXtalOscSel - This function switches to External CRYSTAL oscillator.
1190 //
AuxXtalOscSel(void)1191 void AuxXtalOscSel(void)
1192 {
1193     EALLOW;
1194     ClkCfgRegs.CLKSRCCTL1.bit.XTALOFF=0;            // Turn on XTALOSC
1195     ClkCfgRegs.CLKSRCCTL2.bit.AUXOSCCLKSRCSEL = 1;  // Clk Src = XTAL
1196     EDIS;
1197 }
1198 
1199 //
1200 // AuxAUXCLKOscSel - This function switches to AUXCLKIN (from a GPIO).
1201 //
AuxAuxClkSel(void)1202 void AuxAuxClkSel(void)
1203 {
1204     EALLOW;
1205     ClkCfgRegs.CLKSRCCTL2.bit.AUXOSCCLKSRCSEL = 2; // Clk Src = XTAL
1206     EDIS;
1207 }
1208 
1209 //
1210 // IDLE - Enter IDLE mode (single CPU).
1211 //
IDLE(void)1212 void IDLE(void)
1213 {
1214     EALLOW;
1215     CpuSysRegs.LPMCR.bit.LPM = LPM_IDLE;
1216     EDIS;
1217     asm(" IDLE");
1218 }
1219 
1220 //
1221 // STANDBY - Enter STANDBY mode (single CPU).
1222 //
STANDBY(void)1223 void STANDBY(void)
1224 {
1225     EALLOW;
1226     CpuSysRegs.LPMCR.bit.LPM = LPM_STANDBY;
1227     EDIS;
1228     asm(" IDLE");
1229 }
1230 
1231 //
1232 // HALT - Enter HALT mode (dual CPU). Puts CPU2 in IDLE mode first.
1233 //
HALT(void)1234 void HALT(void)
1235 {
1236 #if defined(CPU2)
1237     IDLE();
1238 #elif defined(CPU1)
1239     EALLOW;
1240     CpuSysRegs.LPMCR.bit.LPM = LPM_HALT;
1241     EDIS;
1242 
1243     while(DevCfgRegs.LPMSTAT.bit.CPU2LPMSTAT != 0x1);
1244 
1245     EALLOW;
1246     ClkCfgRegs.SYSPLLCTL1.bit.PLLCLKEN = 0;
1247     ClkCfgRegs.SYSPLLCTL1.bit.PLLEN = 0;
1248     EDIS;
1249     asm(" IDLE");
1250 #endif
1251 }
1252 
1253 //
1254 // HIB - Enter HIB mode (dual CPU). Puts CPU2 in STANDBY first. Alternately,
1255 //       CPU2 may be in reset.
HIB(void)1256 void HIB(void)
1257 {
1258 #if defined(CPU2)
1259     STANDBY();
1260 #elif defined(CPU1)
1261     EALLOW;
1262     CpuSysRegs.LPMCR.bit.LPM = LPM_HIB;
1263     EDIS;
1264 
1265     while((DevCfgRegs.LPMSTAT.bit.CPU2LPMSTAT == 0x0) &&
1266           (DevCfgRegs.RSTSTAT.bit.CPU2RES == 1));
1267 
1268     DisablePeripheralClocks();
1269     EALLOW;
1270     ClkCfgRegs.SYSPLLCTL1.bit.PLLCLKEN = 0;
1271     ClkCfgRegs.SYSPLLCTL1.bit.PLLEN = 0;
1272     EDIS;
1273     asm(" IDLE");
1274 #endif
1275 }
1276 
1277