circuitpython/ports/stm32/system_stm32f0.c
Damien George 11657f2f20 stm32/system_stm32f0: Add support for using HSE and PLL as SYSCLK.
To configure the SYSCLK on an F0 enable one of:

    MICROPY_HW_CLK_USE_HSI48
    MICROPY_HW_CLK_USE_HSE
    MICROPY_HW_CLK_USE_BYPASS
2019-04-18 16:00:45 +10:00

232 lines
8.8 KiB
C

/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Taken from ST Cube library and modified. See below for original header.
*/
/**
******************************************************************************
* @file system_stm32f0xx.c
* @author MCD Application Team
* @brief CMSIS Cortex-M0 Device Peripheral Access Layer System Source File.
*
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2016 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.
*
******************************************************************************
*/
#include "py/mphal.h"
#ifndef HSE_VALUE
#define HSE_VALUE (8000000)
#endif
#ifndef HSI_VALUE
#define HSI_VALUE (8000000)
#endif
#ifndef HSI48_VALUE
#define HSI48_VALUE (48000000)
#endif
/* 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 there is no need to
call the 2 first functions listed above, since SystemCoreClock variable is
updated automatically.
*/
uint32_t SystemCoreClock = 8000000;
const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
void SystemInit(void) {
// Set HSION bit
RCC->CR |= (uint32_t)0x00000001U;
#if defined(STM32F051x8) || defined(STM32F058x8)
// Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE and MCOSEL[2:0] bits
RCC->CFGR &= (uint32_t)0xF8FFB80CU;
#else
// Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE, MCOSEL[2:0], MCOPRE[2:0] and PLLNODIV bits
RCC->CFGR &= (uint32_t)0x08FFB80CU;
#endif
// Reset HSEON, CSSON and PLLON bits
RCC->CR &= (uint32_t)0xFEF6FFFFU;
// Reset HSEBYP bit
RCC->CR &= (uint32_t)0xFFFBFFFFU;
// Reset PLLSRC, PLLXTPRE and PLLMUL[3:0] bits
RCC->CFGR &= (uint32_t)0xFFC0FFFFU;
// Reset PREDIV[3:0] bits
RCC->CFGR2 &= (uint32_t)0xFFFFFFF0U;
#if defined(STM32F072xB) || defined(STM32F078xx)
// Reset USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW, USBSW and ADCSW bits
RCC->CFGR3 &= (uint32_t)0xFFFCFE2CU;
#elif defined(STM32F071xB)
// Reset USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW and ADCSW bits
RCC->CFGR3 &= (uint32_t)0xFFFFCEACU;
#elif defined(STM32F091xC) || defined(STM32F098xx)
// Reset USART3SW[1:0], USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW and ADCSW bits
RCC->CFGR3 &= (uint32_t)0xFFF0FEACU;
#elif defined(STM32F030x6) || defined(STM32F030x8) || defined(STM32F031x6) || defined(STM32F038xx) || defined(STM32F030xC)
// Reset USART1SW[1:0], I2C1SW and ADCSW bits
RCC->CFGR3 &= (uint32_t)0xFFFFFEECU;
#elif defined(STM32F051x8) || defined(STM32F058xx)
// Reset USART1SW[1:0], I2C1SW, CECSW and ADCSW bits
RCC->CFGR3 &= (uint32_t)0xFFFFFEACU;
#elif defined(STM32F042x6) || defined(STM32F048xx)
// Reset USART1SW[1:0], I2C1SW, CECSW, USBSW and ADCSW bits
RCC->CFGR3 &= (uint32_t)0xFFFFFE2CU;
#elif defined(STM32F070x6) || defined(STM32F070xB)
// Reset USART1SW[1:0], I2C1SW, USBSW and ADCSW bits
RCC->CFGR3 &= (uint32_t)0xFFFFFE6CU;
// Set default USB clock to PLLCLK, since there is no HSI48
RCC->CFGR3 |= (uint32_t)0x00000080U;
#else
#warning "No target selected"
#endif
// Reset HSI14 bit
RCC->CR2 &= (uint32_t)0xFFFFFFFEU;
// Disable all interrupts
RCC->CIR = 0x00000000U;
// dpgeorge: enable 8-byte stack alignment for IRQ handlers, in accord with EABI
SCB->CCR |= SCB_CCR_STKALIGN_Msk;
}
void SystemClock_Config(void) {
// Enable power control peripheral
__HAL_RCC_PWR_CLK_ENABLE();
// Set flash latency to 1 because SYSCLK > 24MHz
FLASH->ACR = (FLASH->ACR & ~0x7) | 0x1;
#if MICROPY_HW_CLK_USE_HSI48
// Use the 48MHz internal oscillator
RCC->CR2 |= RCC_CR2_HSI48ON;
while ((RCC->CR2 & RCC_CR2_HSI48RDY) == 0) {
}
const uint32_t sysclk_src = 3;
#else
// Use HSE and the PLL to get a 48MHz SYSCLK
#if MICROPY_HW_CLK_USE_BYPASS
RCC->CR |= RCC_CR_HSEBYP;
#endif
RCC->CR |= RCC_CR_HSEON;
while ((RCC->CR & RCC_CR_HSERDY) == 0) {
// Wait for HSE to be ready
}
RCC->CFGR = ((48000000 / HSE_VALUE) - 2) << RCC_CFGR_PLLMUL_Pos | 2 << RCC_CFGR_PLLSRC_Pos;
RCC->CFGR2 = 0; // Input clock not divided
RCC->CR |= RCC_CR_PLLON; // Turn PLL on
while ((RCC->CR & RCC_CR_PLLRDY) == 0) {
// Wait for PLL to lock
}
const uint32_t sysclk_src = 2;
#endif
// Select SYSCLK source
RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos;
while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) {
// Wait for SYSCLK source to change
}
SystemCoreClockUpdate();
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
}
void SystemCoreClockUpdate(void) {
// Get SYSCLK source
uint32_t tmp = RCC->CFGR & RCC_CFGR_SWS;
switch (tmp) {
case RCC_CFGR_SWS_HSI:
SystemCoreClock = HSI_VALUE;
break;
case RCC_CFGR_SWS_HSE:
SystemCoreClock = HSE_VALUE;
break;
case RCC_CFGR_SWS_PLL: {
/* Get PLL clock source and multiplication factor */
uint32_t pllmull = RCC->CFGR & RCC_CFGR_PLLMUL;
uint32_t pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
pllmull = (pllmull >> 18) + 2;
uint32_t predivfactor = (RCC->CFGR2 & RCC_CFGR2_PREDIV) + 1;
if (pllsource == RCC_CFGR_PLLSRC_HSE_PREDIV) {
/* HSE used as PLL clock source : SystemCoreClock = HSE/PREDIV * PLLMUL */
SystemCoreClock = (HSE_VALUE/predivfactor) * pllmull;
#if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F072xB) \
|| defined(STM32F078xx) || defined(STM32F091xC) || defined(STM32F098xx)
} else if (pllsource == RCC_CFGR_PLLSRC_HSI48_PREDIV) {
/* HSI48 used as PLL clock source : SystemCoreClock = HSI48/PREDIV * PLLMUL */
SystemCoreClock = (HSI48_VALUE/predivfactor) * pllmull;
#endif
} else {
#if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F070x6) \
|| defined(STM32F078xx) || defined(STM32F071xB) || defined(STM32F072xB) \
|| defined(STM32F070xB) || defined(STM32F091xC) || defined(STM32F098xx) || defined(STM32F030xC)
/* HSI used as PLL clock source : SystemCoreClock = HSI/PREDIV * PLLMUL */
SystemCoreClock = (HSI_VALUE / predivfactor) * pllmull;
#else
/* HSI used as PLL clock source : SystemCoreClock = HSI/2 * PLLMUL */
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
#endif
}
break;
}
case RCC_CFGR_SWS_HSI48:
SystemCoreClock = HSI48_VALUE;
break;
default:
SystemCoreClock = HSI_VALUE;
break;
}
// Compute HCLK clock frequency
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
SystemCoreClock >>= tmp;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/