Configure system clock to run at 96Mhz

This commit is contained in:
Alexander Heldt
2024-07-31 11:57:35 +02:00
parent 0fec3d6a6c
commit d9389b4eb8
9 changed files with 1252 additions and 527 deletions

View File

@@ -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)

View File

@@ -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
View 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

View File

@@ -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