Skip to content

Commit 79cd10a

Browse files
committed
cleaning up TimeAlarm and PinAlarm
1 parent cd28d50 commit 79cd10a

File tree

4 files changed

+55
-66
lines changed

4 files changed

+55
-66
lines changed

ports/atmel-samd/common-hal/alarm/__init__.c

Lines changed: 30 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#include "py/objtuple.h"
3030
#include "py/runtime.h"
3131
#include "lib/utils/interrupt_char.h"
32-
#include <stdio.h>
32+
// #include <stdio.h>
3333

3434
#include "shared-bindings/alarm/__init__.h"
3535
#include "shared-bindings/alarm/SleepMemory.h"
@@ -47,8 +47,10 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
4747
.type = &alarm_sleep_memory_type,
4848
},
4949
};
50-
uint32_t target2 = 0;
5150
// 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;
5254

5355
void alarm_reset(void) {
5456
// Reset the alarm flag
@@ -58,24 +60,19 @@ void alarm_reset(void) {
5860
}
5961

6062
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-
7063
// If in light/fake sleep, check modules
7164
if (alarm_pin_pinalarm_woke_this_cycle()) {
7265
return SAMD_WAKEUP_GPIO;
7366
}
7467
if (alarm_time_timealarm_woke_this_cycle()) {
7568
return SAMD_WAKEUP_RTC;
7669
}
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+
}
7976
return SAMD_WAKEUP_UNDEF;
8077
}
8178

@@ -105,7 +102,8 @@ mp_obj_t common_hal_alarm_create_wake_alarm(void) {
105102
// Set up light sleep or deep sleep alarms.
106103
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
107104
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;
109107
}
110108

111109
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
178176

179177
void NORETURN common_hal_alarm_enter_deep_sleep(void) {
180178
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;
182181
port_disable_tick(); // TODO: Required for SAMD?
183182

184183
// Set a flag in the backup registers to indicate sleep wakeup
@@ -192,7 +191,7 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
192191

193192
// hacky way of checking if time alarm or pin alarm
194193
// TODO: find better way of determining pin vs time
195-
if (target2 == 0) {
194+
if (RTC->MODE0.INTENSET.bit.TAMPER) {
196195
// Disable interrupts
197196
NVIC_DisableIRQ(RTC_IRQn);
198197

@@ -206,6 +205,7 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
206205
RTC->MODE0.CTRLA.reg = RTC_MODE0_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024
207206
RTC_MODE0_CTRLA_MODE_COUNT32; // Set RTC to mode 0, 32-bit timer
208207

208+
// TODO: map requested pin to limited selection of TAMPER pins
209209
//PA02 = IN2
210210
RTC->MODE0.TAMPCTRL.bit.DEBNC2 = 1; // Edge triggered when INn is stable for 4 CLK_RTC_DEB periods
211211
RTC->MODE0.TAMPCTRL.bit.TAMLVL2 = 1; // rising edge
@@ -216,8 +216,8 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
216216
NVIC_EnableIRQ(RTC_IRQn);
217217
// Set interrupts for TAMPER or overflow
218218
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_TAMPER;
219-
}
220-
else {
219+
} else {
220+
// Retrieve COMP1 value before resetting RTC
221221
// Disable interrupts
222222
NVIC_DisableIRQ(RTC_IRQn);
223223

@@ -231,16 +231,15 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
231231
RTC->MODE0.CTRLA.reg = RTC_MODE0_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024
232232
RTC_MODE0_CTRLA_MODE_COUNT32; // Set RTC to mode 0, 32-bit timer
233233

234-
RTC->MODE0.COMP[1].reg = (target2/1024) * 32;
234+
RTC->MODE0.COMP[1].reg = (_target/1024) * 32;
235235
while(RTC->MODE0.SYNCBUSY.reg);
236236

237237
// Enable interrupts
238238
NVIC_SetPriority(RTC_IRQn, 0);
239239
NVIC_EnableIRQ(RTC_IRQn);
240240
// Set interrupts for COMPARE1 or overflow
241241
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP1 | RTC_MODE1_INTENSET_OVF;
242-
}
243-
242+
}
244243
// Set-up Deep Sleep Mode
245244
// RAM retention
246245
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) {
260259
}
261260
}
262261

263-
void common_hal_alarm_pretending_deep_sleep(void) {
262+
MP_NOINLINE void common_hal_alarm_pretending_deep_sleep(void) {
264263
// TODO:
265264
// If tamper detect interrupts cannot be used to wake from the Idle tier of sleep,
266265
// This section will need to re-initialize the pins to allow the PORT peripheral
267266
// to generate external interrupts again. See STM32 for reference.
268267

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();
293277
}
294278
}
295279

ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ void alarm_pin_pinalarm_reset(void) {
159159
// sure to clear any reserved tables, deinit both PORT and TAMPER
160160
// settings, etc. If flags are set to indicate this module is in
161161
// use, reset them.
162+
163+
// Disable TAMPER interrupt
164+
RTC->MODE0.INTENCLR.bit.TAMPER = 1;
162165
}
163166

