aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple/rcc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmaple/rcc.c')
-rw-r--r--libmaple/rcc.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/libmaple/rcc.c b/libmaple/rcc.c
new file mode 100644
index 0000000..98b115a
--- /dev/null
+++ b/libmaple/rcc.c
@@ -0,0 +1,113 @@
+/**
+ * @file rcc.c
+ *
+ * @brief Implements pretty much only the basic clock setup on the maple,
+ * exposes a handful of clock enable/disable and peripheral reset commands.
+ */
+
+#include "libmaple.h"
+#include "flash.h"
+#include "rcc.h"
+
+static void set_ahb_prescaler(uint32_t divider) {
+ uint32_t cfgr = __read(RCC_CFGR);
+
+ cfgr &= ~HPRE;
+
+ switch (divider) {
+ case SYSCLK_DIV_1:
+ cfgr |= SYSCLK_DIV_1;
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ __write(RCC_CFGR, cfgr);
+}
+
+static void set_apb1_prescaler(uint32_t divider) {
+ uint32_t cfgr = __read(RCC_CFGR);
+
+ cfgr &= ~PPRE1;
+
+ switch (divider) {
+ case HCLK_DIV_2:
+ cfgr |= HCLK_DIV_2;
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ __write(RCC_CFGR, cfgr);
+}
+
+static void set_apb2_prescaler(uint32_t divider) {
+ uint32_t cfgr = __read(RCC_CFGR);
+
+ cfgr &= ~PPRE2;
+
+ switch (divider) {
+ case HCLK_DIV_1:
+ cfgr |= HCLK_DIV_1;
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ __write(RCC_CFGR, cfgr);
+}
+
+/* FIXME: magic numbers */
+static void pll_init(void) {
+ uint32_t cfgr;
+
+ cfgr = __read(RCC_CFGR);
+ cfgr &= (~PLLMUL | PLL_INPUT_CLK_HSE);
+
+ /* pll multiplier 9, input clock hse */
+ __write(RCC_CFGR, cfgr | PLL_MUL_9 | PLL_INPUT_CLK_HSE);
+
+ /* enable pll */
+ __set_bits(RCC_CR, PLLON);
+ while(!__get_bits(RCC_CR, PLLRDY)) {
+ asm volatile("nop");
+ }
+
+ /* select pll for system clock source */
+ cfgr = __read(RCC_CFGR);
+ cfgr &= ~RCC_CFGR_SWS;
+ __write(RCC_CFGR, cfgr | RCC_CFGR_SWS_PLL);
+
+ while (__get_bits(RCC_CFGR, 0x00000008) != 0x8) {
+ asm volatile("nop");
+ }
+}
+
+static void hse_init(void) {
+ __set_bits(RCC_CR, HSEON);
+ while (!HSERDY) {
+ asm volatile("nop");
+ }
+}
+
+void rcc_init(void) {
+ hse_init();
+
+ /* Leave this here for now... */
+ /* Enable Prefetch Buffer */
+ flash_enable_prefetch();
+
+ /* Flash 2 wait state */
+ flash_set_latency();
+
+ set_ahb_prescaler(SYSCLK_DIV_1);
+ set_apb1_prescaler(HCLK_DIV_2);
+ set_apb2_prescaler(HCLK_DIV_1);
+ pll_init();
+}
+
+void rcc_set_adc_prescaler(uint32_t divider) {
+ uint32_t cfgr = __read(RCC_CFGR);
+ cfgr &= ~ADCPRE;
+ __write(RCC_CFGR, cfgr | PCLK2_DIV_2);
+}