From a1d82980578ef6c991f316765e4fd422f0e8da1b Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 6 Aug 2018 10:36:16 -0500 Subject: [PATCH 1/4] MIMXRT1050_EVK: Add Low Power Manager files This is needed to support different Low-Power modes available in MXRT1050 Signed-off-by: Mahesh Mahadevan --- .../TARGET_MIMXRT1050/TARGET_EVK/lpm.c | 753 ++++++++++++++++++ .../TARGET_MIMXRT1050/TARGET_EVK/lpm.h | 153 ++++ 2 files changed, 906 insertions(+) create mode 100644 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/lpm.c create mode 100644 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/lpm.h diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/lpm.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/lpm.c new file mode 100644 index 0000000000..35d2d4ede9 --- /dev/null +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/lpm.c @@ -0,0 +1,753 @@ +/* + * The Clear BSD License + * Copyright 2017 NXP + * All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted (subject to the limitations in the disclaimer below) provided + * that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "lpm.h" +#include "fsl_gpc.h" +#include "fsl_dcdc.h" +#include "fsl_gpt.h" +#include "fsl_lpuart.h" +#include "fsl_iomuxc.h" +#include "fsl_clock_config.h" +#include "serial_api.h" +#include "mbed_critical.h" +#include "cmsis.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define LPM_GPC_IMR_NUM (sizeof(GPC->IMR) / sizeof(GPC->IMR[0])) + +typedef struct _lpm_clock_context +{ + uint32_t armDiv; + uint32_t ahbDiv; + uint32_t ipgDiv; + uint32_t perDiv; + uint32_t perSel; + uint32_t periphSel; + uint32_t preperiphSel; + uint32_t pfd480; + uint32_t pfd528; + uint32_t pllArm_loopdiv; + uint32_t pllArm; + uint32_t pllSys; + uint32_t pllUsb1; + uint32_t pllUsb2; + uint32_t pllAudio; + uint32_t pllVideo; + uint32_t pllEnet; + uint32_t is_valid; +} lpm_clock_context_t; + +/******************************************************************************* + * Variables + ******************************************************************************/ + +static lpm_clock_context_t s_clockContext; +static uint32_t s_DllBackupValue = 0; + +/******************************************************************************* + * Code + ******************************************************************************/ + +void BOARD_SetLPClockGate(void) +{ + CCM->CCGR0 = 0x0F4000C5U; + CCM->CCGR1 = 0x541C0000U; + CCM->CCGR2 = 0x00150010U; + CCM->CCGR3 = 0x50040130U; + CCM->CCGR4 = 0x00005514U; + CCM->CCGR5 = 0x51001105U; + CCM->CCGR6 = 0x005405C0U; +} + +void BOARD_ResetLPClockGate(void) +{ + CCM->CCGR0 = 0xFFFFFFFFU; + CCM->CCGR1 = 0xFFFFFFFFU; + CCM->CCGR2 = 0xFFFFFFFFU; + CCM->CCGR3 = 0xFFFFFFFFU; + CCM->CCGR4 = 0xFFFFFFFFU; + CCM->CCGR5 = 0xFFFFFFFFU; + CCM->CCGR6 = 0xFFFFFFFFU; +} + +void LPM_SwitchToRcOSC(void) +{ + /* Switch to RC-OSC */ + XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_SET_OSC_SEL_MASK; + /* Turn off XTAL-OSC */ + CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power down */ + + /* Wait CCM operation finishes */ + CLOCK_CCM_HANDSHAKE_WAIT(); + /* Take some delay */ + LPM_DELAY(40); +} + +void LPM_SwitchToXtalOSC(void) +{ + /* Restore XTAL-OSC and enable detector */ + CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power up */ + while ((XTALOSC24M->LOWPWR_CTRL & XTALOSC24M_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_MASK) == 0) + { + } + CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; /* detect freq */ + while ((CCM_ANALOG->MISC0 & CCM_ANALOG_MISC0_OSC_XTALOK_MASK) == 0) + { + } + CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; + + /* Switch to XTAL-OSC */ + XTALOSC24M->LOWPWR_CTRL_CLR = XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_MASK; + /* Turn off XTAL-OSC detector */ + CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; + + /* Wait CCM operation finishes */ + CLOCK_CCM_HANDSHAKE_WAIT(); + /* Take some delay */ + LPM_DELAY(40); +} + +void LPM_SwitchBandgap(void) +{ + /* Switch bandgap */ + PMU->MISC0_SET = 0x00000004; + XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_LPBG_SEL_MASK; + PMU->MISC0_SET = CCM_ANALOG_MISC0_REFTOP_PWD_MASK; + + /* Wait CCM operation finishes */ + CLOCK_CCM_HANDSHAKE_WAIT(); + /* Take some delay */ + LPM_DELAY(40); +} + +void LPM_RestoreBandgap(void) +{ + /* Restore bandgap */ + /* Turn on regular bandgap and wait for stable */ + PMU->MISC0_CLR = CCM_ANALOG_MISC0_REFTOP_PWD_MASK; + while ((PMU->MISC0 & PMU_MISC0_REFTOP_VBGUP_MASK) == 0) + { + } + /* Low power band gap disable */ + XTALOSC24M->LOWPWR_CTRL_CLR = XTALOSC24M_LOWPWR_CTRL_LPBG_SEL_MASK; + PMU->MISC0_CLR = 0x00000004; + + /* Wait CCM operation finishes */ + CLOCK_CCM_HANDSHAKE_WAIT(); + /* Take some delay */ + LPM_DELAY(40); +} + +void LPM_EnableWakeupSource(uint32_t irq) +{ + GPC_EnableIRQ(GPC, irq); +} + +void LPM_DisableWakeupSource(uint32_t irq) +{ + GPC_DisableIRQ(GPC, irq); +} + +/* + * ERR007265: CCM: When improper low-power sequence is used, + * the SoC enters low power mode before the ARM core executes WFI. + * + * Software workaround: + * 1) Software should trigger IRQ #41 (GPR_IRQ) to be always pending + * by setting IOMUX_GPR1_GINT. + * 2) Software should then unmask IRQ #41 in GPC before setting CCM + * Low-Power mode. + * 3) Software should mask IRQ #41 right after CCM Low-Power mode + * is set (set bits 0-1 of CCM_CLPCR). + */ +static void LPM_SetClockMode(clock_mode_t mode, uint32_t clpcr) +{ + switch (mode) + { + case kCLOCK_ModeRun: + CCM->CLPCR = clpcr; + break; + default: + LPM_EnableWakeupSource(GPR_IRQ_IRQn); + CCM->CLPCR = clpcr; + LPM_DisableWakeupSource(GPR_IRQ_IRQn); + break; + } +} + +void LPM_SwitchFlexspiClock(clock_mode_t powermode) +{ + while (!((FLEXSPI->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) && (FLEXSPI->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) + { + ; + } + FLEXSPI->MCR0 |= FLEXSPI_MCR0_MDIS_MASK; + /* Disable clock gate of flexspi. */ + CCM->CCGR6 &= (~CCM_CCGR6_CG5_MASK); + + /* Periph_clk output will be used as SEMC clock root */ + CLOCK_SET_MUX(kCLOCK_SemcMux, 0x0); + /* Set post divider for SEMC clock as 0. */ + CLOCK_SET_DIV(kCLOCK_SemcDiv, 0x0); + + /* Wait CCM operation finishes */ + while (CCM->CDHIPR != 0) + { + } + + /* Semc_clk_root_pre will be used as flexspi clock. */ + CLOCK_SET_MUX(kCLOCK_FlexspiMux, 0x0); + /* Set divider for flexspi clock root 0. */ + CLOCK_SET_DIV(kCLOCK_FlexspiDiv, 0x0); + + /* Enable clock gate of flexspi. */ + CCM->CCGR6 |= (CCM_CCGR6_CG5_MASK); + + if (kCLOCK_ModeStop == powermode) { + FLEXSPI->DLLCR[0] = FLEXSPI_DLLCR_OVRDEN(1) | FLEXSPI_DLLCR_OVRDVAL(19); + } else { + FLEXSPI->DLLCR[0] = 0x79; + } + FLEXSPI->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; + FLEXSPI->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK; + + while (FLEXSPI->MCR0 & FLEXSPI_MCR0_SWRESET_MASK) { + } + + while (!((FLEXSPI->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) && (FLEXSPI->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) { + } + + /* Take some delay */ + LPM_DELAY(40); +} + +void LPM_RestoreFlexspiClock(void) +{ + while (!((FLEXSPI->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) && (FLEXSPI->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) + { + ; + } + FLEXSPI->MCR0 |= FLEXSPI_MCR0_MDIS_MASK; + /* Disable clock gate of flexspi. */ + CCM->CCGR6 &= (~CCM_CCGR6_CG5_MASK); + + /* PLL3 PFD0 will be used as flexspi clock. */ + CLOCK_SET_MUX(kCLOCK_FlexspiMux, 0x3); + /* Set divider for flexspi clock root 0. */ + CLOCK_SET_DIV(kCLOCK_FlexspiDiv, 0x0); + + /* Enable clock gate of flexspi. */ + CCM->CCGR6 |= (CCM_CCGR6_CG5_MASK); + + /* PLL2 PFD2 output will be used as SEMC clock root */ + CLOCK_SET_MUX(kCLOCK_SemcMux, 0x1); + /* Set post divider for SEMC clock as 1. */ + CLOCK_SET_DIV(kCLOCK_SemcDiv, 0x1); + + /* Wait CCM operation finishes */ + while (CCM->CDHIPR != 0) + { + } + + FLEXSPI->DLLCR[0] = s_DllBackupValue; + FLEXSPI->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; + FLEXSPI->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK; + while (FLEXSPI->MCR0 & FLEXSPI_MCR0_SWRESET_MASK) + { + } + while (!((FLEXSPI->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) && (FLEXSPI->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) + { + ; + } + /* Take some delay */ + LPM_DELAY(40); +} + +void LPM_DisablePLLs(clock_mode_t powermode) +{ + s_clockContext.pfd480 = CCM_ANALOG->PFD_480; + s_clockContext.pfd528 = CCM_ANALOG->PFD_528; + s_clockContext.pllSys = CCM_ANALOG->PLL_SYS; + s_clockContext.pllUsb1 = CCM_ANALOG->PLL_USB1; + s_clockContext.pllUsb2 = CCM_ANALOG->PLL_USB2; + s_clockContext.pllAudio = CCM_ANALOG->PLL_AUDIO; + s_clockContext.pllVideo = CCM_ANALOG->PLL_VIDEO; + s_clockContext.pllEnet = CCM_ANALOG->PLL_ENET; + s_clockContext.pllArm_loopdiv = + (CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_ARM_DIV_SELECT_SHIFT; + s_clockContext.pllArm = CCM_ANALOG->PLL_ARM; + s_clockContext.periphSel = CLOCK_GetMux(kCLOCK_PeriphMux); + s_clockContext.ipgDiv = CLOCK_GetDiv(kCLOCK_IpgDiv); + s_clockContext.ahbDiv = CLOCK_GetDiv(kCLOCK_AhbDiv); + s_clockContext.perSel = CLOCK_GetMux(kCLOCK_PerclkMux); + s_clockContext.perDiv = CLOCK_GetDiv(kCLOCK_PerclkDiv); + s_clockContext.preperiphSel = CLOCK_GetMux(kCLOCK_PrePeriphMux); + s_clockContext.armDiv = CLOCK_GetDiv(kCLOCK_ArmDiv); + s_clockContext.is_valid = 1; + + /* Power off USB2 PLL */ + CCM_ANALOG->PLL_USB2_SET = CCM_ANALOG_PLL_USB2_BYPASS_MASK; + CCM_ANALOG->PLL_USB2_CLR = CCM_ANALOG_PLL_USB2_POWER_MASK; + /* Power off AUDIO PLL */ + CCM_ANALOG->PLL_AUDIO_SET = CCM_ANALOG_PLL_AUDIO_BYPASS_MASK; + CCM_ANALOG->PLL_AUDIO_SET = CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK; + /* Power off VIDEO PLL */ + CCM_ANALOG->PLL_VIDEO_SET = CCM_ANALOG_PLL_VIDEO_BYPASS_MASK; + CCM_ANALOG->PLL_VIDEO_SET = CCM_ANALOG_PLL_VIDEO_POWERDOWN_MASK; + /* Power off ENET PLL */ + CCM_ANALOG->PLL_ENET_SET = CCM_ANALOG_PLL_ENET_BYPASS_MASK; + CCM_ANALOG->PLL_ENET_SET = CCM_ANALOG_PLL_ENET_POWERDOWN_MASK; + + if (kCLOCK_ModeWait == powermode) { + CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 1); + CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0); + CLOCK_SetMux(kCLOCK_PeriphMux, 1); + CLOCK_SetDiv(kCLOCK_IpgDiv, 0); + CLOCK_SetDiv(kCLOCK_AhbDiv, 0); + + /*ARM PLL as clksource*/ + /* 24 * 88 / 2 / 8 = 132MHz */ + CCM_ANALOG->PLL_ARM_CLR = CCM_ANALOG_PLL_ARM_POWERDOWN_MASK; + CCM_ANALOG->PLL_ARM_SET = CCM_ANALOG_PLL_ARM_ENABLE_MASK | CCM_ANALOG_PLL_ARM_BYPASS_MASK; + CCM_ANALOG->PLL_ARM_CLR = CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK; + CCM_ANALOG->PLL_ARM_SET = CCM_ANALOG_PLL_ARM_DIV_SELECT(88); + CLOCK_SetDiv(kCLOCK_ArmDiv, 7); + CCM_ANALOG->PLL_ARM_CLR = CCM_ANALOG_PLL_ARM_BYPASS_MASK; + + /*Select ARM_PLL for pre_periph_clock */ + CLOCK_SetMux(kCLOCK_PrePeriphMux, 3); + CLOCK_SetMux(kCLOCK_PeriphMux, 0); + + /* SET AHB, IPG to 33MHz */ + CLOCK_SetDiv(kCLOCK_IpgDiv, 0); + CLOCK_SetDiv(kCLOCK_AhbDiv, 3); + + /*Set PERCLK to 33MHz*/ + //CLOCK_SetMux(kCLOCK_PerclkMux, 0); + //CLOCK_SetDiv(kCLOCK_PerclkDiv, 0); + } else { + CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 1); + CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0); + CLOCK_SetMux(kCLOCK_PeriphMux, 1); + CLOCK_SetDiv(kCLOCK_IpgDiv, 0); + CLOCK_SetDiv(kCLOCK_AhbDiv, 0); + + /*ARM PLL as clksource*/ + CCM_ANALOG->PLL_ARM |= CCM_ANALOG_PLL_ARM_ENABLE_MASK | CCM_ANALOG_PLL_ARM_BYPASS_MASK; + /* Power off ARM PLL */ + CCM_ANALOG->PLL_ARM_SET = CCM_ANALOG_PLL_ARM_POWERDOWN_MASK; + + /*Select ARM_PLL for pre_periph_clock */ + CLOCK_SetDiv(kCLOCK_ArmDiv, 0x0); + CLOCK_SetMux(kCLOCK_PrePeriphMux, 0x3); + CLOCK_SetMux(kCLOCK_PeriphMux, 0x0); + + /* SET AHB, IPG to 12MHz */ + CLOCK_SetDiv(kCLOCK_IpgDiv, 0); + CLOCK_SetDiv(kCLOCK_AhbDiv, 1); + + /*Set PERCLK to 12Mhz*/ + //CLOCK_SetMux(kCLOCK_PerclkMux, 0x0); + //CLOCK_SetDiv(kCLOCK_PerclkDiv, 0x0); + } + + core_util_critical_section_enter(); + LPM_SwitchFlexspiClock(powermode); + core_util_critical_section_exit(); + + CLOCK_DeinitUsb1Pfd(kCLOCK_Pfd0); + CLOCK_DeinitUsb1Pfd(kCLOCK_Pfd1); + CLOCK_DeinitUsb1Pfd(kCLOCK_Pfd2); + CLOCK_DeinitUsb1Pfd(kCLOCK_Pfd3); + + /* Power off USB1 PLL */ + CCM_ANALOG->PLL_USB1_SET = CCM_ANALOG_PLL_USB1_BYPASS_MASK; + CCM_ANALOG->PLL_USB1_CLR = CCM_ANALOG_PLL_USB1_POWER_MASK; + + CLOCK_DeinitSysPfd(kCLOCK_Pfd0); + CLOCK_DeinitSysPfd(kCLOCK_Pfd1); + CLOCK_DeinitSysPfd(kCLOCK_Pfd2); + CLOCK_DeinitSysPfd(kCLOCK_Pfd3); + + /* When need to close PLL, we need to use bypass clock first and then power it down. */ + /* Power off SYS PLL */ + CCM_ANALOG->PLL_SYS_SET = CCM_ANALOG_PLL_SYS_BYPASS_MASK; + CCM_ANALOG->PLL_SYS_SET = CCM_ANALOG_PLL_SYS_POWERDOWN_MASK; +} + +void LPM_RestorePLLs(void) +{ + if (s_clockContext.is_valid) + { + /* Bypass PLL first */ + CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK)) | + CCM_ANALOG_PLL_USB1_BYPASS_MASK; + + CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK)) | + CCM_ANALOG_PLL_USB1_ENABLE_MASK | CCM_ANALOG_PLL_USB1_POWER_MASK | + CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK; + + while ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_LOCK_MASK) == 0) + { + } + + /* Disable Bypass */ + CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_BYPASS_MASK; + + /* Restore USB1 PLL PFD */ + CCM_ANALOG->PFD_480 = s_clockContext.pfd480; + CCM_ANALOG->PFD_480_CLR = CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK; + + /* Disable Usb1 PLL output for USBPHY1. */ + CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK; + + /* When need to enable PLL, we need to use bypass clock first and then switch pll back. */ + /* Power on SYS PLL and wait for locked */ + CCM_ANALOG->PLL_SYS_SET = CCM_ANALOG_PLL_SYS_BYPASS_MASK; + CCM_ANALOG->PLL_SYS_CLR = CCM_ANALOG_PLL_SYS_POWERDOWN_MASK; + CCM_ANALOG->PLL_SYS = s_clockContext.pllSys; + + while ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_LOCK_MASK) == 0) + { + } + + /* Restore SYS PLL PFD */ + CCM_ANALOG->PFD_528 = s_clockContext.pfd528; + CCM_ANALOG->PFD_528_CLR = CCM_ANALOG_PFD_528_PFD2_CLKGATE_MASK; + + core_util_critical_section_enter(); + LPM_RestoreFlexspiClock(); + core_util_critical_section_exit(); + } else { + return; + } + + CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 0); + CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0); + CLOCK_SetMux(kCLOCK_PeriphMux, 1); + CLOCK_SetDiv(kCLOCK_IpgDiv, 0x3); + CLOCK_SetDiv(kCLOCK_AhbDiv, 0x0); + + /* ARM PLL as clksource*/ + CCM_ANALOG->PLL_ARM_CLR = CCM_ANALOG_PLL_ARM_POWERDOWN_MASK; + CCM_ANALOG->PLL_ARM_SET = CCM_ANALOG_PLL_ARM_ENABLE_MASK | CCM_ANALOG_PLL_ARM_BYPASS_MASK; + + CLOCK_SetDiv(kCLOCK_ArmDiv, s_clockContext.armDiv); + CCM_ANALOG->PLL_ARM_CLR = CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK; + CCM_ANALOG->PLL_ARM_SET = CCM_ANALOG_PLL_ARM_DIV_SELECT(s_clockContext.pllArm_loopdiv); + if ((s_clockContext.pllArm & CCM_ANALOG_PLL_ARM_BYPASS_MASK) == 0) + { + while ((CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_LOCK_MASK) == 0) + { + } + } + if ((s_clockContext.pllArm & CCM_ANALOG_PLL_ARM_BYPASS_MASK) == 0) + { + CCM_ANALOG->PLL_ARM_CLR = CCM_ANALOG_PLL_ARM_BYPASS_MASK; + } + + /* Restore AHB and IPG div */ + CCM->CBCDR = (CCM->CBCDR & ~(CCM_CBCDR_AHB_PODF_MASK | CCM_CBCDR_IPG_PODF_MASK | CCM_CBCDR_PERIPH_CLK_SEL_MASK)) | + CCM_CBCDR_AHB_PODF(s_clockContext.ahbDiv) | CCM_CBCDR_IPG_PODF(s_clockContext.ipgDiv) | + CCM_CBCDR_PERIPH_CLK_SEL(s_clockContext.periphSel); + + /* Restore Periphral clock */ + CCM->CSCMR1 = (CCM->CSCMR1 & ~CCM_CSCMR1_PERCLK_PODF_MASK) | CCM_CSCMR1_PERCLK_PODF(s_clockContext.perDiv) | + CCM_CSCMR1_PERCLK_CLK_SEL(s_clockContext.perSel); + + /* Switch clocks back */ + CCM->CBCMR = + (CCM->CBCMR & ~CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) | CCM_CBCMR_PRE_PERIPH_CLK_SEL(s_clockContext.preperiphSel); + + /* Wait CCM operation finishes */ + while (CCM->CDHIPR != 0) + { + } + + /* Restore USB2 PLL */ + CCM_ANALOG->PLL_USB2_SET = CCM_ANALOG_PLL_USB2_BYPASS_MASK; + CCM_ANALOG->PLL_USB2_SET = CCM_ANALOG_PLL_USB2_POWER_MASK; + CCM_ANALOG->PLL_USB2 = s_clockContext.pllUsb2; + if ((CCM_ANALOG->PLL_USB2 & CCM_ANALOG_PLL_USB2_POWER_MASK) != 0) + { + while ((CCM_ANALOG->PLL_USB2 & CCM_ANALOG_PLL_USB2_LOCK_MASK) == 0) + { + } + } + + /* Restore AUDIO PLL */ + CCM_ANALOG->PLL_AUDIO_SET = CCM_ANALOG_PLL_AUDIO_BYPASS_MASK; + CCM_ANALOG->PLL_AUDIO_CLR = CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK; + CCM_ANALOG->PLL_AUDIO = s_clockContext.pllAudio; + if ((CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK) == 0) + { + while ((CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK_MASK) == 0) + { + } + } + + /* Restore VIDEO PLL */ + CCM_ANALOG->PLL_VIDEO_SET = CCM_ANALOG_PLL_VIDEO_BYPASS_MASK; + CCM_ANALOG->PLL_VIDEO_CLR = CCM_ANALOG_PLL_VIDEO_POWERDOWN_MASK; + CCM_ANALOG->PLL_VIDEO = s_clockContext.pllVideo; + if ((CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_POWERDOWN_MASK) == 0) + { + while ((CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_LOCK_MASK) == 0) + { + } + } + + /* Restore ENET PLL */ + CCM_ANALOG->PLL_ENET_SET = CCM_ANALOG_PLL_ENET_BYPASS_MASK; + CCM_ANALOG->PLL_ENET_SET = CCM_ANALOG_PLL_ENET_POWERDOWN_MASK; + CCM_ANALOG->PLL_ENET = s_clockContext.pllEnet; + if ((CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_POWERDOWN_MASK) == 0) + { + while ((CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_LOCK_MASK) == 0) + { + } + } + + s_clockContext.is_valid = 0; +} + +static void LPM_SystemIdle(clock_mode_t powermode) +{ + /* Switch DCDC to use DCDC internal OSC */ + DCDC_SetClockSource(DCDC, kDCDC_ClockInternalOsc); + + /* Power down USBPHY */ + USBPHY1->CTRL = 0xFFFFFFFF; + USBPHY2->CTRL = 0xFFFFFFFF; + + LPM_DisablePLLs(powermode); + + /* Enable weak 2P5 and turn off regular 2P5 */ + PMU->REG_2P5 &= ~PMU_REG_2P5_ENABLE_LINREG_MASK; + PMU->REG_2P5 |= PMU_REG_2P5_ENABLE_WEAK_LINREG_MASK; + + /* Enable weak 1P1 and turn off regular 1P1 */ + PMU->REG_1P1 &= ~PMU_REG_1P1_ENABLE_LINREG_MASK; + PMU->REG_1P1 |= PMU_REG_1P1_ENABLE_WEAK_LINREG_MASK; + + core_util_critical_section_enter(); + LPM_SwitchToRcOSC(); + core_util_critical_section_exit(); + + /* Lower OSC current by 37.5% */ + CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_OSC_I_MASK; + /* Enable FET ODRIVE */ + PMU->REG_CORE_SET = PMU_REG_CORE_FET_ODRIVE_MASK; + /* Disconnect vdd_high_in and connect vdd_snvs_in */ + CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_DISCON_HIGH_SNVS_MASK; + + DCDC_AdjustTargetVoltage(DCDC, 0x6, 0x1); + + core_util_critical_section_enter(); + LPM_SwitchBandgap(); + core_util_critical_section_exit(); + + /* RBC = 0; Enable COSC, OSC COUNT = 0xAF */ + CCM->CCR = (CCM_CCR_COSC_EN_MASK | CCM_CCR_OSCNT(0xAF)); +} + +void LPM_SystemRestoreIdle(void) +{ + DCDC_AdjustTargetVoltage(DCDC, 0x12, 0x1); + + /* Switch DCDC to use DCDC internal OSC */ + DCDC_SetClockSource(DCDC, kDCDC_ClockExternalOsc); + + /* Disconnect vdd_snvs_in and connect vdd_high_in */ + CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_DISCON_HIGH_SNVS_MASK; + /* Increase OSC current to normal */ + CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_OSC_I_MASK; + + core_util_critical_section_enter(); + LPM_SwitchToXtalOSC(); + LPM_RestoreBandgap(); + core_util_critical_section_exit(); + + /* Disable FET ODRIVE */ + PMU->REG_CORE_CLR = PMU_REG_CORE_FET_ODRIVE_MASK; + + /* Enable regular 2P5 and wait for stable */ + PMU->REG_2P5_SET = PMU_REG_2P5_ENABLE_LINREG_MASK; + while ((PMU->REG_2P5 & PMU_REG_2P5_OK_VDD2P5_MASK) == 0) + { + } + /* Turn off weak 2P5 */ + PMU->REG_2P5_CLR = PMU_REG_2P5_ENABLE_WEAK_LINREG_MASK; + + /* Enable regular 1P1 and wait for stable */ + PMU->REG_1P1_SET = PMU_REG_1P1_ENABLE_LINREG_MASK; + while ((PMU->REG_1P1 & PMU_REG_1P1_OK_VDD1P1_MASK) == 0) + { + } + /* Turn off weak 1P1 */ + PMU->REG_1P1_CLR = PMU_REG_1P1_ENABLE_WEAK_LINREG_MASK; + + LPM_RestorePLLs(); +} + +bool LPM_Init(void) +{ + uint32_t i; + uint32_t tmp_reg = 0; + + CLOCK_SetMode(kCLOCK_ModeRun); + + CCM->CGPR |= CCM_CGPR_INT_MEM_CLK_LPM_MASK; + + /* Enable RC OSC. It needs at least 4ms to be stable, so self tuning need to be enabled. */ + XTALOSC24M->LOWPWR_CTRL |= XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK; + /* Configure RC OSC */ + XTALOSC24M->OSC_CONFIG0 = XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR(0x4) | XTALOSC24M_OSC_CONFIG0_SET_HYST_MINUS(0x2) | + XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG(0xA7) | XTALOSC24M_OSC_CONFIG0_START_MASK | + XTALOSC24M_OSC_CONFIG0_ENABLE_MASK; + XTALOSC24M->OSC_CONFIG1 = XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR(0x40) | XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG(0x2DC); + /* Take some delay */ + LPM_DELAY(40); + /* Add some hysteresis */ + tmp_reg = XTALOSC24M->OSC_CONFIG0; + tmp_reg &= ~(XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK | XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK); + tmp_reg |= XTALOSC24M_OSC_CONFIG0_HYST_PLUS(3) | XTALOSC24M_OSC_CONFIG0_HYST_MINUS(3); + XTALOSC24M->OSC_CONFIG0 = tmp_reg; + /* Set COUNT_1M_TRG */ + tmp_reg = XTALOSC24M->OSC_CONFIG2; + tmp_reg &= ~XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK; + tmp_reg |= XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG(0x2d7); + XTALOSC24M->OSC_CONFIG2 = tmp_reg; + /* Hardware requires to read OSC_CONFIG0 or OSC_CONFIG1 to make OSC_CONFIG2 write work */ + tmp_reg = XTALOSC24M->OSC_CONFIG1; + XTALOSC24M->OSC_CONFIG1 = tmp_reg; + + s_DllBackupValue = FLEXSPI->DLLCR[0]; + + /* ERR007265 */ + IOMUXC_GPR->GPR1 |= IOMUXC_GPR_GPR1_GINT_MASK; + + /* Initialize GPC to mask all IRQs */ + for (i = 0; i < LPM_GPC_IMR_NUM; i++) { + GPC->IMR[i] = 0xFFFFFFFFU; + } + + return true; +} + +void LPM_Deinit(void) +{ + /* ERR007265 */ + IOMUXC_GPR->GPR1 &= ~IOMUXC_GPR_GPR1_GINT_MASK; +} + +void vPortPRE_SLEEP_PROCESSING(clock_mode_t powermode) +{ + uint32_t clpcr; + + clpcr = CCM->CLPCR & (~(CCM_CLPCR_LPM_MASK | CCM_CLPCR_ARM_CLK_DIS_ON_LPM_MASK)); + + switch (powermode) + { + case kCLOCK_ModeWait: +#if 0 + LPM_EnableWakeupSource(PIT_IRQn); + + LPM_SetClockMode(kCLOCK_ModeWait, clpcr | CCM_CLPCR_LPM(kCLOCK_ModeWait) | + CCM_CLPCR_ARM_CLK_DIS_ON_LPM_MASK | CCM_CLPCR_STBY_COUNT_MASK | 0x1C | + 0x08280000); + IOMUXC_GPR->GPR8 = 0xaaaaaaaa; + IOMUXC_GPR->GPR12 = 0x0000000a; +#endif + break; + case kCLOCK_ModeStop: + LPM_EnableWakeupSource(GPT2_IRQn); + + LPM_SetClockMode(kCLOCK_ModeWait, clpcr | CCM_CLPCR_LPM(kCLOCK_ModeWait) | + CCM_CLPCR_ARM_CLK_DIS_ON_LPM_MASK | CCM_CLPCR_STBY_COUNT_MASK | 0x1C | + 0x08280000); + BOARD_SetLPClockGate(); + LPM_SystemIdle(powermode); + IOMUXC_GPR->GPR8 = 0xaaaaaaaa; + IOMUXC_GPR->GPR12 = 0x0000000a; + break; + default: + assert(false); + break; + } +} + +void vPortPOST_SLEEP_PROCESSING(clock_mode_t powermode) +{ + uint32_t clpcr; + + clpcr = CCM->CLPCR & (~(CCM_CLPCR_LPM_MASK | CCM_CLPCR_ARM_CLK_DIS_ON_LPM_MASK)); + + switch (powermode) + { + case kCLOCK_ModeWait: +#if 0 + + IOMUXC_GPR->GPR8 = 0x00000000; + IOMUXC_GPR->GPR12 = 0x00000000; + LPM_SetClockMode(kCLOCK_ModeRun, clpcr); + + LPM_DisableWakeupSource(PIT_IRQn); +#endif + + break; + case kCLOCK_ModeStop: + __NOP(); + __NOP(); + __NOP(); + __NOP(); + IOMUXC_GPR->GPR8 = 0x00000000; + IOMUXC_GPR->GPR12 = 0x00000000; + /* Interrupt occurs before system idle */ + LPM_SystemRestoreIdle(); + BOARD_ResetLPClockGate(); + + LPM_SetClockMode(kCLOCK_ModeRun, clpcr); + + LPM_DisableWakeupSource(GPT2_IRQn); + + break; + default: + assert(false); + break; + } +} + diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/lpm.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/lpm.h new file mode 100644 index 0000000000..c1b9a78744 --- /dev/null +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/lpm.h @@ -0,0 +1,153 @@ +/* + * The Clear BSD License + * Copyright 2017 NXP + * All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted (subject to the limitations in the disclaimer below) provided + * that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LPM_H_ +#define _LPM_H_ + +#include "fsl_clock.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +extern void vPortGPTIsr(void); + +#define vPortGptIsr GPT1_IRQHandler + +#define CLOCK_SET_MUX(mux, value) \ + \ +do \ + { \ + CCM_TUPLE_REG(CCM, mux) = (CCM_TUPLE_REG(CCM, mux) & (~CCM_TUPLE_MASK(mux))) | \ + (((uint32_t)((value) << CCM_TUPLE_SHIFT(mux))) & CCM_TUPLE_MASK(mux)); \ + while (CCM->CDHIPR != 0) \ + { \ + } \ + \ +} \ + while (0) + +#define CLOCK_SET_DIV(divider, value) \ + \ +do \ + { \ + CCM_TUPLE_REG(CCM, divider) = (CCM_TUPLE_REG(CCM, divider) & (~CCM_TUPLE_MASK(divider))) | \ + (((uint32_t)((value) << CCM_TUPLE_SHIFT(divider))) & CCM_TUPLE_MASK(divider)); \ + while (CCM->CDHIPR != 0) \ + { \ + } \ + \ +} \ + while (0) + +#define CLOCK_CCM_HANDSHAKE_WAIT() \ + \ +do \ + { \ + while (CCM->CDHIPR != 0) \ + { \ + } \ + \ +} \ + while (0) + +#define LPM_DELAY(value) \ + \ +do \ + { \ + for (uint32_t i = 0; i < 5 * value; i++) \ + { \ + __NOP(); \ + } \ + \ +} \ + while (0) + +#define ROM_CODE_ENTRY_ADDR (0x200000U) + +/*! @name Time sensitive region */ +/* @{ */ +#if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1) +#if (defined(__ICCARM__)) +#define AT_QUICKACCESS_SECTION_CODE(func) __ramfunc func +#elif(defined(__ARMCC_VERSION)) +#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("RamFunction"))) func +#elif defined(__MCUXPRESSO) +#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section(".ramfunc.$SRAM_ITC"))) func +#elif(defined(__GNUC__)) +#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("RamFunction"))) func +#else +#error Toolchain not supported. +#endif /* defined(__ICCARM__) */ +#else +#if (defined(__ICCARM__)) +#define AT_QUICKACCESS_SECTION_CODE(func) func +#elif(defined(__ARMCC_VERSION)) +#define AT_QUICKACCESS_SECTION_CODE(func) func +#elif(defined(__MCUXPRESSO)) +#define AT_QUICKACCESS_SECTION_CODE(func) func +#elif(defined(__GNUC__)) +#define AT_QUICKACCESS_SECTION_CODE(func) func +#else +#error Toolchain not supported. +#endif +#endif /* __FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE */ + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +AT_QUICKACCESS_SECTION_CODE(void LPM_SwitchFlexspiClock(clock_mode_t powermode)); +AT_QUICKACCESS_SECTION_CODE(void LPM_RestoreFlexspiClock(void)); + +/* Initialize the Low Power Management */ +bool LPM_Init(void); + +/* Deinitialize the Low Power Management */ +void LPM_Deinit(void); + +/* Enable wakeup source in low power mode */ +void LPM_EnableWakeupSource(uint32_t irq); + +/* Disable wakeup source in low power mode */ +void LPM_DisableWakeupSource(uint32_t irq); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +#endif /* _LPM_H_ */ From e18e0f12f47dd628e68ce46c8d6d9cf095be084f Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 6 Aug 2018 10:40:36 -0500 Subject: [PATCH 2/4] MXRT1050_EVK: Ensure certain low power function are linked to internal memory Low power functions related to powering off FLEXSPI and SDRAM needs to be copied to internal memory Signed-off-by: Mahesh Mahadevan --- .../TARGET_EVK/mbed_overrides.c | 30 +++++++++++++- .../TOOLCHAIN_ARM_STD/MIMXRT1052xxxxx.sct | 6 +++ .../TOOLCHAIN_GCC_ARM/MIMXRT1052xxxxx.ld | 17 +++++++- .../device/TOOLCHAIN_IAR/MIMXRT1052xxxxx.icf | 6 +++ .../TARGET_MIMXRT1050/drivers/fsl_common.h | 41 +++---------------- 5 files changed, 63 insertions(+), 37 deletions(-) diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/mbed_overrides.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/mbed_overrides.c index ca9b6e10a1..d27ee85a34 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/mbed_overrides.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/mbed_overrides.c @@ -14,9 +14,9 @@ * limitations under the License. */ #include "pinmap.h" - #include "fsl_clock_config.h" #include "fsl_clock.h" +#include "lpm.h" #define LPSPI_CLOCK_SOURCE_DIVIDER (7U) #define LPI2C_CLOCK_SOURCE_DIVIDER (5U) @@ -124,11 +124,39 @@ void BOARD_ConfigMPU(void) SCB_EnableICache(); } +#if defined(TOOLCHAIN_GCC_ARM) +extern uint32_t __ram_function_flash_start[]; +#define __RAM_FUNCTION_FLASH_START __ram_function_flash_start +extern uint32_t __ram_function_ram_start[]; +#define __RAM_FUNCTION_RAM_START __ram_function_ram_start +extern uint32_t __ram_function_size[]; +#define __RAM_FUNCTION_SIZE __ram_function_size +void Board_CopyToRam() +{ + unsigned char *source; + unsigned char *destiny; + unsigned int size; + + source = (unsigned char *)(__RAM_FUNCTION_FLASH_START); + destiny = (unsigned char *)(__RAM_FUNCTION_RAM_START); + size = (unsigned long)(__RAM_FUNCTION_SIZE); + + while (size--) + { + *destiny++ = *source++; + } +} +#endif + // called before main void mbed_sdk_init() { BOARD_ConfigMPU(); BOARD_BootClockRUN(); +#if defined(TOOLCHAIN_GCC_ARM) + Board_CopyToRam(); +#endif + LPM_Init(); } void spi_setup_clock() diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_ARM_STD/MIMXRT1052xxxxx.sct b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_ARM_STD/MIMXRT1052xxxxx.sct index 4f310217c9..5f6808f434 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_ARM_STD/MIMXRT1052xxxxx.sct +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_ARM_STD/MIMXRT1052xxxxx.sct @@ -77,6 +77,9 @@ #define m_text_start 0x60002400 #define m_text_size 0x03FFDC00 +#define m_text2_start 0x00000000 +#define m_text2_size 0x00020000 + #define m_data_start 0x80000000 #define m_data_size 0x01E00000 @@ -139,6 +142,9 @@ LR_IROM1 m_flash_config_start m_text_start+m_text_size-m_flash_config_start { } ARM_LIB_STACK m_data_start+m_data_size EMPTY -Stack_Size { ; Stack region growing down } + RW_m_ram_text m_text2_start UNINIT m_text2_size { ; load address = execution address + * (RamFunction) + } RW_m_ncache m_ncache_start m_ncache_size { ; ncache RW data * (NonCacheable.init) * (NonCacheable) diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_GCC_ARM/MIMXRT1052xxxxx.ld b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_GCC_ARM/MIMXRT1052xxxxx.ld index d39ceb05e1..6cd4cd0bce 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_GCC_ARM/MIMXRT1052xxxxx.ld +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_GCC_ARM/MIMXRT1052xxxxx.ld @@ -72,6 +72,7 @@ MEMORY m_ivt (RX) : ORIGIN = 0x60001000, LENGTH = 0x00001000 m_interrupts (RX) : ORIGIN = 0x60002000, LENGTH = 0x00000400 m_text (RX) : ORIGIN = 0x60002400, LENGTH = 0x03FFDC00 + m_text2 (RX) : ORIGIN = 0x00000000, LENGTH = 0x00020000 m_data (RW) : ORIGIN = 0x80000000, LENGTH = 0x01E00000 m_ncache (RW) : ORIGIN = 0x81E00000, LENGTH = 0x00200000 m_data2 (RW) : ORIGIN = 0x20000000, LENGTH = 0x00020000 @@ -225,7 +226,21 @@ SECTIONS __data_end__ = .; /* define a global symbol at data end */ } > m_data - __NDATA_ROM = __DATA_ROM + (__data_end__ - __data_start__); + __ram_function_flash_start = __DATA_ROM + (__data_end__ - __data_start__); /* Symbol is used by startup for TCM data initialization */ + + .ram_function : AT(__ram_function_flash_start) + { + . = ALIGN(32); + __ram_function_ram_start = .; + *(RamFunction) + . = ALIGN(128); + __ram_function_ram_end = .; + } > m_text2 + + __ram_function_size = SIZEOF(.ram_function); + + __NDATA_ROM = __ram_function_flash_start + SIZEOF(.ram_function); + .ncache.init : AT(__NDATA_ROM) { __noncachedata_start__ = .; /* create a global symbol at ncache data start */ diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_IAR/MIMXRT1052xxxxx.icf b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_IAR/MIMXRT1052xxxxx.icf index 7bc7fe409c..f96e9c40ce 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_IAR/MIMXRT1052xxxxx.icf +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/device/TOOLCHAIN_IAR/MIMXRT1052xxxxx.icf @@ -67,6 +67,9 @@ define symbol m_interrupts_end = 0x600023FF; define symbol m_text_start = 0x60002400; define symbol m_text_end = 0x63FFFFFF; +define symbol m_text2_start = 0x00000000; +define symbol m_text2_end = 0x0001FFFF; + define symbol m_interrupts_ram_start = 0x20000000; define symbol m_interrupts_ram_end = 0x20000000 + __ram_vector_table_offset__; @@ -108,6 +111,8 @@ define memory mem with size = 4G; define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end] | mem:[from m_text_start to m_text_end]; +define region TEXT2_region = mem:[from m_text2_start to m_text2_end]; + define region DATA_region = mem:[from m_data_start to m_data_end]; define region DATA2_region = mem:[from m_data2_start to m_data2_end]; define region DATA3_region = mem:[from m_data3_start to m_data3_end-__size_cstack__]; @@ -139,4 +144,5 @@ place in DATA3_region { block ZI }; place in DATA3_region { last block HEAP }; place in CSTACK_region { block CSTACK }; place in NCACHE_region { block NCACHE_VAR }; +place in TEXT2_region { section .textrw}; place in m_interrupts_ram_region { section m_interrupts_ram }; diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/drivers/fsl_common.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/drivers/fsl_common.h index a53dbc2713..28d5df5b58 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/drivers/fsl_common.h +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/drivers/fsl_common.h @@ -3,7 +3,7 @@ * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. * Copyright 2016-2017 NXP * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, * are permitted (subject to the limitations in the disclaimer below) provided * that the following conditions are met: @@ -149,7 +149,7 @@ enum _status_groups kStatusGroup_LPC_MINISPI = 76, /*!< Group number for LPC_MINISPI status codes. */ kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */ kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */ - kStatusGroup_SEMC = 100, /*!< Group number for SEMC status codes. */ + kStatusGroup_SEMC = 100, /*!< Group number for SEMC status codes. */ kStatusGroup_ApplicationRangeStart = 101, /*!< Starting number for application groups. */ }; @@ -347,35 +347,6 @@ _Pragma("diag_suppress=Pm120") /* @} */ /*! @name Time sensitive region */ -/* @{ */ -#if defined(FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE) && FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE -#if (defined(__ICCARM__)) -#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess" -#define AT_QUICKACCESS_SECTION_DATA(func) func @"DataQuickAccess" -#elif(defined(__ARMCC_VERSION)) -#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"))) func -#define AT_QUICKACCESS_SECTION_DATA(func) __attribute__((section("DataQuickAccess"))) func -#elif(defined(__GNUC__)) -#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"))) func -#define AT_QUICKACCESS_SECTION_DATA(func) __attribute__((section("DataQuickAccess"))) func -#else -#error Toolchain not supported. -#endif /* defined(__ICCARM__) */ -#else -#if (defined(__ICCARM__)) -#define AT_QUICKACCESS_SECTION_CODE(func) func -#define AT_QUICKACCESS_SECTION_DATA(func) func -#elif(defined(__ARMCC_VERSION)) -#define AT_QUICKACCESS_SECTION_CODE(func) func -#define AT_QUICKACCESS_SECTION_DATA(func) func -#elif(defined(__GNUC__)) -#define AT_QUICKACCESS_SECTION_CODE(func) func -#define AT_QUICKACCESS_SECTION_DATA(func) func -#else -#error Toolchain not supported. -#endif -#endif /* __FSL_SDK_DRIVER_QUICK_ACCESS_ENABLE */ -/* @} */ /******************************************************************************* * API @@ -557,15 +528,15 @@ _Pragma("diag_suppress=Pm120") * @param size The length required to malloc. * @param alignbytes The alignment size. * @retval The allocated memory. - */ + */ void *SDK_Malloc(size_t size, size_t alignbytes); - + /*! * @brief Free memory. * * @param ptr The memory to be release. - */ - void SDK_Free(void *ptr); + */ + void SDK_Free(void *ptr); #if defined(__cplusplus) } From 74c96b6359b1aa4189c263920965932a22a94cac Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 6 Aug 2018 11:49:59 -0500 Subject: [PATCH 3/4] MXRT1050_EVK: Sleep: add pre/post processing steps Signed-off-by: Mahesh Mahadevan --- .../TARGET_MCUXpresso_MCUS/TARGET_IMX/sleep.c | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/sleep.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/sleep.c index 2b5307a99d..59f01d78a4 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/sleep.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/sleep.c @@ -17,23 +17,29 @@ #include "cmsis.h" #include "fsl_clock.h" -static void stop(void) -{ - SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; - __asm("WFI"); -} +extern void vPortPRE_SLEEP_PROCESSING(clock_mode_t powermode); +extern void vPortPOST_SLEEP_PROCESSING(clock_mode_t powermode); + void hal_sleep(void) { - CLOCK_SetMode(kCLOCK_ModeWait); + vPortPRE_SLEEP_PROCESSING(kCLOCK_ModeWait); - stop(); + __DSB(); + __WFI(); + __ISB(); + + vPortPOST_SLEEP_PROCESSING(kCLOCK_ModeWait); } void hal_deepsleep(void) { - CLOCK_SetMode(kCLOCK_ModeStop); + vPortPRE_SLEEP_PROCESSING(kCLOCK_ModeStop); - stop(); + __DSB(); + __WFI(); + __ISB(); + + vPortPOST_SLEEP_PROCESSING(kCLOCK_ModeStop); } From 9cf2b76db959484a02dd48802511a7f996a07983 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 6 Aug 2018 11:51:18 -0500 Subject: [PATCH 4/4] MXRT1050_EVK: Enable Sleep function and add SKIP_SYSCLK_INIT macro SKIP_SYSCLK_INIT prevents reinitializing the SYS_CLK PLL used by SDRAM. This PLL is setup during bootup by the ROM code. Signed-off-by: Mahesh Mahadevan --- targets/targets.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/targets.json b/targets/targets.json index 6982cbbab9..bb2e679fba 100755 --- a/targets/targets.json +++ b/targets/targets.json @@ -749,10 +749,10 @@ "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "extra_labels": ["NXP", "MCUXpresso_MCUS", "EVK", "MIMXRT1050", "IMX"], "is_disk_virtual": true, - "macros": ["CPU_MIMXRT1052DVL6B", "FSL_RTOS_MBED", "XIP_BOOT_HEADER_ENABLE=1", "XIP_EXTERNAL_FLASH=1", "XIP_BOOT_HEADER_DCD_ENABLE=1"], + "macros": ["CPU_MIMXRT1052DVL6B", "FSL_RTOS_MBED", "XIP_BOOT_HEADER_ENABLE=1", "XIP_EXTERNAL_FLASH=1", "XIP_BOOT_HEADER_DCD_ENABLE=1", "SKIP_SYSCLK_INIT"], "inherits": ["Target"], "detect_code": ["0227"], - "device_has": ["USTICKER", "LPTICKER", "ANALOGIN", "I2C", "I2CSLAVE", "ERROR_RED", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["SLEEP", "USTICKER", "LPTICKER", "ANALOGIN", "I2C", "I2CSLAVE", "ERROR_RED", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "release_versions": ["2", "5"], "device_name": "MIMXRT1052" },