29
29
#include "py/objtuple.h"
30
30
#include "py/runtime.h"
31
31
#include "lib/utils/interrupt_char.h"
32
- #include <stdio.h>
32
+ // #include <stdio.h>
33
33
34
34
#include "shared-bindings/alarm/__init__.h"
35
35
#include "shared-bindings/alarm/SleepMemory.h"
@@ -47,8 +47,10 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
47
47
.type = & alarm_sleep_memory_type ,
48
48
},
49
49
};
50
- uint32_t target2 = 0 ;
51
50
// TODO: make a custom enum to avoid weird values like PM_SLEEPCFG_SLEEPMODE_BACKUP_Val?
51
+ STATIC volatile uint32_t _target ;
52
+ STATIC bool fake_sleep ;
53
+ STATIC bool pin_alarm = false;
52
54
53
55
void alarm_reset (void ) {
54
56
// Reset the alarm flag
@@ -58,24 +60,19 @@ void alarm_reset(void) {
58
60
}
59
61
60
62
samd_sleep_source_t alarm_get_wakeup_cause (void ) {
61
- // uint8_t reset_cause = RSTC->RCAUSE.reg;
62
- // printf("reset cause: %u\n",reset_cause);
63
- // printf("POR %u, BKUP %u, EXT %u, SYST %u\n",
64
- // reset_cause & RSTC_RCAUSE_POR,
65
- // reset_cause & RSTC_RCAUSE_BACKUP,
66
- // reset_cause & RSTC_RCAUSE_EXT,
67
- // reset_cause & RSTC_RCAUSE_SYST);
68
- // printf("RTC INTFLAG: %u\n",RTC->MODE0.INTFLAG.reg);
69
-
70
63
// If in light/fake sleep, check modules
71
64
if (alarm_pin_pinalarm_woke_this_cycle ()) {
72
65
return SAMD_WAKEUP_GPIO ;
73
66
}
74
67
if (alarm_time_timealarm_woke_this_cycle ()) {
75
68
return SAMD_WAKEUP_RTC ;
76
69
}
77
- // TODO: for deep sleep, manually determine how the chip woke up
78
- // TODO: try checking the interrupt flag tables for RTC TAMPER vs COMPARE
70
+ if (RSTC -> RCAUSE .bit .BACKUP ) {
71
+ if (RTC -> MODE0 .INTFLAG .bit .TAMPER ) {
72
+ return SAMD_WAKEUP_GPIO ;
73
+ }
74
+ return SAMD_WAKEUP_RTC ;
75
+ }
79
76
return SAMD_WAKEUP_UNDEF ;
80
77
}
81
78
@@ -105,7 +102,8 @@ mp_obj_t common_hal_alarm_create_wake_alarm(void) {
105
102
// Set up light sleep or deep sleep alarms.
106
103
STATIC void _setup_sleep_alarms (bool deep_sleep , size_t n_alarms , const mp_obj_t * alarms ) {
107
104
alarm_pin_pinalarm_set_alarms (deep_sleep , n_alarms , alarms );
108
- target2 = alarm_time_timealarm_set_alarms (deep_sleep , n_alarms , alarms );
105
+ alarm_time_timealarm_set_alarms (deep_sleep , n_alarms , alarms );
106
+ fake_sleep = false;
109
107
}
110
108
111
109
mp_obj_t common_hal_alarm_light_sleep_until_alarms (size_t n_alarms , const mp_obj_t * alarms ) {
@@ -178,7 +176,8 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala
178
176
179
177
void NORETURN common_hal_alarm_enter_deep_sleep (void ) {
180
178
alarm_pin_pinalarm_prepare_for_deep_sleep ();
181
- target2 = alarm_time_timealarm_prepare_for_deep_sleep ();
179
+ alarm_time_timealarm_prepare_for_deep_sleep ();
180
+ _target = RTC -> MODE0 .COMP [1 ].reg ;
182
181
port_disable_tick (); // TODO: Required for SAMD?
183
182
184
183
// Set a flag in the backup registers to indicate sleep wakeup
@@ -192,7 +191,7 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
192
191
193
192
// hacky way of checking if time alarm or pin alarm
194
193
// TODO: find better way of determining pin vs time
195
- if (target2 == 0 ) {
194
+ if (RTC -> MODE0 . INTENSET . bit . TAMPER ) {
196
195
// Disable interrupts
197
196
NVIC_DisableIRQ (RTC_IRQn );
198
197
@@ -206,6 +205,7 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
206
205
RTC -> MODE0 .CTRLA .reg = RTC_MODE0_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024
207
206
RTC_MODE0_CTRLA_MODE_COUNT32 ; // Set RTC to mode 0, 32-bit timer
208
207
208
+ // TODO: map requested pin to limited selection of TAMPER pins
209
209
//PA02 = IN2
210
210
RTC -> MODE0 .TAMPCTRL .bit .DEBNC2 = 1 ; // Edge triggered when INn is stable for 4 CLK_RTC_DEB periods
211
211
RTC -> MODE0 .TAMPCTRL .bit .TAMLVL2 = 1 ; // rising edge
@@ -216,8 +216,8 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
216
216
NVIC_EnableIRQ (RTC_IRQn );
217
217
// Set interrupts for TAMPER or overflow
218
218
RTC -> MODE0 .INTENSET .reg = RTC_MODE0_INTENSET_TAMPER ;
219
- }
220
- else {
219
+ } else {
220
+ // Retrieve COMP1 value before resetting RTC
221
221
// Disable interrupts
222
222
NVIC_DisableIRQ (RTC_IRQn );
223
223
@@ -231,16 +231,15 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
231
231
RTC -> MODE0 .CTRLA .reg = RTC_MODE0_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024
232
232
RTC_MODE0_CTRLA_MODE_COUNT32 ; // Set RTC to mode 0, 32-bit timer
233
233
234
- RTC -> MODE0 .COMP [1 ].reg = (target2 /1024 ) * 32 ;
234
+ RTC -> MODE0 .COMP [1 ].reg = (_target /1024 ) * 32 ;
235
235
while (RTC -> MODE0 .SYNCBUSY .reg );
236
236
237
237
// Enable interrupts
238
238
NVIC_SetPriority (RTC_IRQn , 0 );
239
239
NVIC_EnableIRQ (RTC_IRQn );
240
240
// Set interrupts for COMPARE1 or overflow
241
241
RTC -> MODE0 .INTENSET .reg = RTC_MODE0_INTENSET_CMP1 | RTC_MODE1_INTENSET_OVF ;
242
- }
243
-
242
+ }
244
243
// Set-up Deep Sleep Mode
245
244
// RAM retention
246
245
PM -> BKUPCFG .reg = PM_BKUPCFG_BRAMCFG (0x2 ); // No RAM retention 0x2 partial:0x1
@@ -260,36 +259,21 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
260
259
}
261
260
}
262
261
263
- void common_hal_alarm_pretending_deep_sleep (void ) {
262
+ MP_NOINLINE void common_hal_alarm_pretending_deep_sleep (void ) {
264
263
// TODO:
265
264
// If tamper detect interrupts cannot be used to wake from the Idle tier of sleep,
266
265
// This section will need to re-initialize the pins to allow the PORT peripheral
267
266
// to generate external interrupts again. See STM32 for reference.
268
267
269
- // COMP never fires... I don't know why
270
- if (RTC -> MODE0 .INTFLAG .bit .CMP1 || RTC -> MODE0 .INTFLAG .bit .CMP0 ){
271
- printf ("fake sleep finished (proper way)\n" );
272
- timer_callback ();
273
- RTC -> MODE0 .INTENCLR .reg = RTC_MODE0_INTENCLR_CMP1 ; // clear flag
274
- }
275
- else {
276
- // this works, but is a terrible way of checking
277
- if (port_get_raw_ticks (NULL ) > (RTC -> MODE0 .COMP [1 ].reg )) {
278
- timer_callback ();
279
- // printf("COUNT %lu\n",(uint32_t)port_get_raw_ticks(NULL));
280
- // printf("CTRLA %u\n",RTC->MODE0.CTRLA.reg);
281
- // printf("CTRLB %u\n",RTC->MODE0.CTRLB.reg);
282
- // printf("EVCTRL %lu\n",RTC->MODE0.EVCTRL.reg);
283
- // printf("INTENCLR %u\n",RTC->MODE0.INTENCLR.reg);
284
- // printf("INTENSET %u\n",RTC->MODE0.INTENSET.reg);
285
- // printf("INTFLAG %u\n",RTC->MODE0.INTFLAG.reg);
286
- // printf("SYNCBUSY %lu\n",RTC->MODE0.SYNCBUSY.reg);
287
- // printf("COMP0 %lu\n",RTC->MODE0.COMP[0].reg);
288
- // printf("COMP1 %lu\n",RTC->MODE0.COMP[1].reg);
289
-
290
- RTC -> MODE0 .INTENCLR .reg = RTC_MODE0_INTENCLR_CMP1 ; // clear flag
291
- printf ("fake sleep finished (manual way)\n" );
292
- }
268
+ if (!fake_sleep ) {
269
+ SAMD_ALARM_FLAG = 1 ;
270
+ while (RTC -> MODE0 .SYNCBUSY .reg );
271
+ fake_sleep = true;
272
+ // if () {
273
+ // pin_alarm=true;
274
+ // }
275
+ } else {
276
+ port_idle_until_interrupt ();
293
277
}
294
278
}
295
279
0 commit comments