📄 hal_sleep.lst
字号:
54 * Sleep mode H/W definitions (enabled with POWER_SAVING compile option)
55 */
56 #define CC2430_PM0 0 /* PM0, Clock oscillators on, voltage regulator on */
57 #define CC2430_PM1 1 /* PM1, 32.768 kHz oscillators on, voltage regulator on */
58 #define CC2430_PM2 2 /* PM2, 32.768 kHz oscillators on, voltage regulator off */
59 #define CC2430_PM3 3 /* PM3, All clock oscillators off, voltage regulator off */
60
61 /* HAL power management mode is set according to the power management state. The default
62 * setting is HAL_SLEEP_OFF. The actual value is tailored to different HW platform. Both
63 * HAL_SLEEP_TIMER and HAL_SLEEP_DEEP selections will:
64 * 1. turn off the system clock, and
65 * 2. halt the MCU.
66 * HAL_SLEEP_TIMER can be woken up by sleep timer interrupt, I/O interrupt and reset.
67 * HAL_SLEEP_DEEP can be woken up by I/O interrupt and reset.
68 */
69 #define HAL_SLEEP_OFF CC2430_PM0
70 #define HAL_SLEEP_TIMER CC2430_PM2
71 #define HAL_SLEEP_DEEP CC2430_PM3
72
73 /* MAX_SLEEP_TIME calculation:
74 * Sleep timer maximum duration = 0xFFFF7F / 32768 Hz = 511.996 seconds
75 * Round it to 510 seconds or 510000 ms
76 */
77 #define MAX_SLEEP_TIME 510000 /* maximum time to sleep allowed by ST */
78
79 /* minimum time to sleep, this macro is to:
80 * 1. avoid thrashing in-and-out of sleep with short OSAL timer (~2ms)
81 * 2. define minimum safe sleep period for different CC2430 revisions
82 * AN044 - MINIMUM SLEEP PERIODS WITH PULL-DOWN RESISTOR
83 */
84 #if !defined (PM_MIN_SLEEP_TIME)
85 #define PM_MIN_SLEEP_TIME 14 /* default to minimum safe sleep time for CC2430 Rev B */
86 #endif
87
88 /* to disallow PM2/PM3 and use PM1 only set this value to false
89 * AN044 - RESTRICT_USE_TO_PM1_ONLY
90 */
91 #if !defined (PM1_ONLY)
92 #define PM1_ONLY FALSE /* default to no AN044 - RESTRICT USE TO PM1 ONLY */
93 #endif
94
95 /* when a device is waken up be key interrupt, it
96 * should stay in PM1 for PM2_HOLDOFF_TIME expecting
97 * more key presses. When the timer is expired, the device
98 * is allowed to go back to PM2 sleep.
99 * AN044 - COMBINING POWER MODES
100 */
101 #if !defined (PM2_HOLDOFF_TIME)
102 #define PM2_HOLDOFF_TIME 0
103 #endif
104
105 /* Add code to set external interrupt line to output, drive the line to inactive level,
106 * delay for 180us (30us if P1.0 or P1.1), set the line to input as close to PCON.IDLE = 1
107 * as possible, and set the line tri-state. The following macro is using S1 key as an example.
108 * User should tailor this macro for different interrupt line(s). On CC2430EB or CC2430DB boards,
109 * the S1 key is mapped to P0.1. Thus 180us should be used for delays.
110 * AN044 - DELAYING EXTERNAL INTERRUPTS
111 */
112 #define EXTERNAL_INTERRUPT_DELAY() st(P0DIR |= BV(1); /* set P0.1 output */ \
113 P0_1 = 1; /* drive P0.1 inactive (high) */ \
114 halSleepWait(180); /* delay 180us */ \
115 P0DIR &= ~BV(1); /* set P0.1 input */ \
116 P0INP |= BV(1);) /* set P0.1 tri-state */
117
118 /* This value is used to adjust the sleep timer compare value such that the sleep timer
119 * compare takes into account the amount of processing time spent in function halSleep().
120 * The first value is determined by measuring the number of sleep timer ticks it from
121 * the beginning of the function to entering sleep mode. The second value is determined
122 * by measuring the number of sleep timer ticks from exit of sleep mode to the call to
123 * osal_adjust_timers().
124 */
125 #define HAL_SLEEP_ADJ_TICKS (9 + 25)
126
127 #ifndef HAL_SLEEP_DEBUG_POWER_MODE
128 /* set CC2430 power mode; always use PM2 */
129 #define HAL_SLEEP_SET_POWER_MODE(mode) st( if( CHVER <= REV_D ) \
130 { \
131 HAL_SLEEP_SET_POWER_MODE_REV_D(mode); \
132 } \
133 else \
134 { \
135 HAL_SLEEP_SET_POWER_MODE_REV_E(mode); \
136 }; )
137 #else
138 /* Debug: don't set power mode, just block until sleep timer interrupt */
139 #define HAL_SLEEP_SET_POWER_MODE(mode) st( while(halSleepInt == FALSE); \
140 halSleepInt = FALSE; )
141 #endif
142
143 /* for revision E, this sw workaround require additional code in all
144 * ISR's that are used to wake up from PM.
145 */
146 #define HAL_SLEEP_SET_POWER_MODE_REV_E(mode) st( SLEEP &= ~0x03; /* clear mode bits */ \
147 SLEEP |= mode; /* set mode bits */ \
148 asm("NOP"); \
149 asm("NOP"); \
150 asm("NOP"); \
151 if( SLEEP & 0x03 ) \
152 { \
153 PCON |= 0x01; /* enable mode */ \
154 asm("NOP"); /* first instruction after sleep*/ \
155 }; )
156
157 /* for revision D and earlier */
158 #define HAL_SLEEP_SET_POWER_MODE_REV_D(mode) st(SLEEP &= ~0x03; /* clear mode bits */ \
159 SLEEP |= mode; /* set mode bits */ \
160 PCON |= 0x01; /* enable mode */ \
161 asm("NOP");) /* first instruction after sleep*/
162
163 /* set main clock source to crystal (exit sleep) */
164 #define HAL_SLEEP_SET_MAIN_CLOCK_CRYSTAL() st(SLEEP &= ~0x04; /* turn on both oscs */ \
165 while(!(SLEEP & 0x40)); /* wait for XOSC */ \
166 asm("NOP"); \
167 halSleepWait(63); /* required for Rev B */\
168 CLKCON = (0x00 | OSC_32KHZ); /* 32MHx XOSC */ \
169 while (CLKCON != (0x00 | OSC_32KHZ)); \
170 SLEEP |= 0x04;) /* turn off 16MHz RC */
171
172 /* set main clock source to RC oscillator (enter sleep) */
173 #define HAL_SLEEP_SET_MAIN_CLOCK_RC() st(SLEEP &= ~0x04; /* turn on both oscs */ \
174 while(!(SLEEP & 0x20)); /* wait for RC osc */ \
175 asm("NOP"); \
176 CLKCON = (0x49 | OSC_32KHZ); /* select RC osc */ \
177 /* wait for requested settings to take effect */ \
178 while (CLKCON != (0x49 | OSC_32KHZ)); \
179 SLEEP |= 0x04;) /* turn off XOSC */
180
181 /* sleep and external interrupt port masks */
182 #define STIE_BV BV(5)
183 #define P0IE_BV BV(5)
184 #define P1IE_BV BV(4)
185 #define P2IE_BV BV(1)
186
187 /* sleep timer interrupt control */
188 #define HAL_SLEEP_TIMER_ENABLE_INT() st(IEN0 |= STIE_BV;) /* enable sleep timer interrupt */
189 #define HAL_SLEEP_TIMER_DISABLE_INT() st(IEN0 &= ~STIE_BV;) /* disable sleep timer interrupt */
190 #define HAL_SLEEP_TIMER_CLEAR_INT() st(IRCON &= ~0x80;) /* clear sleep interrupt flag */
191
192 /* backup interrupt enable registers before sleep */
193 #define HAL_SLEEP_IE_BACKUP_AND_DISABLE(ien0, ien1, ien2) st(ien0 = IEN0; /* backup IEN0 register */ \
194 ien1 = IEN1; /* backup IEN1 register */ \
195 ien2 = IEN2; /* backup IEN2 register */ \
196 IEN0 &= STIE_BV; /* disable IEN0 except STIE */ \
197 IEN1 &= P0IE_BV; /* disable IEN1 except P0IE */ \
198 IEN2 &= (P1IE_BV|P2IE_BV);) /* disable IEN2 except P1IE, P2IE */
199
200 /* restore interrupt enable registers before sleep */
201 #define HAL_SLEEP_IE_RESTORE(ien0, ien1, ien2) st(IEN0 = ien0; /* restore IEN0 register */ \
202 IEN1 = ien1; /* restore IEN1 register */ \
203 IEN2 = ien2;) /* restore IEN2 register */
204
205 /* Internal (MCU) Stack addresses. This is to check if the stack is exceeding the disappearing
206 * RAM boundary of 0xF000. If the stack does exceed the boundary (unlikely), do not enter sleep
207 * until the stack is back to normal.
208 */
209 #define CSTK_PTR _Pragma("segment=\"XSP\"") __segment_begin("XSP")
210
211 /* convert msec to 320 usec units with round */
212 #define HAL_SLEEP_MS_TO_320US(ms) (((((uint32) (ms)) * 100) + 31) / 32)
213
214 /* for optimized indexing of uint32's */
215 #if HAL_MCU_LITTLE_ENDIAN()
216 #define UINT32_NDX0 0
217 #define UINT32_NDX1 1
218 #define UINT32_NDX2 2
219 #define UINT32_NDX3 3
220 #else
221 #define UINT32_NDX0 3
222 #define UINT32_NDX1 2
223 #define UINT32_NDX2 1
224 #define UINT32_NDX3 0
225 #endif
226
227 /* ------------------------------------------------------------------------------------------------
228 * Local Variables
229 * ------------------------------------------------------------------------------------------------
230 */
231
232 /* HAL power management mode is set according to the power management state.
233 */
\ In segment XDATA_Z, align 1, keep-with-next
\ 000000 REQUIRE __INIT_XDATA_Z
234 static uint8 halPwrMgtMode = HAL_SLEEP_OFF;
\ ??halPwrMgtMode:
\ 000000 DS 1
235
236 /* stores the sleep timer count upon entering sleep */
\ In segment XDATA_Z, align 1, keep-with-next
\ 000000 REQUIRE __INIT_XDATA_Z
237 static uint32 halSleepTimerStart;
\ ??halSleepTimerStart:
\ 000000 DS 4
238
239 /* stores the accumulated sleep time */
\ In segment XDATA_Z, align 1, keep-with-next
\ 000000 REQUIRE __INIT_XDATA_Z
240 static uint32 halAccumulatedSleepTime;
\ ??halAccumulatedSleepTime:
\ 000000 DS 4
241
242 /* stores the deepest level the device is allowed to sleep
243 * See AN044 - COMBINING POWER MODES
244 */
\ In segment XDATA_I, align 1, keep-with-next
245 static uint8 halSleepLevel = CC2430_PM2;
\ ??halSleepLevel:
\ 000000 DS 1
\ 000001 REQUIRE `?<Initializer for halSleepLevel>`
\ 000001 REQUIRE __INIT_XDATA_I
246
247 #ifdef HAL_SLEEP_DEBUG_POWER_MODE
248 static bool halSleepInt = FALSE;
249 #endif
250
251 /* ------------------------------------------------------------------------------------------------
252 * Function Prototypes
253 * ------------------------------------------------------------------------------------------------
254 */
255
256 void halSleepSetTimer(uint32 timeout);
257 uint32 HalTimerElapsed( void );
258
259 /**************************************************************************************************
260 * @fn halSleep
261 *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -