SAMV71 Xplained Ultra Software Package 1.5

system_samv71.c

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