1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

kinetis: Unify cpu.c, update clocking initialization

Unify cpu_init for all Kinetis CPUs to reduce code duplication.
Updated the MCG driver implementation to make the configuration easier.
Most clock settings are initialized by kinetis_mcg_init() called from
cpu_init. Board specific external clock source initialization
(FRDM-K64F, PhyNode) needs to be performed in board_init instead of
in cpu_init.
This commit is contained in:
Joakim Nohlgård 2017-04-27 15:42:22 +02:00
parent aa67bdbc42
commit 742bcad912
18 changed files with 639 additions and 688 deletions

View File

@ -25,17 +25,8 @@
#include "mcg.h"
#include "periph/gpio.h"
#define SIM_CLKDIV1_48MHZ (SIM_CLKDIV1_OUTDIV1(0) | \
SIM_CLKDIV1_OUTDIV2(1) | \
SIM_CLKDIV1_OUTDIV3(1) | \
SIM_CLKDIV1_OUTDIV4(1))
static void cpu_clock_init(void);
void board_init(void)
{
/* initialize the clock system */
cpu_clock_init();
/* initialize the CPU core */
cpu_init();
@ -47,22 +38,3 @@ void board_init(void)
gpio_set(LED1_PIN);
gpio_set(LED2_PIN);
}
/**
* @brief Configure the controllers clock system
*
* | Clock name | Run mode frequency (max) | VLPR mode frequency (max) |
*
* | Core | 120 MHz | 4 MHz |
* | System | 120 MHz | 4 MHz |
* | Bus | 60 MHz | 4 MHz |
* | FlexBus | 30 MHz | 800 kHz |
* | Flash | 26.67 MHz | 4 MHz |
*/
static void cpu_clock_init(void)
{
/* setup system prescalers */
SIM->CLKDIV1 = (uint32_t)SIM_CLKDIV1_48MHZ;
kinetis_mcg_set_mode(KINETIS_MCG_PEE);
}

View File

