BeRTOS
|
00001 00038 #include "clock_lm3s.h" 00039 00040 #include <cfg/compiler.h> 00041 #include <cfg/debug.h> 00042 00043 #include <io/lm3s.h> 00044 00045 00046 /* The PLL VCO frequency is 400 MHz */ 00047 #define PLL_VCO 400000000UL 00048 00049 /* Extract the system clock divisor from the RCC register */ 00050 #define RCC_TO_DIV(rcc) \ 00051 (((rcc & SYSCTL_RCC_SYSDIV_MASK) >> \ 00052 SYSCTL_RCC_SYSDIV_SHIFT) + 1) 00053 00054 /* 00055 * Very small delay: each loop takes 3 cycles. 00056 */ 00057 void NAKED lm3s_busyWait(unsigned long iterations) 00058 { 00059 register uint32_t __n asm("r0") = iterations; 00060 00061 asm volatile ( 00062 "1: subs r0, #1\n\t" 00063 "bne 1b\n\t" 00064 "bx lr\n\t" 00065 : : "r"(__n) : "memory", "cc"); 00066 } 00067 00068 INLINE unsigned long clock_get_rate(void) 00069 { 00070 reg32_t rcc = HWREG(SYSCTL_RCC); 00071 00072 return rcc & SYSCTL_RCC_USESYSDIV ? 00073 PLL_VCO / 2 / RCC_TO_DIV(rcc) : PLL_VCO; 00074 } 00075 00076 /* 00077 * Try to evaluate the correct SYSDIV value depending on the desired CPU 00078 * frequency. 00079 */ 00080 INLINE int evaluate_sysdiv(unsigned long freq) 00081 { 00082 int i; 00083 00084 /* 00085 * NOTE: with BYPASS=0, SYSDIV < 3 are reserved values (see LM3S1968 00086 * Microcontroller DATASHEET, p.78). 00087 */ 00088 for (i = 3; i < 16; i++) 00089 if (freq >= (PLL_VCO / 2 / (i + 1))) 00090 break; 00091 return i; 00092 } 00093 00094 void clock_init(void) 00095 { 00096 reg32_t rcc, rcc2; 00097 unsigned long clk; 00098 int i; 00099 00100 /* 00101 * PLL may not function properly at default LDO setting. 00102 * 00103 * Description: 00104 * 00105 * In designs that enable and use the PLL module, unstable device 00106 * behavior may occur with the LDO set at its default of 2.5 volts or 00107 * below (minimum of 2.25 volts). Designs that do not use the PLL 00108 * module are not affected. 00109 * 00110 * Workaround: Prior to enabling the PLL module, it is recommended that 00111 * the default LDO voltage setting of 2.5 V be adjusted to 2.75 V using 00112 * the LDO Power Control (LDOPCTL) register. 00113 * 00114 * Silicon Revision Affected: A1, A2 00115 * 00116 * See also: Stellaris LM3S1968 A2 Errata documentation. 00117 */ 00118 if (REVISION_IS_A1 | REVISION_IS_A2) 00119 HWREG(SYSCTL_LDOPCTL) = SYSCTL_LDOPCTL_2_75V; 00120 00121 rcc = HWREG(SYSCTL_RCC); 00122 rcc2 = HWREG(SYSCTL_RCC2); 00123 00124 /* 00125 * Step #1: bypass the PLL and system clock divider by setting the 00126 * BYPASS bit and clearing the USESYS bit in the RCC register. This 00127 * configures the system to run off a “raw” clock source (using the 00128 * main oscillator or internal oscillator) and allows for the new PLL 00129 * configuration to be validated before switching the system clock to 00130 * the PLL. 00131 */ 00132 rcc |= SYSCTL_RCC_BYPASS; 00133 rcc &= ~SYSCTL_RCC_USESYSDIV; 00134 rcc2 |= SYSCTL_RCC2_BYPASS2; 00135 00136 /* Write back RCC/RCC2 registers */ 00137 HWREG(SYSCTL_RCC) = rcc; 00138 HWREG(SYSCTL_RCC) = rcc2; 00139 00140 lm3s_busyWait(16); 00141 00142 /* 00143 * Step #2: select the crystal value (XTAL) and oscillator source 00144 * (OSCSRC), and clear the PWRDN bit in RCC/RCC2. Setting the XTAL 00145 * field automatically pulls valid PLL configuration data for the 00146 * appropriate crystal, and clearing the PWRDN bit powers and enables 00147 * the PLL and its output. 00148 */ 00149 00150 /* Enable the main oscillator first. */ 00151 rcc &= ~(SYSCTL_RCC_IOSCDIS | SYSCTL_RCC_MOSCDIS); 00152 rcc |= SYSCTL_RCC_IOSCDIS; 00153 00154 /* Do not override RCC register fields */ 00155 rcc2 &= ~SYSCTL_RCC2_USERCC2; 00156 00157 rcc &= ~(SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M | SYSCTL_RCC_PWRDN); 00158 rcc |= XTAL_FREQ | SYSCTL_RCC_OSCSRC_MAIN; 00159 00160 /* Clear the PLL lock interrupt. */ 00161 HWREG(SYSCTL_MISC) = SYSCTL_INT_PLL_LOCK; 00162 00163 HWREG(SYSCTL_RCC) = rcc; 00164 HWREG(SYSCTL_RCC) = rcc2; 00165 00166 lm3s_busyWait(16); 00167 00168 /* 00169 * Step #3: select the desired system divider (SYSDIV) in RCC/RCC2 and 00170 * set the USESYS bit in RCC. The SYSDIV field determines the system 00171 * frequency for the microcontroller. 00172 */ 00173 rcc &= ~(SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV); 00174 00175 clk = PLL_VCO / 2; 00176 for (i = 3; i < 16; i++) 00177 if (CPU_FREQ >= (clk / (i + 1))) 00178 break; 00179 rcc |= SYSCTL_RCC_USESYSDIV | 00180 (evaluate_sysdiv(CPU_FREQ) << SYSCTL_RCC_SYSDIV_SHIFT); 00181 00182 /* 00183 * Step #4: wait for the PLL to lock by polling the PLLLRIS bit in the 00184 * Raw Interrupt Status (RIS) register. 00185 */ 00186 for (i = 0; i < 32768; i++) 00187 if (HWREG(SYSCTL_RIS) & SYSCTL_INT_PLL_LOCK) 00188 break; 00189 00190 /* 00191 * Step #5: enable use of the PLL by clearing the BYPASS bit in 00192 * RCC/RCC2. 00193 */ 00194 rcc &= ~SYSCTL_RCC_BYPASS; 00195 00196 HWREG(SYSCTL_RCC) = rcc; 00197 00198 lm3s_busyWait(16); 00199 }