diff options
-rw-r--r-- | wirish/boards.cpp | 167 | ||||
-rw-r--r-- | wirish/boards_private.h | 59 | ||||
-rw-r--r-- | wirish/include/wirish/boards.h | 5 | ||||
-rw-r--r-- | wirish/rules.mk | 22 | ||||
-rw-r--r-- | wirish/stm32f1/boards_setup.cpp | 141 | ||||
-rw-r--r-- | wirish/stm32f2/boards_setup.cpp | 75 |
6 files changed, 363 insertions, 106 deletions
diff --git a/wirish/boards.cpp b/wirish/boards.cpp index 5d5ecb5..7d783db 100644 --- a/wirish/boards.cpp +++ b/wirish/boards.cpp @@ -25,49 +25,55 @@ *****************************************************************************/ /** - * @brief Generic board initialization routines. + * @file boards.cpp + * @brief Generic board routines. * * This file is mostly interesting for the init() function, which * configures Flash, the core sytem 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. + * How init() does this is chip-specific. See the chip-specific pieces + * of Wirish (under e.g. wirish/stm32f1/, wirish/stmf32f2) for + * details. * - * Specifically how init() works varies across boards and MCUs. + * Finally, 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. */ #include <wirish/boards.h> - #include <libmaple/flash.h> -#include <libmaple/rcc.h> #include <libmaple/nvic.h> #include <libmaple/systick.h> -#include <libmaple/gpio.h> -#include <libmaple/adc.h> -#include <libmaple/timer.h> -#include <libmaple/usb_cdcacm.h> +#include "boards_private.h" + +static void setup_flash(void); +static void setup_clocks(void); +static void setup_nvic(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(); + wirish::priv::board_setup_adc(); + wirish::priv::board_setup_timers(); + wirish::priv::board_setup_usb(); boardInit(); } +/* Provide a default boardInit(). */ +__attribute__((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...). */ bool boardUsesPin(uint8 pin) { @@ -79,24 +85,56 @@ bool boardUsesPin(uint8 pin) { return false; } -static void setupFlash(void) { - flash_enable_prefetch(); +/* + * Auxiliary routines + */ + +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); } -/* - * 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. - */ -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_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::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 @@ -107,60 +145,3 @@ static void setupNVIC() { #error "You must select a base address for the vector table." #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 timerDefaultConfig(timer_dev*); - -static void setupTimers() { - timer_foreach(timerDefaultConfig); -} - -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) { - timer_adv_reg_map *regs = (dev->regs).adv; - const uint16 full_overflow = 0xFFFF; - const uint16 half_duty = 0x8FFF; - - timer_init(dev); - timer_pause(dev); - - regs->CR1 = TIMER_CR1_ARPE; - regs->PSC = 1; - 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); - } - // fall-through - case TIMER_BASIC: - break; - } - - timer_resume(dev); -} diff --git a/wirish/boards_private.h b/wirish/boards_private.h new file mode 100644 index 0000000..a4101c9 --- /dev/null +++ b/wirish/boards_private.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file wirish/boards_private.h + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief Private board support header. + */ + +#ifndef _WIRISH_BOARDS_PRIVATE_H_ +#define _WIRISH_BOARDS_PRIVATE_H_ + +namespace wirish { + namespace priv { + + /* + * Chip-specific initialization data + */ + + extern rcc_pll_cfg board_pll_cfg; + + /* + * Chip-specific initialization routines and helper functions. + */ + + void board_reset_pll(void); + void board_setup_clock_prescalers(void); + void board_setup_gpio(void); + void board_setup_adc(void); + void board_setup_timers(void); + void board_setup_usb(void); + + } +} + +#endif diff --git a/wirish/include/wirish/boards.h b/wirish/include/wirish/boards.h index e708f79..c762542 100644 --- a/wirish/include/wirish/boards.h +++ b/wirish/include/wirish/boards.h @@ -29,11 +29,6 @@ * @author Bryan Newbold <bnewbold@leaflabs.com>, * Marti Bolivar <mbolivar@leaflabs.com> * @brief Board-specific pin information. - * - * To add a new board type, add a new pair of files to - * /wirish/boards/, update the section below with a new "BOARD" type, - * and update /wirish/rules.mk to include your boards/your_board.cpp - * file in the top-level Makefile build. */ #ifndef _WIRISH_BOARDS_H_ diff --git a/wirish/rules.mk b/wirish/rules.mk index c72e60f..17c4d05 100644 --- a/wirish/rules.mk +++ b/wirish/rules.mk @@ -4,22 +4,26 @@ dirstack_$(sp) := $(d) d := $(dir) BUILDDIRS += $(BUILD_PATH)/$(d) -# Board config -- TODO allow user override -# WIRISH_BOARD_PATH := boards/$(BOARD) -# BUILDDIRS += $(BUILD_PATH)/$(d)/$(WIRISH_BOARD_PATH) +# Add board directory and MCU-specific directory to BUILDDIRS. These +# are in subdirectories, but they're logically part of the Wirish +# submodule. +WIRISH_BOARD_PATH := boards/$(BOARD) +BUILDDIRS += $(BUILD_PATH)/$(d)/$(WIRISH_BOARD_PATH) +BUILDDIRS += $(BUILD_PATH)/$(d)/$(MCU_SERIES) -# WIRISH_INCLUDES := -I$(d)/include -I$(d)/$(WIRISH_BOARD_PATH)/include +# Safe includes for Wirish. +WIRISH_INCLUDES := -I$(d)/include -I$(d)/$(WIRISH_BOARD_PATH)/include -# Local flags -CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) +# Local flags. Add -I$(d) to allow for private includes. +CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) $(WIRISH_INCLUDES) -I$(d) # Local rules and targets - sSRCS_$(d) := start.S cSRCS_$(d) := start_c.c +cppSRCS_$(d) := boards.cpp +# TODO: test these on F2 and put them back in: # cppSRCS_$(d) := wirish_math.cpp \ # Print.cpp \ -# boards.cpp \ # HardwareSerial.cpp \ # HardwareSPI.cpp \ # HardwareTimer.cpp \ @@ -31,7 +35,9 @@ cSRCS_$(d) := start_c.c # pwm.cpp \ # ext_interrupts.cpp \ # wirish_digital.cpp +# TODO: Put this back in once we've got the necessary libmaple support back. # cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp +cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%) cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%) diff --git a/wirish/stm32f1/boards_setup.cpp b/wirish/stm32f1/boards_setup.cpp new file mode 100644 index 0000000..4ee292a --- /dev/null +++ b/wirish/stm32f1/boards_setup.cpp @@ -0,0 +1,141 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*****************************************************************************/ + +/** + * @file wirish/stm32f1/boards_setup.cpp + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief STM32F1 chip setup. + */ + +#include <libmaple/rcc.h> +#include <libmaple/gpio.h> +#include <libmaple/adc.h> +#include <libmaple/timer.h> +#include <libmaple/usb_cdcacm.h> + +#include <board/board.h> + +/* FIXME: Reintroduce all "#if 0"'ed blocks once libmaple provides + * these definitions again. */ + +namespace wirish { + namespace priv { + + static stm32f1_rcc_pll_data pll_data = {RCC_PLLMUL_9}; + rcc_pll_cfg board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + +#if 0 + static void config_adc(const adc_dev* dev); + static void config_timer(timer_dev*); +#endif + + void board_reset_pll(void) { + // TODO + } + + void board_setup_clock_prescalers(void) { + 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); + } + + void board_setup_gpio(void) { + gpio_init_all(); + // Initialize AFIO here, too, so peripheral remaps and external + // interrupts work out of the box. + afio_init(); + } + + void board_setup_adc(void) { +#if 0 + rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_6); + adc_foreach(config_adc); +#endif + } + + void board_setup_timers(void) { +#if 0 + timer_foreach(config_timer); +#endif + } + + void board_setup_usb(void) { +#if 0 + usb_cdcacm_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT); +#endif + } + + /* + * Auxiliary routines + */ + +#if 0 + static void config_adc(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 config_timer(timer_dev *dev) { + timer_adv_reg_map *regs = (dev->regs).adv; + const uint16 full_overflow = 0xFFFF; + const uint16 half_duty = 0x8FFF; + + timer_init(dev); + timer_pause(dev); + + regs->CR1 = TIMER_CR1_ARPE; + regs->PSC = 1; + 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); + } + // fall-through + case TIMER_BASIC: + break; + } + + timer_resume(dev); + } +#endif + } +} diff --git a/wirish/stm32f2/boards_setup.cpp b/wirish/stm32f2/boards_setup.cpp new file mode 100644 index 0000000..b3c690c --- /dev/null +++ b/wirish/stm32f2/boards_setup.cpp @@ -0,0 +1,75 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file wirish/stm32f2/boards_setup.cpp + * @author Marti Bolivar <mbolivar@leaflabs.com> + * @brief STM32F2 chip setup. + */ + +#include <libmaple/rcc.h> +#include <libmaple/gpio.h> + +#define PLL_Q 5 +#define PLL_P 2 +#define PLL_N 240 +#define PLL_M 25 +static stm32f2_rcc_pll_data pll_data = {PLL_Q, PLL_P, PLL_N, PLL_M}; + +namespace wirish { + namespace priv { + rcc_pll_cfg board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data}; + + void board_reset_pll(void) { + // Set PLLCFGR to its reset value. + RCC_BASE->PLLCFGR = 0x24003010; // FIXME lose the magic number. + } + + void board_setup_clock_prescalers(void) { + rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1); + rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_4); + rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_2); + } + + void board_setup_gpio(void) { + gpio_init_all(); + } + + void board_setup_adc(void) { + // TODO + } + + void board_setup_timers(void) { + // TODO + } + + void board_setup_usb(void) { + // TODO + } + + } +} + |