@ -30,20 +30,33 @@ extern "C"
* @name Clock system configuration
* @{
*/
#define KINETIS_CPU_USE_MCG 1
#define KINETIS_MCG_USE_ERC 1
#define KINETIS_MCG_USE_PLL 1
/* The crystal connected to OSC0 is 8 MHz */
#define KINETIS_MCG_DCO_RANGE (48000000u)
#define KINETIS_MCG_ERC_OSCILLATOR 1
#define KINETIS_MCG_ERC_FRDIV 3 /* ERC divider = 256 */
#define KINETIS_MCG_ERC_RANGE 1
#define KINETIS_MCG_ERC_FREQ (40000000u)
#define KINETIS_MCG_PLL_PRDIV 3 /* divide factor = 4 */
#define KINETIS_MCG_PLL_VDIV0 0 /* multiply factor = 24 */
#define KINETIS_MCG_PLL_FREQ (48000000u)
#define CLOCK_CORECLOCK KINETIS_MCG_PLL_FREQ
static const clock_config_t clock_config = {
/*
* This configuration results in the system running from the FLL output with
* the following clock frequencies:
* Core: 60 MHz
* Bus: 30 MHz
* Flex: 20 MHz
* Flash: 20 MHz
*/
.clkdiv1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) |
SIM_CLKDIV1_OUTDIV3(2) | SIM_CLKDIV1_OUTDIV4(2),
.default_mode = KINETIS_MCG_MODE_FEE,
/* The crystal connected to OSC0 is 8 MHz */
.erc_range = KINETIS_MCG_ERC_RANGE_HIGH,
.fcrdiv = 0, /* Fast IRC divide by 1 => 4 MHz */
.oscsel = 0, /* Use OSC0 for external clock */
.clc = 0, /* External load caps on the FRDM-K22F board */
.fll_frdiv = 0b011, /* Divide by 256 */
.fll_factor_fei = KINETIS_MCG_FLL_FACTOR_1464, /* FLL freq = 48 MHz */
.fll_factor_fee = KINETIS_MCG_FLL_FACTOR_1920, /* FLL freq = 60 MHz */
.pll_prdiv = 0b00011, /* Divide by 4 */
.pll_vdiv = 0b00110, /* Multiply by 30 => PLL freq = 60 MHz */
.enable_oscillator = true,
.select_fast_irc = true,
.enable_mcgirclk = false,
};
#define CLOCK_CORECLOCK (60000000ul)
#define CLOCK_BUSCLOCK (CLOCK_CORECLOCK / 2)
/** @} */
@ -211,20 +224,20 @@ static const spi_conf_t spi_config[] = {
* @{
*/
#define I2C_NUMOF (1U)
#define I2C_CLK CLOCK_CORECLOCK
#define I2C_CLK CLOCK_BUSCLOCK
#define I2C_0_EN 1
#define I2C_IRQ_PRIO 1
/* Low (10 kHz): MUL = 4, SCL divider = 1280, total: 5120 */
#define KINETIS_I2C_F_ICR_LOW (0x35)
#define KINETIS_I2C_F_MULT_LOW (2)
/* Normal (100 kHz): MUL = 2, SCL divider = 240, total: 480 */
#define KINETIS_I2C_F_ICR_NORMAL (0x1F)
/* Low (10 kHz): MUL = 2, SCL divider = 1536, total: 3072 */
#define KINETIS_I2C_F_ICR_LOW (0x36)
#define KINETIS_I2C_F_MULT_LOW (1)
/* Normal (100 kHz): MUL = 2, SCL divider = 160, total: 320 */
#define KINETIS_I2C_F_ICR_NORMAL (0x1D)
#define KINETIS_I2C_F_MULT_NORMAL (1)
/* Fast (400 kHz): MUL = 1, SCL divider = 128, total: 128 */
#define KINETIS_I2C_F_ICR_FAST (0x17)
/* Fast (400 kHz): MUL = 1, SCL divider = 80, total: 80 */
#define KINETIS_I2C_F_ICR_FAST (0x14)
#define KINETIS_I2C_F_MULT_FAST (0)
/* Fast plus (1000 kHz): MUL = 1, SCL divider = 48, total: 48 */
#define KINETIS_I2C_F_ICR_FAST_PLUS (0x10)
/* Fast plus (1000 kHz): MUL = 1, SCL divider = 30, total: 30 */
#define KINETIS_I2C_F_ICR_FAST_PLUS (0x05)
#define KINETIS_I2C_F_MULT_FAST_PLUS (0)
/* I2C 0 device configuration */
@ -235,7 +248,7 @@ static const spi_conf_t spi_config[] = {
#define I2C_0_IRQ_HANDLER isr_i2c0
/* I2C 0 pin configuration */
#define I2C_0_PORT PORTB
#define I2C_0_PORT_CLKEN() (SIM->SCGC5 |= (SIM_SCGC5_PORTE_MASK))
#define I2C_0_PORT_CLKEN() (SIM->SCGC5 |= (SIM_SCGC5_PORTB_MASK))
#define I2C_0_PIN_AF 2
#define I2C_0_SDA_PIN 3
#define I2C_0_SCL_PIN 2

View File

@ -24,6 +24,10 @@
void board_init(void)
{
/* RMII RXCLK pin configuration */
SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
PORTA->PCR[18] &= ~(PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07));
/* initialize the CPU core */
cpu_init();

View File

@ -31,21 +31,34 @@ extern "C"
* @name Clock system configuration
* @{
*/
#define KINETIS_CPU_USE_MCG 1
#define KINETIS_MCG_USE_ERC 1
#define KINETIS_MCG_USE_PLL 1
#define KINETIS_MCG_DCO_RANGE (24000000U)
#define KINETIS_MCG_ERC_OSCILLATOR 0
#define KINETIS_MCG_ERC_FRDIV 6 /* ERC devider = 1280 */
#define KINETIS_MCG_ERC_RANGE 2
#define KINETIS_MCG_ERC_FREQ 50000000
#define KINETIS_MCG_PLL_PRDIV 19 /* divide factor = 20 */
#define KINETIS_MCG_PLL_VDIV0 0 /* multiply factor = 24 */
#define KINETIS_MCG_PLL_FREQ 60000000
#define CLOCK_CORECLOCK KINETIS_MCG_PLL_FREQ
#define CLOCK_BUSCLOCK (CLOCK_CORECLOCK / 2)
static const clock_config_t clock_config = {
/*
* This configuration results in the system running from the PLL output with
* the following clock frequencies:
* Core: 60 MHz
* Bus: 60 MHz
* Flex: 20 MHz
* Flash: 20 MHz
*/
.clkdiv1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) |
SIM_CLKDIV1_OUTDIV3(2) | SIM_CLKDIV1_OUTDIV4(2),
.default_mode = KINETIS_MCG_MODE_PEE,
/* The board has an external RMII (Ethernet) clock which drives the ERC at 50 MHz */
.erc_range = KINETIS_MCG_ERC_RANGE_VERY_HIGH,
.fcrdiv = 0, /* Fast IRC divide by 1 => 4 MHz */
.oscsel = 0, /* Use EXTAL for external clock */
.clc = 0, /* External load caps on board */
.fll_frdiv = 0b111, /* Divide by 1536 => FLL input 32252 Hz */
.fll_factor_fei = KINETIS_MCG_FLL_FACTOR_1464, /* FLL freq = 48 MHz */
.fll_factor_fee = KINETIS_MCG_FLL_FACTOR_1920, /* FLL freq = 62.5 MHz */
.pll_prdiv = 0b10011, /* Divide by 20 */
.pll_vdiv = 0b00000, /* Multiply by 24 => PLL freq = 60 MHz */
.enable_oscillator = false, /* Use EXTAL directly without OSC0 */
.select_fast_irc = true,
.enable_mcgirclk = false,
};
#define CLOCK_CORECLOCK (60000000ul)
#define CLOCK_BUSCLOCK (CLOCK_CORECLOCK / 1)
/** @} */
/**
@ -206,20 +219,20 @@ static const spi_conf_t spi_config[] = {
* @{
*/
#define I2C_NUMOF (1U)
#define I2C_CLK CLOCK_CORECLOCK
#define I2C_CLK CLOCK_BUSCLOCK
#define I2C_0_EN 1
#define I2C_IRQ_PRIO 1
/* Low (10 kHz): MUL = 4, SCL divider = 2560, total: 10240 */
#define KINETIS_I2C_F_ICR_LOW (0x3D)
/* Low (10 kHz): MUL = 4, SCL divider = 1536, total: 6144 */
#define KINETIS_I2C_F_ICR_LOW (0x36)
#define KINETIS_I2C_F_MULT_LOW (2)
/* Normal (100 kHz): MUL = 2, SCL divider = 240, total: 480 */
#define KINETIS_I2C_F_ICR_NORMAL (0x1F)
/* Normal (100 kHz): MUL = 2, SCL divider = 320, total: 640 */
#define KINETIS_I2C_F_ICR_NORMAL (0x25)
#define KINETIS_I2C_F_MULT_NORMAL (1)
/* Fast (400 kHz): MUL = 1, SCL divider = 128, total: 128 */
#define KINETIS_I2C_F_ICR_FAST (0x17)
/* Fast (400 kHz): MUL = 1, SCL divider = 160, total: 160 */
#define KINETIS_I2C_F_ICR_FAST (0x1D)
#define KINETIS_I2C_F_MULT_FAST (0)
/* Fast plus (1000 kHz): MUL = 1, SCL divider = 48, total: 48 */
#define KINETIS_I2C_F_ICR_FAST_PLUS (0x10)
/* Fast plus (1000 kHz): MUL = 1, SCL divider = 64, total: 64 */
#define KINETIS_I2C_F_ICR_FAST_PLUS (0x12)
#define KINETIS_I2C_F_MULT_FAST_PLUS (0)
/* I2C 0 device configuration */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2015 Eistec AB
* Copyright (C) 2014-2017 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
@ -74,17 +74,6 @@ static devfs_t mulle_nor_devfs = {
/** @brief Initialize the GPIO pins controlling the power switches. */
static inline void power_pins_init(void);
/**
* @brief Set clock prescalers to safe values
*
* This should be done before switching to FLL/PLL as clock source to ensure
* that all clocks remain within the specified limits.
*/
static inline void set_safe_clock_dividers(void);
/** @brief Set the FLL source clock to RTC32k */
static inline void set_fll_source(void);
static void increase_boot_count(void);
static int mulle_nvram_init(void);
@ -123,12 +112,8 @@ void board_init(void)
* for debug prints as well */
rtt_init();
/* Set up clocks */
set_safe_clock_dividers();
set_fll_source();
kinetis_mcg_set_mode(KINETIS_MCG_FEE);
/* Set 32 kHz clock source */
SIM->SOPT1 = (SIM->SOPT1 & ~(SIM_SOPT1_OSC32KSEL_MASK)) | SIM_SOPT1_OSC32KSEL(2);
/* At this point we need to wait for 1 ms until the clock is stable.
* Since the clock is not yet stable we can only guess how long we must
@ -167,36 +152,6 @@ static inline void power_pins_init(void)
gpio_clear(MULLE_POWER_VSEC);
}
static inline void set_safe_clock_dividers(void)
{
/*
* We want to achieve the following clocks:
* Core/system: <100MHz
* Bus: <50MHz
* FlexBus: <50MHz
* Flash: <25MHz
*
* using dividers 1-2-2-4 will obey the above limits when using a 96MHz FLL source.
*/
SIM->CLKDIV1 = (
SIM_CLKDIV1_OUTDIV1(CONFIG_CLOCK_K60_SYS_DIV) | /* Core/System clock divider */
SIM_CLKDIV1_OUTDIV2(CONFIG_CLOCK_K60_BUS_DIV) | /* Bus clock divider */
SIM_CLKDIV1_OUTDIV3(CONFIG_CLOCK_K60_FB_DIV) | /* FlexBus divider, not used in Mulle */
SIM_CLKDIV1_OUTDIV4(CONFIG_CLOCK_K60_FLASH_DIV)); /* Flash clock divider */
}
static inline void set_fll_source(void)
{
/* Select FLL as source (as opposed to PLL) */
SIM->SOPT2 &= ~(SIM_SOPT2_PLLFLLSEL_MASK);
/* Use external 32kHz RTC clock as source for OSC32K */
SIM->SOPT1 = (SIM->SOPT1 & ~(SIM_SOPT1_OSC32KSEL_MASK)) | SIM_SOPT1_OSC32KSEL(2);
/* Select RTC 32kHz clock as reference clock for the FLL */
MCG->C7 = (MCG_C7_OSCSEL_MASK);
}
static int mulle_nvram_init(void)
{
union {

View File

@ -176,32 +176,5 @@ extern mtd_dev_t *mtd0;
#define MULLE_VBAT_ADC_LINE ADC_LINE(6)
#define MULLE_VCHR_ADC_LINE ADC_LINE(7)
/** @} */
/**
* @name K60 clock dividers
*/
/** @{ */
/**
* System clock divider setting, the actual hardware register value, see reference manual for details.
*/
#define CONFIG_CLOCK_K60_SYS_DIV 0x00
/**
* Bus clock divider setting, the actual hardware register value, see reference manual for details
*/
#define CONFIG_CLOCK_K60_BUS_DIV 0x01
/**
* Flexbus clock divider setting, the actual hardware register value, see reference manual for details
*/
#define CONFIG_CLOCK_K60_FB_DIV 0x01
/**
* Flash clock divider setting, the actual hardware register value, see reference manual for details
*/
#define CONFIG_CLOCK_K60_FLASH_DIV 0x03
/** @} */
#endif /* BOARD_H */
/** @} */

View File

@ -33,30 +33,42 @@ extern "C"
* @name Clock system configuration
* @{
*/
#define KINETIS_CPU_USE_MCG 1
#define KINETIS_MCG_USE_ERC 1
#define KINETIS_MCG_USE_PLL 0
#define KINETIS_MCG_DCO_RANGE (96000000U)
#define KINETIS_MCG_ERC_OSCILLATOR 0
#define KINETIS_MCG_ERC_FRDIV 0
#define KINETIS_MCG_ERC_RANGE 0
#define KINETIS_MCG_ERC_FREQ (32768U)
/** Value of the external crystal or oscillator clock frequency in Hz */
#define CPU_XTAL_CLK_HZ 8000000u
/** Value of the external 32k crystal or oscillator clock frequency in Hz */
#define CPU_XTAL32k_CLK_HZ 32768u
/** Value of the slow internal oscillator clock frequency in Hz */
#define CPU_INT_SLOW_CLK_HZ 32768u
/** Value of the fast internal oscillator clock frequency in Hz */
#define CPU_INT_FAST_CLK_HZ 4000000u
/** Default System clock value */
#define DEFAULT_SYSTEM_CLOCK (CPU_XTAL32k_CLK_HZ * 2929u)
/* bus clock for the peripherals */
#define CLOCK_CORECLOCK (DEFAULT_SYSTEM_CLOCK)
#define CLOCK_BUSCLOCK (CLOCK_CORECLOCK / 2)
static const clock_config_t clock_config = {
/*
* This configuration results in the system running from the FLL output with
* the following clock frequencies:
* Core: 48 MHz
* Bus: 48 MHz
* Flex: 24 MHz
* Flash: 24 MHz
*/
/* The board has a 16 MHz crystal, though it is not used in this configuration */
/* This configuration uses the RTC crystal to provide the base clock, it
* should have better accuracy than the internal slow clock, and lower power
* consumption than using the 16 MHz crystal and the OSC0 module */
.clkdiv1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) |
SIM_CLKDIV1_OUTDIV3(2) | SIM_CLKDIV1_OUTDIV4(2),
.default_mode = KINETIS_MCG_MODE_FEE,
.erc_range = KINETIS_MCG_ERC_RANGE_LOW, /* Input clock is 32768 Hz */
.fcrdiv = 0, /* Fast IRC divide by 1 => 4 MHz */
.oscsel = 1, /* Use RTC for external clock */
/* 16 pF capacitors yield ca 10 pF load capacitance as required by the
* onboard xtal, not used when OSC0 is disabled */
.clc = 0b0001,
.fll_frdiv = 0b000, /* Divide by 1 => FLL input 32768 Hz */
.fll_factor_fei = KINETIS_MCG_FLL_FACTOR_1464, /* FLL freq = 48 MHz */
.fll_factor_fee = KINETIS_MCG_FLL_FACTOR_1464, /* FLL freq = 48 MHz */
/* PLL is unavailable when using a 32768 Hz source clock, so the
* configuration below can only be used if the above config is modified to
* use the 16 MHz crystal instead of the RTC. */
.pll_prdiv = 0b00111, /* Divide by 8 */
.pll_vdiv = 0b01100, /* Multiply by 36 => PLL freq = 72 MHz */
.enable_oscillator = false, /* the RTC module provides the clock input signal */
.select_fast_irc = true, /* Only used for FBI mode */
.enable_mcgirclk = false,
};
#define CLOCK_CORECLOCK (48000000ul)
#define CLOCK_BUSCLOCK (CLOCK_CORECLOCK / 1)
/** @} */
/**
@ -328,9 +340,9 @@ static const spi_conf_t spi_config[] = {
* @name I2C baud rate configuration
* @{
*/
/* Low (10 kHz): MUL = 4, SCL divider = 2560, total: 10240 */
/* Low (10 kHz): MUL = 2, SCL divider = 2560, total: 5120 */
#define KINETIS_I2C_F_ICR_LOW (0x3D)
#define KINETIS_I2C_F_MULT_LOW (2)
#define KINETIS_I2C_F_MULT_LOW (1)
/* Normal (100 kHz): MUL = 2, SCL divider = 240, total: 480 */
#define KINETIS_I2C_F_ICR_NORMAL (0x1F)
#define KINETIS_I2C_F_MULT_NORMAL (1)
@ -378,8 +390,14 @@ static const spi_conf_t spi_config[] = {
* to the data sheet, the K60 will have a 5 pF parasitic capacitance on the
* XTAL32/EXTAL32 connection. The board traces might give some minor parasitic
* capacitance as well. */
/* enable 6pF load capacitance, might need adjusting.. */
#define RTT_LOAD_CAP_BITS (RTC_CR_SC4P_MASK | RTC_CR_SC2P_MASK | RTC_CR_SC1P_MASK)
/* Use the equation
* CL = (C1 * C2) / (C1 + C2) + Cstray
* with C1 == C2:
* C1 = 2 * (CL - Cstray)
*/
/* enable 14pF load capacitor which will yield a crystal load capacitance of 12 pF */
#define RTC_LOAD_CAP_BITS (RTC_CR_SC8P_MASK | RTC_CR_SC4P_MASK | RTC_CR_SC2P_MASK)
/** @} */

View File

@ -21,8 +21,39 @@
*/
#include "board.h"
#include "bit.h"
#include "periph/gpio.h"
static inline void modem_clock_init(void)
{
/* Use the CLK_OUT of the modem as the clock source. */
/* Enable GPIO clock gates */
KW2XDRF_PORT_CLKEN();
KW2XDRF_CLK_CTRL_CLKEN();
/* Modem RST_B is connected to PTB19 and can be used to reset the modem. */
KW2XDRF_PORT_DEV->PCR[KW2XDRF_RST_PIN] = PORT_PCR_MUX(1);
bit_set32(&KW2XDRF_GPIO->PDDR, KW2XDRF_RST_PIN);
KW2XDRF_GPIO->PCOR = (1 << KW2XDRF_RST_PIN);
/* Modem GPIO5 is connected to PTC0 and can be used to select CLK_OUT frequency, */
/* set PTC0 high for CLK_OUT=32.787kHz and low for CLK_OUT=4MHz. */
KW2XDRF_CLK_CTRL_PORT_DEV->PCR[KW2XDRF_CLK_CTRL_PIN] = PORT_PCR_MUX(1);
bit_set32(&KW2XDRF_CLK_CTRL_GPIO->PDDR, KW2XDRF_CLK_CTRL_PIN);
KW2XDRF_CLK_CTRL_GPIO->PCOR = (1 << KW2XDRF_CLK_CTRL_PIN);
/* Modem IRQ_B is connected to PTB3, modem interrupt request to the MCU. */
KW2XDRF_PORT_DEV->PCR[KW2XDRF_IRQ_PIN] = PORT_PCR_MUX(1);
bit_clear32(&KW2XDRF_GPIO->PDDR, KW2XDRF_IRQ_PIN);
/* release the reset */
KW2XDRF_GPIO->PSOR = (1 << KW2XDRF_RST_PIN);
/* wait for modem IRQ_B interrupt request */
while (KW2XDRF_GPIO->PDIR & (1 << KW2XDRF_IRQ_PIN));
}
void board_init(void)
{
/* initialize the on-board LEDs */
@ -33,6 +64,8 @@ void board_init(void)
gpio_init(LED2_PIN, GPIO_OUT);
gpio_set(LED2_PIN);
modem_clock_init();
/* initialize the CPU core */
cpu_init();
}

View File

@ -33,21 +33,33 @@ extern "C"
* @name Clock system configuration
* @{
*/
#define KINETIS_CPU_USE_MCG 1
#define KINETIS_MCG_USE_ERC 1
#define KINETIS_MCG_USE_PLL 1
#define KINETIS_MCG_DCO_RANGE (24000000U)
#define KINETIS_MCG_ERC_OSCILLATOR 0
#define KINETIS_MCG_ERC_FRDIV 2
#define KINETIS_MCG_ERC_RANGE 1
#define KINETIS_MCG_ERC_FREQ 4000000
#define KINETIS_MCG_PLL_PRDIV 1
#define KINETIS_MCG_PLL_VDIV0 0
#define KINETIS_MCG_PLL_FREQ 48000000
#define CLOCK_CORECLOCK KINETIS_MCG_PLL_FREQ
#define CLOCK_BUSCLOCK CLOCK_CORECLOCK
static const clock_config_t clock_config = {
/*
* This configuration results in the system running from the PLL output with
* the following clock frequencies:
* Core: 48 MHz
* Bus: 48 MHz
* Flash: 24 MHz
*/
.clkdiv1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) |
SIM_CLKDIV1_OUTDIV4(1),
.default_mode = KINETIS_MCG_MODE_PEE,
/* The modem generates a 4 MHz clock signal */
.erc_range = KINETIS_MCG_ERC_RANGE_HIGH,
.fcrdiv = 0, /* Fast IRC divide by 1 => 4 MHz */
.oscsel = 0, /* Use EXTAL0 for external clock */
.clc = 0, /* OSC0 is unused*/
.fll_frdiv = 0b010, /* Divide by 128 */
.fll_factor_fei = KINETIS_MCG_FLL_FACTOR_1464, /* FLL freq = 48 MHz */
.fll_factor_fee = KINETIS_MCG_FLL_FACTOR_1280, /* FLL freq = 40 MHz */
.pll_prdiv = 0b00001, /* Divide by 2 */
.pll_vdiv = 0b00000, /* Multiply by 24 => PLL freq = 48 MHz */
.enable_oscillator = false, /* Use modem clock from EXTAL0 */
.select_fast_irc = true,
.enable_mcgirclk = false,
};
#define CLOCK_CORECLOCK (48000000ul)
#define CLOCK_BUSCLOCK (CLOCK_CORECLOCK / 1)
/** @} */
/**
@ -236,12 +248,12 @@ static const spi_conf_t spi_config[] = {
* @{
*/
#define I2C_NUMOF (1U)
#define I2C_CLK (48e6)
#define I2C_CLK (CLOCK_BUSCLOCK)
#define I2C_0_EN 1
#define I2C_IRQ_PRIO 1
/* Low (10 kHz): MUL = 4, SCL divider = 2560, total: 10240 */
/* Low (10 kHz): MUL = 2, SCL divider = 2560, total: 5120 */
#define KINETIS_I2C_F_ICR_LOW (0x3D)
#define KINETIS_I2C_F_MULT_LOW (2)
#define KINETIS_I2C_F_MULT_LOW (1)
/* Normal (100 kHz): MUL = 2, SCL divider = 240, total: 480 */
#define KINETIS_I2C_F_ICR_NORMAL (0x1F)
#define KINETIS_I2C_F_MULT_NORMAL (1)

View File

@ -1,34 +0,0 @@
/*
* Copyright (C) 2015 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
#include "cpu.h"
#include "board.h"
#include "periph/init.h"
/**
* @ingroup cpu_k60
* @{
*
* @file
* @brief Implementation of K60 CPU initialization.
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
/**
* @brief Initialize the CPU, set IRQ priorities
*/
void cpu_init(void)
{
/* initialize the Cortex-M core */
cortexm_init();
/* trigger static peripheral initialization */
periph_init();
}
/** @} */

View File

@ -14581,6 +14581,7 @@ typedef struct {
#define SIM_SCGC5_LPTMR_MASK SIM_SCGC5_LPTIMER_MASK
#define SIM_SCGC5_LPTMR_SHIFT SIM_SCGC5_LPTIMER_SHIFT
#define OSC0 OSC
#define MCG_C7_OSCSEL(x) (((uint32_t)(x) << MCG_C7_OSCSEL_SHIFT) & MCG_C7_OSCSEL_MASK)
/*!
* @}

View File

@ -1,69 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2015 PHYTEC Messtechnik GmbH
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_k64f
* @{
*
* @file
* @brief Implementation of the K64F CPU initialization
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Johann Fischer <j.fischer@phytec.de>
* @}
*/
#include <stdint.h>
#include "cpu.h"
#include "mcg.h"
#include "cpu_conf.h"
#include "periph/init.h"
#define SIM_CLKDIV1_60MHZ (SIM_CLKDIV1_OUTDIV1(0) | \
SIM_CLKDIV1_OUTDIV2(0) | \
SIM_CLKDIV1_OUTDIV3(1) | \
SIM_CLKDIV1_OUTDIV4(2))
static void cpu_clock_init(void);
/**
* @brief Initialize the CPU, set IRQ priorities
*/
void cpu_init(void)
{
/* initialize the Cortex-M core */
cortexm_init();
/* initialize the clock system */
cpu_clock_init();
/* trigger static peripheral initialization */
periph_init();
}
/**
* @brief Configure the controllers clock system
*
* | Clock name | Run mode frequency (max) | VLPR mode frequency (max) |
*
* | Core | 120 MHz | 4 MHz |
* | System | 120 MHz | 4 MHz |
* | Bus | 60 MHz | 4 MHz |
* | FlexBus | 50 MHz | 800 kHz |
* | Flash | 25 MHz | 4 MHz |
*/
static void cpu_clock_init(void)
{
/* setup system prescalers */
SIM->CLKDIV1 = (uint32_t)SIM_CLKDIV1_60MHZ;
/* RMII RXCLK */
SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
PORTA->PCR[18] &= ~(PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07));
kinetis_mcg_set_mode(KINETIS_MCG_PEE);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Eistec AB
* Copyright (C) 2017 SKF AB
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
@ -7,11 +7,11 @@
*/
/**
* @ingroup cpu_k22f
* @ingroup cpu_kinetis_common
* @{
*
* @file
* @brief Implementation of the K22F CPU initialization
* @brief Kinetis CPU initialization
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
* @}
@ -19,6 +19,7 @@
#include "cpu.h"
#include "periph/init.h"
#include "mcg.h"
/**
* @brief Initialize the CPU, set IRQ priorities
@ -27,6 +28,13 @@ void cpu_init(void)
{
/* initialize the Cortex-M core */
cortexm_init();
/* Clear LLS protection */
/* Clear VLPS, VLPW, VLPR protection */
/* Note: This register can only be written once after each reset, so we must
* enable all power modes that we wish to use. */
SMC->PMPROT |= SMC_PMPROT_ALLS_MASK | SMC_PMPROT_AVLP_MASK;
/* initialize the CPU clocking provided by the MCG module */
kinetis_mcg_init();
/* trigger static peripheral initialization */
periph_init();
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 PHYTEC Messtechnik GmbH
* Copyright (C) 2017 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
@ -12,31 +13,16 @@
* @brief Implementation of the Kinetis Multipurpose Clock Generator
* (MCG) driver
*
* Please add mcg.h in cpu conf.h
* Please add mcg.h in cpu_conf.h
* and MCG configuration to periph_conf.h
*
* MCG neighbor modes matrix:
* The configuration consists of the clock_config struct
* (@ref clock_config_t) and two macros @ref CLOCK_CORECLOCK,
* @ref CLOCK_BUSCLOCK. The two macros are used by other periph
* driver configurations to tell the driver what value the module
* clock is running at.
*
* x | FEI | FEE | FBI | FBE | BLPI | BLPE | PBE | PEE
* :---:|:---:|:---:|:---:|:---:|:----:|:----:|:---:|:---:
* PEE | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0
* PBE | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1
* BLPE | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0
* BLPI | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0
* FBE | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0
* FBI | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0
* FEE | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0
* FEI | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0
*
* Each neighbor mode can be selected directly.
* Further, the paths between the following modes are defined:
* - FEI -> PEE
* - BLPE -> PEE
* - PEE -> BLPE
* - FEE -> BLPE
* - FEE -> BLPI
* - BLPE -> FEE
* - BLPI -> FEE
* ### State transition map
*
* \dot
* digraph states {
@ -62,64 +48,73 @@
* }
* \enddot
*
* The driver will automatically move step by step through the map
* if the requested mode is not a direct neighbor of the current mode.
*
* ### MCG Configuration Examples (for periph_conf.h) ###
*
* Example for FEI Mode (MCGOUTCLK = 20MHz ... 25MHz):
* #### Example for PEE Mode with an 8 MHz crystal connected to XTAL0/EXTAL0
*
* #define KINETIS_MCG_USE_ERC 0
* #define KINETIS_MCG_DCO_RANGE (24000000U)
* The resulting PLL output frequency will be 60 MHz, the core will
* be running at the full PLL output frequency.
*
* static const clock_config_t clock_config = {
* // safe clock dividers for this CPU
* .clkdiv1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) |
* SIM_CLKDIV1_OUTDIV3(1) | SIM_CLKDIV1_OUTDIV4(2),
* // Select default clocking mode
* .default_mode = KINETIS_MCG_MODE_PEE,
* // The crystal connected to OSC0 is 8 MHz
* .erc_range = KINETIS_MCG_ERC_RANGE_HIGH,
* .fcrdiv = 0, // Fast IRC divide by 1 => 4 MHz
* .oscsel = 0, // Use OSC0 for external clock
* .clc = 0, // Use external load caps on board
* .fll_frdiv = 0b011, // Divide by 256
* .fll_factor_fei = KINETIS_MCG_FLL_FACTOR_1920, // FLL freq = 60 MHz ?
* .fll_factor_fee = KINETIS_MCG_FLL_FACTOR_1920, // FLL freq = 60 MHz
* .pll_prdiv = 0b00011, // Divide by 4 => PLL input freq = 2 MHz
* .pll_vdiv = 0b00110, // Multiply by 30 => PLL output freq = 60 MHz
* .enable_oscillator = true, // Enable oscillator, EXTAL0 is connected to a crystal
* .select_fast_irc = true, // Use fast IRC when in FBI mode
* .enable_mcgirclk = false, // We don't need the internal reference clock while running in PEE mode
* };
* #define CLOCK_CORECLOCK (60000000ul)
* #define CLOCK_BUSCLOCK (CLOCK_CORECLOCK / 1)
*
* Example for FEE Mode, 32768Hz Crystal,
* (MCGOUTCLK = 24MHz):
* #### Example for FEE Mode, 32.768 kHz crystal connected to RTC
*
* #define KINETIS_MCG_USE_ERC 1
* #define KINETIS_MCG_USE_PLL 0
* #define KINETIS_MCG_DCO_RANGE (24000000U)
* #define KINETIS_MCG_ERC_OSCILLATOR 1
* #define KINETIS_MCG_ERC_FRDIV 0
* #define KINETIS_MCG_ERC_RANGE 0
* #define KINETIS_MCG_ERC_FREQ (32768U)
* The resulting FLL output frequency will be circa 72 MHz, the core
* will be running at the full FLL output frequency.
*
* static const clock_config_t clock_config = {
* // safe clock dividers for this CPU
* .clkdiv1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) |
* SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV3(2),
* .default_mode = KINETIS_MCG_MODE_FEE,
* // The board has a 16 MHz crystal, though it is not used in this configuration
* .erc_range = KINETIS_MCG_ERC_RANGE_VERY_HIGH,
* .fcrdiv = 0, // Fast IRC divide by 1 => 4 MHz
* .oscsel = 1, // Use RTC for external clock
* .clc = 0b0001, // 16 pF capacitors yield ca 10 pF load capacitance
* .fll_frdiv = 0b000, // Divide by 1 => FLL input 32768 Hz
* .fll_factor_fei = KINETIS_MCG_FLL_FACTOR_1920, // FLL freq = 60 MHz ?
* .fll_factor_fee = KINETIS_MCG_FLL_FACTOR_2197, // FLL freq = 71.991296 MHz
* .pll_prdiv = 0b00111, // Divide by 8
* .pll_vdiv = 0b01100, // Multiply by 36 => PLL freq = 72 MHz
* .enable_oscillator = false, // OSC0 disabled
* .select_fast_irc = true, // Use fast IRC for internal reference clock
* .enable_mcgirclk = false, // We don't need the internal reference clock while running in FEE mode
* };
* #define CLOCK_CORECLOCK (71991296ul)
* #define CLOCK_BUSCLOCK (CLOCK_CORECLOCK / 2)
*
* Example for FEE Mode, external 4MHz reference
* (\f$MCGOUTCLK
* = \frac{ERC_{\mathrm{freq}}\cdot FFL_{\mathrm{Factor}}}{FRDIV}
* = \frac{4\,\mathrm{MHz}\cdot 732}{128} = 22.875\,\mathrm{MHz}\f$):
*
* #define KINETIS_MCG_USE_ERC 1
* #define KINETIS_MCG_USE_PLL 0
* #define KINETIS_MCG_DCO_RANGE (24000000U)
* #define KINETIS_MCG_ERC_OSCILLATOR 0
* #define KINETIS_MCG_ERC_FRDIV 2
* #define KINETIS_MCG_ERC_RANGE 1
* #define KINETIS_MCG_ERC_FREQ (4000000U)
*
* Example for PEE Mode, external 4MHz reference
* (\f$MCGOUTCLK
* = \frac{ERC_{\mathrm{freq}}\cdot VDIV0}{PRDIV}
* = \frac{4\,\mathrm{MHz}\cdot 24}{2} = 48\,\mathrm{MHz}\f$):
*
* #define KINETIS_MCG_USE_ERC 1
* #define KINETIS_MCG_USE_PLL 1
* #define KINETIS_MCG_DCO_RANGE (24000000U)
* #define KINETIS_MCG_ERC_OSCILLATOR 0
* #define KINETIS_MCG_ERC_FRDIV 2
* #define KINETIS_MCG_ERC_RANGE 1
* #define KINETIS_MCG_ERC_FREQ (4000000U)
* #define KINETIS_MCG_PLL_PRDIV 1
* #define KINETIS_MCG_PLL_VDIV0 0
* #define KINETIS_MCG_PLL_FREQ (48000000U)
*
*
* The desired mode can be selected in cpu.c:cpu_clock_init()
* with kinetis_mcg_set_mode(KINETIS_MCG_PEE);
* @{
*
* @file
* @brief Interface definition for the Kinetis MCG driver.
*
* @author Johann Fischer <j.fischer@phytec.de>
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
#ifndef MCG_H
@ -127,35 +122,52 @@
#include "periph_conf.h"
#if KINETIS_CPU_USE_MCG
#ifdef __cplusplus
extern "C"
{
#endif
typedef enum kinetis_mcg_mode {
KINETIS_MCG_PEE = 0, /**< PLL Engaged External Mode */
KINETIS_MCG_PBE, /**< PLL Bypassed External Mode */
KINETIS_MCG_BLPE, /**< FLL Bypassed Low Power External Mode */
KINETIS_MCG_BLPI, /**< FLL Bypassed Low Power Internal Mode */
KINETIS_MCG_FBE, /**< FLL Bypassed External Mode */
KINETIS_MCG_FBI, /**< FLL Bypassed Internal Mode */
KINETIS_MCG_FEE, /**< FLL Engaged External Mode */
KINETIS_MCG_FEI, /**< FLL Engaged Internal Mode */
} kinetis_mcg_mode_t;
#if DOXYGEN
/**
* @brief Core clock frequency, used by the ARM core and certain hardware modules in Kinetis CPUs
*
* The clock is derived from the MCG output clock divided by an integer divisor,
* which is controlled by the @ref clock_config_t::clkdiv1 settings
*/
#define CLOCK_CORECLOCK (MCGOUTCLK)
/**
* @brief Bus clock frequency, used by several hardware modules in Kinetis CPUs
*
* The clock is derived from the MCG output clock divided by an integer divisor,
* which is controlled by the @ref clock_config_t::clkdiv1 settings
*/
#define CLOCK_BUSCLOCK (CLOCK_CORECLOCK / x)
#endif
/**
* @brief Switch the MCG to the specified clocking mode
*
* Depending on the current clocking mode, this function may step through
* several other clocking modes in order to be able to reach the target mode.
*
* @param[in] mode Target mode
*
* @return 0 on success
* @return <0 on error
*/
int kinetis_mcg_set_mode(kinetis_mcg_mode_t mode);
/**
* @brief Initialize the MCG
*
* The configuration is found in the clock_config struct defined in periph_conf.h
*/
int kinetis_mcg_set_mode(kinetis_mcg_mode_t mode);
void kinetis_mcg_init(void);
#ifdef __cplusplus
}
#endif
#endif /* KINETIS_CPU_USE_MCG */
/** @} */
#endif /* MCG_H */

View File

@ -20,6 +20,7 @@
#define PERIPH_CPU_H
#include <stdint.h>
#include <stdbool.h>
#include "cpu.h"
@ -323,6 +324,112 @@ typedef struct {
uint8_t mode; /**< UART mode: data bits, parity, stop bits */
} uart_conf_t;
#if !defined(KINETIS_HAVE_PLL)
#if defined(MCG_C6_PLLS_MASK) || DOXYGEN
/**
* @brief Defined to 1 if the MCG in this Kinetis CPU has a PLL
*/
#define KINETIS_HAVE_PLL 1
#else
#define KINETIS_HAVE_PLL 0
#endif
#endif /* !defined(KINETIS_HAVE_PLL) */
/**
* @brief Kinetis possible MCG modes
*/
typedef enum kinetis_mcg_mode {
KINETIS_MCG_MODE_FEI = 0, /**< FLL Engaged Internal Mode */
KINETIS_MCG_MODE_FEE = 1, /**< FLL Engaged External Mode */
KINETIS_MCG_MODE_FBI = 2, /**< FLL Bypassed Internal Mode */
KINETIS_MCG_MODE_FBE = 3, /**< FLL Bypassed External Mode */
KINETIS_MCG_MODE_BLPI = 4, /**< FLL Bypassed Low Power Internal Mode */
KINETIS_MCG_MODE_BLPE = 5, /**< FLL Bypassed Low Power External Mode */
#if KINETIS_HAVE_PLL
KINETIS_MCG_MODE_PBE = 6, /**< PLL Bypassed External Mode */
KINETIS_MCG_MODE_PEE = 7, /**< PLL Engaged External Mode */
#endif
KINETIS_MCG_MODE_NUMOF, /**< Number of possible modes */
} kinetis_mcg_mode_t;
/**
* @brief Kinetis MCG FLL multiplier settings
*/
typedef enum {
/** FLL multiplier = 640 */
KINETIS_MCG_FLL_FACTOR_640 = (MCG_C4_DRST_DRS(0)),
/** FLL multiplier = 732 */
KINETIS_MCG_FLL_FACTOR_732 = (MCG_C4_DRST_DRS(0) | MCG_C4_DMX32_MASK),
/** FLL multiplier = 1280 */
KINETIS_MCG_FLL_FACTOR_1280 = (MCG_C4_DRST_DRS(1)),
/** FLL multiplier = 1464 */
KINETIS_MCG_FLL_FACTOR_1464 = (MCG_C4_DRST_DRS(1) | MCG_C4_DMX32_MASK),
/** FLL multiplier = 1920 */
KINETIS_MCG_FLL_FACTOR_1920 = (MCG_C4_DRST_DRS(2)),
/** FLL multiplier = 2197 */
KINETIS_MCG_FLL_FACTOR_2197 = (MCG_C4_DRST_DRS(2) | MCG_C4_DMX32_MASK),
/** FLL multiplier = 2560 */
KINETIS_MCG_FLL_FACTOR_2560 = (MCG_C4_DRST_DRS(3)),
/** FLL multiplier = 2929 */
KINETIS_MCG_FLL_FACTOR_2929 = (MCG_C4_DRST_DRS(3) | MCG_C4_DMX32_MASK),
} kinetis_mcg_fll_t;
/**
* @brief Kinetis FLL external reference clock range settings
*/
typedef enum {
KINETIS_MCG_ERC_RANGE_LOW = MCG_C2_RANGE0(0), /**< for 31.25-39.0625 kHz crystal */
KINETIS_MCG_ERC_RANGE_HIGH = MCG_C2_RANGE0(1), /**< for 3-8 MHz crystal */
KINETIS_MCG_ERC_RANGE_VERY_HIGH = MCG_C2_RANGE0(2), /**< for 8-32 MHz crystal */
} kinetis_mcg_erc_range_t;
/**
* @brief Clock configuration for Kinetis CPUs
*/
typedef struct {
/** Clock divider bitfield setting, see reference manual for SIM_CLKDIV1 */
uint32_t clkdiv1;
/** MCG mode used after initialization, see kinetis_mcg_mode_t */
kinetis_mcg_mode_t default_mode;
/** ERC range setting, see kinetis_mcg_erc_range_t */
kinetis_mcg_erc_range_t erc_range;
/** Fast internal reference clock divider, see reference manual for MCG_SC[FCRDIV] */
uint8_t fcrdiv;
/** Oscillator selection, see reference manual for MCG_C7[OSCSEL] */
uint8_t oscsel;
/** Capacitor Load configuration bits, see reference manual for OSC_CR */
uint8_t clc;
/** FLL ERC divider setting, see reference manual for MCG_C1[FRDIV] */
uint8_t fll_frdiv;
/** FLL multiplier when running in FEI mode */
kinetis_mcg_fll_t fll_factor_fei;
/** FLL multiplier when running in FEE mode */
kinetis_mcg_fll_t fll_factor_fee;
#if KINETIS_HAVE_PLL
/** PLL ERC divider setting, see reference manual for MCG_C5[PRDIV] */
uint8_t pll_prdiv;
/** PLL VCO divider setting, see reference manual for MCG_C6[VDIV0] */
uint8_t pll_vdiv;
#endif /* KINETIS_HAVE_PLL */
/**
* @brief External reference clock selection
*
* True: Use oscillator circuit with external crystal.
* False: Use external clock signal directly.
*/
bool enable_oscillator;
/**
* @brief Use fast internal reference clock for MCGIRCLK
*
* See reference manual for MCG module and MCG_C2[IRCS]
*/
bool select_fast_irc;
/**
* @brief Enable MCGIRCLK output from MCG for use as alternate clock in some modules
*/
bool enable_mcgirclk;
} clock_config_t;
/**
* @brief CPU internal function for initializing PORTs
*

View File

@ -21,126 +21,35 @@
*/
#include <stdint.h>
#include "mcg.h"
#include "periph_conf.h"
#if KINETIS_CPU_USE_MCG
#if defined(MCG_C6_PLLS_MASK)
#define KINETIS_HAVE_PLL 1
#else
#define KINETIS_HAVE_PLL 0
#endif
#include "mcg.h"
#include "bit.h"
/* Pathfinding for the clocking modes, this table lists the next mode in the
* chain when moving from mode <first> to mode <second> */
static const uint8_t mcg_mode_routing[8][8] = {
{0, 1, 1, 1, 1, 1, 1, 1}, /* from PEE */
{0, 1, 2, 4, 4, 4, 4, 4}, /* from PBE */
{1, 1, 2, 4, 4, 4, 4, 4}, /* from BLPE */
{5, 5, 5, 3, 5, 5, 5, 5}, /* from BLPI */
{1, 1, 2, 5, 4, 5, 6, 7}, /* from FBE */
{4, 4, 4, 3, 4, 5, 6, 7}, /* from FBI */
{4, 4, 4, 5, 4, 5, 6, 7}, /* from FEE */
{4, 4, 4, 5, 4, 5, 6, 7}, /* from FEI */
{0, 1, 2, 3, 2, 3, 3, 3}, /* from FEI */
{0, 1, 2, 3, 2, 3, 3, 3}, /* from FEE */
{0, 1, 2, 3, 4, 3, 3, 3}, /* from FBI */
{0, 1, 2, 3, 2, 5, 6, 6}, /* from FBE */
{2, 2, 2, 2, 4, 2, 2, 2}, /* from BLPI */
{3, 3, 3, 3, 3, 5, 6, 6}, /* from BLPE */
{3, 3, 3, 3, 3, 5, 6, 7}, /* from PBE */
{6, 6, 6, 6, 6, 6, 6, 7}, /* from PEE */
};
static uint8_t current_mode = KINETIS_MCG_FEI;
#define KINETIS_MCG_FLL_FACTOR_640 0
#define KINETIS_MCG_FLL_FACTOR_732 (MCG_C4_DRST_DRS(0) | MCG_C4_DMX32_MASK)
#define KINETIS_MCG_FLL_FACTOR_1280 (MCG_C4_DRST_DRS(1))
#define KINETIS_MCG_FLL_FACTOR_1464 (MCG_C4_DRST_DRS(1) | MCG_C4_DMX32_MASK)
#define KINETIS_MCG_FLL_FACTOR_1920 (MCG_C4_DRST_DRS(2))
#define KINETIS_MCG_FLL_FACTOR_2197 (MCG_C4_DRST_DRS(2) | MCG_C4_DMX32_MASK)
#define KINETIS_MCG_FLL_FACTOR_2560 (MCG_C4_DRST_DRS(3))
#define KINETIS_MCG_FLL_FACTOR_2929 (MCG_C4_DRST_DRS(3) | MCG_C4_DMX32_MASK)
#ifndef KINETIS_MCG_DCO_RANGE
#define KINETIS_MCG_DCO_RANGE (48000000U)
#endif
/* Default DCO_RANGE should be defined in periph_conf.h */
#if (KINETIS_MCG_DCO_RANGE == 24000000U)
#define KINETIS_MCG_FLL_FACTOR_FEI KINETIS_MCG_FLL_FACTOR_640
#define KINETIS_MCG_FLL_FACTOR_FEE KINETIS_MCG_FLL_FACTOR_732
#elif (KINETIS_MCG_DCO_RANGE == 48000000U)
#define KINETIS_MCG_FLL_FACTOR_FEI KINETIS_MCG_FLL_FACTOR_1280
#define KINETIS_MCG_FLL_FACTOR_FEE KINETIS_MCG_FLL_FACTOR_1464
#elif (KINETIS_MCG_DCO_RANGE == 72000000U)
#define KINETIS_MCG_FLL_FACTOR_FEI KINETIS_MCG_FLL_FACTOR_1920
#define KINETIS_MCG_FLL_FACTOR_FEE KINETIS_MCG_FLL_FACTOR_2197
#elif (KINETIS_MCG_DCO_RANGE == 96000000U)
#define KINETIS_MCG_FLL_FACTOR_FEI KINETIS_MCG_FLL_FACTOR_2560
#define KINETIS_MCG_FLL_FACTOR_FEE KINETIS_MCG_FLL_FACTOR_2929
#else
#error "KINETIS_MCG_DCO_RANGE is wrong"
#endif
#ifndef KINETIS_MCG_USE_FAST_IRC
#define KINETIS_MCG_USE_FAST_IRC 0
#endif
#if (KINETIS_MCG_USE_ERC == 0)
#define KINETIS_MCG_USE_ERC 0
#define KINETIS_MCG_USE_PLL 0
#define KINETIS_MCG_ERC_FREQ 0
#define KINETIS_MCG_ERC_FRDIV 0
#define KINETIS_MCG_ERC_RANGE 0
#define KINETIS_MCG_ERC_OSCILLATOR 0
#endif
#if (KINETIS_MCG_USE_PLL == 0)
#define KINETIS_MCG_PLL_PRDIV 0
#define KINETIS_MCG_PLL_VDIV0 0
#define KINETIS_MCG_PLL_FREQ 0
#endif
#ifndef KINETIS_MCG_OSC_CLC
#define KINETIS_MCG_OSC_CLC 0
#endif
#ifndef KINETIS_MCG_ERC_OSCILLATOR
#error "KINETIS_MCG_ERC_OSCILLATOR not defined in periph_conf.h"
#endif
#ifndef KINETIS_MCG_ERC_FREQ
#error "KINETIS_MCG_ERC_FREQ not defined in periph_conf.h"
#endif
#ifndef KINETIS_MCG_ERC_FRDIV
#error "KINETIS_MCG_ERC_FRDIV not defined in periph_conf.h"
#endif
#ifndef KINETIS_MCG_ERC_RANGE
#error "KINETIS_MCG_ERC_RANGE not defined in periph_conf.h"
#endif
#if KINETIS_HAVE_PLL
#ifndef KINETIS_MCG_PLL_PRDIV
#error "KINETIS_MCG_PLL_PRDIV not defined in periph_conf.h"
#endif
#ifndef KINETIS_MCG_PLL_VDIV0
#error "KINETIS_MCG_PLL_VDIV0 not defined in periph_conf.h"
#endif
#ifndef KINETIS_MCG_PLL_FREQ
#error "KINETIS_MCG_PLL_FREQ not defined in periph_conf.h"
#endif
/* The CPU is in FEI mode after hardware reset */
static kinetis_mcg_mode_t current_mode = KINETIS_MCG_MODE_FEI;
/**
* @brief Disable Phase Locked Loop (PLL)
*
*/
static inline void kinetis_mcg_disable_pll(void)
{
MCG->C5 = (uint8_t)0;
MCG->C6 = (uint8_t)0;
}
#else
static inline void kinetis_mcg_disable_pll(void) {}
#if KINETIS_HAVE_PLL
bit_clear8(&MCG->C6, MCG_C6_PLLS_SHIFT);
#endif /* KINETIS_HAVE_PLL */
}
/**
* @brief Set Frequency Locked Loop (FLL) factor.
@ -149,58 +58,48 @@ static inline void kinetis_mcg_disable_pll(void) {}
* FLL factor will be selected by DRST_DRS and DMX32 bits
* and depends on KINETIS_MCG_DCO_RANGE value.
*/
static inline void kinetis_mcg_set_fll_factor(uint8_t factor)
static inline void kinetis_mcg_set_fll_factor(kinetis_mcg_fll_t factor)
{
MCG->C4 &= ~(uint8_t)(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK);
MCG->C4 |= (uint8_t)(factor);
MCG->C4 = (MCG->C4 & ~(MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) | (uint8_t)factor;
}
#ifdef OSC0
/* Kinetis with OSC module */
/**
* @brief Enable Oscillator module
*
* The module settings depend on KINETIS_MCG_ERC_RANGE
* KINETIS_MCG_ERC_OSCILLATOR values.
*/
static void kinetis_mcg_enable_osc(void)
{
if (KINETIS_MCG_ERC_RANGE == 1) {
/* select high frequency range and oscillator clock */
MCG->C2 = (uint8_t)(MCG_C2_RANGE0(1));
}
else if (KINETIS_MCG_ERC_RANGE == 2) {
/* select very high frequency range and osciallor clock */
MCG->C2 = (uint8_t)(MCG_C2_RANGE0(2));
}
else {
/* select low frequency range and osciallor clock */
MCG->C2 = (uint8_t)(MCG_C2_RANGE0(0));
}
OSC0->CR = (uint8_t)(OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK
| (KINETIS_MCG_OSC_CLC & 0xf));
/* Configure ERC range for the DCO input. */
MCG->C2 = (MCG->C2 & ~MCG_C2_RANGE0_MASK) | clock_config.erc_range;
#if defined(OSC0)
/* Kinetis CPU with OSC module */
/* Enable Oscillator */
if (KINETIS_MCG_ERC_OSCILLATOR) {
MCG->C2 |= (uint8_t)(MCG_C2_EREFS0_MASK);
if (clock_config.enable_oscillator) {
/* Configure oscillator */
OSC0->CR = (uint8_t)(OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK |
(clock_config.clc & 0xf));
bit_set8(&MCG->C2, MCG_C2_EREFS0_SHIFT);
/* wait fo OSC initialization */
/* wait for OSC initialization */
while ((MCG->S & MCG_S_OSCINIT0_MASK) == 0) {}
}
}
else {
bit_clear8(&MCG->C2, MCG_C2_EREFS0_SHIFT);
}
#elif defined(RSIM)
/**
* @brief Enable oscillator from RSIM module
*
* This is for Kinetis CPUs with a radio system integration module which can
* provide an oscillator output.
*/
static void kinetis_mcg_enable_osc(void)
{
/* Kinetis CPU with a radio system integration module which can provide an
* oscillator output. */
/* The CPUs with RSIM (currently only KW41Z, KW31Z, KW21Z) ignore the EREFS0
* bit in MCG_C2 because they have no OSC module. These CPUs need to use the
* RF oscillator inside the RSIM module if an oscillator is needed. */
/* The external reference clock line on these CPUs is permanently connected
* to the RSIM clock output, thus the RSIM, instead of the MCG, controls the
* external clock source selection. */
/* Enable RF oscillator circuit */
/* Current setting is that the OSC only runs in RUN and WAIT modes, see ref.man. */
*bme_bitfield32(&RSIM->CONTROL, RSIM_CONTROL_RF_OSC_EN_SHIFT, 4) = RSIM_CONTROL_RF_OSC_EN(1);
RSIM->CONTROL = (RSIM->CONTROL & ~RSIM_CONTROL_RF_OSC_EN_MASK) | RSIM_CONTROL_RF_OSC_EN(1);
/* Chip errata
* e10224: RSIM: XTAL_OUT_EN signal from the pin is enabled by default
*
@ -214,10 +113,19 @@ static void kinetis_mcg_enable_osc(void)
*/
bit_set32(&RSIM->RF_OSC_CTRL, RSIM_RF_OSC_CTRL_RADIO_EXT_OSC_OVRD_EN_SHIFT);
/* Wait for oscillator ready signal */
while((RSIM->CONTROL & RSIM_CONTROL_RF_OSC_READY_MASK) == 0) {}
if (clock_config.enable_oscillator) {
/* Disable RF oscillator bypass, if it was enabled before */
bit_clear32(&RSIM->RF_OSC_CTRL, RSIM_RF_OSC_CTRL_RF_OSC_BYPASS_EN_SHIFT);
/* Wait for oscillator ready signal */
while((RSIM->CONTROL & RSIM_CONTROL_RF_OSC_READY_MASK) == 0) {}
}
else {
/* Enable RF oscillator bypass, to use the EXTAL pin as external clock
* source without the oscillator circuit */
bit_set32(&RSIM->RF_OSC_CTRL, RSIM_RF_OSC_CTRL_RF_OSC_BYPASS_EN_SHIFT);
}
#endif /* defined OSC0/RSIM */
}
#endif
/**
* @brief Initialize the FLL Engaged Internal Mode.
@ -228,12 +136,15 @@ static void kinetis_mcg_enable_osc(void)
*/
static void kinetis_mcg_set_fei(void)
{
kinetis_mcg_set_fll_factor(KINETIS_MCG_FLL_FACTOR_FEI);
/* enable and select slow internal reference clock */
MCG->C1 = (uint8_t)(MCG_C1_CLKS(0) | MCG_C1_IREFS_MASK);
/* The internal reference clock frequency and source is configured during
* initialization */
/* Select the correct FLL multiplier for the target frequency */
kinetis_mcg_set_fll_factor(clock_config.fll_factor_fei);
/* select slow internal reference clock for FLL source and use FLL output clock */
MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | (MCG_C1_CLKS(0) | MCG_C1_IREFS_MASK);
/* set to defaults */
MCG->C2 = (uint8_t)0;
/* Make sure FLL is enabled if we have somehow ended up in an unknown state */
bit_clear8(&MCG->C2, MCG_C2_LP_SHIFT);
/* source of the FLL reference clock shall be internal reference clock */
while ((MCG->S & MCG_S_IREFST_MASK) == 0) {}
@ -241,8 +152,7 @@ static void kinetis_mcg_set_fei(void)
/* Wait until output of the FLL is selected */
while (MCG->S & (MCG_S_CLKST_MASK)) {}
kinetis_mcg_disable_pll();
current_mode = KINETIS_MCG_FEI;
current_mode = KINETIS_MCG_MODE_FEI;
}
/**
@ -255,16 +165,15 @@ static void kinetis_mcg_set_fei(void)
static void kinetis_mcg_set_fee(void)
{
kinetis_mcg_enable_osc();
kinetis_mcg_set_fll_factor(KINETIS_MCG_FLL_FACTOR_FEE);
kinetis_mcg_set_fll_factor(clock_config.fll_factor_fee);
/* select external reference clock and divide factor */
MCG->C1 = (uint8_t)(MCG_C1_CLKS(0) | MCG_C1_FRDIV(KINETIS_MCG_ERC_FRDIV));
/* enable and select external reference clock */
MCG->C1 = (MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(0));
/* Wait until output of FLL is selected */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(0)) {}
kinetis_mcg_disable_pll();
current_mode = KINETIS_MCG_FEE;
current_mode = KINETIS_MCG_MODE_FEE;
}
/**
@ -278,17 +187,16 @@ static void kinetis_mcg_set_fee(void)
*/
static void kinetis_mcg_set_fbi(void)
{
/* select IRC source */
if (KINETIS_MCG_USE_FAST_IRC) {
MCG->C2 = (uint8_t)(MCG_C2_IRCS_MASK);
}
else {
MCG->C2 = (uint8_t)(0);
}
/* The internal reference clock frequency and source is configured during
* initialization */
/* Select the correct FLL multiplier for the target frequency */
kinetis_mcg_set_fll_factor(clock_config.fll_factor_fei);
kinetis_mcg_set_fll_factor(KINETIS_MCG_FLL_FACTOR_FEI);
/* enable and select slow internal reference clock */
MCG->C1 = (uint8_t)(MCG_C1_CLKS(1) | MCG_C1_IREFS_MASK);
/* Re-enable FLL when coming from BLPI mode */
bit_clear8(&MCG->C2, MCG_C2_LP_SHIFT);
/* enable and select slow internal reference clock for the FLL */
MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | (MCG_C1_CLKS(1) | MCG_C1_IREFS_MASK);
/* Wait until output of IRC is selected */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(1)) {}
@ -296,8 +204,7 @@ static void kinetis_mcg_set_fbi(void)
/* source of the FLL reference clock shall be internal reference clock */
while ((MCG->S & MCG_S_IREFST_MASK) == 0) {}
kinetis_mcg_disable_pll();
current_mode = KINETIS_MCG_FBI;
current_mode = KINETIS_MCG_MODE_FBI;
}
/**
@ -311,19 +218,20 @@ static void kinetis_mcg_set_fbi(void)
static void kinetis_mcg_set_fbe(void)
{
kinetis_mcg_enable_osc();
kinetis_mcg_set_fll_factor(KINETIS_MCG_FLL_FACTOR_FEE);
/* Select the correct FLL multiplier for the target frequency */
kinetis_mcg_set_fll_factor(clock_config.fll_factor_fee);
/* FLL is not disabled in bypass mode */
MCG->C2 &= ~(uint8_t)(MCG_C2_LP_MASK);
/* Re-enable FLL when coming from BLPE mode */
bit_clear8(&MCG->C2, MCG_C2_LP_SHIFT);
/* select external reference clock and divide factor */
MCG->C1 = (uint8_t)(MCG_C1_CLKS(2) | MCG_C1_FRDIV(KINETIS_MCG_ERC_FRDIV));
/* select external reference clock for FLL source */
MCG->C1 = (MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(2));
/* Wait until ERC is selected */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) {}
kinetis_mcg_disable_pll();
current_mode = KINETIS_MCG_FBE;
current_mode = KINETIS_MCG_MODE_FBE;
}
@ -331,26 +239,28 @@ static void kinetis_mcg_set_fbe(void)
* @brief Initialize the FLL Bypassed Low Power Internal Mode.
*
* MCGOUTCLK is derived from IRC.
* FLL and PLL are disable.
* FLL and PLL are disabled.
* Previous and next allowed mode is FBI.
*/
static void kinetis_mcg_set_blpi(void)
{
MCG->C2 |= (uint8_t)(MCG_C2_LP_MASK);
current_mode = KINETIS_MCG_BLPI;
bit_set8(&MCG->C2, MCG_C2_LP_SHIFT);
kinetis_mcg_disable_pll();
current_mode = KINETIS_MCG_MODE_BLPI;
}
/**
* @brief Initialize the FLL Bypassed Low Power External Mode.
*
* MCGOUTCLK is derived from ERC.
* FLL and PLL are disable.
* FLL and PLL are disabled.
* Previous and next allowed mode: FBE or PBE.
*/
static void kinetis_mcg_set_blpe(void)
{
MCG->C2 |= (uint8_t)(MCG_C2_LP_MASK);
current_mode = KINETIS_MCG_BLPE;
bit_set8(&MCG->C2, MCG_C2_LP_SHIFT);
kinetis_mcg_disable_pll();
current_mode = KINETIS_MCG_MODE_BLPE;
}
#if KINETIS_HAVE_PLL
@ -366,23 +276,17 @@ static void kinetis_mcg_set_blpe(void)
*/
static void kinetis_mcg_set_pbe(void)
{
/* select external reference clock and divide factor */
MCG->C1 = (uint8_t)(MCG_C1_CLKS(2) | MCG_C1_FRDIV(KINETIS_MCG_ERC_FRDIV));
/* PLL is enabled, but put in bypass mode */
bit_clear8(&MCG->C2, MCG_C2_LP_SHIFT);
/* select external reference clock instead of FLL/PLL */
MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(2);
/* Wait until ERC is selected */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) {}
/* PLL is not disabled in bypass mode */
MCG->C2 &= ~(uint8_t)(MCG_C2_LP_MASK);
/* set external reference devider */
MCG->C5 = (uint8_t)(MCG_C5_PRDIV0(KINETIS_MCG_PLL_PRDIV));
/* set external reference devider */
MCG->C6 = (uint8_t)(MCG_C6_VDIV0(KINETIS_MCG_PLL_VDIV0));
/* select PLL */
MCG->C6 |= (uint8_t)(MCG_C6_PLLS_MASK);
bit_set8(&MCG->C6, MCG_C6_PLLS_SHIFT);
/* Wait until the source of the PLLS clock is PLL */
while ((MCG->S & MCG_S_PLLST_MASK) == 0) {}
@ -390,7 +294,7 @@ static void kinetis_mcg_set_pbe(void)
/* Wait until PLL locked */
while ((MCG->S & MCG_S_LOCK0_MASK) == 0) {}
current_mode = KINETIS_MCG_PBE;
current_mode = KINETIS_MCG_MODE_PBE;
}
/**
@ -407,50 +311,162 @@ static void kinetis_mcg_set_pee(void)
/* Wait until output of the PLL is selected */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) {}
current_mode = KINETIS_MCG_PEE;
current_mode = KINETIS_MCG_MODE_PEE;
}
#endif /* KINETIS_HAVE_PLL */
int kinetis_mcg_set_mode(kinetis_mcg_mode_t mode)
{
if (mode > KINETIS_MCG_FEI) {
if (mode >= KINETIS_MCG_MODE_NUMOF) {
return -1;
}
while (current_mode != mode) {
/* Using `do` because if we already are on the desired mode we still want to
* update the hardware settings, e.g. when using FEI mode (since FEI is the
* hardware reset default) */
do {
switch(mcg_mode_routing[current_mode][mode]) {
case KINETIS_MCG_MODE_FEI:
kinetis_mcg_set_fei();
break;
case KINETIS_MCG_MODE_FEE:
kinetis_mcg_set_fee();
break;
case KINETIS_MCG_MODE_FBI:
kinetis_mcg_set_fbi();
break;
case KINETIS_MCG_MODE_FBE:
kinetis_mcg_set_fbe();
break;
case KINETIS_MCG_MODE_BLPI:
kinetis_mcg_set_blpi();
break;
case KINETIS_MCG_MODE_BLPE:
kinetis_mcg_set_blpe();
break;
#if KINETIS_HAVE_PLL
case KINETIS_MCG_PEE:
case KINETIS_MCG_MODE_PEE:
kinetis_mcg_set_pee();
break;
case KINETIS_MCG_PBE:
case KINETIS_MCG_MODE_PBE:
kinetis_mcg_set_pbe();
break;
#endif /* KINETIS_HAVE_PLL */
case KINETIS_MCG_BLPE:
kinetis_mcg_set_blpe();
break;
case KINETIS_MCG_BLPI:
kinetis_mcg_set_blpi();
break;
case KINETIS_MCG_FBE:
kinetis_mcg_set_fbe();
break;
case KINETIS_MCG_FBI:
kinetis_mcg_set_fbi();
break;
case KINETIS_MCG_FEE:
kinetis_mcg_set_fee();
break;
case KINETIS_MCG_FEI:
kinetis_mcg_set_fei();
break;
default:
return -1;
}
}
} while (current_mode != mode);
return 0;
}
#endif /* KINETIS_CPU_USE_MCG */
/**
* @brief Go to a safe clocking mode that should work for all boards regardless
* of external components
*
* If the board is warm rebooting, for example when starting RIOT from a boot loader,
* the MCG may be in a different state than what we expect. We need to carefully
* step back to a mode which is clocked by the internal reference clock before
* trying to modify the clock settings.
*/
static void kinetis_mcg_set_safe_mode(void)
{
if (MCG->C2 & MCG_C2_LP_MASK) {
/* We are currently in BLPE or BLPI */
/* Leave LP mode */
/* Moving to either of FBI, FBE, PBE */
bit_clear8(&MCG->C2, MCG_C2_LP_SHIFT);
}
#if KINETIS_HAVE_PLL
/* See if the PLL is engaged */
if (MCG->C6 & MCG_C6_PLLS_MASK) {
if ((MCG->C1 & MCG_C1_CLKS_MASK) == 0) {
/* we are currently in PEE mode, we need to step back to PBE */
/* switch MCGOUTCLK from PLL output to ERC */
MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(2);
/* Wait until ERC is selected */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) {}
}
bit_clear8(&MCG->C6, MCG_C6_PLLS_SHIFT);
/* Wait until the source of the PLLS clock is FLL */
while ((MCG->S & MCG_S_PLLST_MASK) != 0) {}
}
#endif
/* when we reach this line we are in one of the FLL modes: FEI, FBI, FEE, FBE */
/* Move to FEI mode with minimum multiplier factor */
/* Select the correct FLL multiplier for the target frequency */
kinetis_mcg_set_fll_factor(KINETIS_MCG_FLL_FACTOR_640);
/* select slow internal reference clock for FLL source and use FLL output clock */
MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | (MCG_C1_CLKS(0) | MCG_C1_IREFS_MASK);
/* source of the FLL reference clock shall be internal reference clock */
while ((MCG->S & MCG_S_IREFST_MASK) == 0) {}
/* Wait until output of the FLL is selected */
while (MCG->S & (MCG_S_CLKST_MASK)) {}
current_mode = KINETIS_MCG_MODE_FEI;
/* We avoid messing with the settings of the internal reference clock here
* because it may be driving the LPTMR */
/* At this point the core will be clocked from the FLL running off the slow
* internal reference clock (32768 Hz) with a 640 multiplier which yields
* 32.768 kHz x 640 = 20.971520 MHz. This should be safe regardless of the
* SIM_CLKDIV1 settings used, for all supported Kinetis CPUs */
}
void kinetis_mcg_init(void)
{
unsigned mask = irq_disable();
/* Go to FBI mode for safety */
kinetis_mcg_set_safe_mode();
/* at this point the core should be running from the internal reference
* clock, slow or fast, which is 32.768 kHz up to 4 MHz, depending on
* previous settings */
/* Set module clock dividers */
SIM->CLKDIV1 = clock_config.clkdiv1;
/* Select external reference clock source for the FLL */
MCG->C7 = MCG_C7_OSCSEL(clock_config.oscsel);
/* Set external reference clock divider for the FLL */
MCG->C1 = (MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(clock_config.fll_frdiv);
#if KINETIS_HAVE_PLL
/* set ERC divider for the PLL */
MCG->C5 = (uint8_t)(MCG_C5_PRDIV0(clock_config.pll_prdiv));
/* set PLL VCO divider */
MCG->C6 = (uint8_t)(MCG_C6_VDIV0(clock_config.pll_vdiv));
#endif /* KINETIS_HAVE_PLL */
/* Configure internal reference clock */
if (clock_config.select_fast_irc) {
/* Fast IRC divider setting */
uint8_t tmp = MCG->SC;
/* Avoid clearing w1c flags during writeback */
tmp &= ~(MCG_SC_ATMF_MASK | MCG_SC_LOCS0_MASK);
/* Write new FCRDIV setting */
tmp &= ~MCG_SC_FCRDIV_MASK;
tmp |= MCG_SC_FCRDIV(clock_config.fcrdiv);
MCG->SC = tmp;
bit_set8(&MCG->C2, MCG_C2_IRCS_SHIFT);
}
else {
bit_clear8(&MCG->C2, MCG_C2_IRCS_SHIFT);
}
/* Enable/disable MCGIRCLK */
/* MCGIRCLK can be used as an alternate clock source for certain modules */
if (clock_config.enable_mcgirclk) {
bit_set8(&MCG->C1, MCG_C1_IRCLKEN_SHIFT);
}
else {
bit_clear8(&MCG->C1, MCG_C1_IRCLKEN_SHIFT);
}
/* Switch to the selected MCG mode */
kinetis_mcg_set_mode(clock_config.default_mode);
irq_restore(mask);
}
/** @} */

View File

@ -1,85 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2014 PHYTEC Messtechnik GmbH
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_kw2xd
* @{
*
* @file
* @brief Implementation of the KW2xD CPU initialization
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Johann Fischer <j.fischer@phytec.de>
* @}
*/
#include <stdint.h>
#include "cpu.h"
#include "mcg.h"
#include "cpu_conf.h"
#include "periph/init.h"
#define FLASH_BASE (0x00000000)
static void cpu_clock_init(void);
/**
* @brief Initialize the CPU, set IRQ priorities
*/
void cpu_init(void)
{
/* initialize the Cortex-M core */
cortexm_init();
/* initialize the clock system */
cpu_clock_init();
/* trigger static peripheral initialization */
periph_init();
}
static inline void modem_clock_init(void)
{
/* Use the CLK_OUT of the modem as the clock source. */
/* Enable GPIO clock gates */
KW2XDRF_PORT_CLKEN();
KW2XDRF_CLK_CTRL_CLKEN();
/* Modem RST_B is connected to PTB19 and can be used to reset the modem. */
KW2XDRF_PORT_DEV->PCR[KW2XDRF_RST_PIN] = PORT_PCR_MUX(1);
BITBAND_REG32(KW2XDRF_GPIO->PDDR, KW2XDRF_RST_PIN) = 1;
KW2XDRF_GPIO->PCOR = (1 << KW2XDRF_RST_PIN);
/* Modem GPIO5 is connected to PTC0 and can be used to select CLK_OUT frequency, */
/* set PTC0 high for CLK_OUT=32.787kHz and low for CLK_OUT=4MHz. */
KW2XDRF_CLK_CTRL_PORT_DEV->PCR[KW2XDRF_CLK_CTRL_PIN] = PORT_PCR_MUX(1);
BITBAND_REG32(KW2XDRF_CLK_CTRL_GPIO->PDDR, KW2XDRF_CLK_CTRL_PIN) = 1;
KW2XDRF_CLK_CTRL_GPIO->PCOR = (1 << KW2XDRF_CLK_CTRL_PIN);
/* Modem IRQ_B is connected to PTB3, modem interrupt request to the MCU. */
KW2XDRF_PORT_DEV->PCR[KW2XDRF_IRQ_PIN] = PORT_PCR_MUX(1);
BITBAND_REG32(KW2XDRF_GPIO->PDDR, KW2XDRF_IRQ_PIN) = 0;
/* release the reset */
KW2XDRF_GPIO->PSOR = (1 << KW2XDRF_RST_PIN);
/* wait for modem IRQ_B interrupt request */
while (KW2XDRF_GPIO->PDIR & (1 << KW2XDRF_IRQ_PIN));
}
/**
* @brief Configure the controllers clock system
*/
static void cpu_clock_init(void)
{
/* setup system prescalers */
SIM->CLKDIV1 = (uint32_t)SIM_CLKDIV1_OUTDIV4(1);
modem_clock_init();
kinetis_mcg_set_mode(KINETIS_MCG_PEE);
}

View File

@ -9282,6 +9282,8 @@ typedef struct {
#define UART_TIDT_TIDT(x) This_symbol_has_been_deprecated
#define OSC0 ((OSC_Type *)OSC_BASE)
#define MCG_C7_OSCSEL(x) (((uint32_t)(x) << MCG_C7_OSCSEL_SHIFT) & MCG_C7_OSCSEL_MASK)
/*!
* @}
*/ /* end of group Backward_Compatibility_Symbols */