summaryrefslogtreecommitdiffstats
path: root/boot/bootloader.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot/bootloader.c')
-rw-r--r--boot/bootloader.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/boot/bootloader.c b/boot/bootloader.c
new file mode 100644
index 0000000..27b6b98
--- /dev/null
+++ b/boot/bootloader.c
@@ -0,0 +1,139 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "project.h"
+
+
+#define BOOTLOADER_BUTTON GPIO15
+#define BOOTLOADER_BUTTON_PORT GPIOE
+
+
+static const clock_scale_t hsi_16mhz_3v3_48 = {
+ /* 48MHz */
+ .pllm = 16,
+ .plln = 96,
+ .pllp = 2,
+ .pllq = 2,
+ .hpre = RCC_CFGR_HPRE_DIV_NONE,
+ .ppre1 = RCC_CFGR_PPRE_DIV_4,
+ .ppre2 = RCC_CFGR_PPRE_DIV_2,
+ .power_save = 1,
+ .flash_config = FLASH_ACR_ICE | FLASH_ACR_DCE |
+ FLASH_ACR_LATENCY_3WS,
+ .apb1_frequency = 12000000,
+ .apb2_frequency = 24000000,
+};
+
+static void rcc_clock_setup_hsi_3v3 (const clock_scale_t *clock)
+{
+
+ /* Enable internal high-speed oscillator. */
+ rcc_osc_on (HSI);
+ rcc_wait_for_osc_ready (HSI);
+
+ /* Select HSI as SYSCLK source. */
+ rcc_set_sysclk_source (RCC_CFGR_SW_HSI);
+ rcc_wait_for_sysclk_status (HSI);
+
+ rcc_osc_off (PLL);
+
+ while (RCC_CR & RCC_CR_PLLRDY);
+
+ pwr_set_vos_scale (SCALE1);
+
+ /*
+ * Set prescalers for AHB, ADC, ABP1, ABP2.
+ * Do this before touching the PLL (TODO: why?).
+ */
+ rcc_set_hpre (clock->hpre);
+ rcc_set_ppre1 (clock->ppre1);
+ rcc_set_ppre2 (clock->ppre2);
+
+ rcc_set_main_pll_hsi (clock->pllm, clock->plln,
+ clock->pllp, clock->pllq);
+
+ /* Enable PLL oscillator and wait for it to stabilize. */
+ rcc_osc_on (PLL);
+ rcc_wait_for_osc_ready (PLL);
+
+ /* Configure flash settings. */
+ flash_set_ws (clock->flash_config);
+
+ /* Select PLL as SYSCLK source. */
+ rcc_set_sysclk_source (RCC_CFGR_SW_PLL);
+
+ /* Wait for PLL clock to be selected. */
+ rcc_wait_for_sysclk_status (PLL);
+
+ /* Set the peripheral clock frequencies used. */
+ rcc_apb1_frequency = clock->apb1_frequency;
+ rcc_apb2_frequency = clock->apb2_frequency;
+
+}
+
+
+int main (void)
+{
+
+ rcc_periph_clock_enable (RCC_GPIOE);
+ MAP_INPUT_PU (BOOTLOADER_BUTTON);
+
+
+ if ((dfu_flag != 0xfee1dead) && (GET(BOOTLOADER_BUTTON))) {
+ /* Boot the application if it's valid. */
+ if ((* (volatile uint32_t *)APP_ADDRESS & 0x2FFE0000) == 0x20020000) {
+ /* Set vector table base address. */
+ SCB_VTOR = APP_ADDRESS & 0xFFFF;
+ /* Initialise master stack pointer. */
+ asm volatile ("msr msp, %0\n"
+ "blx %1\n" ::
+ "g" (* (volatile uint32_t *)APP_ADDRESS),
+ "r" (* (uint32_t *) (APP_ADDRESS + 4))
+ : "memory");
+ }
+ }
+
+
+
+
+ dfu_flag = 0;
+
+ rcc_periph_clock_enable (RCC_SYSCFG);
+ rcc_periph_clock_enable (RCC_GPIOB);
+ rcc_periph_clock_enable (RCC_GPIOG);
+
+ rcc_clock_setup_hsi_3v3 (&hsi_16mhz_3v3_48);
+
+ RCC_AHB1RSTR |= RCC_AHB1RSTR_ETHMACRST;
+ RCC_AHB2RSTR |= RCC_AHB2RSTR_OTGFSRST;
+ asm ("nop":::"memory");
+ RCC_AHB2RSTR &= ~RCC_AHB2RSTR_OTGFSRST;
+ RCC_AHB1RSTR &= ~RCC_AHB1RSTR_ETHMACRST;
+
+ max7219_init();
+
+ usart_init();
+ usart2_xmit_str("\r\nDFU Bootloader\r\n");
+ delay_ms (100);
+ usart_init();
+ usart2_xmit_str ("Ready\r\n");
+
+
+ usb();
+}