1 /******************************************************************************
\r 
   2  * @file     system_XMC4500.c
\r 
   3  * @brief    Device specific initialization for the XMC4500-Series according to CMSIS
\r 
   5  * @date     20. January 2012
\r 
   8  * Copyright (C) 2011 Infineon Technologies AG. All rights reserved.
\r 
  12  * Infineon Technologies AG (Infineon) is supplying this software for use with Infineon
\92s microcontrollers.  
\r 
  13  * This file can be freely distributed within development tools that are supporting such microcontrollers. 
\r 
  17  * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
\r 
  18  * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
\r 
  19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
\r 
  20  * INFINEON SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
\r 
  21  * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
\r 
  24  ******************************************************************************/
\r 
  26 #include "System_XMC4500.h"
\r 
  27 #include <XMC4500.h>
\r 
  29 /*----------------------------------------------------------------------------
\r 
  30   Define clocks is located in System_XMC4500.h
\r 
  31  *----------------------------------------------------------------------------*/
\r 
  33 /*----------------------------------------------------------------------------
\r 
  34   Clock Variable definitions
\r 
  35  *----------------------------------------------------------------------------*/
\r 
  36 /*!< System Clock Frequency (Core Clock)*/
\r 
  37 uint32_t SystemCoreClock = CLOCK_OSC_HP;
\r 
  40 //-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
\r 
  45 /*--------------------- Watchdog Configuration -------------------------------
\r 
  47 // <e> Watchdog Configuration
\r 
  48 //     <o1.0> Disable Watchdog
\r 
  53 #define WDTENB_nVal             0x00000001
\r 
  55 /*--------------------- CLOCK Configuration -------------------------------
\r 
  57 // <e> Main Clock Configuration
\r 
  58 //     <o1.0..1> CPU clock divider
\r 
  59 //                     <0=> fCPU = fSYS 
\r 
  60 //                     <1=> fCPU = fSYS / 2
\r 
  61 //     <o2.0..1>  Peripheral Bus clock divider
\r 
  63 //                     <1=> fPB = fCPU / 2
\r 
  64 //     <o3.0..1>  CCU Bus clock divider
\r 
  66 //                     <1=> fCCU = fCPU / 2
\r 
  72 #define SCU_CLOCK_SETUP               1
\r 
  73 #define SCU_CPUCLKCR_DIV                0x00000000
\r 
  74 #define SCU_PBCLKCR_DIV             0x00000000
\r 
  75 #define SCU_CCUCLKCR_DIV                0x00000000
\r 
  79 /*--------------------- USB CLOCK Configuration ---------------------------
\r 
  81 // <e> USB Clock Configuration
\r 
  87 #define SCU_USB_CLOCK_SETUP              0
\r 
  90 /*--------------------- CLOCKOUT Configuration -------------------------------
\r 
  92 // <e> Clock OUT Configuration
\r 
  93 //     <o1.0..1>   Clockout Source Selection
\r 
  94 //                     <0=> System Clock
\r 
  96 //                     <3=> Divided value of PLL Clock
\r 
  97 //     <o2.0..1>   Clockout Pin Selection
\r 
 106 #define SCU_CLOCKOUT_SETUP              0  // recommended to keep disabled
\r 
 107 #define SCU_CLOCKOUT_SOURCE             0x00000000
\r 
 108 #define SCU_CLOCKOUT_PIN                0x00000000
\r 
 110 /*----------------------------------------------------------------------------
\r 
 111   static functions declarations
\r 
 112  *----------------------------------------------------------------------------*/
\r 
 113 #if (SCU_CLOCK_SETUP == 1)
\r 
 114 static int SystemClockSetup(void);
\r 
 117 #if (SCU_USB_CLOCK_SETUP == 1)
\r 
 118 static void USBClockSetup(void);
\r 
 122   * @brief  Setup the microcontroller system.
\r 
 123   *         Initialize the PLL and update the 
\r 
 124   *         SystemCoreClock variable.
\r 
 128 void SystemInit(void)
\r 
 130 /* Setup the WDT */
\r 
 131 #if (WDT_SETUP == 1)
\r 
 132 WDT->CTR &= ~WDTENB_nVal; 
\r 
 135 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
