blob: 3562252911d110dd18358e7ecbb8eb9c8ec3bd10 [file] [log] [blame]
Brian Silverman44311d62013-12-06 22:03:29 -08001#include <stdint.h>
2
Brian Silverman1b6fbd02013-12-12 18:08:47 -08003#include <STM32F2XX.h>
4
Brian Silverman44311d62013-12-06 22:03:29 -08005#include "cape/bootloader_handoff.h"
Brian Silvermaned183e62013-12-18 15:51:16 -08006#include "cape/led.h"
Brian Silverman44311d62013-12-06 22:03:29 -08007
8// Sets everything up and then jumps to the main code.
9static void jump_to_main(void) __attribute__((noreturn));
10static void jump_to_main(void) {
Brian Silvermanaa9183a2013-12-08 10:33:47 -080011 __asm__ __volatile__(
Brian Silverman44311d62013-12-06 22:03:29 -080012 "mov sp, %[stack]\n\t"
13 "bx %[reset]" : :
14 [stack]"r"(RAM_START + RAM_SIZE), [reset]"r"(MAIN_FLASH_START | 1)
15 : "memory");
16 __builtin_unreachable();
17}
18
Brian Silvermaned183e62013-12-18 15:51:16 -080019static void setup_main_clock(void) {
20 // We set up a couple of registers here separately from the actual register to
21 // avoid having to think about what happens when the value is in some
22 // intermediate state.
Brian Silverman1b6fbd02013-12-12 18:08:47 -080023
Brian Silvermaned183e62013-12-18 15:51:16 -080024 RCC->CR |= RCC_CR_HSEON; // get the HSE oscillator going
25
26 FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN |
27 FLASH_ACR_LATENCY_3WS;
28
29 uint32_t rcc_pllcfgr = 0;
30 rcc_pllcfgr |= RCC_PLLCFGR_PLLSRC; // use the external oscillator
31 // 8MHz * 120 / 4 / 2 = 120MHz
32 rcc_pllcfgr |= 120 << 6; // multiplier
33 rcc_pllcfgr |= 4; // divider
34 rcc_pllcfgr |= 5 << 24; // other stuff divider = 5, just in case
35 RCC->PLLCFGR = rcc_pllcfgr;
36
37 uint32_t rcc_cfgr = 0;
38 rcc_cfgr |= 4 << 13; // APB2 divider = 2
39 rcc_cfgr |= 5 << 10; // APB1 divider = 4
40 rcc_cfgr |= 2; // use the PLL
41
42 // Wait for the HSE oscillator to be stable.
43 while (!(RCC->CR & RCC_CR_HSERDY)) {}
44
45 RCC->CR |= RCC_CR_PLLON;
46 // Wait for the main PLL to be stable.
47 while (!(RCC->CR & RCC_CR_PLLRDY)) {}
48 // Wait until the flash is using 3 wait states.
49 while ((FLASH->ACR & 7) != 3) {}
50 RCC->CFGR = rcc_cfgr;
51 // Wait until we are using the PLL as our main clock source.
52 while ((RCC->CFGR & (3 << 2)) != (2 << 2)) {}
53}
54
55void _start(void) {
56 // Enable the GPIO pin clocks.
Brian Silverman1b6fbd02013-12-12 18:08:47 -080057 // We don't have anything on the 1 port D pin, so don't bother enabling it.
Brian Silvermaned183e62013-12-18 15:51:16 -080058 RCC->AHB1ENR |=
59 RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
60 led_init();
Brian Silverman176c6762013-12-19 16:28:09 -080061 led_set(LED_HB, 1);
Brian Silvermaned183e62013-12-18 15:51:16 -080062
63 setup_main_clock();
64
Brian Silverman3e0a05b2013-12-22 11:33:42 -080065 RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
Brian Silvermaned183e62013-12-18 15:51:16 -080066 SYSCFG->CMPCR |= SYSCFG_CMPCR_CMP_PD; // enable IO compensation cell
67 while (!(SYSCFG->CMPCR & SYSCFG_CMPCR_READY)) {} // wait for it to be ready
Brian Silverman1b6fbd02013-12-12 18:08:47 -080068
Brian Silverman44311d62013-12-06 22:03:29 -080069 jump_to_main();
Brian Silverman5020be62013-12-06 19:09:07 -080070}