1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-13 03:20:00 +03:00
betaflight/src/main/startup/system_stm32h7xx.c
Dominic Clifton 91483d2e8e STM32H7 - SDMMC Fix the short busy loop being compiled out by newer
versions of GCC.

STM32H7 - Don't go into an infinite loop if an SDIO read fails.

STM32H7 - Generate compiliation error for non-8Mhz crystals when SDCARD
via SDIO is used.  Prevents accidental overclocking of hardware.

Avoid double-init of SD card when CONFIG_IN_SDCARD is used.

Note: There's no SD_DeInit() function.

STM32H7 - Fix MSC SD initialisation when using USE_DMA_SPEC.
2021-09-10 02:28:29 +12:00

1087 lines
35 KiB
C

/**
******************************************************************************
* @file system_stm32h7xx.c
* @author MCD Application Team
* @brief CMSIS Cortex-Mx Device Peripheral Access Layer System Source File.
*
* This file provides two functions and one global variable to be called from
* user application:
* - SystemInit(): This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32h7xx.s" file.
*
* - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
* by the user application to setup the SysTick
* timer or configure other parameters.
*
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
* be called whenever the core clock is changed
* during program execution.
*
*
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32h7xx_system
* @{
*/
/** @addtogroup STM32H7xx_System_Private_Includes
* @{
*/
#include "stm32h7xx.h"
#include "drivers/system.h"
#include "platform.h"
#include "string.h"
#include "common/utils.h"
#include "build/debug.h"
void systemResetWithoutDisablingCaches(void);
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (CSI_VALUE)
#define CSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* CSI_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)64000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_Defines
* @{
*/
/************************* Miscellaneous Configuration ************************/
/*!< Uncomment the following line if you need to use external SRAM or SDRAM mounted
on EVAL board as data memory */
/*#define DATA_IN_ExtSRAM */
/*#define DATA_IN_ExtSDRAM*/
#if defined(DATA_IN_ExtSRAM) && defined(DATA_IN_ExtSDRAM)
#error "Please select DATA_IN_ExtSRAM or DATA_IN_ExtSDRAM "
#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */
/*!< Uncomment the following line if you need to relocate your vector Table in
Internal SRAM. */
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
/******************************************************************************/
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_Variables
* @{
*/
/* This variable is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
Note: If you use this function to configure the system clock; then there
is no need to call the 2 first functions listed above, since SystemCoreClock
variable is updated automatically.
*/
uint32_t SystemCoreClock = 64000000;
uint32_t SystemD2Clock = 64000000;
const uint8_t D1CorePrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_FunctionPrototypes
* @{
*/
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
static void SystemInit_ExtMemCtl(void);
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_Functions
* @{
*/
static void ErrorHandler(void)
{
while (1);
}
void HandleStuckSysTick(void)
{
uint32_t tickStart = HAL_GetTick();
uint32_t tickEnd = 0;
// H7 at 480Mhz requires a loop count of 160000. Double this for the timeout to be safe.
int attemptsRemaining = 320000;
while (((tickEnd = HAL_GetTick()) == tickStart) && --attemptsRemaining) {
}
if (tickStart == tickEnd) {
systemResetWithoutDisablingCaches();
}
}
typedef struct pllConfig_s {
uint16_t clockMhz;
uint8_t m;
uint16_t n;
uint8_t p;
uint8_t q;
uint8_t r;
uint32_t vos;
uint32_t vciRange;
} pllConfig_t;
#if defined(STM32H743xx) || defined(STM32H750xx)
/*
PLL1 configuration for different silicon revisions of H743 and H750.
Note for future overclocking support.
- Rev.Y (and Rev.X), nominal max at 400MHz, runs stably overclocked to 480MHz.
- Rev.V, nominal max at 480MHz, runs stably at 540MHz, but not to 600MHz (VCO probably out of operating range)
- A possible frequency table would look something like this, and a revision
check logic would place a cap for Rev.Y and V.
400 420 440 460 (Rev.Y & V ends here) 480 500 520 540
*/
// 400MHz for Rev.Y (and Rev.X)
pllConfig_t pll1ConfigRevY = {
.clockMhz = 400,
.m = 4,
.n = 400,
.p = 2,
.q = 8,
.r = 5,
.vos = PWR_REGULATOR_VOLTAGE_SCALE1,
.vciRange = RCC_PLL1VCIRANGE_2,
};
// 480MHz for Rev.V
pllConfig_t pll1ConfigRevV = {
.clockMhz = 480,
.m = 4,
.n = 480,
.p = 2,
.q = 8,
.r = 5,
.vos = PWR_REGULATOR_VOLTAGE_SCALE0,
.vciRange = RCC_PLL1VCIRANGE_2,
};
#define MCU_HCLK_DIVIDER RCC_HCLK_DIV2
// H743 and H750
// For HCLK=200MHz with VOS1 range, ST recommended flash latency is 2WS.
// RM0433 (Rev.5) Table 12. FLASH recommended number of wait states and programming delay
//
// For higher HCLK frequency, VOS0 is available on RevV silicons, with FLASH wait states 4WS
// AN5312 (Rev.1) Section 1.2.1 Voltage scaling Table.1
//
// XXX Check if Rev.V requires a different value
#define MCU_FLASH_LATENCY FLASH_LATENCY_2
// Source for CRS input
#define MCU_RCC_CRS_SYNC_SOURCE RCC_CRS_SYNC_SOURCE_USB2
// Workaround for weird HSE behaviors
// (Observed only on Rev.V H750, but may also apply to H743 and Rev.V.)
#define USE_H7_HSERDY_SLOW_WORKAROUND
#define USE_H7_HSE_TIMEOUT_WORKAROUND
#elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ)
// Nominal max 280MHz with 8MHz HSE
// (340 is okay, 360 doesn't work.)
//
pllConfig_t pll1Config7A3 = {
.clockMhz = 280,
.m = 4,
.n = 280,
.p = 2,
.q = 8,
.r = 5,
.vos = PWR_REGULATOR_VOLTAGE_SCALE0,
.vciRange = RCC_PLL1VCIRANGE_1,
};
// Unlike H743/H750, HCLK can be directly fed with SYSCLK.
#define MCU_HCLK_DIVIDER RCC_HCLK_DIV1
// RM0455 (Rev.6) Table 15. FLASH recommended number of wait states and programming delay
// 280MHz at VOS0 is 6WS
#define MCU_FLASH_LATENCY FLASH_LATENCY_6
// Source for CRS input
#define MCU_RCC_CRS_SYNC_SOURCE RCC_CRS_SYNC_SOURCE_USB1
#elif defined(STM32H723xx) || defined(STM32H725xx)
// Nominal max 550MHz
pllConfig_t pll1Config72x = {
.clockMhz = 550,
.m = 4,
.n = 275,
.p = 1,
.q = 2,
.r = 2,
.vos = PWR_REGULATOR_VOLTAGE_SCALE0,
.vciRange = RCC_PLL1VCIRANGE_1,
};
#define MCU_HCLK_DIVIDER RCC_HCLK_DIV2
// RM0468 (Rev.2) Table 16.
// 550MHz (AXI Interface clock) at VOS0 is 3WS
#define MCU_FLASH_LATENCY FLASH_LATENCY_3
#define MCU_RCC_CRS_SYNC_SOURCE RCC_CRS_SYNC_SOURCE_USB1
#else
#error Unknown MCU type
#endif
// HSE clock configuration, originally taken from
// STM32Cube_FW_H7_V1.3.0/Projects/STM32H743ZI-Nucleo/Examples/RCC/RCC_ClockConfig/Src/main.c
static void SystemClockHSE_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
#ifdef notdef
// CSI has been disabled at SystemInit().
// HAL_RCC_ClockConfig() will fail because CSIRDY is off.
/* -1- Select CSI as system clock source to allow modification of the PLL configuration */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_CSI;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
/* Initialization Error */
ErrorHandler();
}
#endif
pllConfig_t *pll1Config;
#if defined(STM32H743xx) || defined(STM32H750xx)
pll1Config = (HAL_GetREVID() == REV_ID_V) ? &pll1ConfigRevV : &pll1ConfigRevY;
#elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ)
pll1Config = &pll1Config7A3;
#elif defined(STM32H723xx) || defined(STM32H725xx)
pll1Config = &pll1Config72x;
#else
#error Unknown MCU type
#endif
// Configure voltage scale.
// It has been pre-configured at PWR_REGULATOR_VOLTAGE_SCALE1,
// and it may stay or overridden by PWR_REGULATOR_VOLTAGE_SCALE0 depending on the clock config.
__HAL_PWR_VOLTAGESCALING_CONFIG(pll1Config->vos);
while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {
// Empty
}
/* -2- Enable HSE Oscillator, select it as PLL source and finally activate the PLL */
#ifdef USE_H7_HSERDY_SLOW_WORKAROUND
// With reference to 2.3.22 in the ES0250 Errata for the L476.
// Applying the same workaround here in the vain hopes that it improves startup times.
// Randomly the HSERDY bit takes AGES, over 10 seconds, to be set.
__HAL_RCC_GPIOH_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_0 | GPIO_PIN_1, GPIO_PIN_RESET);
GPIO_InitTypeDef gpio_initstruct;
gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;
gpio_initstruct.Pull = GPIO_NOPULL;
gpio_initstruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOH, &gpio_initstruct);
#endif
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON; // Even Nucleo-H473ZI and Nucleo-H7A3ZI work without RCC_HSE_BYPASS
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = pll1Config->m;
RCC_OscInitStruct.PLL.PLLN = pll1Config->n;
RCC_OscInitStruct.PLL.PLLP = pll1Config->p;
RCC_OscInitStruct.PLL.PLLQ = pll1Config->q;
RCC_OscInitStruct.PLL.PLLR = pll1Config->r;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLRGE = pll1Config->vciRange;
HAL_StatusTypeDef status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
#ifdef USE_H7_HSE_TIMEOUT_WORKAROUND
if (status == HAL_TIMEOUT) {
systemResetWithoutDisablingCaches(); // DC - sometimes HSERDY gets stuck, waiting longer doesn't help.
}
#endif
if (status != HAL_OK) {
/* Initialization Error */
ErrorHandler();
}
// Configure PLL2 and PLL3
// Use of PLL2 and PLL3 are not determined yet.
// A review of total system wide clock requirements is necessary.
// Configure SCGU (System Clock Generation Unit)
// Select PLL as system clock source and configure bus clock dividers.
//
// Clock type and divider member names do not have direct visual correspondence.
// Here is how these correspond:
// RCC_CLOCKTYPE_SYSCLK sys_ck
// RCC_CLOCKTYPE_HCLK AHBx (rcc_hclk1,rcc_hclk2,rcc_hclk3,rcc_hclk4)
// RCC_CLOCKTYPE_D1PCLK1 APB3 (rcc_pclk3)
// RCC_CLOCKTYPE_PCLK1 APB1 (rcc_pclk1)
// RCC_CLOCKTYPE_PCLK2 APB2 (rcc_pclk2)
// RCC_CLOCKTYPE_D3PCLK1 APB4 (rcc_pclk4)
RCC_ClkInitStruct.ClockType = ( \
RCC_CLOCKTYPE_SYSCLK | \
RCC_CLOCKTYPE_HCLK | \
RCC_CLOCKTYPE_D1PCLK1 | \
RCC_CLOCKTYPE_PCLK1 | \
RCC_CLOCKTYPE_PCLK2 | \
RCC_CLOCKTYPE_D3PCLK1);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = MCU_HCLK_DIVIDER;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, MCU_FLASH_LATENCY) != HAL_OK) {
/* Initialization Error */
ErrorHandler();
}
/* -4- Optional: Disable CSI Oscillator (if the HSI is no more needed by the application)*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_CSI;
RCC_OscInitStruct.CSIState = RCC_CSI_OFF;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
/* Initialization Error */
ErrorHandler();
}
}
void SystemClock_Config(void)
{
// Configure power supply
#if defined(STM32H743xx) || defined(STM32H750xx) || defined(STM32H723xx) || defined(STM32H7A3xx)
// Legacy H7 devices (H743, H750) and newer but SMPS-less devices(H7A3, H723)
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
// Pre-configure voltage scale to PWR_REGULATOR_VOLTAGE_SCALE1.
// SystemClockHSE_Config may configure PWR_REGULATOR_VOLTAGE_SCALE0.
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
#elif defined(STM32H7A3xxQ) || defined(STM32H725xx)
// We assume all SMPS equipped devices use this mode (Direct SMPS).
// - All STM32H7A3xxQ devices.
// - All STM32H725xx devices (Note STM32H725RG is Direct SMPS only - no LDO).
//
// Note that:
// - Nucleo-H7A3ZI-Q is preconfigured for power supply configuration 2 (Direct SMPS).
// - Nucleo-H723ZI-Q transplanted with STM32H725ZG is the same as above.
HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
#else
#error Unknown MCU
#endif
while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {
// Empty
}
SystemClockHSE_Config();
/*activate CSI clock mondatory for I/O Compensation Cell*/
__HAL_RCC_CSI_ENABLE() ;
/* Enable SYSCFG clock mondatory for I/O Compensation Cell */
__HAL_RCC_SYSCFG_CLK_ENABLE() ;
/* Enables the I/O Compensation Cell */
HAL_EnableCompensationCell();
HandleStuckSysTick();
HAL_Delay(10);
// Configure peripheral clocks
RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;
// Configure HSI48 as peripheral clock for USB
RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
RCC_PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
// Configure CRS for dynamic calibration of HSI48
// While ES0392 Rev 5 "STM32H742xI/G and STM32H743xI/G device limitations" states CRS not working for REV.Y,
// it is always turned on as it seems that it has no negative effect on clock accuracy.
RCC_CRSInitTypeDef crsInit = {
.Prescaler = RCC_CRS_SYNC_DIV1,
.Source = MCU_RCC_CRS_SYNC_SOURCE,
.Polarity = RCC_CRS_SYNC_POLARITY_RISING,
.ReloadValue = RCC_CRS_RELOADVALUE_DEFAULT,
.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT,
.HSI48CalibrationValue = RCC_CRS_HSI48CALIBRATION_DEFAULT,
};
__HAL_RCC_CRS_CLK_ENABLE();
HAL_RCCEx_CRSConfig(&crsInit);
#ifdef USE_CRS_INTERRUPTS
// Turn on USE_CRS_INTERRUPTS to see CRS in action
HAL_NVIC_SetPriority(CRS_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(CRS_IRQn);
__HAL_RCC_CRS_ENABLE_IT(RCC_CRS_IT_SYNCOK|RCC_CRS_IT_SYNCWARN|RCC_CRS_IT_ESYNC|RCC_CRS_IT_ERR);
#endif
// Configure UART peripheral clock sources
//
// Possible sources:
// D2PCLK1 (pclk1 for APB1 = USART234578)
// D2PCLK2 (pclk2 for APB2 = USART16)
// PLL2 (pll2_q_ck)
// PLL3 (pll3_q_ck),
// HSI (hsi_ck),
// CSI (csi_ck),LSE(lse_ck);
RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART16|RCC_PERIPHCLK_USART234578;
RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
RCC_PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
// Configure SPI peripheral clock sources
//
// Possible sources for SPI123:
// PLL (pll1_q_ck)
// PLL2 (pll2_p_ck)
// PLL3 (pll3_p_ck)
// PIN (I2S_CKIN)
// CLKP (per_ck)
// Possible sources for SPI45:
// D2PCLK1 (rcc_pclk2 = APB1) 100MHz
// PLL2 (pll2_q_ck)
// PLL3 (pll3_q_ck)
// HSI (hsi_ker_ck)
// CSI (csi_ker_ck)
// HSE (hse_ck)
// Possible sources for SPI6:
// D3PCLK1 (rcc_pclk4 = APB4) 100MHz
// PLL2 (pll2_q_ck)
// PLL3 (pll3_q_ck)
// HSI (hsi_ker_ck)
// CSI (csi_ker_ck)
// HSE (hse_ck)
// We use 100MHz for Rev.Y and 120MHz for Rev.V from various sources
RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI123|RCC_PERIPHCLK_SPI45|RCC_PERIPHCLK_SPI6;
RCC_PeriphClkInit.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
RCC_PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_D2PCLK1;
RCC_PeriphClkInit.Spi6ClockSelection = RCC_SPI6CLKSOURCE_D3PCLK1;
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
// Configure I2C peripheral clock sources
//
// Current source for I2C123:
// D2PCLK1 (rcc_pclk1 = APB1 peripheral clock)
//
// Current source for I2C4:
// D3PCLK1 (rcc_pclk4 = APB4 peripheral clock)
//
// Note that peripheral clock determination in bus_i2c_hal_init.c must be modified when the sources are modified.
RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C123|RCC_PERIPHCLK_I2C4;
RCC_PeriphClkInit.I2c123ClockSelection = RCC_I2C123CLKSOURCE_D2PCLK1;
RCC_PeriphClkInit.I2c4ClockSelection = RCC_I2C4CLKSOURCE_D3PCLK1;
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
#ifdef USE_SDCARD_SDIO
RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SDMMC;
#if (HSE_VALUE != 8000000)
#error Unsupported external oscillator speed. The calculations below are based on 8Mhz resonators
// if you are seeing this, then calculate the PLL2 settings for your resonator and add support as required.
#else
RCC_PeriphClkInit.PLL2.PLL2M = 5;
RCC_PeriphClkInit.PLL2.PLL2N = 500;
RCC_PeriphClkInit.PLL2.PLL2P = 2; // 500Mhz
RCC_PeriphClkInit.PLL2.PLL2Q = 3; // 266Mhz - 133Mhz can be derived from this for for QSPI if flash chip supports the speed.
RCC_PeriphClkInit.PLL2.PLL2R = 4; // 200Mhz HAL LIBS REQUIRE 200MHZ SDMMC CLOCK, see HAL_SD_ConfigWideBusOperation, SDMMC_HSpeed_CLK_DIV, SDMMC_NSpeed_CLK_DIV
RCC_PeriphClkInit.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_0;
RCC_PeriphClkInit.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
RCC_PeriphClkInit.PLL2.PLL2FRACN = 0;
RCC_PeriphClkInit.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL2;
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
#endif // 8Mhz HSE_VALUE
#endif
// Configure MCO clocks for clock test/verification
// Possible sources for MCO1:
// RCC_MCO1SOURCE_HSI (hsi_ck)
// RCC_MCO1SOURCE_LSE (?)
// RCC_MCO1SOURCE_HSE (hse_ck)
// RCC_MCO1SOURCE_PLL1QCLK (pll1_q_ck)
// RCC_MCO1SOURCE_HSI48 (hsi48_ck)
// HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1); // HSE(8M) / 1 = 1M
HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSI48, RCC_MCODIV_4); // HSI48(48M) / 4 = 12M
// Possible sources for MCO2:
// RCC_MCO2SOURCE_SYSCLK (sys_ck)
// RCC_MCO2SOURCE_PLL2PCLK (pll2_p_ck)
// RCC_MCO2SOURCE_HSE (hse_ck)
// RCC_MCO2SOURCE_PLLCLK (pll1_p_ck)
// RCC_MCO2SOURCE_CSICLK (csi_ck)
// RCC_MCO2SOURCE_LSICLK (lsi_ck)
HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO2SOURCE_PLLCLK, RCC_MCODIV_15); // PLL1P(400M) / 15 = 26.67M
}
#ifdef USE_CRS_INTERRUPTS
static uint32_t crs_syncok = 0;
static uint32_t crs_syncwarn = 0;
static uint32_t crs_expectedsync = 0;
static uint32_t crs_error = 0;
void HAL_RCCEx_CRS_SyncOkCallback(void)
{
++crs_syncok;
}
void HAL_RCCEx_CRS_SyncWarnCallback(void)
{
++crs_syncwarn;
}
void HAL_RCCEx_CRS_ExpectedSyncCallback(void)
{
++crs_expectedsync;
}
void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error)
{
++crs_error;
}
void CRS_IRQHandler(void)
{
HAL_RCCEx_CRS_IRQHandler();
}
#endif
#include "build/debug.h"
void systemCheckResetReason(void);
#include "drivers/memprot.h"
void SystemInit (void)
{
memProtReset();
initialiseMemorySections();
#if !defined(USE_EXST)
// only stand-alone and bootloader firmware needs to do this.
// if it's done in the EXST firmware as well as the BOOTLOADER firmware you get a reset loop.
systemCheckResetReason();
#endif
// FPU settings
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); // Set CP10 and CP11 Full Access
#endif
// Reset the RCC clock configuration to the default reset state
// Set HSION bit
RCC->CR = RCC_CR_HSION;
// Reset CFGR register
RCC->CFGR = 0x00000000;
// Reset HSEON, CSSON , CSION,RC48ON, CSIKERON PLL1ON, PLL2ON and PLL3ON bits
// XXX Don't do this until we are established with clock handling
// RCC->CR &= (uint32_t)0xEAF6ED7F;
// Instead, we explicitly turn those on
RCC->CR |= RCC_CR_CSION;
RCC->CR |= RCC_CR_HSION;
RCC->CR |= RCC_CR_HSEON;
RCC->CR |= RCC_CR_HSI48ON;
#if defined(STM32H743xx) || defined(STM32H750xx)
/* Reset D1CFGR register */
RCC->D1CFGR = 0x00000000;
/* Reset D2CFGR register */
RCC->D2CFGR = 0x00000000;
/* Reset D3CFGR register */
RCC->D3CFGR = 0x00000000;
#elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ)
/* Reset CDCFGR1 register */
RCC->CDCFGR1 = 0x00000000;
/* Reset CDCFGR2 register */
RCC->CDCFGR2 = 0x00000000;
/* Reset SRDCFGR register */
RCC->SRDCFGR = 0x00000000;
#endif
/* Reset PLLCKSELR register */
RCC->PLLCKSELR = 0x00000000;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x00000000;
/* Reset PLL1DIVR register */
RCC->PLL1DIVR = 0x00000000;
/* Reset PLL1FRACR register */
RCC->PLL1FRACR = 0x00000000;
/* Reset PLL2DIVR register */
RCC->PLL2DIVR = 0x00000000;
/* Reset PLL2FRACR register */
RCC->PLL2FRACR = 0x00000000;
/* Reset PLL3DIVR register */
RCC->PLL3DIVR = 0x00000000;
/* Reset PLL3FRACR register */
RCC->PLL3FRACR = 0x00000000;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Disable all interrupts */
RCC->CIER = 0x00000000;
/* Change the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */
*((__IO uint32_t*)0x51008108) = 0x00000001;
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/* Configure the Vector Table location add offset address ------------------*/
#if defined(VECT_TAB_SRAM)
#if defined(STM32H743xx) || defined(STM32H750xx)
SCB->VTOR = D1_AXISRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal ITCMSRAM */
#elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ)
SCB->VTOR = CD_AXISRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal ITCMSRAM */
#else
#error Unknown MCU type
#endif
#elif defined(USE_EXST)
extern void *isr_vector_table_base;
SCB->VTOR = (uint32_t)&isr_vector_table_base;
#else
SCB->VTOR = FLASH_BANK1_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
#ifdef USE_HAL_DRIVER
HAL_Init();
#endif
SystemClock_Config();
SystemCoreClockUpdate();
#ifdef STM32H7
initialiseD2MemorySections();
#endif
// Configure MPU
memProtConfigure(mpuRegions, mpuRegionCount);
// Enable CPU L1-Cache
SCB_EnableICache();
SCB_EnableDCache();
}
/**
* @brief Update SystemCoreClock variable according to Clock Register Values.
* The SystemCoreClock variable contains the core clock , it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock changes, this function must be called
* to update SystemCoreClock variable value. Otherwise, any configuration
* based on this variable will be incorrect.
*
* @note - The system frequency computed by this function is not the real
* frequency in the chip. It is calculated based on the predefined
* constant and the selected clock source:
*
* - If SYSCLK source is CSI, SystemCoreClock will contain the CSI_VALUE(*)
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**)
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
* - If SYSCLK source is PLL, SystemCoreClock will contain the CSI_VALUE(*),
* HSI_VALUE(**) or HSE_VALUE(***) multiplied/divided by the PLL factors.
*
* (*) CSI_VALUE is a constant defined in stm32h7xx_hal.h file (default value
* 4 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
* (**) HSI_VALUE is a constant defined in stm32h7xx_hal.h file (default value
* 64 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (***)HSE_VALUE is a constant defined in stm32h7xx_hal.h file (default value
* 25 MHz), user has to ensure that HSE_VALUE is same as the real
* frequency of the crystal used. Otherwise, this function may
* have wrong result.
*
* - The result of this function could be not correct when using fractional
* value for HSE crystal.
* @param None
* @retval None
*/
void SystemCoreClockUpdate (void)
{
SystemCoreClock = HAL_RCC_GetSysClockFreq();
}
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
/**
* @brief Setup the external memory controller.
* Called in startup_stm32h7xx.s before jump to main.
* This function configures the external memories (SRAM/SDRAM)
* This SRAM/SDRAM will be used as program data memory (including heap and stack).
* @param None
* @retval None
*/
void SystemInit_ExtMemCtl(void)
{
#if defined (DATA_IN_ExtSDRAM)
register uint32_t tmpreg = 0, timeout = 0xFFFF;
register __IO uint32_t index;
/* Enable GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */
RCC->AHB4ENR |= 0x000001F8;
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x000000CC;
GPIOD->AFR[1] = 0xCC000CCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xAFEAFFFA;
/* Configure PDx pins speed to 50 MHz */
GPIOD->OSPEEDR = 0xA02A000A;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x55555505;
/* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[0] = 0xC00000CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAABFFA;
/* Configure PEx pins speed to 50 MHz */
GPIOE->OSPEEDR = 0xAAAA800A;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x55554005;
/* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[0] = 0x00CCCCCC;
GPIOF->AFR[1] = 0xCCCCC000;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAABFFAAA;
/* Configure PFx pins speed to 50 MHz */
GPIOF->OSPEEDR = 0xAA800AAA;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x55400555;
/* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[0] = 0x00CCCCCC;
GPIOG->AFR[1] = 0xC000000C;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0xBFFEFAAA;
/* Configure PGx pins speed to 50 MHz */
GPIOG->OSPEEDR = 0x80020AAA;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x40010515;
/* Connect PHx pins to FMC Alternate function */
GPIOH->AFR[0] = 0xCCC00000;
GPIOH->AFR[1] = 0xCCCCCCCC;
/* Configure PHx pins in Alternate function mode */
GPIOH->MODER = 0xAAAAABFF;
/* Configure PHx pins speed to 50 MHz */
GPIOH->OSPEEDR = 0xAAAAA800;
/* Configure PHx pins Output type to push-pull */
GPIOH->OTYPER = 0x00000000;
/* No pull-up, pull-down for PHx pins */
GPIOH->PUPDR = 0x55555400;
/* Connect PIx pins to FMC Alternate function */
GPIOI->AFR[0] = 0xCCCCCCCC;
GPIOI->AFR[1] = 0x00000CC0;
/* Configure PIx pins in Alternate function mode */
GPIOI->MODER = 0xFFEBAAAA;
/* Configure PIx pins speed to 50 MHz */
GPIOI->OSPEEDR = 0x0028AAAA;
/* Configure PIx pins Output type to push-pull */
GPIOI->OTYPER = 0x00000000;
/* No pull-up, pull-down for PIx pins */
GPIOI->PUPDR = 0x00145555;
/*-- FMC Configuration ------------------------------------------------------*/
/* Enable the FMC interface clock */
(RCC->AHB3ENR |= (RCC_AHB3ENR_FMCEN));
/*SDRAM Timing and access interface configuration*/
/*LoadToActiveDelay = 2
ExitSelfRefreshDelay = 6
SelfRefreshTime = 4
RowCycleDelay = 6
WriteRecoveryTime = 2
RPDelay = 2
RCDDelay = 2
SDBank = FMC_SDRAM_BANK2
ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9
RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12
MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32
InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4
CASLatency = FMC_SDRAM_CAS_LATENCY_2
WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE
SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2
ReadBurst = FMC_SDRAM_RBURST_ENABLE
ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0*/
FMC_Bank5_6->SDCR[0] = 0x00001800;
FMC_Bank5_6->SDCR[1] = 0x00000165;
FMC_Bank5_6->SDTR[0] = 0x00105000;
FMC_Bank5_6->SDTR[1] = 0x01010351;
/* SDRAM initialization sequence */
/* Clock enable command */
FMC_Bank5_6->SDCMR = 0x00000009;
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Delay */
for (index = 0; index<1000; index++);
/* PALL command */
FMC_Bank5_6->SDCMR = 0x0000000A;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
FMC_Bank5_6->SDCMR = 0x000000EB;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
FMC_Bank5_6->SDCMR = 0x0004400C;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Set refresh count */
tmpreg = FMC_Bank5_6->SDRTR;
FMC_Bank5_6->SDRTR = (tmpreg | (0x00000603<<1));
/* Disable write protection */
tmpreg = FMC_Bank5_6->SDCR[1];
FMC_Bank5_6->SDCR[1] = (tmpreg & 0xFFFFFDFF);
/*FMC controller Enable*/
FMC_Bank1->BTCR[0] |= 0x80000000;
#endif /* DATA_IN_ExtSDRAM */
#if defined(DATA_IN_ExtSRAM)
/*-- GPIOs Configuration -----------------------------------------------------*/
/* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
RCC->AHB4ENR |= 0x00000078;
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x00CCC0CC;
GPIOD->AFR[1] = 0xCCCCCCCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xAAAA0A8A;
/* Configure PDx pins speed to 100 MHz */
GPIOD->OSPEEDR = 0xFFFF0FCF;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x55550545;
/* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[0] = 0xC00CC0CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA828A;
/* Configure PEx pins speed to 100 MHz */
GPIOE->OSPEEDR = 0xFFFFC3CF;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x55554145;
/* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[0] = 0x00CCCCCC;
GPIOF->AFR[1] = 0xCCCC0000;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA000AAA;
/* Configure PFx pins speed to 100 MHz */
GPIOF->OSPEEDR = 0xFF000FFF;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x55000555;
/* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[0] = 0x00CCCCCC;
GPIOG->AFR[1] = 0x000000C0;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0x00200AAA;
/* Configure PGx pins speed to 100 MHz */
GPIOG->OSPEEDR = 0x00300FFF;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00100555;
/*-- FMC/FSMC Configuration --------------------------------------------------*/
/* Enable the FMC/FSMC interface clock */
(RCC->AHB3ENR |= (RCC_AHB3ENR_FMCEN));
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[4] = 0x00001091;
FMC_Bank1->BTCR[5] = 0x00110212;
FMC_Bank1E->BWTR[4] = 0x0FFFFFFF;
/*FMC controller Enable*/
FMC_Bank1->BTCR[0] |= 0x80000000;
#endif /* DATA_IN_ExtSRAM */
}
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/