From 2587ee10c544deda0bead0ec30abcd803b9ef7f9 Mon Sep 17 00:00:00 2001 From: aleph Date: Tue, 28 Sep 2010 15:37:57 +0000 Subject: [PATCH] sam3n port: add code to setup system clock git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4330 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/cortex-m3/drv/clock_sam3.c | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/bertos/cpu/cortex-m3/drv/clock_sam3.c b/bertos/cpu/cortex-m3/drv/clock_sam3.c index 967e3798..ae70d529 100644 --- a/bertos/cpu/cortex-m3/drv/clock_sam3.c +++ b/bertos/cpu/cortex-m3/drv/clock_sam3.c @@ -36,7 +36,58 @@ */ #include "clock_sam3.h" +#include +#include +#include + +/* Value to use when writing CKGR_MOR, to unlock write */ +#define CKGR_KEY 0x37 + +/* + * Try to evaluate the correct divider and multiplier value depending + * on the desired CPU frequency. + * + * We try all combinations in a certain range of divider and multiplier + * values. The range can change, with better match with "strange" + * frequencies, but boot time will be longer. + * + * Limits for SAM3N: divider [1,255], multiplier [1,2047]. + */ +INLINE uint32_t evaluate_pll(void) +{ + int mul, div, best_mul, best_div; + int best_delta = CPU_FREQ; + int freq = 0; + + for (mul = 1; mul <= 8; mul++) + { + for (div = 1; div <= 24; div++) + { + // RC oscillator set to 12 MHz + freq = 12000000 / div * (1 + mul); + if (ABS(CPU_FREQ - freq) < best_delta) { + best_delta = ABS(CPU_FREQ - freq); + best_mul = mul; + best_div = div; + } + } + } + + // Bit 29 must always be set to 1 + return CKGR_PLLR_DIV(best_div) | CKGR_PLLR_MUL(best_mul) | BV(29); +} + void clock_init(void) { + /* Enable and configure internal Fast RC oscillator */ + CKGR_MOR_R = + CKGR_MOR_KEY(CKGR_KEY) // Unlock key + | CKGR_MOR_MOSCRCEN // Main On-Chip RC oscillator enable + | CKGR_MOR_MOSCRCF_12MHZ; // RC oscillator frequency + + /* Master clock: select PLL clock and no prescaling */ + PMC_MCKR_R = PMC_MCKR_CSS_PLL_CLK; + + CKGR_PLLR_R = evaluate_pll(); } -- 2.25.1