164167
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
@@ -175,6 +178,8 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob
175178
mp_raise_ValueError(translate("Pin cannot wake from Deep Sleep"));
176179
}
177180
deep_wkup_enabled = true;
181+
// Set tamper interrupt so deep sleep knows that's the intent
182+
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_TAMPER;
178183
// TODO: Set up deep sleep alarms.
179184
// For deep sleep alarms, first check if the
180185
// alarm pin value is valid for RTC->TAMPER. Ensure

ports/atmel-samd/common-hal/alarm/time/TimeAlarm.c

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626

2727
#include "py/runtime.h"
2828
#include "hpl/pm/hpl_pm_base.h"
29-
#include <stdio.h>
30-
#include "shared-bindings/microcontroller/__init__.h"
29+
// #include <stdio.h>
30+
// #include "shared-bindings/microcontroller/__init__.h"
3131

3232

3333
#include "shared-bindings/alarm/time/TimeAlarm.h"
@@ -72,22 +72,21 @@ mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) {
7272
}
7373

7474
void timer_callback(void) {
75+
RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP1 | RTC_MODE0_INTENCLR_CMP0 | RTC_MODE0_INTENCLR_OVF; // clear flags
7576
woke_up = true;
7677
}
7778

7879
bool alarm_time_timealarm_woke_this_cycle(void) {
79-
if (RTC->MODE0.INTFLAG.reg & RTC_MODE0_INTFLAG_CMP1){
80-
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP1; // clear flag
81-
woke_up = true;
82-
}
8380
return woke_up;
8481
}
8582

8683
void alarm_time_timealarm_reset(void) {
8784
woke_up = false;
8885
}
8986

90-
uint32_t alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
87+
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
88+
// Turn on debug control
89+
RTC->MODE0.DBGCTRL.bit.DBGRUN = 1;
9190
// Search through alarms for TimeAlarm instances, and check that there's only one
9291
bool timealarm_set = false;
9392
alarm_time_timealarm_obj_t *timealarm = MP_OBJ_NULL;
@@ -102,7 +101,7 @@ uint32_t alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const
102101
timealarm_set = true;
103102
}
104103
if (!timealarm_set) {
105-
return 0;
104+
return;
106105
}
107106

108107
// Compute how long to actually sleep, considering the time now.
@@ -118,17 +117,13 @@ uint32_t alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const
118117
} else {
119118
deep_sleep_ticks = 0;
120119
}
121-
122120
// Set COMP1 for fake sleep. This will be reset for real deep sleep anyways.
123-
uint32_t current_cnt = port_get_raw_ticks(NULL);
124-
RTC->MODE0.COMP[1].reg = current_cnt + wakeup_in_ticks;
125-
while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COMP1)) != 0) {
126-
}
127-
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP1;
128-
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP1;
129-
130-
return wakeup_in_ticks;
121+
RTC->MODE0.COMP[1].reg = wakeup_in_ticks;
122+
while (RTC->MODE0.SYNCBUSY.reg);
131123

124+
// This is set for fake sleep. Max fake sleep time is ~72 hours
125+
// True deep sleep isn't limited by this
126+
port_interrupt_after_ticks(wakeup_in_ticks);
132127

133128
// TODO: set up RTC->COMP[1] and create a callback pointing to
134129
// timer_callback. See atmel-samd/supervisor/port.c -> _port_interrupt_after_ticks()
@@ -142,8 +137,7 @@ uint32_t alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const
142137

143138
}
144139

145-
uint32_t alarm_time_timealarm_prepare_for_deep_sleep(void) {
146-
uint32_t temp_ticks = deep_sleep_ticks;
140+
void alarm_time_timealarm_prepare_for_deep_sleep(void) {
147141
if (deep_sleep_ticks) {
148142
// TODO: set up RTC->COMP[1] again, since it needs to start AFTER the USB enumeration delay.
149143
// Just do the exact same setup as alarm_time_timealarm_set_alarms(). Note, this
@@ -155,5 +149,4 @@ uint32_t alarm_time_timealarm_prepare_for_deep_sleep(void) {
155149
// }
156150
deep_sleep_ticks = 0;
157151
}
158-
return temp_ticks;
159152
}

ports/atmel-samd/supervisor/port.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#error Unknown chip family
5454
#endif
5555

56+
#include "common-hal/alarm/__init__.h"
5657
#include "common-hal/analogio/AnalogIn.h"
5758
#include "common-hal/analogio/AnalogOut.h"
5859
#include "common-hal/audiobusio/PDMIn.h"
@@ -77,6 +78,7 @@
7778
#include "samd/dma.h"
7879
#include "shared-bindings/microcontroller/__init__.h"
7980
#include "shared-bindings/rtc/__init__.h"
81+
#include "shared-bindings/alarm/time/TimeAlarm.h"
8082
#include "shared_timers.h"
8183
#include "reset.h"
8284

@@ -496,6 +498,11 @@ void RTC_Handler(void) {
496498
// SAMD21 ticks are handled by EVSYS
497499
#ifdef SAM_D5X_E5X
498500
RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0;
501+
// Check if we're sleeping
502+
if (SAMD_ALARM_FLAG){
503+
timer_callback();
504+
SAMD_ALARM_FLAG = 0;
505+
}
499506
#endif
500507
}
501508
}

0 commit comments

Comments
 (0)