diff options
Diffstat (limited to 'system-clock/src')
-rw-r--r-- | system-clock/src/clock.c | 149 | ||||
-rw-r--r-- | system-clock/src/gpio.c | 48 | ||||
-rw-r--r-- | system-clock/src/main.c | 183 |
3 files changed, 380 insertions, 0 deletions
diff --git a/system-clock/src/clock.c b/system-clock/src/clock.c new file mode 100644 index 0000000..b846ceb --- /dev/null +++ b/system-clock/src/clock.c @@ -0,0 +1,149 @@ +/* + * This file sets the system clock to its full glory of 80Mhz + */ + +#include "clock.h" +#include <stdint.h> + +#define RCC_CR_HSERDY ((uint32_t)0x00020000) /* High-speed clock ready? */ +#define RCC_CR_HSEON ((uint32_t)0x00020000) /*!< External High Speed clock ready flag */ + +#define FLASH_ACR_LATENCY ((uint32_t)0x00000001) /*!< Latency */ +#define FLASH_ACR_PRFTEN ((uint32_t)0x00000002) /*!< Prefetch Buffer Enable */ +#define FLASH_ACR_ACC64 ((uint32_t)0x00000004) /*!< Access 64 bits */ + +#define RCC_APB1ENR_PWREN ((uint32_t)0x10000000) /*!< Power interface clock enable */ +#define PWR_CR_VOS_0 ((uint16_t)0x0800) /*!< Bit 0 */ + +/*!< HPRE configuration */ +#define RCC_CFGR_HPRE_DIV1 ((uint32_t)0x00000000) /*!< SYSCLK not divided */ +#define RCC_CFGR_HPRE_DIV2 ((uint32_t)0x00000080) /*!< SYSCLK divided by 2 */ +#define RCC_CFGR_HPRE_DIV4 ((uint32_t)0x00000090) /*!< SYSCLK divided by 4 */ +#define RCC_CFGR_HPRE_DIV8 ((uint32_t)0x000000A0) /*!< SYSCLK divided by 8 */ +#define RCC_CFGR_HPRE_DIV16 ((uint32_t)0x000000B0) /*!< SYSCLK divided by 16 */ +#define RCC_CFGR_HPRE_DIV64 ((uint32_t)0x000000C0) /*!< SYSCLK divided by 64 */ +#define RCC_CFGR_HPRE_DIV128 ((uint32_t)0x000000D0) /*!< SYSCLK divided by 128 */ +#define RCC_CFGR_HPRE_DIV256 ((uint32_t)0x000000E0) /*!< SYSCLK divided by 256 */ +#define RCC_CFGR_HPRE_DIV512 ((uint32_t)0x000000F0) /*!< SYSCLK divided by 512 */ + +#define RCC_CFGR_PPRE1 ((uint32_t)0x00000700) /*!< PRE1[2:0] bits (APB1 prescaler) */ +#define RCC_CFGR_PPRE1_0 ((uint32_t)0x00000100) /*!< Bit 0 */ +#define RCC_CFGR_PPRE1_1 ((uint32_t)0x00000200) /*!< Bit 1 */ +#define RCC_CFGR_PPRE1_2 ((uint32_t)0x00000400) /*!< Bit 2 */ + +/*!< PPRE1 configuration */ +#define RCC_CFGR_PPRE1_DIV1 ((uint32_t)0x00000000) /*!< HCLK not divided */ +#define RCC_CFGR_PPRE1_DIV2 ((uint32_t)0x00000400) /*!< HCLK divided by 2 */ +#define RCC_CFGR_PPRE1_DIV4 ((uint32_t)0x00000500) /*!< HCLK divided by 4 */ +#define RCC_CFGR_PPRE1_DIV8 ((uint32_t)0x00000600) /*!< HCLK divided by 8 */ +#define RCC_CFGR_PPRE1_DIV16 ((uint32_t)0x00000700) /*!< HCLK divided by 16 */ + +#define RCC_CFGR_PPRE2 ((uint32_t)0x00003800) /*!< PRE2[2:0] bits (APB2 prescaler) */ +#define RCC_CFGR_PPRE2_0 ((uint32_t)0x00000800) /*!< Bit 0 */ +#define RCC_CFGR_PPRE2_1 ((uint32_t)0x00001000) /*!< Bit 1 */ +#define RCC_CFGR_PPRE2_2 ((uint32_t)0x00002000) /*!< Bit 2 */ + +/*!< PPRE2 configuration */ +#define RCC_CFGR_PPRE2_DIV1 ((uint32_t)0x00000000) /*!< HCLK not divided */ +#define RCC_CFGR_PPRE2_DIV2 ((uint32_t)0x00002000) /*!< HCLK divided by 2 */ +#define RCC_CFGR_PPRE2_DIV4 ((uint32_t)0x00002800) /*!< HCLK divided by 4 */ +#define RCC_CFGR_PPRE2_DIV8 ((uint32_t)0x00003000) /*!< HCLK divided by 8 */ +#define RCC_CFGR_PPRE2_DIV16 ((uint32_t)0x00003800) /*!< HCLK divided by 16 */ +#define RCC_CFGR_PLLMUL ((uint32_t)0x003C0000) /*!< PLLMUL[3:0] bits (PLL multiplication factor) */ +#define RCC_CFGR_PLLDIV ((uint32_t)0x00C00000) /*!< PLLDIV[1:0] bits (PLL Output Division) */ + +#define RCC_CFGR_PLLSRC ((uint32_t)0x00010000) /*!< PLL entry clock source */ +#define RCC_CFGR_PLLSRC_HSE ((uint32_t)0x00010000) /*!< HSE as PLL entry clock source */ +#define RCC_CFGR_PLLMUL8 ((uint32_t)0x000C0000) /*!< PLL input clock * 8 */ +#define RCC_CFGR_PLLDIV2 ((uint32_t)0x00400000) /*!< PLL clock output = CKVCO / 2 */ +#define RCC_CR_PLLON ((uint32_t)0x01000000) /*!< PLL enable */ +#define RCC_CR_PLLRDY ((uint32_t)0x02000000) /*!< PLL clock ready flag */ +#define RCC_CFGR_SW ((uint32_t)0x00000003) /*!< SW[1:0] bits (System clock Switch) */ +#define RCC_CFGR_SW_PLL ((uint32_t)0x00000003) /*!< PLL selected as system clock */ +#define RCC_CFGR_SWS ((uint32_t)0x0000000C) /*!< SWS[1:0] bits (System Clock Switch Status) */ +#define RCC_CFGR_SWS_PLL ((uint32_t)0x0000000C) /*!< PLL used as system clock */ + +inline int is_hse_ready() +{ + return RCC.cr & RCC_CR_HSERDY; +} + +inline void hse_on() +{ + RCC.cr |= RCC_CR_HSEON; +} + +#define TIMER 1000000 +int set_sys_clock() +{ + uint32_t c = 0; /* Time the PLL startup. */ + + /* Turn on the HSE */ + hse_on(); + + /* Wait 'til ready, or if it takes tool long, (c == TIMER). */ + for (c = 0; !is_hse_ready() && c < TIMER; ++ c); + + if (c == TIMER) { + /* The HSE never came up. That's not cool! */ + return -1; + } + + /* The HSE came up, now we just need to set it to be the main clock. */ + + /* Don't really know why we're touching the flash registers ... */ + FLASH.acr |= FLASH_ACR_ACC64; /* Enable 64-bit access. */ + FLASH.acr |= FLASH_ACR_PRFTEN; /* Enable prefetch buffer. */ + FLASH.acr |= FLASH_ACR_LATENCY; /* Flash 1 wait state. */ + + RCC.apb1enr |= RCC_APB1ENR_PWREN; /* Enable power. */ + PWR.cr = PWR_CR_VOS_0; /* Set voltage to 1.8v. */ + + /* Wait for the vwoltage regulator to turn on. */ + for (c = 0; (PWR.csr & PWR_CSR_VOSF) && c < TIMER; ++ c); + + if (c == TIMER) { + /* Timeout occurred. */ + return -2; + } + + RCC.cfgr |= RCC_CFGR_HPRE_DIV1; /* HCLK = SYSCLK/1. */ + RCC.cfgr |= RCC_CFGR_PPRE2_DIV1; /* PCLK2 = HCLK/1 */ + RCC.cfgr |= RCC_CFGR_PPRE1_DIV1; /* PCLK1 = HCLK/1 */ + + /* PLL Configuration */ + RCC.cfgr &= ~( + RCC_CFGR_PLLSRC | + RCC_CFGR_PLLMUL | + RCC_CFGR_PLLDIV ); + + RCC.cfgr |= + RCC_CFGR_PLLSRC_HSE | + RCC_CFGR_PLLMUL8 | + RCC_CFGR_PLLDIV2; + + /* Enable the PLL. */ + RCC.cr |= RCC_CR_PLLON; + + /* Wait for PLL to become ready. */ + for(c = 0; !(RCC.cr & RCC_CR_PLLRDY) && c < TIMER; ++ c); + + if (c == TIMER) { + /* Timeout occurred. */ + return -3; + } + + /* Set PLL as the system clock. */ + RCC.cfgr &= ~RCC_CFGR_SW; + RCC.cfgr |= RCC_CFGR_SW_PLL; + + /* Wait for PLL to be used as system clock. */ + for (c = 0; (RCC.cfgr & RCC_CFGR_SWS) != RCC_CFGR_SW_PLL && c < TIMER; ++ c); + + if (c == TIMER) { + /* Timeout occurred. */ + return -4; + } + + return 0; +} diff --git a/system-clock/src/gpio.c b/system-clock/src/gpio.c new file mode 100644 index 0000000..ab3606d --- /dev/null +++ b/system-clock/src/gpio.c @@ -0,0 +1,48 @@ +#include "gpio.h" + +/* + * Sets the mode of a pin on a gpio por. + */ +void set_gpio_pin_mode( + __IO gpio_port_t* gpio_port, + gpio_pin_t pin, + gpio_pin_mode_t mode) +{ + /* Each pin has a 2-bit mode provided at bits pin#*2 and pin#*2+1 */ + gpio_port->mode_r &= ~(0x03 << pin * 2); + gpio_port->mode_r |= mode << pin * 2; +} + + +gpio_output_pin_t set_gpio_pin_output( + __IO gpio_port_t* gpio_port, + gpio_pin_t pin) +{ + set_gpio_pin_mode(gpio_port, pin, MODE_OUTPUT); + + return (gpio_output_pin_t) { + .gpio_port = gpio_port, + .pin = pin + }; +} + +void set_gpio_output_pin( + gpio_output_pin_t pin, + bool onoff) +{ + if (onoff) { + pin.gpio_port->output_r |= 1 << pin.pin; + } else { + pin.gpio_port->output_r &= ~(1 << pin.pin); + } +} + +#define GPIO_PORTS_BASE_ADDR ((uint32_t)0x48000000) +#define RCC_BASE ((uint32_t)0x40021000) +#define RCC_AHB2ENR (*((__IO uint32_t*) (RCC_BASE + 0x4c))) +__IO gpio_port_t* enable_gpio(gpio_port_number_t gpio_port_number) +{ + RCC_AHB2ENR |= 1 << gpio_port_number; /* Enable the port. */ + return + (__IO gpio_port_t*) (GPIO_PORTS_BASE_ADDR + (gpio_port_number * 0x400)); +} diff --git a/system-clock/src/main.c b/system-clock/src/main.c new file mode 100644 index 0000000..f7a30e8 --- /dev/null +++ b/system-clock/src/main.c @@ -0,0 +1,183 @@ +#include "gpio.h" + +int main(); + +void spin(); + +/* + * Interrupt service routine handlers. + */ +const void* vectors[] __attribute__((section(".vectors"))) = { + (void *) 0x2000c000, /* Top of stack at top of sram1. 48k */ + main, /* Reset handler */ + spin, /* NMI */ + spin, /* Hard Fault */ + spin, /* MemManage */ + spin, /* BusFault */ + spin, /* UsageFault */ + spin, /* Reserved */ + spin, /* Reserved */ + spin, /* Reserved */ + spin, /* Reserved */ + spin, /* SVCall */ + spin, /* Debug */ + spin, /* Reserved */ + spin, /* PendSV */ + spin, /* SysTick */ + +/* External interrupt handlers follow */ + spin, /* 0 WWDG */ + spin, /* 1 PVD */ + spin, /* 2 TAMP_SAMP */ + spin, /* 3 RTC_WKUP */ + spin, /* 4 FLASH */ + spin, /* 5 RCC */ + spin, /* 6 EXTI0 */ + spin, /* 7 EXTI1 */ + spin, /* 8 EXTI2 */ + spin, /* 9 EXTI3 */ + spin, /* 10 EXTI4 */ + spin, /* 11 DMA_CH1 */ + spin, /* 12 DMA_CH2 */ + spin, /* 13 DMA_CH3 */ + spin, /* 14 DMA_CH4 */ + spin, /* 15 DMA_CH5 */ + spin, /* 16 DMA_CH6 */ + spin, /* 17 DMA_CH7 */ + spin, /* 18 ADC1 */ + spin, /* 19 CAN_TX */ + spin, /* 20 CAN_RX0 */ + spin, /* 21 CAN_RX1 */ + spin, /* 22 CAN_SCE */ + spin, /* 23 EXTI9_5 */ + spin, /* 24 TIM1_BRK/TIM15 */ + spin, /* 25 TIM1_UP/TIM16 */ + spin, /* 26 TIM1_TRG_COM */ + spin, /* 27 TIM1_CC */ + spin, /* 28 TIM2 */ + spin, /* 29 Reserved */ + spin, /* 30 Reserved */ + spin, /* 31 I2C1_EV */ + spin, /* 32 I2C1_ER */ + spin, /* 33 I2C2_EV */ + spin, /* 34 I2C2_ER */ + spin, /* 35 SPI1 */ + spin, /* 36 SPI2 */ + spin, /* 37 USART1 */ + spin, /* 38 USART2 */ + spin, /* 39 USART3 */ + spin, /* 40 EXTI15_10 */ + spin, /* 41 RTCAlarm */ + spin, /* 42 Reserved */ + spin, /* 43 Reserved */ + spin, /* 44 Reserved */ + spin, /* 45 Reserved */ + spin, /* 46 Reserved */ + spin, /* 47 Reserved */ + spin, /* 48 Reserved */ + spin, /* 49 SDMMC1 */ + spin, /* 50 Reserved */ + spin, /* 51 SPI3 */ + spin, /* 52 Reserved */ + spin, /* 53 Reserved */ + spin, /* 54 TIM6_DACUNDER */ + spin, /* 55 TIM7 */ + spin, /* 56 DMA2_CH1 */ + spin, /* 57 DMA2_CH2 */ + spin, /* 58 DMA2_CH3 */ + spin, /* 59 DMA2_CH4 */ + spin, /* 60 DMA2_CH5 */ + spin, /* 61 Reserved */ + spin, /* 62 Reserved */ + spin, /* 63 Reserved*/ + spin, /* 64 COMP */ + spin, /* 65 LPTIM1 */ + spin, /* 66 LPTIM2 */ + spin, /* 67 USB_FS */ + spin, /* 68 DMA_CH6 */ + spin, /* 69 DMA_CH7 */ + spin, /* 70 LPUART1 */ + spin, /* 71 QUADSPI */ + spin, /* 72 I2C3_EV */ + spin, /* 73 I2C3_ER */ + spin, /* 74 SAI1 */ + spin, /* 75 Reserved */ + spin, /* 76 SWPMI1 */ + spin, /* 77 TSC */ + spin, /* 78 Reserved */ + spin, /* 79 AES */ + spin, /* 80 RNG */ + spin, /* 81 FPU */ + spin /* 82 CRS */ +}; + +/* Delay for some number of iterations. */ +void delay(uint32_t itrs) +{ + /* Need to keep the compiler from optimizing this loop out entirely. */ + while(itrs --) { + asm volatile (""); + } +} + +/* Main function. This gets executed from the interrupt vector defined above. */ +int main() +{ + /* Enable the GPIO port B. */ + + __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); + gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); + gpio_output_pin_t pin1 = set_gpio_pin_output(port_b, PIN_1); + + while(1) { + /* Set the GPIO pin to high. */ + pin_on(pin3); + pin_off(pin1); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + + /* Set the GPIO pin to low. */ + pin_off(pin3); + pin_on(pin1); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + delay(65535); + } +} + +/* + * Does nothing ... forever. + */ +void spin() +{ + __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); + gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); + for(;;) { + + /* Flash in a distinct pattern to know that something went wrong. */ + + pin_off(pin3); + delay(100000); + pin_on(pin3); + delay(100000); + pin_off(pin3); + delay(100000); + pin_on(pin3); + delay(500000); + } +} |