diff options
Diffstat (limited to 'wirish/boards.cpp')
-rw-r--r-- | wirish/boards.cpp | 178 |
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); +} |