Configure system clock to run at 96Mhz
This commit is contained in:
@@ -17,7 +17,6 @@ struct flash {
|
||||
|
||||
// ACR Register
|
||||
// Data cache enable
|
||||
|
||||
#define FLASH_ACR_DCEN_BIT 10
|
||||
#define FLASH_ACR_DCEN_ENABLE (1 <<FLASH_ACR_DCEN_BIT)
|
||||
|
||||
|
||||
68
src/main.c
68
src/main.c
@@ -1,14 +1,82 @@
|
||||
#include <inttypes.h>
|
||||
#include "rcc.h"
|
||||
#include "gpio.h"
|
||||
#include "flash.h"
|
||||
#include "pwr.h"
|
||||
|
||||
#define exit 42
|
||||
|
||||
static void system_clock_init(void) {
|
||||
// Power on clock for PLL
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN_CLOCK_ENABLE;
|
||||
|
||||
// Set voltage scaling to "high"
|
||||
PWR->CR &= ~(PWR_CR_VOS_MASK << PWR_CR_VOS_BIT);
|
||||
PWR->CR |= (PWR_SCALE3 << PWR_CR_VOS_BIT);
|
||||
|
||||
// Turn on HSE
|
||||
RCC->CR |= RCC_CR_HSEON_ON;
|
||||
|
||||
// Wait indefinitely for HSE to be ready
|
||||
// TODO indicate error/timeout somehow?
|
||||
while (!(RCC->CR & RCC_CR_HSERDY_READY));
|
||||
|
||||
// Disable PLL before changing settings as documentation state
|
||||
// "These bits should be written only if PLL is disabled."
|
||||
RCC->CR &= ~RCC_CR_PLLON_ON;
|
||||
|
||||
// Set HSE as PLL source
|
||||
RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE;
|
||||
|
||||
// Settings to achieve system clock of 96Mhz
|
||||
RCC->PLLCFGR |= RCC_PLLCFGR_PLLM(25) | RCC_PLLCFGR_PLLN(196) | RCC_PLLCFGR_PLLP(2) | RCC_PLLCFGR_PLLQ(4);
|
||||
|
||||
// Set AHB prescalar to /1
|
||||
RCC->CFGR &= ~(RCC_CFGR_HPRE_MASK << RCC_CFGR_HPRE_BIT);
|
||||
RCC->CFGR |= (RCC_CFGR_HPRE_DIV_NONE << RCC_CFGR_HPRE_BIT);
|
||||
|
||||
// Set APB1 prescalar to /2
|
||||
RCC->CFGR &= ~(RCC_CFGR_PPRE1_MASK << RCC_CFGR_PPRE1_BIT);
|
||||
RCC->CFGR |= (RCC_CFGR_PPRE_DIV_2 << RCC_CFGR_PPRE1_BIT);
|
||||
|
||||
// Set APB2 prescalar to /1
|
||||
RCC->CFGR &= ~(RCC_CFGR_PPRE2_MASK << RCC_CFGR_PPRE2_BIT);
|
||||
RCC->CFGR |= (RCC_CFGR_PPRE_DIV_NONE << RCC_CFGR_PPRE2_BIT);
|
||||
|
||||
// Turn PLL back on
|
||||
RCC->CR |= RCC_CR_PLLON_ON;
|
||||
|
||||
// Wait indefinitely for PLL to be ready
|
||||
// TODO indicate error/timeout somehow?
|
||||
while (!(RCC->CR & RCC_CR_HSERDY_READY));
|
||||
|
||||
// Enable caching of instructions and data
|
||||
FLASH->ACR |= FLASH_ACR_DCEN_ENABLE;
|
||||
FLASH->ACR |= FLASH_ACR_ICEN_ENABLE;
|
||||
|
||||
// Set latency to be 3 wait states (TODO: understand why exactly 3)
|
||||
FLASH->ACR &= ~(FLASH_ACR_LATENCY_MASK << FLASH_ACR_LATENCY_BIT);
|
||||
RCC->CFGR |= (FLASH_ACR_LATENCY_3_WAIT_STATES << FLASH_ACR_LATENCY_BIT);
|
||||
|
||||
// Use PLL as system clock
|
||||
RCC->CFGR &= ~(RCC_CFGR_SW_MASK << RCC_CFGR_SW_BIT);
|
||||
RCC->CFGR |= (RCC_CFGR_SW_PLL << RCC_CFGR_SW_BIT);
|
||||
|
||||
// Wait indefinitely for PLL clock to be selected
|
||||
// TODO indicate error/timeout somehow?
|
||||
while (((RCC->CFGR >> RCC_CFGR_SWS_BIT) & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL);
|
||||
|
||||
// Turn off HSI (which is on by default)
|
||||
RCC->CR &= ~RCC_CR_HSION_ON;
|
||||
}
|
||||
|
||||
static inline void spin(volatile uint32_t count) {
|
||||
while (count--) (void) 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
(void) system_clock_init();
|
||||
|
||||
uint16_t led = PIN('C', 13); // Blue LED
|
||||
RCC->AHB1ENR |= BIT(PINPORT(led)); // Enable GPIO clock for LED
|
||||
gpio_set_mode(led, GPIO_MODE_OUTPUT); // Set blue LED to output mode
|
||||
|
||||
22
src/pwr.h
Normal file
22
src/pwr.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef PWR_H_
|
||||
#define PWR_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
struct pwr {
|
||||
volatile uint32_t CR; // Power control register
|
||||
volatile uint32_t CSR; // Power control/status registe
|
||||
};
|
||||
|
||||
#define PWR_BASE_ADDR (0x40007000U)
|
||||
#define PWR ((struct pwr *) PWR_BASE_ADDR)
|
||||
|
||||
// Power control register
|
||||
#define PWR_SCALE3 (0b11)
|
||||
|
||||
// Regulator voltage scaling output selection
|
||||
#define PWR_CR_VOS_BIT 14 // Bits [15:14]
|
||||
#define PWR_CR_VOS_MASK (0b11)
|
||||
#define PWR_CR_VOS(scale) ((scale & PWR_CR_VOS_MASK) << PWR_CR_VOS_BIT)
|
||||
|
||||
#endif
|
||||
16
src/rcc.h
16
src/rcc.h
@@ -44,13 +44,8 @@ struct rcc {
|
||||
|
||||
// PLL toggle
|
||||
#define RCC_CR_PLLON_BIT 24
|
||||
#define RCC_CR_PLLON_OFF (0 << RCC_CR_PLLON_BIT)
|
||||
#define RCC_CR_PLLON_ON (1 << RCC_CR_PLLON_BIT)
|
||||
|
||||
// HSE clock bypass
|
||||
#define RCC_CR_HSEBYP_BIT 18
|
||||
#define RCC_CR_HSEBYP (1 << RCC_CR_HSEBYP_BIT)
|
||||
|
||||
// HSE clock ready flag
|
||||
#define RCC_CR_HSERDY_BIT 17
|
||||
#define RCC_CR_HSERDY_READY (1 << RCC_CR_HSERDY_BIT)
|
||||
@@ -59,8 +54,13 @@ struct rcc {
|
||||
#define RCC_CR_HSEON_BIT 16
|
||||
#define RCC_CR_HSEON_ON (1 << RCC_CR_HSEON_BIT)
|
||||
|
||||
// HSI clock ready flag
|
||||
#define RCC_CR_HSIRDY_BIT 1
|
||||
#define RCC_CR_HSIRDY_READY (1 << RCC_CR_HSIRDY_BIT)
|
||||
|
||||
// HSI clock enable
|
||||
#define RCC_CR_HSION_BIT 0
|
||||
#define RCC_CR_HSION_OFF (0 << RCC_CR_HSION_BIT)
|
||||
#define RCC_CR_HSION_ON (1 << RCC_CR_HSION_BIT)
|
||||
|
||||
// PLLCFGR Register
|
||||
#define RCC_PLLCFGR_PLLQ_BIT 24 // Bits [27:24]
|
||||
@@ -114,4 +114,8 @@ struct rcc {
|
||||
#define RCC_CFGR_SW_MASK (0b11)
|
||||
#define RCC_CFGR_SW(clock) ((clock & RCC_CFGR_SW_MASK) << RCC_CFGR_SW_BIT)
|
||||
|
||||
// APB1ENR Register
|
||||
#define RCC_APB1ENR_PWREN_BIT 28
|
||||
#define RCC_APB1ENR_PWREN_CLOCK_ENABLE (1 << RCC_APB1ENR_PWREN_BIT)
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user