blob: 12b6f4b32e1446d32364daf36bf8bd1551414431 [file] [log] [blame]
/******************************************************************************
* @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 Infineon’s 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