SAMV71 Xplained Ultra Software Package 1.3

system_sam.c

00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License 
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2014, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029  
00030 #include "samv71.h"
00031 
00032 /* @cond 0 */
00033 /**INDENT-OFF**/
00034 #ifdef __cplusplus
00035 extern "C" {
00036 #endif
00037 /**INDENT-ON**/
00038 /* @endcond */
00039 
00040 /* %ATMEL_SYSTEM% */
00041 /* Clock Settings (500MHz PLL VDDIO 3.3V and VDDCORE 1.2V) */
00042 /* Clock Settings (300MHz HCLK, 150MHz MCK)=> PRESC = 1, MDIV = 2 */
00043 #define SYS_BOARD_OSCOUNT   (CKGR_MOR_MOSCXTST(0x8U))
00044 #define SYS_BOARD_PLLAR     (CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0x18U) | \
00045                 CKGR_PLLAR_PLLACOUNT(0x3fU) | CKGR_PLLAR_DIVA(0x1U))
00046 
00047 #define SYS_BOARD_MCKR      (PMC_MCKR_PRES_CLK_1 | PMC_MCKR_CSS_PLLA_CLK \
00048                 | PMC_MCKR_MDIV_PCK_DIV2)
00049 
00050 uint32_t SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
00051 #define USBCLK_DIV          10
00052 
00053 /**
00054  * \brief Set up the Microcontroller system.
00055  * Initialize the System and update the SystemFrequency variable.
00056  */
00057  void SystemInit( void )
00058 {
00059     uint32_t read_MOR;
00060     /* Set FWS according to SYS_BOARD_MCKR configuration */
00061     EFC->EEFC_FMR = EEFC_FMR_FWS(5);
00062     
00063      /* Before switching MAIN OSC on external crystal : enable it and don't 
00064      * disable at the same time RC OSC in case of if MAIN OSC is still using RC
00065      * OSC
00066      */
00067     
00068     read_MOR = PMC->CKGR_MOR;
00069      /* enable external crystal - enable RC OSC */
00070     read_MOR |= (CKGR_MOR_KEY_PASSWD |CKGR_MOR_XT32KFME); 
00071     PMC->CKGR_MOR = read_MOR;
00072     
00073     /* Select XTAL 32k instead of internal slow RC 32k for slow clock */
00074     if ( (SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST )
00075     {
00076         SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL_CRYSTAL_SEL;
00077     
00078         while( !(SUPC->SUPC_SR & SUPC_SR_OSCSEL) );
00079     }
00080     
00081     /* Initialize main oscillator */
00082     if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
00083     {
00084       PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT
00085                     | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
00086     
00087       while ( !(PMC->PMC_SR & PMC_SR_MOSCXTS) )
00088       {
00089       }
00090     }
00091     
00092     /* Switch to 3-20MHz Xtal oscillator */
00093     PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | SYS_BOARD_OSCOUNT 
00094                     | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
00095     
00096     while ( !(PMC->PMC_SR & PMC_SR_MOSCSELS) )
00097     {
00098     }
00099     
00100     PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk)
00101                     | PMC_MCKR_CSS_MAIN_CLK;
00102 
00103     while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) )
00104     {
00105     }
00106    
00107     /* Initialize PLLA */
00108     PMC->CKGR_PLLAR = SYS_BOARD_PLLAR;
00109     while ( !(PMC->PMC_SR & PMC_SR_LOCKA) )
00110     {
00111     }
00112    
00113     /* Switch to main clock */
00114     PMC->PMC_MCKR = (SYS_BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
00115     while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) )
00116     {
00117     }
00118    
00119     /* Switch to PLLA */
00120     PMC->PMC_MCKR = SYS_BOARD_MCKR;
00121     while ( !(PMC->PMC_SR & PMC_SR_MCKRDY) )
00122     {
00123     }
00124    
00125     SystemCoreClock = CHIP_FREQ_CPU_MAX;
00126 }
00127 
00128 void SystemCoreClockUpdate( void )
00129 {
00130   /* Determine clock frequency according to clock register values */
00131     switch (PMC->PMC_MCKR & (uint32_t) PMC_MCKR_CSS_Msk)
00132     {
00133     case PMC_MCKR_CSS_SLOW_CLK: /* Slow clock */
00134         if ( SUPC->SUPC_SR & SUPC_SR_OSCSEL )
00135         {
00136         SystemCoreClock = CHIP_FREQ_XTAL_32K;
00137         }
00138         else
00139         {
00140         SystemCoreClock = CHIP_FREQ_SLCK_RC;
00141         }
00142         break;
00143 
00144     case PMC_MCKR_CSS_MAIN_CLK: /* Main clock */
00145         if ( PMC->CKGR_MOR & CKGR_MOR_MOSCSEL )
00146         {
00147         SystemCoreClock = CHIP_FREQ_XTAL_12M;
00148         }
00149         else
00150         {
00151         SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
00152 
00153             switch ( PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk )
00154             {
00155             case CKGR_MOR_MOSCRCF_4_MHz:
00156                 break;
00157 
00158             case CKGR_MOR_MOSCRCF_8_MHz:
00159                 SystemCoreClock *= 2U;
00160                 break;
00161 
00162             case CKGR_MOR_MOSCRCF_12_MHz:
00163                 SystemCoreClock *= 3U;
00164                 break;
00165 
00166             default:
00167                 break;
00168             }
00169         }
00170     break;
00171 
00172     case PMC_MCKR_CSS_PLLA_CLK: /* PLLA clock */
00173         if ( PMC->CKGR_MOR & CKGR_MOR_MOSCSEL )
00174         {
00175             SystemCoreClock = CHIP_FREQ_XTAL_12M ;
00176         }
00177         else
00178         {
00179             SystemCoreClock = CHIP_FREQ_MAINCK_RC_4MHZ;
00180 
00181             switch ( PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk )
00182             {
00183             case CKGR_MOR_MOSCRCF_4_MHz:
00184                 break;
00185 
00186             case CKGR_MOR_MOSCRCF_8_MHz:
00187                 SystemCoreClock *= 2U;
00188                 break;
00189 
00190             case CKGR_MOR_MOSCRCF_12_MHz:
00191                 SystemCoreClock *= 3U;
00192                 break;
00193 
00194             default:
00195                 break;
00196             }
00197         }
00198 
00199         if ( (uint32_t) (PMC->PMC_MCKR & (uint32_t) PMC_MCKR_CSS_Msk)
00200                         == PMC_MCKR_CSS_PLLA_CLK )
00201         {
00202             SystemCoreClock *= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_MULA_Msk)
00203                             >> CKGR_PLLAR_MULA_Pos) + 1U);
00204             SystemCoreClock /= ((((PMC->CKGR_PLLAR) & CKGR_PLLAR_DIVA_Msk)
00205                             >> CKGR_PLLAR_DIVA_Pos));
00206         }
00207     break;
00208 
00209     default:
00210     break;
00211     }
00212 
00213     if ( (PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) == PMC_MCKR_PRES_CLK_3 )
00214     {
00215         SystemCoreClock /= 3U;
00216     }
00217     else
00218     {
00219         SystemCoreClock >>= ((PMC->PMC_MCKR & PMC_MCKR_PRES_Msk)
00220                         >> PMC_MCKR_PRES_Pos);
00221     }
00222 }
00223 /**
00224  * Initialize flash.
00225  */
00226 void system_init_flash( uint32_t ul_clk )
00227 {
00228     /* Set FWS for embedded Flash access according to operating frequency */
00229     if ( ul_clk < CHIP_FREQ_FWS_0 )
00230     {
00231         EFC->EEFC_FMR = EEFC_FMR_FWS(0)|EEFC_FMR_CLOE;
00232     }
00233     else
00234     {
00235         if (ul_clk < CHIP_FREQ_FWS_1)
00236         {
00237         EFC->EEFC_FMR = EEFC_FMR_FWS(1)|EEFC_FMR_CLOE;
00238         }
00239         else
00240         {
00241             if (ul_clk < CHIP_FREQ_FWS_2)
00242             {
00243             EFC->EEFC_FMR = EEFC_FMR_FWS(2)|EEFC_FMR_CLOE;
00244             }
00245             else
00246             {
00247                 if ( ul_clk < CHIP_FREQ_FWS_3 )
00248                 {
00249                     EFC->EEFC_FMR = EEFC_FMR_FWS(3)|EEFC_FMR_CLOE;
00250                 }
00251                 else
00252                 {
00253                     if ( ul_clk < CHIP_FREQ_FWS_4 )
00254                     {
00255                         EFC->EEFC_FMR = EEFC_FMR_FWS(4)|EEFC_FMR_CLOE;
00256                     }
00257                     else
00258                     {
00259                         EFC->EEFC_FMR = EEFC_FMR_FWS(5)|EEFC_FMR_CLOE;
00260                     }
00261                 }
00262             }
00263         }
00264     }
00265 }
00266 
00267 /**
00268  * \brief Enable  USB clock.
00269  *
00270  * \param pll_id Source of the USB clock.
00271  * \param div Actual clock divisor. Must be superior to 0.
00272  */
00273 void sysclk_enable_usb(void)
00274 {
00275     /* Disable FS USB clock*/
00276     PMC->PMC_SCDR = PMC_SCDR_USBCLK;
00277     
00278     /* Enable PLL 480 MHz */
00279     PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);    
00280     /* Wait that PLL is considered locked by the PMC */
00281     while( !(PMC->PMC_SR & PMC_SR_LOCKU) );
00282     
00283     /* USB clock register: USB Clock Input is UTMI PLL */
00284     PMC->PMC_USB = (PMC_USB_USBS | PMC_USB_USBDIV(USBCLK_DIV - 1) );
00285     
00286     PMC->PMC_SCER = PMC_SCER_USBCLK;
00287 }
00288 
00289 
00290 /**
00291  * \brief Disables USB clock.
00292  *
00293  *
00294  * \param pll_id Source of the USB clock.
00295  * \param div Actual clock divisor. Must be superior to 0.
00296  */
00297 void sysclk_disable_usb(void)
00298 {
00299     /* Disable FS USB clock*/
00300     PMC->PMC_SCDR = PMC_SCDR_USBCLK;
00301     
00302     /* Enable PLL 480 MHz */
00303     PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);    
00304     /* Wait that PLL is considered locked by the PMC */
00305     while( !(PMC->PMC_SR & PMC_SR_LOCKU) );
00306     
00307     /* USB clock register: USB Clock Input is UTMI PLL */
00308     PMC->PMC_USB = (PMC_USB_USBS | PMC_USB_USBDIV(USBCLK_DIV - 1) );
00309     
00310 
00311 }
00312 
00313 
00314 /* @cond 0 */
00315 /**INDENT-OFF**/
00316 #ifdef __cplusplus
00317 }
00318 #endif
00319 /**INDENT-ON**/
00320 /* @endcond */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines