@@ -50,6 +50,7 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
50
50
// TODO: make a custom enum to avoid weird values like PM_SLEEPCFG_SLEEPMODE_BACKUP_Val?
51
51
STATIC volatile uint32_t _target ;
52
52
STATIC bool fake_sleep ;
53
+ STATIC bool pin_wake ;
53
54
54
55
void alarm_reset (void ) {
55
56
// Reset the alarm flag
@@ -67,9 +68,9 @@ samd_sleep_source_t alarm_get_wakeup_cause(void) {
67
68
return SAMD_WAKEUP_RTC ;
68
69
}
69
70
if (!fake_sleep && RSTC -> RCAUSE .bit .BACKUP ) {
70
- // not able to detect PinAlarm wake since registers are getting reset
71
- // TODO: come up with a way to detect a TAMPER
72
- if ( RTC -> MODE0 . TAMPID . reg || RTC -> MODE0 . INTFLAG . bit . TAMPER ) {
71
+ // This is checked during rtc_init to cache TAMPID if necessary
72
+ if ( pin_wake || RTC -> MODE0 . TAMPID . reg ) {
73
+ pin_wake = true;
73
74
return SAMD_WAKEUP_GPIO ;
74
75
}
75
76
return SAMD_WAKEUP_RTC ;
@@ -132,12 +133,6 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
132
133
shared_alarm_save_wake_alarm (wake_alarm );
133
134
break ;
134
135
}
135
- // TODO: the SAMD implementation of this (purportedly) disables interrupts
136
- // Presumably this doesn't impact the RTC interrupts, somehow, or it would never wake up?
137
- // Will it prevent an external interrupt from waking?
138
- // port_idle_until_interrupt();
139
- // Alternative would be `sleep(PM_SLEEPCFG_SLEEPMODE_IDLE2_Val)`, I think?
140
-
141
136
// ATTEMPT ------------------------------
142
137
// This works but achieves same power consumption as time.sleep()
143
138
@@ -161,8 +156,6 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
161
156
__WFI (); // Wait For Interrupt
162
157
// Enable RTC interrupts
163
158
NVIC_EnableIRQ (RTC_IRQn );
164
-
165
-
166
159
// END ATTEMPT ------------------------------
167
160
}
168
161
if (mp_hal_is_interrupted ()) {
@@ -183,75 +176,55 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
183
176
_target = RTC -> MODE0 .COMP [1 ].reg ;
184
177
port_disable_tick (); // TODO: Required for SAMD?
185
178
186
- // Set a flag in the backup registers to indicate sleep wakeup
187
- SAMD_ALARM_FLAG = 0x01 ;
179
+ // cache alarm flag since backup registers about to be reset
180
+ uint32_t _SAMD_ALARM_FLAG = SAMD_ALARM_FLAG ;
188
181
189
182
// Clear the FPU interrupt because it can prevent us from sleeping.
190
183
if (__get_FPSCR () & ~(0x9f )) {
191
184
__set_FPSCR (__get_FPSCR () & ~(0x9f ));
192
185
(void )__get_FPSCR ();
193
186
}
194
187
195
- // TODO: Be able to set PinAlarm and TimeAlarm together
196
- // PinAlarm (hacky way of checking if time alarm or pin alarm)
197
- if (RTC -> MODE0 .INTENSET .bit .TAMPER ) {
198
- // Disable interrupts
199
- NVIC_DisableIRQ (RTC_IRQn );
200
- // Must disable the RTC before writing to EVCTRL and TMPCTRL
201
- RTC -> MODE0 .CTRLA .bit .ENABLE = 0 ; // Disable the RTC
202
- while (RTC -> MODE0 .SYNCBUSY .bit .ENABLE ) { // Wait for synchronization
203
- ;
204
- }
205
- RTC -> MODE0 .CTRLA .bit .SWRST = 1 ; // Software reset the RTC
206
- while (RTC -> MODE0 .SYNCBUSY .bit .SWRST ) { // Wait for synchronization
188
+ NVIC_DisableIRQ (RTC_IRQn );
189
+ // Must disable the RTC before writing to EVCTRL and TMPCTRL
190
+ RTC -> MODE0 .CTRLA .bit .ENABLE = 0 ; // Disable the RTC
191
+ while (RTC -> MODE0 .SYNCBUSY .bit .ENABLE ) { // Wait for synchronization
192
+ ;
193
+ }
194
+ RTC -> MODE0 .CTRLA .bit .SWRST = 1 ; // Software reset the RTC
195
+ while (RTC -> MODE0 .SYNCBUSY .bit .SWRST ) { // Wait for synchronization
196
+ ;
197
+ }
198
+ RTC -> MODE0 .CTRLA .reg = RTC_MODE0_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024
199
+ RTC_MODE0_CTRLA_MODE_COUNT32 ; // Set RTC to mode 0, 32-bit timer
200
+
201
+ // Check if we're setting TimeAlarm
202
+ if (_SAMD_ALARM_FLAG & SAMD_ALARM_FLAG_TIME ) {
203
+ RTC -> MODE0 .COMP [1 ].reg = (_target / 1024 ) * 32 ;
204
+ while (RTC -> MODE0 .SYNCBUSY .reg ) {
207
205
;
208
206
}
209
- RTC -> MODE0 .CTRLA .reg = RTC_MODE0_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024
210
- RTC_MODE0_CTRLA_MODE_COUNT32 ; // Set RTC to mode 0, 32-bit timer
211
-
212
- // TODO: map requested pin to limited selection of TAMPER pins
207
+ }
208
+ // Check if we're setting PinAlarm
209
+ if (_SAMD_ALARM_FLAG & SAMD_ALARM_FLAG_PIN ) {
213
210
RTC -> MODE0 .TAMPCTRL .bit .DEBNC2 = 1 ; // Edge triggered when INn is stable for 4 CLK_RTC_DEB periods
214
211
RTC -> MODE0 .TAMPCTRL .bit .TAMLVL2 = 1 ; // rising edge
215
212
// PA02 = IN2
216
213
RTC -> MODE0 .TAMPCTRL .bit .IN2ACT = 1 ; // WAKE on IN2 (doesn't save timestamp)
217
-
218
- // Enable interrupts
219
- NVIC_SetPriority (RTC_IRQn , 0 );
220
- NVIC_EnableIRQ (RTC_IRQn );
221
- // Set interrupts for TAMPER or overflow
214
+ }
215
+ // Enable interrupts
216
+ NVIC_SetPriority (RTC_IRQn , 0 );
217
+ NVIC_EnableIRQ (RTC_IRQn );
218
+ if (_SAMD_ALARM_FLAG & SAMD_ALARM_FLAG_TIME ) {
219
+ // Set interrupts for COMPARE1
220
+ RTC -> MODE0 .INTENSET .reg = RTC_MODE0_INTENSET_CMP1 ;
221
+ }
222
+ if (_SAMD_ALARM_FLAG & SAMD_ALARM_FLAG_PIN ) {
223
+ // Set interrupts for TAMPER pins
222
224
RTC -> MODE0 .INTENSET .reg = RTC_MODE0_INTENSET_TAMPER ;
223
- } else {
224
- // TimeAlarm
225
- // Retrieve COMP1 value before resetting RTC
226
- NVIC_DisableIRQ (RTC_IRQn );
227
-
228
- // Must disable the RTC before writing to EVCTRL and TMPCTRL
229
- RTC -> MODE0 .CTRLA .bit .ENABLE = 0 ; // Disable the RTC
230
- while (RTC -> MODE0 .SYNCBUSY .bit .ENABLE ) { // Wait for synchronization
231
- ;
232
- }
233
-
234
- RTC -> MODE0 .CTRLA .bit .SWRST = 1 ; // Software reset the RTC
235
- while (RTC -> MODE0 .SYNCBUSY .bit .SWRST ) { // Wait for synchronization
236
- ;
237
- }
238
-
239
- RTC -> MODE0 .CTRLA .reg = RTC_MODE0_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024
240
- RTC_MODE0_CTRLA_MODE_COUNT32 ; // Set RTC to mode 0, 32-bit timer
241
-
242
- RTC -> MODE0 .COMP [1 ].reg = (_target / 1024 ) * 32 ;
243
- while (RTC -> MODE0 .SYNCBUSY .reg ) {
244
- ;
245
- }
246
-
247
- // Enable interrupts
248
- NVIC_SetPriority (RTC_IRQn , 0 );
249
- NVIC_EnableIRQ (RTC_IRQn );
250
- // Set interrupts for COMPARE1 or overflow
251
- RTC -> MODE0 .INTENSET .reg = RTC_MODE0_INTENSET_CMP1 | RTC_MODE1_INTENSET_OVF ;
252
225
}
253
- // Set-up Deep Sleep Mode
254
- // RAM retention
226
+
227
+ // Set-up Deep Sleep Mode & RAM retention
255
228
PM -> BKUPCFG .reg = PM_BKUPCFG_BRAMCFG (0x2 ); // No RAM retention 0x2 partial:0x1
256
229
while (PM -> BKUPCFG .bit .BRAMCFG != 0x2 ) { // Wait for synchronization
257
230
;
@@ -260,7 +233,6 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
260
233
while (PM -> SLEEPCFG .bit .SLEEPMODE != PM_SLEEPCFG_SLEEPMODE_BACKUP_Val ) {
261
234
;
262
235
}
263
-
264
236
RTC -> MODE0 .CTRLA .bit .ENABLE = 1 ; // Enable the RTC
265
237
while (RTC -> MODE0 .SYNCBUSY .bit .ENABLE ) { // Wait for synchronization
266
238
;
@@ -282,10 +254,6 @@ void common_hal_alarm_pretending_deep_sleep(void) {
282
254
// to generate external interrupts again. See STM32 for reference.
283
255
284
256
if (!fake_sleep ) {
285
- SAMD_ALARM_FLAG = 1 ;
286
- while (RTC -> MODE0 .SYNCBUSY .reg ) {
287
- ;
288
- }
289
257
fake_sleep = true;
290
258
}
291
259
}
0 commit comments