\r 
 136 SCB->CPACR |= ((3UL << 10*2) |                 /* set CP10 Full Access */
\r 
 137                (3UL << 11*2)  );               /* set CP11 Full Access */
\r 
 140 /* Disable branch prediction - PCON.PBS = 1 */
\r 
 141 PREF->PCON |= (PREF_PCON_PBS_Msk);
\r 
 143 /* Enable unaligned memory access - SCB_CCR.UNALIGN_TRP = 0 */
\r 
 144 SCB->CCR &= ~(SCB_CCR_UNALIGN_TRP_Msk);
\r 
 146 /* Setup the clockout */
\r 
 147 /* README README README README README README README README README README */
\r 
 149  * Please use the CLOCKOUT feature with diligence. Use this only if you know
\r 
 150  * what you are doing.
\r 
 152  * You must be aware that the settings below can potentially be in conflict
\r 
 153  * with DAVE code generation engine preferences.
\r 
 155  * Even worse, the setting below configures the ports as output ports while in
\r 
 156  * reality, the board on which this chip is mounted may have a source driving
\r 
 159  * So use this feature only when you are absolutely sure that the port must 
\r 
 160  * indeed be configured as an output AND you are NOT linking this startup code
\r 
 161  * with code that was generated by DAVE code engine.
\r 
 163 #if (SCU_CLOCKOUT_SETUP == 1)
\r 
 164 SCU_CLK->EXTCLKCR       |= SCU_CLOCKOUT_SOURCE;
