X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Fcortex-m3%2Fdrv%2Fclock_lm3s.c;h=0c79f8780c60017a4ce2673896c303b236aa9fdb;hb=f81df2ee3de292493462ee9d0a8905eaafb57243;hp=b91b09bd17625b959e8c214a3d51f33cb5d12cf7;hpb=73a7e9cb144007905b5b9de8e3086423e79b6d71;p=bertos.git diff --git a/bertos/cpu/cortex-m3/drv/clock_lm3s.c b/bertos/cpu/cortex-m3/drv/clock_lm3s.c index b91b09bd..0c79f878 100644 --- a/bertos/cpu/cortex-m3/drv/clock_lm3s.c +++ b/bertos/cpu/cortex-m3/drv/clock_lm3s.c @@ -35,10 +35,13 @@ * \author Andrea Righi */ +#include "clock_lm3s.h" + #include #include -#include "io/lm3s.h" -#include "clock_lm3s.h" + +#include + /* The PLL VCO frequency is 400 MHz */ #define PLL_VCO 400000000UL @@ -51,28 +54,70 @@ /* * Very small delay: each loop takes 3 cycles. */ -INLINE void __delay(unsigned long iterations) +void NAKED lm3s_busyWait(unsigned long iterations) { + register uint32_t __n asm("r0") = iterations; + asm volatile ( - "1: subs %0, #1\n\t" - " bne 1b\n\t" - : "=r"(iterations) : : "memory", "cc"); + "1: subs r0, #1\n\t" + "bne 1b\n\t" + "bx lr\n\t" + : : "r"(__n) : "memory", "cc"); } -unsigned long clock_get_rate(void) +INLINE unsigned long clock_get_rate(void) { reg32_t rcc = HWREG(SYSCTL_RCC); return rcc & SYSCTL_RCC_USESYSDIV ? - PLL_VCO / RCC_TO_DIV(rcc) : PLL_VCO; + PLL_VCO / 2 / RCC_TO_DIV(rcc) : PLL_VCO; } -void clock_set_rate(void) +/* + * Try to evaluate the correct SYSDIV value depending on the desired CPU + * frequency. + */ +INLINE int evaluate_sysdiv(unsigned long freq) +{ + int i; + + /* + * NOTE: with BYPASS=0, SYSDIV < 3 are reserved values (see LM3S1968 + * Microcontroller DATASHEET, p.78). + */ + for (i = 3; i < 16; i++) + if (freq >= (PLL_VCO / 2 / (i + 1))) + break; + return i; +} + +void clock_init(void) { reg32_t rcc, rcc2; unsigned long clk; int i; + /* + * PLL may not function properly at default LDO setting. + * + * Description: + * + * In designs that enable and use the PLL module, unstable device + * behavior may occur with the LDO set at its default of 2.5 volts or + * below (minimum of 2.25 volts). Designs that do not use the PLL + * module are not affected. + * + * Workaround: Prior to enabling the PLL module, it is recommended that + * the default LDO voltage setting of 2.5 V be adjusted to 2.75 V using + * the LDO Power Control (LDOPCTL) register. + * + * Silicon Revision Affected: A1, A2 + * + * See also: Stellaris LM3S1968 A2 Errata documentation. + */ + if (REVISION_IS_A1 | REVISION_IS_A2) + HWREG(SYSCTL_LDOPCTL) = SYSCTL_LDOPCTL_2_75V; + rcc = HWREG(SYSCTL_RCC); rcc2 = HWREG(SYSCTL_RCC2); @@ -92,6 +137,8 @@ void clock_set_rate(void) HWREG(SYSCTL_RCC) = rcc; HWREG(SYSCTL_RCC) = rcc2; + lm3s_busyWait(16); + /* * Step #2: select the crystal value (XTAL) and oscillator source * (OSCSRC), and clear the PWRDN bit in RCC/RCC2. Setting the XTAL @@ -116,7 +163,7 @@ void clock_set_rate(void) HWREG(SYSCTL_RCC) = rcc; HWREG(SYSCTL_RCC) = rcc2; - __delay(16); + lm3s_busyWait(16); /* * Step #3: select the desired system divider (SYSDIV) in RCC/RCC2 and @@ -125,19 +172,12 @@ void clock_set_rate(void) */ rcc &= ~(SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV); - /* - * Try to evaluate the correct SYSDIV value depending on the desired - * CPU frequency. - * - * NOTE: with BYPASS=0, SYSDIV < 3 are reserved values (see LM3S1968 - * Microcontroller DATASHEET, p.78). - */ clk = PLL_VCO / 2; for (i = 3; i < 16; i++) if (CPU_FREQ >= (clk / (i + 1))) break; - if (i) - rcc |= SYSCTL_RCC_USESYSDIV | (i << SYSCTL_RCC_SYSDIV_SHIFT); + rcc |= SYSCTL_RCC_USESYSDIV | + (evaluate_sysdiv(CPU_FREQ) << SYSCTL_RCC_SYSDIV_SHIFT); /* * Step #4: wait for the PLL to lock by polling the PLLLRIS bit in the @@ -155,5 +195,5 @@ void clock_set_rate(void) HWREG(SYSCTL_RCC) = rcc; - __delay(16); + lm3s_busyWait(16); }