00001 /****************************************************************************** 00002 ** Copyright (C) 2007 Pablo Garcia 00003 ** 00004 ** This library is free software; you can redistribute it and/or 00005 ** modify it under the terms of the GNU Lesser General Public 00006 ** License as published by the Free Software Foundation; either 00007 ** version 2.1 of the License, or (at your option) any later version. 00008 00009 ** This library is distributed in the hope that it will be useful, 00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 ** Lesser General Public License for more details. 00013 00014 ** You should have received a copy of the GNU Lesser General Public 00015 ** License along with this library; if not, write to the Free Software 00016 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00017 ******************************************************************************/ 00018 00019 // -------------------------------------------------------------------------- 00020 // Includes 00021 // -------------------------------------------------------------------------- 00022 #include "cpu.h" 00023 00024 /*----------------------------------------------------------------------------- 00025 Variables 00026 ------------------------------------------------------------------------------*/ 00027 volatile struct CPUConfiguration cpuConf; 00028 00029 00030 void InitCPU(Uint32 oscCLK, Uint16 dsp28_DIVSEL, Uint16 dsp28_PLLCR, 00031 Uint16 hspCLK, Uint16 lspCLK) 00032 { 00033 cpuConf.oscCLK = oscCLK; 00034 cpuConf.dsp28_DIVSEL = dsp28_DIVSEL; 00035 cpuConf.dsp28_PLLCR =dsp28_PLLCR; 00036 cpuConf.hspCLK = hspCLK; 00037 cpuConf.lspCLK = lspCLK; 00038 InitSysCtrl(); 00039 // Initialize the PIE control registers to their default state. 00040 // The default state is all PIE interrupts disabled and flags 00041 // are cleared. 00042 InitPieCtrl(); 00043 // Disable CPU interrupts and clear all CPU interrupt flags: 00044 IER = 0x0000; 00045 IFR = 0x0000; 00046 // Initialize the PIE vector table with pointers to the shell Interrupt 00047 // Service Routines (ISR). 00048 // InitPieVectTable(); 00049 } 00050 00051 //--------------------------------------------------------------------------- 00052 // InitSysCtrl: 00053 //--------------------------------------------------------------------------- 00054 // This function initializes the System Control registers to a known state. 00055 // - Disables the watchdog 00056 // - Set the PLLCR for proper SYSCLKOUT frequency 00057 // - Set the pre-scaler for the high and low frequency peripheral clocks 00058 // - Enable the clocks to the peripherals 00059 00060 void InitSysCtrl(void) 00061 { 00062 // Disable the watchdog 00063 DisableDog(); 00064 00065 // Initialize the PLL control: PLLCR and DIVSEL 00066 InitPll(cpuConf.dsp28_PLLCR, cpuConf.dsp28_DIVSEL); 00067 00068 // Initialize the peripheral clocks 00069 InitPeripheralClocks(); 00070 } 00071 00072 //--------------------------------------------------------------------------- 00073 00074 //--------------------------------------------------------------------------- 00075 // InitPieCtrl: 00076 //--------------------------------------------------------------------------- 00077 // This function initializes the PIE control registers to a known state. 00078 // 00079 void InitPieCtrl(void) 00080 { 00081 // Clear all interrupts and initialize PIE vector table: 00082 // Disable CPU interrupts 00083 DINT; 00084 00085 // Disable the PIE 00086 PieCtrlRegs.PIECTRL.bit.ENPIE = 0; 00087 00088 // Clear all PIEIER registers: 00089 PieCtrlRegs.PIEIER1.all = 0; 00090 PieCtrlRegs.PIEIER2.all = 0; 00091 PieCtrlRegs.PIEIER3.all = 0; 00092 PieCtrlRegs.PIEIER4.all = 0; 00093 PieCtrlRegs.PIEIER5.all = 0; 00094 PieCtrlRegs.PIEIER6.all = 0; 00095 PieCtrlRegs.PIEIER7.all = 0; 00096 PieCtrlRegs.PIEIER8.all = 0; 00097 PieCtrlRegs.PIEIER9.all = 0; 00098 PieCtrlRegs.PIEIER10.all = 0; 00099 PieCtrlRegs.PIEIER11.all = 0; 00100 PieCtrlRegs.PIEIER12.all = 0; 00101 00102 // Clear all PIEIFR registers: 00103 PieCtrlRegs.PIEIFR1.all = 0; 00104 PieCtrlRegs.PIEIFR2.all = 0; 00105 PieCtrlRegs.PIEIFR3.all = 0; 00106 PieCtrlRegs.PIEIFR4.all = 0; 00107 PieCtrlRegs.PIEIFR5.all = 0; 00108 PieCtrlRegs.PIEIFR6.all = 0; 00109 PieCtrlRegs.PIEIFR7.all = 0; 00110 PieCtrlRegs.PIEIFR8.all = 0; 00111 PieCtrlRegs.PIEIFR9.all = 0; 00112 PieCtrlRegs.PIEIFR10.all = 0; 00113 PieCtrlRegs.PIEIFR11.all = 0; 00114 PieCtrlRegs.PIEIFR12.all = 0; 00115 } 00116 00117 00118 //--------------------------------------------------------------------------- 00119 // EnableInterrupts: 00120 //--------------------------------------------------------------------------- 00121 // This function enables the PIE module and CPU interrupts 00122 // 00123 void EnableInterrupts(void) 00124 { 00125 // Enable the PIE 00126 PieCtrlRegs.PIECTRL.bit.ENPIE = 1; 00127 00128 // Enables PIE to drive a pulse into the CPU 00129 PieCtrlRegs.PIEACK.all = 0xFFFF; 00130 00131 // Enable Interrupts at the CPU level 00132 EINT; 00133 00134 // Enable Global realtime interrupt DBGM 00135 ERTM; 00136 } 00137 00138 //--------------------------------------------------------------------------- 00139 00140 //--------------------------------------------------------------------------- 00141 // ServiceDog: 00142 //--------------------------------------------------------------------------- 00143 // This function resets the watchdog timer. 00144 // Enable this function for using ServiceDog in the application 00145 00146 void ServiceDog(void) 00147 { 00148 EALLOW; 00149 SysCtrlRegs.WDKEY = 0x0055; 00150 SysCtrlRegs.WDKEY = 0x00AA; 00151 EDIS; 00152 } 00153 00154 //--------------------------------------------------------------------------- 00155 // DisableDog: 00156 //--------------------------------------------------------------------------- 00157 // This function disables the watchdog timer. 00158 00159 void DisableDog(void) 00160 { 00161 EALLOW; 00162 SysCtrlRegs.WDCR= 0x0068; 00163 EDIS; 00164 } 00165 00166 // ---------------------------------------------------------------------------- 00167 00168 void InitPll(Uint16 val, Uint16 divsel) 00169 { 00170 volatile Uint16 iVol; 00171 00172 // Make sure the PLL is not running in limp mode 00173 if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0) { 00174 // Missing external clock has been detected 00175 // Replace this line with a call to an appropriate 00176 // SystemShutdown(); function. 00177 asm(" ESTOP0"); 00178 } 00179 00180 // CLKINDIV MUST be 0 before PLLCR can be changed from 00181 // 0x0000. It is set to 0 by an external reset XRSn 00182 if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0){ 00183 EALLOW; 00184 SysCtrlRegs.PLLSTS.bit.DIVSEL = 0; 00185 EDIS; 00186 } 00187 00188 // Change the PLLCR 00189 if (SysCtrlRegs.PLLCR.bit.DIV != val){ 00190 EALLOW; 00191 // Before setting PLLCR turn off missing clock detect logic 00192 SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1; 00193 SysCtrlRegs.PLLCR.bit.DIV = val; 00194 EDIS; 00195 00196 // Optional: Wait for PLL to lock. 00197 // During this time the CPU will switch to OSCCLK/2 until 00198 // the PLL is stable. Once the PLL is stable the CPU will 00199 // switch to the new PLL value. 00200 // 00201 // This time-to-lock is monitored by a PLL lock counter. 00202 // 00203 // Code is not required to sit and wait for the PLL to lock. 00204 // However, if the code does anything that is timing critical, 00205 // and requires the correct clock be locked, then it is best to 00206 // wait until this switching has completed. 00207 00208 // Wait for the PLL lock bit to be set. 00209 // Note this bit is not available on 281x devices. For those devices 00210 // use a software loop to perform the required count. 00211 00212 // The watchdog should be disabled before this loop, or fed within 00213 // the loop via ServiceDog(). 00214 00215 // Uncomment to disable the watchdog 00216 DisableDog(); 00217 00218 while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1){ 00219 // Uncomment to service the watchdog 00220 // ServiceDog(); 00221 } 00222 00223 EALLOW; 00224 SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0; 00225 SysCtrlRegs.PLLSTS.bit.DIVSEL = divsel; 00226 EDIS; 00227 } 00228 /* 00229 // Make sure the PLL is not running in limp mode 00230 if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0) 00231 { 00232 // Missing external clock has been detected 00233 // Replace this line with a call to an appropriate 00234 // SystemShutdown(); function. 00235 asm(" ESTOP0"); 00236 } 00237 00238 // DIVSEL MUST be 0 before PLLCR can be changed from 00239 // 0x0000. It is set to 0 by an external reset XRSn 00240 // This puts us in 1/4 00241 if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0) 00242 { 00243 EALLOW; 00244 SysCtrlRegs.PLLSTS.bit.DIVSEL = 0; 00245 EDIS; 00246 } 00247 00248 // Change the PLLCR 00249 if (SysCtrlRegs.PLLCR.bit.DIV != val) 00250 { 00251 00252 EALLOW; 00253 // Before setting PLLCR turn off missing clock detect logic 00254 SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1; 00255 SysCtrlRegs.PLLCR.bit.DIV = val; 00256 EDIS; 00257 00258 // Optional: Wait for PLL to lock. 00259 // During this time the CPU will switch to OSCCLK/2 until 00260 // the PLL is stable. Once the PLL is stable the CPU will 00261 // switch to the new PLL value. 00262 // 00263 // This time-to-lock is monitored by a PLL lock counter. 00264 // 00265 // Code is not required to sit and wait for the PLL to lock. 00266 // However, if the code does anything that is timing critical, 00267 // and requires the correct clock be locked, then it is best to 00268 // wait until this switching has completed. 00269 00270 // Wait for the PLL lock bit to be set. 00271 00272 // The watchdog should be disabled before this loop, or fed within 00273 // the loop via ServiceDog(). 00274 00275 // Uncomment to disable the watchdog 00276 DisableDog(); 00277 00278 while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1) 00279 { 00280 // Uncomment to service the watchdog 00281 // ServiceDog(); 00282 } 00283 00284 EALLOW; 00285 SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0; 00286 EDIS; 00287 } 00288 */ 00289 // If switching to 1/2 00290 if((divsel == 1)||(divsel == 2)) { 00291 EALLOW; 00292 SysCtrlRegs.PLLSTS.bit.DIVSEL = divsel; 00293 EDIS; 00294 } 00295 00296 // If switching to 1/1 00297 // * First go to 1/2 and let the power settle 00298 // The time required will depend on the system, this is only an example 00299 // * Then switch to 1/1 00300 if(divsel == 3) { 00301 EALLOW; 00302 SysCtrlRegs.PLLSTS.bit.DIVSEL = 2; 00303 DELAY_US(50L); 00304 SysCtrlRegs.PLLSTS.bit.DIVSEL = 3; 00305 EDIS; 00306 } 00307 } 00308 00309 // ---------------------------------------------------------------------------- 00310 00311 // ---------------------------------------------------------------------------- 00312 // If HISPCP(2:0) > 0, HSPCLK = SYSCLKOUT/(HISPCP X 2) 00313 // If HISPCP = 0, HSPCLK = SYSCLKOUT 00314 // 000 High speed clock = SYSCLKOUT/1 00315 // 001 High speed clock = SYSCLKOUT/2 (reset default) 00316 // 010 High speed clock = SYSCLKOUT/4 00317 // 011 High speed clock = SYSCLKOUT/6 00318 // 100 High speed clock = SYSCLKOUT/8 00319 // 101 High speed clock = SYSCLKOUT/10 00320 // 110 High speed clock = SYSCLKOUT/12 00321 // 111 High speed clock = SYSCLKOUT/14 00322 // If LOSPCP(2:0) > 0, LSPCLK = SYSCLKOUT/(LOSPCP X 2) 00323 // If LOSPCP = 0, LSPCLK = SYSCLKOUT 00324 // 000 Low speed clock = SYSCLKOUT/1 00325 // 001 Low speed clock = SYSCLKOUT/2 00326 // 010 Low speed clock = SYSCLKOUT/4 (reset default) 00327 // 011 Low speed clock = SYSCLKOUT/6 00328 // 100 Low speed clock = SYSCLKOUT/8 00329 // 101 Low speed clock = SYSCLKOUT/10 00330 // 110 Low speed clock = SYSCLKOUT/12 00331 // 111 Low speed clock = SYSCLKOUT/14 00332 // ---------------------------------------------------------------------------- 00333 void InitPeripheralClocks(void) 00334 { 00335 EALLOW; 00336 // PABLO, I DO NOT KNOW WHY x2 WAS USED HERE. IF WE WANT InitCPU TO RECEIVE 00337 // DIRECTLY THE HSPCLK and LSPCLK DIVIDERS, WE SHOULD INSTEAD DIVIDE IT BY 2 00338 SysCtrlRegs.HISPCP.all = cpuConf.hspCLK > 0 ? cpuConf.hspCLK>>1 : 1; 00339 SysCtrlRegs.LOSPCP.all = cpuConf.lspCLK > 0 ? cpuConf.lspCLK>>1 : 2; 00340 00341 /* 00342 // external interface XINTF configuration 00343 // XCLKOUT to SYSCLKOUT ratio. By default XCLKOUT = 1/4 SYSCLKOUT 00344 // XTIMCLK = SYSCLKOUT/2 00345 XintfRegs.XINTCNF2.bit.XTIMCLK = 1; 00346 // XCLKOUT = XTIMCLK/4 00347 XintfRegs.XINTCNF2.bit.CLKMODE = 0; 00348 // Enable XCLKOUT 00349 XintfRegs.XINTCNF2.bit.CLKOFF = 0; 00350 */ 00351 00352 EDIS; 00353 } 00354 00355 // ---------------------------------------------------------------------------- 00356 00357 00358 //----------------------------------------------------------------------------- 00359 // End Of File 00360 //----------------------------------------------------------------------------- 00361