]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/src/ASF/sam/drivers/pmc/sleep.c
Rename DummyTCB_t to StaticTCB_t.
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAME70_Xplained_AtmelStudio / src / ASF / sam / drivers / pmc / sleep.c
diff --git a/FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/src/ASF/sam/drivers/pmc/sleep.c b/FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/src/ASF/sam/drivers/pmc/sleep.c
new file mode 100644 (file)
index 0000000..83bf577
--- /dev/null
@@ -0,0 +1,389 @@
+/**\r
+ * \file\r
+ *\r
+ * \brief Sleep mode access\r
+ *\r
+ * Copyright (c) 2012-2015 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+/*\r
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>\r
+ */\r
+\r
+#include <compiler.h>\r
+#include "sleep.h"\r
+\r
+/* SAM3,SAM4,SAMG,SAMV,SAMS and SAME series */\r
+#if (SAM3S || SAM3N || SAM3XA || SAM3U || SAM4S || SAM4E || SAM4N || SAM4C || \\r
+               SAM4CM || SAMG || SAM4CP || SAMV71 || SAMV70 || SAMS70 || SAME70)\r
+# include "pmc.h"\r
+# include "board.h"\r
+\r
+/* Checking board configuration of main clock xtal statup time */\r
+#if !defined(BOARD_OSC_STARTUP_US)\r
+# warning The board main clock xtal statup time has not been defined. Using default settings.\r
+# define BOARD_OSC_STARTUP_US    (15625UL)\r
+#endif\r
+\r
+#if !defined(EFC0)\r
+# define EFC0 EFC\r
+#endif\r
+\r
+/**\r
+ * Save clock settings and shutdown PLLs\r
+ */\r
+__always_inline static void pmc_save_clock_settings(\r
+               uint32_t *p_osc_setting,\r
+               uint32_t *p_pll0_setting,\r
+               uint32_t *p_pll1_setting,\r
+               uint32_t *p_mck_setting,\r
+               uint32_t *p_fmr_setting,\r
+#if defined(EFC1)\r
+               uint32_t *p_fmr_setting1,\r
+#endif\r
+               const bool disable_xtal)\r
+{\r
+       uint32_t mor  = PMC->CKGR_MOR;\r
+       uint32_t mckr = PMC->PMC_MCKR;\r
+       uint32_t fmr  = EFC0->EEFC_FMR;\r
+# if defined(EFC1)\r
+       uint32_t fmr1 = EFC1->EEFC_FMR;\r
+# endif\r
+\r
+       if (p_osc_setting) {\r
+               *p_osc_setting = mor;\r
+       }\r
+       if (p_pll0_setting) {\r
+               *p_pll0_setting = PMC->CKGR_PLLAR;\r
+       }\r
+       if (p_pll1_setting) {\r
+#if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)\r
+               *p_pll1_setting = PMC->CKGR_PLLBR;\r
+#elif (SAM3U || SAM3XA)\r
+               *p_pll1_setting = PMC->CKGR_UCKR;\r
+#else\r
+               *p_pll1_setting = 0;\r
+#endif\r
+       }\r
+       if (p_mck_setting) {\r
+               *p_mck_setting  = mckr;\r
+       }\r
+       if (p_fmr_setting) {\r
+               *p_fmr_setting  = fmr;\r
+       }\r
+#if defined(EFC1)\r
+       if (p_fmr_setting1) {\r
+               *p_fmr_setting1 = fmr1;\r
+       }\r
+#endif\r
+\r
+       /* Enable FAST RC */\r
+       PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | mor | CKGR_MOR_MOSCRCEN;\r
+       /* if MCK source is PLL, switch to mainck */\r
+       if ((mckr & PMC_MCKR_CSS_Msk) > PMC_MCKR_CSS_MAIN_CLK) {\r
+               /* MCK -> MAINCK */\r
+               mckr = (mckr & (~PMC_MCKR_CSS_Msk)) | PMC_MCKR_CSS_MAIN_CLK;\r
+               PMC->PMC_MCKR = mckr;\r
+               while(!(PMC->PMC_SR & PMC_SR_MCKRDY));\r
+       }\r
+       /* MCK prescale -> 1 */\r
+       if (mckr & PMC_MCKR_PRES_Msk) {\r
+               mckr = (mckr & (~PMC_MCKR_PRES_Msk));\r
+               PMC->PMC_MCKR = mckr;\r
+               while(!(PMC->PMC_SR & PMC_SR_MCKRDY));\r
+       }\r
+       /* Disable PLLs */\r
+       pmc_disable_pllack();\r
+#if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)\r
+       pmc_disable_pllbck();\r
+#elif (SAM3U || SAM3XA)\r
+       pmc_disable_upll_clock();\r
+#endif\r
+\r
+       /* Prepare for entering WAIT mode */\r
+       /* Wait fast RC ready */\r
+       while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));\r
+\r
+       /* Switch mainck to FAST RC */\r
+#if SAMG\r
+       /**\r
+        * For the sleepwalking feature, we need an accurate RC clock. Only 24M and\r
+        * 16M are trimmed in production. Here we select the 24M.\r
+        * And so wait state need to be 1.\r
+        */\r
+       EFC0->EEFC_FMR = (fmr & (~EEFC_FMR_FWS_Msk)) | EEFC_FMR_FWS(1);\r
+\r
+       PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) | CKGR_MOR_MOSCRCF_24_MHz |\r
+                       CKGR_MOR_KEY_PASSWD;\r
+#else\r
+       PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) |\r
+                       CKGR_MOR_KEY_PASSWD;\r
+#endif\r
+       while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));\r
+\r
+#if (!SAMG)\r
+       /* FWS update */\r
+       EFC0->EEFC_FMR = fmr & (~EEFC_FMR_FWS_Msk);\r
+#if defined(EFC1)\r
+       EFC1->EEFC_FMR = fmr1 & (~EEFC_FMR_FWS_Msk);\r
+#endif\r
+#endif\r
+\r
+       /* Disable XTALs */\r
+       if (disable_xtal) {\r
+               PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |\r
+                               CKGR_MOR_KEY_PASSWD;\r
+       }\r
+}\r
+\r
+/**\r
+ * Restore clock settings\r
+ */\r
+__always_inline static void pmc_restore_clock_setting(\r
+               const uint32_t osc_setting,\r
+               const uint32_t pll0_setting,\r
+               const uint32_t pll1_setting,\r
+               const uint32_t mck_setting,\r
+               const uint32_t fmr_setting\r
+#if defined(EFC1)\r
+               , const uint32_t fmr_setting1\r
+#endif\r
+               )\r
+{\r
+       uint32_t mckr;\r
+       uint32_t pll_sr = 0;\r
+\r
+       /* Switch mainck to external xtal */\r
+       if (CKGR_MOR_MOSCXTBY == (osc_setting & CKGR_MOR_MOSCXTBY)) {\r
+               /* Bypass mode */\r
+               PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |\r
+                               CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTBY |\r
+                               CKGR_MOR_MOSCSEL;\r
+               PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN &\r
+                                       ~CKGR_MOR_MOSCRCF_Msk)\r
+                               | CKGR_MOR_KEY_PASSWD;\r
+       } else if (CKGR_MOR_MOSCXTEN == (osc_setting & CKGR_MOR_MOSCXTEN)) {\r
+               /* Enable External XTAL */\r
+               if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCXTEN)) {\r
+                       PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |\r
+                                       CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTEN;\r
+                       /* Wait the Xtal to stabilize */\r
+                       while (!(PMC->PMC_SR & PMC_SR_MOSCXTS));\r
+               }\r
+               /* Select External XTAL */\r
+               if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)) {\r
+                       PMC->CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCSEL;\r
+                       while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));\r
+               }\r
+               /* Disable Fast RC */\r
+               PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN &\r
+                                               ~CKGR_MOR_MOSCRCF_Msk)\r
+                                       | CKGR_MOR_KEY_PASSWD;\r
+       }\r
+\r
+       if (pll0_setting & CKGR_PLLAR_MULA_Msk) {\r
+#if (SAM4C || SAM4CM || SAMG || SAM4CP)\r
+               PMC->CKGR_PLLAR = pll0_setting;\r
+#else\r
+               PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | pll0_setting;\r
+#endif\r
+               pll_sr |= PMC_SR_LOCKA;\r
+       }\r
+#if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)\r
+       if (pll1_setting & CKGR_PLLBR_MULB_Msk) {\r
+               PMC->CKGR_PLLBR = pll1_setting;\r
+               pll_sr |= PMC_SR_LOCKB;\r
+       }\r
+#elif (SAM3U || SAM3XA)\r
+       if (pll1_setting & CKGR_UCKR_UPLLEN) {\r
+               PMC->CKGR_UCKR = pll1_setting;\r
+               pll_sr |= PMC_SR_LOCKU;\r
+       }\r
+#else\r
+       UNUSED(pll1_setting);\r
+#endif\r
+       /* Wait MCK source ready */\r
+       switch(mck_setting & PMC_MCKR_CSS_Msk) {\r
+       case PMC_MCKR_CSS_PLLA_CLK:\r
+               while (!(PMC->PMC_SR & PMC_SR_LOCKA));\r
+               break;\r
+#if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)\r
+       case PMC_MCKR_CSS_PLLB_CLK:\r
+               while (!(PMC->PMC_SR & PMC_SR_LOCKB));\r
+               break;\r
+#elif (SAM3U || SAM3XA)\r
+       case PMC_MCKR_CSS_UPLL_CLK:\r
+               while (!(PMC->PMC_SR & PMC_SR_LOCKU));\r
+               break;\r
+#endif\r
+       }\r
+\r
+       /* Switch to faster clock */\r
+       mckr = PMC->PMC_MCKR;\r
+\r
+       /* Set PRES */\r
+       PMC->PMC_MCKR = (mckr & ~PMC_MCKR_PRES_Msk)\r
+               | (mck_setting & PMC_MCKR_PRES_Msk);\r
+       while (!(PMC->PMC_SR & PMC_SR_MCKRDY));\r
+\r
+       /* Restore flash wait states */\r
+       EFC0->EEFC_FMR = fmr_setting;\r
+#if defined(EFC1)\r
+       EFC1->EEFC_FMR = fmr_setting1;\r
+#endif\r
+\r
+       /* Set CSS and others */\r
+       PMC->PMC_MCKR = mck_setting;\r
+       while (!(PMC->PMC_SR & PMC_SR_MCKRDY));\r
+\r
+       /* Waiting all restored PLLs ready */\r
+       while (!(PMC->PMC_SR & pll_sr));\r
+}\r
+\r
+/** If clocks are switched for some sleep mode */\r
+static volatile bool b_is_sleep_clock_used = false;\r
+/** Callback invoked once when clocks are restored */\r
+static pmc_callback_wakeup_clocks_restored_t callback_clocks_restored = NULL;\r
+\r
+void pmc_sleep(int sleep_mode)\r
+{\r
+       switch (sleep_mode) {\r
+#if (!(SAMG51 || SAMG53 || SAMG54))\r
+       case SAM_PM_SMODE_SLEEP_WFI:\r
+       case SAM_PM_SMODE_SLEEP_WFE:\r
+#if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG55 || SAMV71 || SAMV70 || SAMS70 || SAME70)\r
+               SCB->SCR &= (uint32_t)~SCR_SLEEPDEEP;\r
+               cpu_irq_enable();\r
+               __WFI();\r
+               break;\r
+#else\r
+               PMC->PMC_FSMR &= (uint32_t)~PMC_FSMR_LPM;\r
+               SCB->SCR &= (uint32_t)~SCR_SLEEPDEEP;\r
+               cpu_irq_enable();\r
+               if (sleep_mode == SAM_PM_SMODE_SLEEP_WFI)\r
+                       __WFI();\r
+               else\r
+                       __WFE();\r
+               break;\r
+#endif\r
+#endif\r
+\r
+       case SAM_PM_SMODE_WAIT_FAST:\r
+       case SAM_PM_SMODE_WAIT: {\r
+               uint32_t mor, pllr0, pllr1, mckr;\r
+               uint32_t fmr;\r
+#if defined(EFC1)\r
+               uint32_t fmr1;\r
+#endif\r
+#if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG55 || SAMV71 || SAMV70 || SAMS70 || SAME70)\r
+               (sleep_mode == SAM_PM_SMODE_WAIT_FAST) ?\r
+                               pmc_set_flash_in_wait_mode(PMC_FSMR_FLPM_FLASH_STANDBY) :\r
+                               pmc_set_flash_in_wait_mode(PMC_FSMR_FLPM_FLASH_DEEP_POWERDOWN);\r
+#endif\r
+               cpu_irq_disable();\r
+               b_is_sleep_clock_used = true;\r
+\r
+#if (SAM4C || SAM4CM || SAM4CP)\r
+               /* Backup the sub-system 1 status and stop sub-system 1 */\r
+               uint32_t cpclk_backup = PMC->PMC_SCSR &\r
+                               (PMC_SCSR_CPCK | PMC_SCSR_CPBMCK);\r
+               PMC->PMC_SCDR = cpclk_backup | PMC_SCDR_CPKEY_PASSWD;\r
+#endif\r
+               pmc_save_clock_settings(&mor, &pllr0, &pllr1, &mckr, &fmr,\r
+#if defined(EFC1)\r
+                               &fmr1,\r
+#endif\r
+                               (sleep_mode == SAM_PM_SMODE_WAIT));\r
+\r
+               /* Enter wait mode */\r
+               cpu_irq_enable();\r
+\r
+               pmc_enable_waitmode();\r
+\r
+               cpu_irq_disable();\r
+               pmc_restore_clock_setting(mor, pllr0, pllr1, mckr, fmr\r
+#if defined(EFC1)\r
+                               , fmr1\r
+#endif\r
+                               );\r
+\r
+#if (SAM4C || SAM4CM || SAM4CP)\r
+               /* Restore the sub-system 1 */\r
+               PMC->PMC_SCER = cpclk_backup | PMC_SCER_CPKEY_PASSWD;\r
+#endif\r
+               b_is_sleep_clock_used = false;\r
+               if (callback_clocks_restored) {\r
+                       callback_clocks_restored();\r
+                       callback_clocks_restored = NULL;\r
+               }\r
+               cpu_irq_enable();\r
+\r
+               break;\r
+       }\r
+#if (!(SAMG51 || SAMG53 || SAMG54))\r
+       case SAM_PM_SMODE_BACKUP:\r
+               SCB->SCR |= SCR_SLEEPDEEP;\r
+#if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG55 || SAMV71 || SAMV70 || SAMS70 || SAME70)\r
+               SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_VROFF_STOP_VREG;\r
+               cpu_irq_enable();\r
+               __WFI() ;\r
+#else\r
+               cpu_irq_enable();\r
+               __WFE() ;\r
+#endif\r
+               break;\r
+#endif\r
+       }\r
+}\r
+\r
+bool pmc_is_wakeup_clocks_restored(void)\r
+{\r
+       return !b_is_sleep_clock_used;\r
+}\r
+\r
+void pmc_wait_wakeup_clocks_restore(\r
+               pmc_callback_wakeup_clocks_restored_t callback)\r
+{\r
+       if (b_is_sleep_clock_used) {\r
+               cpu_irq_disable();\r
+               callback_clocks_restored = callback;\r
+       } else if (callback) {\r
+               callback();\r
+       }\r
+}\r
+\r
+#endif\r