\r 
 166 if (SCU_CLOCKOUT_PIN) {
\r 
 167               PORT0->IOCR8 = 0x00000088;  /*P0.8 --> ALT1 select +  HWSEL */
\r 
 168               PORT0->HWSEL &= (~PORT0_HWSEL_HW8_Msk);
\r 
 170 else PORT1->IOCR12 = 0x88000000; /*P1.15--> ALT1 select */
\r 
 173 /* Setup the System clock */ 
\r 
 174 #if (SCU_CLOCK_SETUP == 1)
\r 
 175 SystemClockSetup();
\r 
 178 /* Setup the USB PL */ 
\r 
 179 #if (SCU_USB_CLOCK_SETUP == 1)
\r 
 187   * @brief  Update SystemCoreClock according to Clock Register Values
\r 
 192 void SystemCoreClockUpdate(void)
\r 
 195 /*----------------------------------------------------------------------------
\r 
 196   Clock Variable definitions
\r 
 197  *----------------------------------------------------------------------------*/
\r 
 198 SystemCoreClock = SYSTEM_FREQUENCY;/*!< System Clock Frequency (Core Clock)*/
\r 
 209 #if (SCU_CLOCK_SETUP == 1)
\r 
 210 static int SystemClockSetup(void)
\r 
 212 /* enable PLL first */
\r 
 213   SCU_PLL->PLLCON0 &= ~(SCU_PLL_PLLCON0_VCOPWD_Msk | 
\r 
 214                                                                                                         SCU_PLL_PLLCON0_PLLPWD_Msk);
\r 
 216 /* Enable OSC_HP */
\r 
 217   if (SCU_PLL_CLOCK_INPUT == SCU_CLOCK_CRYSTAL)
\r 
 219    /* Enable the OSC_HP*/
\r 
 220    SCU_OSC->OSCHPCTRL = (OSC_HP_MODE<<4);        
\r 
 221    /* Setup OSC WDG devider */
\r 
 222    SCU_OSC->OSCHPCTRL |= (OSCHPWDGDIV<<16);         
\r 
 223    /* Select external OSC as PLL input */
\r 
 224    SCU_PLL->PLLCON2 &= ~SCU_PLL_PLLCON2_PINSEL_Msk;
\r 
 225    /* Restart OSC Watchdog */
\r 
 226    SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCRES_Msk;  
\r 
 230         ;  /* here a timeout need to be added */
\r 
 231    }while(!( (SCU_PLL->PLLSTAT) & 
\r 
 232                                            (SCU_PLL_PLLSTAT_PLLHV_Msk | SCU_PLL_PLLSTAT_PLLLV_Msk |
\r 
 233                                             SCU_PLL_PLLSTAT_PLLSP_Msk)
\r 
 239 /* Setup Main PLL */
\r 
 240    /* Select FOFI as system clock */
\r 
 241    if(SCU_CLK->SYSCLKCR != 0X000000)
\r 
 242           SCU_CLK->SYSCLKCR = 0x00000000; /*Select FOFI*/
\r 
 244          /* Go to bypass the Main PLL */
\r 
 245    SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_VCOBYP_Msk;
\r 
 247          /* disconnect OSC_HP to PLL */
\r 
 248    SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_FINDIS_Msk;
\r 
 250          /* Setup devider settings for main PLL */
\r 
 251    SCU_PLL->PLLCON1 = ((PLL_K1DIV) | (PLL_NDIV<<8) | 
\r 
 252                                      (PLL_K2DIV_STEP_1<<16) | (PLL_PDIV<<24));
\r 
 254          /* we may have to set OSCDISCDIS */
\r 
 255    SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_OSCDISCDIS_Msk;
\r 
 257          /* connect OSC_HP to PLL */
\r 
 258    SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_FINDIS_Msk;
\r 
 260          /* restart PLL Lock detection */
\r 
 261    SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_RESLD_Msk;
\r 
 263          /* wait for PLL Lock */
\r 
 264    while (!(SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk));
\r 
 266         /* Go back to the Main PLL */
\r 
 267    SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_VCOBYP_Msk;
\r 
 269    /*********************************************************
\r 
 270    here we need to setup the system clock divider
\r 
 271    *********************************************************/
\r 
 273         SCU_CLK->CPUCLKCR = SCU_CPUCLKCR_DIV;
\r 
 274         SCU_CLK->PBCLKCR = SCU_PBCLKCR_DIV;     
\r 
 275         SCU_CLK->CCUCLKCR = SCU_CCUCLKCR_DIV;
\r 
 277    /* Switch system clock to PLL */
\r 
 278    SCU_CLK->SYSCLKCR |=  0x00010000; 
\r 
 280    /*********************************************************
\r 
 281    here the ramp up of the system clock starts
\r 
 282    *********************************************************/
\r 
 283     /* Delay for next K2 step ~50µs */
\r 
 284    /********************************/
\r 
 285    /* Set reload register */
\r 
 286    SysTick->LOAD  = ((1250+100) & SysTick_LOAD_RELOAD_Msk) - 1;
\r 
 288    /* Load the SysTick Counter Value */
\r 
 291    /* Enable SysTick IRQ and SysTick Timer */
\r 
 292    SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
\r 
 293                    SysTick_CTRL_ENABLE_Msk;                    
\r 
 295          /* wait for ~50µs  */
\r 
 296    while (SysTick->VAL >= 100);                                                            
\r 
 298    /* Stop SysTick Timer */
\r 
 299    SysTick->CTRL  &= ~SysTick_CTRL_ENABLE_Msk;                 
\r 
 300    /********************************/
\r 
 302    /* Setup devider settings for main PLL */
\r 
 303    SCU_PLL->PLLCON1 = ((PLL_K1DIV) | (PLL_NDIV<<8) | 
\r 
 304                                      (PLL_K2DIV_STEP_2<<16) | (PLL_PDIV<<24));
\r 
 306    /* Delay for next K2 step ~50µs */
\r 
 307    /********************************/
\r 
 308    SysTick->LOAD  = ((3000+100) & SysTick_LOAD_RELOAD_Msk) - 1;
\r 
 310    /* Load the SysTick Counter Value */
\r 
 313    /* Enable SysTick IRQ and SysTick Timer */
\r 
 314    SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
\r 
 316    /* Wait for ~50µs  */
\r 
 317    while (SysTick->VAL >= 100);                                                            
\r 
 319    /* Stop SysTick Timer */
\r 
 320    SysTick->CTRL  &= ~SysTick_CTRL_ENABLE_Msk;                 
\r 
 321    /********************************/
\r 
 323    /* Setup devider settings for main PLL */
\r 
 324    SCU_PLL->PLLCON1 = ((PLL_K1DIV) | (PLL_NDIV<<8) | 
\r 
 325                                                                                             (PLL_K2DIV_STEP_3<<16) | (PLL_PDIV<<24));
\r 
 327    /* Delay for next K2 step ~50µs */
\r 
 328    /********************************/
\r 
 329    SysTick->LOAD  = ((4800+100) & SysTick_LOAD_RELOAD_Msk) - 1;
\r 
 331    /* Load the SysTick Counter Value */
\r 
 334    /* Enable SysTick IRQ and SysTick Timer */
\r 
 335    SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
\r 
 337    /* Wait for ~50µs  */
\r 
 338    while (SysTick->VAL >= 100);                                                            
\r 
 340    /* Stop SysTick Timer */
\r 
 341    SysTick->CTRL  &= ~SysTick_CTRL_ENABLE_Msk;                 
\r 
 342    /********************************/
\r 
 344    /* Setup devider settings for main PLL */
\r 
 345    SCU_PLL->PLLCON1 = ((PLL_K1DIV) | (PLL_NDIV<<8) | (PLL_K2DIV<<16) | 
\r 
 348          /* clear request for System OCS Watchdog Trap and System VCO Lock Trap  */
\r 
 349    SCU_TRAP->TRAPCLR = SCU_TRAP_TRAPCLR_SOSCWDGT_Msk | 
\r 
 350                                                                             SCU_TRAP_TRAPCLR_SVCOLCKT_Msk;  
\r 
 363 #if(SCU_USB_CLOCK_SETUP == 1)
\r 
 364 static void USBClockSetup(void)
\r 
 366 /* enable PLL first */
\r 
 367   SCU_PLL->USBPLLCON &= ~(SCU_PLL_USBPLLCON_VCOPWD_Msk | 
\r 
 368                                                                                                        SCU_PLL_USBPLLCON_PLLPWD_Msk);
\r 
 370 /* check and if not already running enable OSC_HP */
\r 
 371   if(!((SCU_PLL->PLLSTAT) & 
\r 
 372                          (SCU_PLL_PLLSTAT_PLLHV_Msk | 
\r 
 373         SCU_PLL_PLLSTAT_PLLLV_Msk |SCU_PLL_PLLSTAT_PLLSP_Msk)))
\r 
 375           if (SCU_PLL_CLOCK_INPUT == SCU_CLOCK_CRYSTAL)
\r 
 378            SCU_OSC->OSCHPCTRL = (OSC_HP_MODE<<4);        /*enable the OSC_HP*/
\r 
 379            /* setup OSC WDG devider */
\r 
 380            SCU_OSC->OSCHPCTRL |= (OSCHPWDGDIV<<16);         
\r 
 381            /* select external OSC as PLL input */
\r 
 382            SCU_PLL->PLLCON2 &= ~SCU_PLL_PLLCON2_PINSEL_Msk;
\r 
 383            /* restart OSC Watchdog */
\r 
 384            SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCRES_Msk;  
\r 
 388                 ;  /* here a timeout need to be added */
\r 
 389            }while(!((SCU_PLL->PLLSTAT) & (SCU_PLL_PLLSTAT_PLLHV_Msk | 
\r 
 390                SCU_PLL_PLLSTAT_PLLLV_Msk |SCU_PLL_PLLSTAT_PLLSP_Msk))); 
\r 
 396 /* Setup USB PLL */
\r 
 397    /* Go to bypass the Main PLL */
\r 
 398    SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_VCOBYP_Msk;
\r 
 399    /* disconnect OSC_FI to PLL */
\r 
 400    SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_FINDIS_Msk;
\r 
 401    /* Setup devider settings for main PLL */
\r 
 402    SCU_PLL->USBPLLCON = ((USBPLL_NDIV<<8) | (USBPLL_PDIV<<24));
\r 
 403    /* we may have to set OSCDISCDIS */
\r 
 404    SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_OSCDISCDIS_Msk;
\r 
 405    /* connect OSC_FI to PLL */
\r 
 406    SCU_PLL->USBPLLCON &= ~SCU_PLL_USBPLLCON_FINDIS_Msk;
\r 
 407    /* restart PLL Lock detection */
\r 
 408    SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_RESLD_Msk;
\r 
 409    /* wait for PLL Lock */
\r 
 410    while (!(SCU_PLL->USBPLLSTAT & SCU_PLL_USBPLLSTAT_VCOLOCK_Msk));
\r