mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #7419 from codeauroraforum/Add_MXRT_Sleep_Support
MIMXRT1050EVK: Fix Sleep supportpull/7734/head
commit
d360da9d1d
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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_ */
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue