kopia lustrzana https://github.com/OpenRTX/OpenRTX
131 wiersze
5.6 KiB
C++
131 wiersze
5.6 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2018 by Terraneo Federico *
|
|
* 2024 - 2025 by Silvano Seva IU2KWO *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program 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. *
|
|
* *
|
|
* As a special exception, if other files instantiate templates or use *
|
|
* macros or inline functions from this file, or you compile this file *
|
|
* and link it with other works to produce a work based on this file, *
|
|
* this file does not by itself cause the resulting work to be covered *
|
|
* by the GNU General Public License. However the source code for this *
|
|
* file must still be made available in accordance with the GNU General *
|
|
* Public License. This exception does not invalidate any other reasons *
|
|
* why a work based on this file might be covered by the GNU General *
|
|
* Public License. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
|
***************************************************************************/
|
|
|
|
#include <stm32h7xx.h>
|
|
#include "rcc.h"
|
|
|
|
/**
|
|
* Clock tree configuration:
|
|
*
|
|
* - input clock from 25MHz external crystal
|
|
* - VCO clock 800MHz
|
|
* - PLL_P clock 400MHz
|
|
* - PLL_Q clock 100MHz
|
|
* - PLL_R clock 400MHz
|
|
*
|
|
* Clocks derived from PLL_P output:
|
|
* - CPU clock 400MHz
|
|
* - AHB1/2/3 clock 200MHz
|
|
* - APB1/2/4 clock 200MHz
|
|
*/
|
|
|
|
void startPll()
|
|
{
|
|
//In the STM32H7 DVFS was introduced (chapter 6, Power control)
|
|
//The default voltage is the lowest, switch to highest to run @ 400MHz
|
|
//QUIRK: it looks like VOS can only be set by first setting SCUEN to 0.
|
|
//This isn't documented anywhere in the reference manual
|
|
PWR->CR3 &= ~PWR_CR3_SCUEN;
|
|
PWR->D3CR = PWR_D3CR_VOS_1 | PWR_D3CR_VOS_0;
|
|
while((PWR->D3CR & PWR_D3CR_VOSRDY)==0) ; //Wait
|
|
|
|
//Enable HSE oscillator
|
|
RCC->CR |= RCC_CR_HSEON;
|
|
while((RCC->CR & RCC_CR_HSERDY)==0) ; //Wait
|
|
|
|
//Start the PLL
|
|
RCC->PLLCKSELR |= RCC_PLLCKSELR_DIVM1_0
|
|
| RCC_PLLCKSELR_DIVM1_2 //M=5 (25MHz/5)5MHz
|
|
| RCC_PLLCKSELR_PLLSRC_HSE; //HSE selected as PLL source
|
|
RCC->PLL1DIVR = (2-1) << 24 // R=2
|
|
| (8-1) << 16 // Q=8
|
|
| (2-1) << 9 // P=2
|
|
| (160-1); // N=160
|
|
RCC->PLLCFGR |= RCC_PLLCFGR_PLL1RGE_2 // Pll ref clock between 4 and 8MHz
|
|
| RCC_PLLCFGR_DIVP1EN // Enable output P
|
|
| RCC_PLLCFGR_DIVQ1EN // Enable output Q
|
|
| RCC_PLLCFGR_DIVR1EN; // Enable output R
|
|
RCC->CR |= RCC_CR_PLL1ON;
|
|
while((RCC->CR & RCC_CR_PLL1RDY)==0) ; //Wait
|
|
|
|
//Before increasing the fequency set dividers
|
|
RCC->D1CFGR = RCC_D1CFGR_D1CPRE_DIV1 //CPU clock /1
|
|
| RCC_D1CFGR_D1PPRE_DIV1 //D1 APB3 /1
|
|
| RCC_D1CFGR_HPRE_DIV2; //D1 AHB /2
|
|
RCC->D2CFGR = RCC_D2CFGR_D2PPRE2_DIV1 //D2 APB2 /1
|
|
| RCC_D2CFGR_D2PPRE1_DIV1;//D2 APB1 /1
|
|
RCC->D3CFGR = RCC_D3CFGR_D3PPRE_DIV1; //D3 APB4 /1
|
|
|
|
//And increase FLASH wait states
|
|
FLASH->ACR = FLASH_ACR_WRHIGHFREQ_1 //Settings for FLASH freq=200MHz
|
|
| FLASH_ACR_LATENCY_3WS;
|
|
|
|
//Finally, increase frequency
|
|
RCC->CFGR |= RCC_CFGR_SW_PLL1;
|
|
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL1) ; //Wait
|
|
|
|
//Configure PLL2 to have 168MHz on P output
|
|
RCC->PLLCKSELR |= 25 << RCC_PLLCKSELR_DIVM2_Pos; // M=25, VCO input 1MHz
|
|
RCC->PLL2DIVR = (168-1); // N=168, P,Q,R = 1
|
|
RCC->PLLCFGR |= RCC_PLLCFGR_PLL2VCOSEL // Medium VCO range
|
|
| RCC_PLLCFGR_DIVP2EN;
|
|
RCC->CR |= RCC_CR_PLL2ON; // Start PLL2
|
|
while((RCC->CR & RCC_CR_PLL2RDY)==0) ; // Wait until ready
|
|
|
|
// Configure USART6 kernel clock source to use PCLK2
|
|
// USART16SEL field is bits [5:3]: 000 = pclk2
|
|
RCC->D2CCIP2R &= ~RCC_D2CCIP2R_USART16SEL;
|
|
}
|
|
|
|
uint32_t getBusClock(const uint8_t bus)
|
|
{
|
|
switch(bus) {
|
|
case PERIPH_BUS_AHB:
|
|
return 200000000; // AHB: CPU(400MHz) / HPRE_DIV2 = 200MHz
|
|
break;
|
|
|
|
case PERIPH_BUS_APB1:
|
|
return 200000000; // APB1: AHB(200MHz) / D2PPRE1_DIV1 = 200MHz
|
|
break;
|
|
|
|
case PERIPH_BUS_APB2:
|
|
return 200000000; // APB2: AHB(200MHz) / D2PPRE2_DIV1 = 200MHz
|
|
break;
|
|
|
|
case PERIPH_BUS_APB3:
|
|
return 200000000; // APB3: AHB(200MHz) / D1PPRE_DIV1 = 200MHz
|
|
break;
|
|
|
|
case PERIPH_BUS_APB4:
|
|
return 200000000; // APB4: AHB(200MHz) / D3PPRE_DIV1 = 200MHz
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|