aboutsummaryrefslogtreecommitdiffstats
path: root/wirish/boards.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'wirish/boards.cpp')
-rw-r--r--wirish/boards.cpp178
1 files changed, 108 insertions, 70 deletions
diff --git a/wirish/boards.cpp b/wirish/boards.cpp
index 569ca6d..5771df5 100644
--- a/wirish/boards.cpp
+++ b/wirish/boards.cpp
@@ -2,6 +2,7 @@
* The MIT License
*
* Copyright (c) 2010 Perry Hung.
+ * Copyright (c) 2011, 2012 LeafLabs, LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -25,45 +26,61 @@
*****************************************************************************/
/**
- * @brief Generic board initialization routines.
+ * @file wirish/boards.cpp
+ * @brief init() and board routines.
*
- * By default, we bring up all Maple boards to 72MHz, clocked off the
- * PLL, driven by the 8MHz external crystal. AHB and APB2 are clocked
- * at 72MHz. APB1 is clocked at 36MHz.
+ * This file is mostly interesting for the init() function, which
+ * configures Flash, the core clocks, and a variety of other available
+ * peripherals on the board so the rest of Wirish doesn't have to turn
+ * things on before using them.
+ *
+ * Prior to returning, init() calls boardInit(), which allows boards
+ * to perform any initialization they need to. This file includes a
+ * weak no-op definition of boardInit(), so boards that don't need any
+ * special initialization don't have to define their own.
+ *
+ * How init() works is chip-specific. See the boards_setup.cpp files
+ * under e.g. wirish/stm32f1/, wirish/stmf32f2 for the details, but be
+ * advised: their contents are unstable, and can/will change without
+ * notice.
*/
-#include "boards.h"
+#include <wirish/boards.h>
+#include <libmaple/libmaple_types.h>
+#include <libmaple/flash.h>
+#include <libmaple/nvic.h>
+#include <libmaple/systick.h>
+#include "boards_private.h"
-#include "flash.h"
-#include "rcc.h"
-#include "nvic.h"
-#include "systick.h"
-#include "gpio.h"
-#include "adc.h"
-#include "timer.h"
-#include "usb_cdcacm.h"
+static void setup_flash(void);
+static void setup_clocks(void);
+static void setup_nvic(void);
+static void setup_adcs(void);
+static void setup_timers(void);
-static void setupFlash(void);
-static void setupClocks(void);
-static void setupNVIC(void);
-static void setupADC(void);
-static void setupTimers(void);
+/*
+ * Exported functions
+ */
void init(void) {
- setupFlash();
- setupClocks();
- setupNVIC();
+ setup_flash();
+ setup_clocks();
+ setup_nvic();
systick_init(SYSTICK_RELOAD_VAL);
- gpio_init_all();
- afio_init();
- setupADC();
- setupTimers();
- usb_cdcacm_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
+ wirish::priv::board_setup_gpio();
+ setup_adcs();
+ setup_timers();
+ wirish::priv::board_setup_usb();
+ wirish::priv::series_init();
boardInit();
}
+/* Provide a default no-op boardInit(). */
+__weak void boardInit(void) {
+}
+
/* You could farm this out to the files in boards/ if e.g. it takes
- * too long to test on Maple Native (all those FSMC pins...). */
+ * too long to test on boards with lots of pins. */
bool boardUsesPin(uint8 pin) {
for (int i = 0; i < BOARD_NR_USED_PINS; i++) {
if (pin == boardUsedPins[i]) {
@@ -73,27 +90,56 @@ bool boardUsesPin(uint8 pin) {
return false;
}
-static void setupFlash(void) {
- flash_enable_prefetch();
- flash_set_latency(FLASH_WAIT_STATE_2);
-}
-
/*
- * Clock setup. Note that some of this only takes effect if we're
- * running bare metal and the bootloader hasn't done it for us
- * already.
- *
- * If you change this function, you MUST change the file-level Doxygen
- * comment above.
+ * Auxiliary routines
*/
-static void setupClocks() {
- rcc_clk_init(RCC_CLKSRC_PLL, RCC_PLLSRC_HSE, RCC_PLLMUL_9);
- rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1);
- rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2);
- rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1);
+
+static void setup_flash(void) {
+ // Turn on as many Flash "go faster" features as
+ // possible. flash_enable_features() just ignores any flags it
+ // can't support.
+ flash_enable_features(FLASH_PREFETCH | FLASH_ICACHE | FLASH_DCACHE);
+ // Configure the wait states, assuming we're operating at "close
+ // enough" to 3.3V.
+ flash_set_latency(FLASH_SAFE_WAIT_STATES);
+}
+
+static void setup_clocks(void) {
+ // Turn on HSI. We'll switch to and run off of this while we're
+ // setting up the main PLL.
+ rcc_turn_on_clk(RCC_CLK_HSI);
+
+ // Turn off and reset the clock subsystems we'll be using, as well
+ // as the clock security subsystem (CSS). Note that resetting CFGR
+ // to its default value of 0 implies a switch to HSI for SYSCLK.
+ RCC_BASE->CFGR = 0x00000000;
+ rcc_disable_css();
+ rcc_turn_off_clk(RCC_CLK_PLL);
+ rcc_turn_off_clk(RCC_CLK_HSE);
+ wirish::priv::board_reset_pll();
+ // Clear clock readiness interrupt flags and turn off clock
+ // readiness interrupts.
+ RCC_BASE->CIR = 0x00000000;
+
+ // Enable HSE, and wait until it's ready.
+ rcc_turn_on_clk(RCC_CLK_HSE);
+ while (!rcc_is_clk_ready(RCC_CLK_HSE))
+ ;
+
+ // Configure AHBx, APBx, etc. prescalers and the main PLL.
+ wirish::priv::board_setup_clock_prescalers();
+ rcc_configure_pll(&wirish::priv::w_board_pll_cfg);
+
+ // Enable the PLL, and wait until it's ready.
+ rcc_turn_on_clk(RCC_CLK_PLL);
+ while(!rcc_is_clk_ready(RCC_CLK_PLL))
+ ;
+
+ // Finally, switch to the now-ready PLL as the main clock source.
+ rcc_switch_sysclk(RCC_CLKSRC_PLL);
}
-static void setupNVIC() {
+static void setup_nvic(void) {
#ifdef VECT_TAB_FLASH
nvic_init(USER_ADDR_ROM, 0);
#elif defined VECT_TAB_RAM
@@ -105,31 +151,17 @@ static void setupNVIC() {
#endif
}
-static void adcDefaultConfig(const adc_dev* dev);
-
-static void setupADC() {
- rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_6);
- adc_foreach(adcDefaultConfig);
+static void adc_default_config(const adc_dev *dev) {
+ adc_enable_single_swstart(dev);
+ adc_set_sample_rate(dev, wirish::priv::w_adc_smp);
}
-static void timerDefaultConfig(timer_dev*);
-
-static void setupTimers() {
- timer_foreach(timerDefaultConfig);
+static void setup_adcs(void) {
+ adc_set_prescaler(wirish::priv::w_adc_pre);
+ adc_foreach(adc_default_config);
}
-static void adcDefaultConfig(const adc_dev *dev) {
- adc_init(dev);
-
- adc_set_extsel(dev, ADC_SWSTART);
- adc_set_exttrig(dev, true);
-
- adc_enable(dev);
- adc_calibrate(dev);
- adc_set_sample_rate(dev, ADC_SMPR_55_5);
-}
-
-static void timerDefaultConfig(timer_dev *dev) {
+static void timer_default_config(timer_dev *dev) {
timer_adv_reg_map *regs = (dev->regs).adv;
const uint16 full_overflow = 0xFFFF;
const uint16 half_duty = 0x8FFF;
@@ -142,22 +174,28 @@ static void timerDefaultConfig(timer_dev *dev) {
regs->SR = 0;
regs->DIER = 0;
regs->EGR = TIMER_EGR_UG;
-
switch (dev->type) {
case TIMER_ADVANCED:
regs->BDTR = TIMER_BDTR_MOE | TIMER_BDTR_LOCK_OFF;
// fall-through
case TIMER_GENERAL:
timer_set_reload(dev, full_overflow);
-
- for (int channel = 1; channel <= 4; channel++) {
- timer_set_compare(dev, channel, half_duty);
- timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE);
+ for (uint8 channel = 1; channel <= 4; channel++) {
+ if (timer_has_cc_channel(dev, channel)) {
+ timer_set_compare(dev, channel, half_duty);
+ timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1,
+ TIMER_OC_PE);
+ }
}
// fall-through
case TIMER_BASIC:
break;
}
+ timer_generate_update(dev);
timer_resume(dev);
}
+
+static void setup_timers(void) {
+ timer_foreach(timer_default_config);
+}