~aleteoryx/muditaos

ref: 958ce4906c5386ad8aaa0e7e72697be7388ca9ef muditaos/module-bsp/board/rt1051/bsp/pwr/lpm.h -rw-r--r-- 10.7 KiB
958ce490 — Marcin Smoczyński [BH-897] Split module-sys 4 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/*
 * Copyright 2017 NXP
 * All rights reserved.
 *
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef _LPM_H_
#define _LPM_H_

#include "fsl_common.h"
#include "fsl_clock.h"
#include "fsl_device_registers.h"
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#ifndef FSL_RTOS_FREE_RTOS
#define FSL_RTOS_FREE_RTOS
#endif

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)

#if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1)
#define LPM_EnterCritical()                                                                                            \
                                                                                                                       \
    do {                                                                                                               \
        __disable_irq();                                                                                               \
        SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;                                                                     \
                                                                                                                       \
    } while (0)

#define LPM_ExitCritical()                                                                                             \
                                                                                                                       \
    do {                                                                                                               \
        __enable_irq();                                                                                                \
        SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;                                                                      \
                                                                                                                       \
    } while (0)

#else
#define LPM_EnterCritical()
#define LPM_ExitCritical()
#endif

/* Power mode definition of low power management.
 * Waken up duration Off > Dsm > Idle > Wait > Run.
 */
typedef enum _lpm_power_mode
{
    LPM_PowerModeOverRun = 0, /* Over RUN mode, CPU won't stop running */

    LPM_PowerModeFullRun, /* Full RUN mode, CPU won't stop running */

    LPM_PowerModeLowSpeedRun,

    LPM_PowerModeLowPowerRun,

    LPM_PowerModeRunEnd = LPM_PowerModeLowPowerRun,
    /* In system wait mode, cpu clock is gated.
     * All peripheral can remain active, clock gating decided by CCGR setting.
     * DRAM enters auto-refresh mode when there is no access.
     */
    LPM_PowerModeSysIdle, /* System WAIT mode, also system low speed idle */

    /* In low power idle mode, all PLL/PFD is off, cpu power is off.
     * Analog modules running in low power mode.
     * All high-speed peripherals are power gated
     * Low speed peripherals can remain running at low frequency
     * DRAM in self-refresh.
     */
    LPM_PowerModeLPIdle, /* Low Power Idle mode */

    /* In deep sleep mode, all PLL/PFD is off, XTAL is off, cpu power is off.
     * All clocks are shut off except 32K RTC clock
     * All high-speed peripherals are power gated
     * Low speed peripherals are clock gated
     * DRAM in self-refresh.
     * If RTOS is used, systick will be disabled in DSM
     */
    LPM_PowerModeSuspend, /* Deep Sleep mode, suspend. */

    LPM_PowerModeSNVS, /* Power off mode, or shutdown mode */

    LPM_PowerModeEnd = LPM_PowerModeSNVS
} lpm_power_mode_t;

typedef bool (*lpm_power_mode_callback_t)(lpm_power_mode_t curMode, lpm_power_mode_t newMode, void *data);

/*! @name Time sensitive region */
/* @{ */
#if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1)
#if (defined(__ICCARM__))
#define QUICKACCESS_SECTION_CODE(func) __ramfunc func
#elif (defined(__ARMCC_VERSION))
#define QUICKACCESS_SECTION_CODE(func) __attribute__((section("RamFunction"))) func
#elif defined(__MCUXPRESSO)
#define QUICKACCESS_SECTION_CODE(func) __attribute__((section(".ramfunc.$SRAM_ITC"))) func
#elif (defined(__GNUC__))
#define QUICKACCESS_SECTION_CODE(func) __attribute__((section("RamFunction"))) func
#else
#error Toolchain not supported.
#endif /* defined(__ICCARM__) */
#else
#if (defined(__ICCARM__))
#define QUICKACCESS_SECTION_CODE(func) func
#elif (defined(__ARMCC_VERSION))
#define QUICKACCESS_SECTION_CODE(func) func
#elif (defined(__MCUXPRESSO))
#define QUICKACCESS_SECTION_CODE(func) func
#elif (defined(__GNUC__))
#define 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*/

    QUICKACCESS_SECTION_CODE(void LPM_SwitchBandgap(void));
    QUICKACCESS_SECTION_CODE(void LPM_RestoreBandgap(void));
    QUICKACCESS_SECTION_CODE(void LPM_SwitchToXtalOSC(void));
    QUICKACCESS_SECTION_CODE(void LPM_SwitchToRcOSC(void));
    QUICKACCESS_SECTION_CODE(void LPM_SwitchFlexspiClock(lpm_power_mode_t power_mode));
    QUICKACCESS_SECTION_CODE(void LPM_RestoreFlexspiClock(void));

    /* Initialize the Low Power Management */
    bool LPM_Init(lpm_power_mode_t run_mode);

    /* 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);

    /* Set power mode, all registered listeners will be notified.
     * Return true if all the registered listeners return true.
     */
    bool LPM_SetPowerMode(lpm_power_mode_t mode);

    /* LPM_SetPowerMode() won't switch system power status immediately,
     * instead, such operation is done by LPM_WaitForInterrupt().
     * It can be callled in idle task of FreeRTOS, or main loop in bare
     * metal application. The sleep depth of this API depends
     * on current power mode set by LPM_SetPowerMode().
     * The timeoutMilliSec means if no interrupt occurs before timeout, the
     * system will be waken up by systick. If timeout exceeds hardware timer
     * limitation, timeout will be reduced to maximum time of hardware.
     * timeoutMilliSec only works in FreeRTOS, in bare metal application,
     * it's just ignored.
     */
    void LPM_WaitForInterrupt(uint32_t timeoutMilliSec);

#ifdef FSL_RTOS_FREE_RTOS
    /* Register power mode switch listener. When LPM_SetPowerMode()
     * is called, all the registered listeners will be invoked. The
     * listener returns true if it allows the power mode switch,
     * otherwise returns FALSE.
     */
    void LPM_RegisterPowerListener(lpm_power_mode_callback_t callback, void *data);

    /* Unregister power mode switch listener */
    void LPM_UnregisterPowerListener(lpm_power_mode_callback_t callback, void *data);

    void LPM_SystemRestoreDsm(void);
    void LPM_SystemRestoreIdle(void);
    void LPM_SystemResumeDsm(void);

    void LPM_RestorePLLs(lpm_power_mode_t power_mode);
    void LPM_DisablePLLs(lpm_power_mode_t power_mode);

    void LPM_SystemFullRun(void);
    void LPM_SystemOverRun(void);
    void LPM_SystemLowSpeedRun(void);
    void LPM_SystemLowPowerRun(void);

#endif

    void APP_PowerPostSwitchHook(lpm_power_mode_t targetMode);

    void APP_SetLPMPowerMode(lpm_power_mode_t mode);

#if defined(__cplusplus)
}
#endif /* __cplusplus*/

#endif /* _LPM_H_ */