178 lines
4.1 KiB
C
178 lines
4.1 KiB
C
|
/*
|
||
|
* (c) danielinux 2019
|
||
|
*
|
||
|
* GPLv.2
|
||
|
*
|
||
|
* See LICENSE for details
|
||
|
*/
|
||
|
#include <stdint.h>
|
||
|
#include "system.h"
|
||
|
|
||
|
uint32_t cpu_freq = 84000000;
|
||
|
/*** FLASH ***/
|
||
|
#define FLASH_BASE (0x40023C00)
|
||
|
#define FLASH_ACR (*(volatile uint32_t *)(FLASH_BASE + 0x00))
|
||
|
#define FLASH_ACR_ENABLE_DATA_CACHE (1 << 10)
|
||
|
#define FLASH_ACR_ENABLE_INST_CACHE (1 << 9)
|
||
|
|
||
|
static void flash_set_waitstates(int waitstates)
|
||
|
{
|
||
|
FLASH_ACR |= waitstates | FLASH_ACR_ENABLE_DATA_CACHE | FLASH_ACR_ENABLE_INST_CACHE;
|
||
|
}
|
||
|
/*** RCC ***/
|
||
|
|
||
|
#define RCC_BASE (0x40023800)
|
||
|
#define RCC_CR (*(volatile uint32_t *)(RCC_BASE + 0x00))
|
||
|
#define RCC_PLLCFGR (*(volatile uint32_t *)(RCC_BASE + 0x04))
|
||
|
#define RCC_CFGR (*(volatile uint32_t *)(RCC_BASE + 0x08))
|
||
|
#define RCC_CR_PLLRDY (1 << 25)
|
||
|
#define RCC_CR_PLLON (1 << 24)
|
||
|
#define RCC_CR_HSERDY (1 << 17)
|
||
|
#define RCC_CR_HSEON (1 << 16)
|
||
|
#define RCC_CR_HSIRDY (1 << 1)
|
||
|
#define RCC_CR_HSION (1 << 0)
|
||
|
|
||
|
#define RCC_CFGR_SW_HSI 0x0
|
||
|
#define RCC_CFGR_SW_HSE 0x1
|
||
|
#define RCC_CFGR_SW_PLL 0x2
|
||
|
|
||
|
|
||
|
#define RCC_PLLCFGR_PLLSRC (1 << 22)
|
||
|
|
||
|
#define RCC_PRESCALER_DIV_NONE 0
|
||
|
#define RCC_PRESCALER_DIV_2 8
|
||
|
#define RCC_PRESCALER_DIV_4 9
|
||
|
|
||
|
|
||
|
void clock_pll_off(void)
|
||
|
{
|
||
|
uint32_t reg32;
|
||
|
/* Enable internal high-speed oscillator. */
|
||
|
RCC_CR |= RCC_CR_HSION;
|
||
|
DMB();
|
||
|
while ((RCC_CR & RCC_CR_HSIRDY) == 0) {};
|
||
|
|
||
|
/* Select HSI as SYSCLK source. */
|
||
|
reg32 = RCC_CFGR;
|
||
|
reg32 &= ~((1 << 1) | (1 << 0));
|
||
|
RCC_CFGR = (reg32 | RCC_CFGR_SW_HSI);
|
||
|
DMB();
|
||
|
|
||
|
/* Turn off PLL */
|
||
|
RCC_CR &= ~RCC_CR_PLLON;
|
||
|
DMB();
|
||
|
}
|
||
|
|
||
|
|
||
|
void clock_pll_on(int powersave)
|
||
|
{
|
||
|
uint32_t reg32;
|
||
|
uint32_t plln, pllm, pllq, pllp, pllr, hpre, ppre1, ppre2, flash_waitstates;
|
||
|
|
||
|
/* Enable Power controller */
|
||
|
APB1_CLOCK_ER |= PWR_APB1_CLOCK_ER_VAL;
|
||
|
|
||
|
/* Select clock parameters */
|
||
|
cpu_freq = 84000000 ;
|
||
|
pllm = 12;
|
||
|
plln = 336;
|
||
|
pllp = 4;
|
||
|
pllq = 7;
|
||
|
pllr = 0;
|
||
|
hpre = RCC_PRESCALER_DIV_NONE;
|
||
|
ppre1 = RCC_PRESCALER_DIV_2;
|
||
|
ppre2 = RCC_PRESCALER_DIV_NONE;
|
||
|
flash_waitstates = 2;
|
||
|
|
||
|
flash_set_waitstates(flash_waitstates);
|
||
|
|
||
|
/* Enable internal high-speed oscillator. */
|
||
|
RCC_CR |= RCC_CR_HSION;
|
||
|
DMB();
|
||
|
while ((RCC_CR & RCC_CR_HSIRDY) == 0) {};
|
||
|
|
||
|
/* Select HSI as SYSCLK source. */
|
||
|
reg32 = RCC_CFGR;
|
||
|
reg32 &= ~((1 << 1) | (1 << 0));
|
||
|
RCC_CFGR = (reg32 | RCC_CFGR_SW_HSI);
|
||
|
DMB();
|
||
|
|
||
|
/* Enable external high-speed oscillator 12MHz. */
|
||
|
RCC_CR |= RCC_CR_HSEON;
|
||
|
DMB();
|
||
|
while ((RCC_CR & RCC_CR_HSERDY) == 0) {};
|
||
|
|
||
|
/*
|
||
|
* Set prescalers for AHB, ADC, ABP1, ABP2.
|
||
|
*/
|
||
|
reg32 = RCC_CFGR;
|
||
|
reg32 &= ~(0xF0);
|
||
|
RCC_CFGR = (reg32 | (hpre << 4));
|
||
|
DMB();
|
||
|
reg32 = RCC_CFGR;
|
||
|
reg32 &= ~(0x1C00);
|
||
|
RCC_CFGR = (reg32 | (ppre1 << 10));
|
||
|
DMB();
|
||
|
reg32 = RCC_CFGR;
|
||
|
reg32 &= ~(0x07 << 13);
|
||
|
RCC_CFGR = (reg32 | (ppre2 << 13));
|
||
|
DMB();
|
||
|
|
||
|
/* Set PLL config */
|
||
|
reg32 = RCC_PLLCFGR;
|
||
|
reg32 &= ~(PLL_FULL_MASK);
|
||
|
RCC_PLLCFGR = reg32 | RCC_PLLCFGR_PLLSRC | pllm |
|
||
|
(plln << 6) | (((pllp >> 1) - 1) << 16) |
|
||
|
(pllq << 24);
|
||
|
DMB();
|
||
|
|
||
|
/* Enable power-save mode if selected */
|
||
|
if (powersave) {
|
||
|
POW_CR |= (POW_CR_VOS);
|
||
|
}
|
||
|
|
||
|
/* Enable PLL oscillator and wait for it to stabilize. */
|
||
|
RCC_CR |= RCC_CR_PLLON;
|
||
|
DMB();
|
||
|
while ((RCC_CR & RCC_CR_PLLRDY) == 0) {};
|
||
|
|
||
|
/* Select PLL as SYSCLK source. */
|
||
|
reg32 = RCC_CFGR;
|
||
|
reg32 &= ~((1 << 1) | (1 << 0));
|
||
|
RCC_CFGR = (reg32 | RCC_CFGR_SW_PLL);
|
||
|
DMB();
|
||
|
|
||
|
/* Wait for PLL clock to be selected. */
|
||
|
while (((RCC_CFGR & ((1 << 3) | (1 << 2))) >> 2) != RCC_CFGR_SW_PLL) {};
|
||
|
|
||
|
/* Disable internal high-speed oscillator. */
|
||
|
RCC_CR &= ~RCC_CR_HSION;
|
||
|
}
|
||
|
|
||
|
void *__attribute__((weak)) memcpy(void *d, void *s, uint32_t len)
|
||
|
{
|
||
|
uint32_t *src, *dst;
|
||
|
uint8_t *sb, *db;
|
||
|
src = s;
|
||
|
dst = d;
|
||
|
while(len > 3) {
|
||
|
*(dst++) = *(src++);
|
||
|
len -= 4;
|
||
|
}
|
||
|
sb = (uint8_t *)src;
|
||
|
db = (uint8_t *)dst;
|
||
|
while(len > 0) {
|
||
|
*(db++) = *(sb++);
|
||
|
len--;
|
||
|
}
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
void panic(void)
|
||
|
{
|
||
|
printf("PANIC!");
|
||
|
while(1)
|
||
|
;
|
||
|
}
|
||
|
|