152 lines
3.8 KiB
C
152 lines
3.8 KiB
C
|
/*
|
||
|
* This is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License version 2, as
|
||
|
* published by the Free Software Foundation.
|
||
|
*
|
||
|
* this software is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this software. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*
|
||
|
* Author: Daniele Lacamera
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
#include <stdint.h>
|
||
|
#include "system.h"
|
||
|
#include <unicore-mx/stm32/gpio.h>
|
||
|
#include <unicore-mx/stm32/rcc.h>
|
||
|
#include <unicore-mx/cm3/nvic.h>
|
||
|
|
||
|
extern uint32_t cpu_freq;
|
||
|
|
||
|
static void flash_set_waitstates(int waitstates)
|
||
|
{
|
||
|
FLASH_ACR |= waitstates | FLASH_ACR_ENABLE_DATA_CACHE | FLASH_ACR_ENABLE_INST_CACHE;
|
||
|
}
|
||
|
|
||
|
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 = 100000000;
|
||
|
pllm = 12;
|
||
|
plln = 192;
|
||
|
pllp = 2;
|
||
|
pllq = 4;
|
||
|
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 */
|
||
|
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 << 1) | (1 << 0))) != 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;
|
||
|
}
|