/****************************************************************************** | |
* @file system_XMC4500.c | |
* @brief Device specific initialization for the XMC4500-Series according to CMSIS | |
* @version V2.2 | |
* @date 20. January 2012 | |
* | |
* @note | |
* Copyright (C) 2011 Infineon Technologies AG. All rights reserved. | |
* | |
* @par | |
* Infineon Technologies AG (Infineon) is supplying this software for use with Infineons microcontrollers. | |
* This file can be freely distributed within development tools that are supporting such microcontrollers. | |
* | |
* @par | |
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED | |
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF | |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. | |
* INFINEON SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR | |
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. | |
* | |
* | |
******************************************************************************/ | |
#include "System_XMC4500.h" | |
#include <XMC4500.h> | |
/*---------------------------------------------------------------------------- | |
Define clocks is located in System_XMC4500.h | |
*----------------------------------------------------------------------------*/ | |
/*---------------------------------------------------------------------------- | |
Clock Variable definitions | |
*----------------------------------------------------------------------------*/ | |
/*!< System Clock Frequency (Core Clock)*/ | |
uint32_t SystemCoreClock = CLOCK_OSC_HP; | |
/*---------------------------------------------------------------------------- | |
Keil pragma to prevent warnings | |
*----------------------------------------------------------------------------*/ | |
#if defined(__ARMCC_VERSION) | |
#pragma diag_suppress 177 | |
#endif | |
/* | |
//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------ | |
*/ | |
/*--------------------- Watchdog Configuration ------------------------------- | |
// | |
// <e> Watchdog Configuration | |
// <o1.0> Disable Watchdog | |
// | |
// </e> | |
*/ | |
#define WDT_SETUP 1 | |
#define WDTENB_nVal 0x00000001 | |
/*--------------------- CLOCK Configuration ------------------------------- | |
// | |
// <e> Main Clock Configuration | |
// <o1.0..1> CPU clock divider | |
// <0=> fCPU = fSYS | |
// <1=> fCPU = fSYS / 2 | |
// <o2.0..1> Peripheral Bus clock divider | |
// <0=> fPB = fCPU | |
// <1=> fPB = fCPU / 2 | |
// <o3.0..1> CCU Bus clock divider | |
// <0=> fCCU = fCPU | |
// <1=> fCCU = fCPU / 2 | |
// | |
// </e> | |
// | |
*/ | |
#define SCU_CLOCK_SETUP 1 | |
#define SCU_CPUCLKCR_DIV 0x00000000 | |
#define SCU_PBCLKCR_DIV 0x00000000 | |
#define SCU_CCUCLKCR_DIV 0x00000000 | |
/*--------------------- USB CLOCK Configuration --------------------------- | |
// | |
// <e> USB Clock Configuration | |
// | |
// </e> | |
// | |
*/ | |
#define SCU_USB_CLOCK_SETUP 0 | |
/*--------------------- CLOCKOUT Configuration ------------------------------- | |
// | |
// <e> Clock OUT Configuration | |
// <o1.0..1> Clockout Source Selection | |
// <0=> System Clock | |
// <2=> USB Clock | |
// <3=> Divided value of PLL Clock | |
// <o2.0..1> Clockout Pin Selection | |
// <0=> P1.15 | |
// <1=> P0.8 | |
// | |
// | |
// </e> | |
// | |
*/ | |
#define SCU_CLOCKOUT_SETUP 0 // recommended to keep disabled | |
#define SCU_CLOCKOUT_SOURCE 0x00000000 | |
#define SCU_CLOCKOUT_PIN 0x00000000 | |
/*---------------------------------------------------------------------------- | |
static functions declarations | |
*----------------------------------------------------------------------------*/ | |
#if (SCU_CLOCK_SETUP == 1) | |
static int SystemClockSetup(void); | |
#endif | |
#if (SCU_USB_CLOCK_SETUP == 1) | |
static void USBClockSetup(void); | |
#endif | |
/** | |
* @brief Setup the microcontroller system. | |
* Initialize the PLL and update the | |
* SystemCoreClock variable. | |
* @param None | |
* @retval None | |
*/ | |
void SystemInit(void) | |
{ | |
/* Setup the WDT */ | |
#if (WDT_SETUP == 1) | |
WDT->CTR &= ~WDTENB_nVal; | |
#endif | |
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) | |
SCB->CPACR |= ((3UL << 10*2) | /* set CP10 Full Access */ | |
(3UL << 11*2) ); /* set CP11 Full Access */ | |
#endif | |
/* Disable branch prediction - PCON.PBS = 1 */ | |
PREF->PCON |= (PREF_PCON_PBS_Msk); | |
/* Enable unaligned memory access - SCB_CCR.UNALIGN_TRP = 0 */ | |
SCB->CCR &= ~(SCB_CCR_UNALIGN_TRP_Msk); | |
/* Setup the clockout */ | |
/* README README README README README README README README README README */ | |
/* | |
* Please use the CLOCKOUT feature with diligence. Use this only if you know | |
* what you are doing. | |
* | |
* You must be aware that the settings below can potentially be in conflict | |
* with DAVE code generation engine preferences. | |
* | |
* Even worse, the setting below configures the ports as output ports while in | |
* reality, the board on which this chip is mounted may have a source driving | |
* the ports. | |
* | |
* So use this feature only when you are absolutely sure that the port must | |
* indeed be configured as an output AND you are NOT linking this startup code | |
* with code that was generated by DAVE code engine. | |
*/ | |
#if (SCU_CLOCKOUT_SETUP == 1) | |
SCU_CLK->EXTCLKCR |= SCU_CLOCKOUT_SOURCE; | |
if (SCU_CLOCKOUT_PIN) { | |
PORT0->IOCR8 = 0x00000088; /*P0.8 --> ALT1 select + HWSEL */ | |
PORT0->HWSEL &= (~PORT0_HWSEL_HW8_Msk); | |
} | |
else PORT1->IOCR12 = 0x88000000; /*P1.15--> ALT1 select */ | |
#endif | |
/* Setup the System clock */ | |
#if (SCU_CLOCK_SETUP == 1) | |
SystemClockSetup(); | |
#endif | |
/* Setup the USB PL */ | |
#if (SCU_USB_CLOCK_SETUP == 1) | |
USBClockSetup(); | |
#endif | |
} | |
/** | |
* @brief Update SystemCoreClock according to Clock Register Values | |
* @note - | |
* @param None | |
* @retval None | |
*/ | |
void SystemCoreClockUpdate(void) | |
{ | |
/*---------------------------------------------------------------------------- | |
Clock Variable definitions | |
*----------------------------------------------------------------------------*/ | |
SystemCoreClock = SYSTEM_FREQUENCY;/*!< System Clock Frequency (Core Clock)*/ | |
} | |
/** | |
* @brief - | |
* @note - | |
* @param None | |
* @retval None | |
*/ | |
#if (SCU_CLOCK_SETUP == 1) | |
static int SystemClockSetup(void) | |
{ | |
/* enable PLL first */ | |
SCU_PLL->PLLCON0 &= ~(SCU_PLL_PLLCON0_VCOPWD_Msk | | |
SCU_PLL_PLLCON0_PLLPWD_Msk); | |
/* Enable OSC_HP */ | |
if (SCU_PLL_CLOCK_INPUT == SCU_CLOCK_CRYSTAL) | |
{ | |
/* Enable the OSC_HP*/ | |
SCU_OSC->OSCHPCTRL = (OSC_HP_MODE<<4); | |
/* Setup OSC WDG devider */ | |
SCU_OSC->OSCHPCTRL |= (OSCHPWDGDIV<<16); | |
/* Select external OSC as PLL input */ | |
SCU_PLL->PLLCON2 &= ~SCU_PLL_PLLCON2_PINSEL_Msk; | |
/* Restart OSC Watchdog */ | |
SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCRES_Msk; | |
do | |
{ | |
; /* here a timeout need to be added */ | |
}while(!( (SCU_PLL->PLLSTAT) & | |
(SCU_PLL_PLLSTAT_PLLHV_Msk | SCU_PLL_PLLSTAT_PLLLV_Msk | | |
SCU_PLL_PLLSTAT_PLLSP_Msk) | |
) | |
); | |
} | |
/* Setup Main PLL */ | |
/* Select FOFI as system clock */ | |
if(SCU_CLK->SYSCLKCR != 0X000000) | |
SCU_CLK->SYSCLKCR = 0x00000000; /*Select FOFI*/ | |
/* Go to bypass the Main PLL */ | |
SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_VCOBYP_Msk; | |
/* disconnect OSC_HP to PLL */ | |
SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_FINDIS_Msk; | |
/* Setup devider settings for main PLL */ | |
SCU_PLL->PLLCON1 = ((PLL_K1DIV) | (PLL_NDIV<<8) | | |
(PLL_K2DIV_STEP_1<<16) | (PLL_PDIV<<24)); | |
/* we may have to set OSCDISCDIS */ | |
SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_OSCDISCDIS_Msk; | |
/* connect OSC_HP to PLL */ | |
SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_FINDIS_Msk; | |
/* restart PLL Lock detection */ | |
SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_RESLD_Msk; | |
/* wait for PLL Lock */ | |
while (!(SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk)); | |
/* Go back to the Main PLL */ | |
SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_VCOBYP_Msk; | |
/********************************************************* | |
here we need to setup the system clock divider | |
*********************************************************/ | |
SCU_CLK->CPUCLKCR = SCU_CPUCLKCR_DIV; | |
SCU_CLK->PBCLKCR = SCU_PBCLKCR_DIV; | |
SCU_CLK->CCUCLKCR = SCU_CCUCLKCR_DIV; | |
/* Switch system clock to PLL */ | |
SCU_CLK->SYSCLKCR |= 0x00010000; | |
/********************************************************* | |
here the ramp up of the system clock starts | |
*********************************************************/ | |
/* Delay for next K2 step ~50µs */ | |
/********************************/ | |
/* Set reload register */ | |
SysTick->LOAD = ((1250+100) & SysTick_LOAD_RELOAD_Msk) - 1; | |
/* Load the SysTick Counter Value */ | |
SysTick->VAL = 0; | |
/* Enable SysTick IRQ and SysTick Timer */ | |
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | | |
SysTick_CTRL_ENABLE_Msk; | |
/* wait for ~50µs */ | |
while (SysTick->VAL >= 100); | |
/* Stop SysTick Timer */ | |
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; | |
/********************************/ | |
/* Setup devider settings for main PLL */ | |
SCU_PLL->PLLCON1 = ((PLL_K1DIV) | (PLL_NDIV<<8) | | |
(PLL_K2DIV_STEP_2<<16) | (PLL_PDIV<<24)); | |
/* Delay for next K2 step ~50µs */ | |
/********************************/ | |
SysTick->LOAD = ((3000+100) & SysTick_LOAD_RELOAD_Msk) - 1; | |
/* Load the SysTick Counter Value */ | |
SysTick->VAL = 0; | |
/* Enable SysTick IRQ and SysTick Timer */ | |
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; | |
/* Wait for ~50µs */ | |
while (SysTick->VAL >= 100); | |
/* Stop SysTick Timer */ | |
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; | |
/********************************/ | |
/* Setup devider settings for main PLL */ | |
SCU_PLL->PLLCON1 = ((PLL_K1DIV) | (PLL_NDIV<<8) | | |
(PLL_K2DIV_STEP_3<<16) | (PLL_PDIV<<24)); | |
/* Delay for next K2 step ~50µs */ | |
/********************************/ | |
SysTick->LOAD = ((4800+100) & SysTick_LOAD_RELOAD_Msk) - 1; | |
/* Load the SysTick Counter Value */ | |
SysTick->VAL = 0; | |
/* Enable SysTick IRQ and SysTick Timer */ | |
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; | |
/* Wait for ~50µs */ | |
while (SysTick->VAL >= 100); | |
/* Stop SysTick Timer */ | |
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; | |
/********************************/ | |
/* Setup devider settings for main PLL */ | |
SCU_PLL->PLLCON1 = ((PLL_K1DIV) | (PLL_NDIV<<8) | (PLL_K2DIV<<16) | | |
(PLL_PDIV<<24)); | |
/* clear request for System OCS Watchdog Trap and System VCO Lock Trap */ | |
SCU_TRAP->TRAPCLR = SCU_TRAP_TRAPCLR_SOSCWDGT_Msk | | |
SCU_TRAP_TRAPCLR_SVCOLCKT_Msk; | |
return(1); | |
} | |
#endif | |
/** | |
* @brief - | |
* @note - | |
* @param None | |
* @retval None | |
*/ | |
#if(SCU_USB_CLOCK_SETUP == 1) | |
static void USBClockSetup(void) | |
{ | |
/* enable PLL first */ | |
SCU_PLL->USBPLLCON &= ~(SCU_PLL_USBPLLCON_VCOPWD_Msk | | |
SCU_PLL_USBPLLCON_PLLPWD_Msk); | |
/* check and if not already running enable OSC_HP */ | |
if(!((SCU_PLL->PLLSTAT) & | |
(SCU_PLL_PLLSTAT_PLLHV_Msk | | |
SCU_PLL_PLLSTAT_PLLLV_Msk |SCU_PLL_PLLSTAT_PLLSP_Msk))) | |
{ | |
if (SCU_PLL_CLOCK_INPUT == SCU_CLOCK_CRYSTAL) | |
{ | |
SCU_OSC->OSCHPCTRL = (OSC_HP_MODE<<4); /*enable the OSC_HP*/ | |
/* setup OSC WDG devider */ | |
SCU_OSC->OSCHPCTRL |= (OSCHPWDGDIV<<16); | |
/* select external OSC as PLL input */ | |
SCU_PLL->PLLCON2 &= ~SCU_PLL_PLLCON2_PINSEL_Msk; | |
/* restart OSC Watchdog */ | |
SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCRES_Msk; | |
do | |
{ | |
; /* here a timeout need to be added */ | |
}while(!((SCU_PLL->PLLSTAT) & (SCU_PLL_PLLSTAT_PLLHV_Msk | | |
SCU_PLL_PLLSTAT_PLLLV_Msk |SCU_PLL_PLLSTAT_PLLSP_Msk))); | |
} | |
} | |
/* Setup USB PLL */ | |
/* Go to bypass the Main PLL */ | |
SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_VCOBYP_Msk; | |
/* disconnect OSC_FI to PLL */ | |
SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_FINDIS_Msk; | |
/* Setup devider settings for main PLL */ | |
SCU_PLL->USBPLLCON = ((USBPLL_NDIV<<8) | (USBPLL_PDIV<<24)); | |
/* we may have to set OSCDISCDIS */ | |
SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_OSCDISCDIS_Msk; | |
/* connect OSC_FI to PLL */ | |
SCU_PLL->USBPLLCON &= ~SCU_PLL_USBPLLCON_FINDIS_Msk; | |
/* restart PLL Lock detection */ | |
SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_RESLD_Msk; | |
/* wait for PLL Lock */ | |
while (!(SCU_PLL->USBPLLSTAT & SCU_PLL_USBPLLSTAT_VCOLOCK_Msk)); | |
} | |
#endif |