Skip to content

Commit 8486502

Browse files
committed
reworked fake sleep. functional for pin and time
1 parent 6811c5e commit 8486502

File tree

6 files changed

+93
-43
lines changed

6 files changed

+93
-43
lines changed

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ samd_sleep_source_t alarm_get_wakeup_cause(void) {
6666
if (alarm_time_timealarm_woke_this_cycle()) {
6767
return SAMD_WAKEUP_RTC;
6868
}
69-
if (RSTC->RCAUSE.bit.BACKUP) {
69+
if (!fake_sleep && RSTC->RCAUSE.bit.BACKUP) {
7070
// not able to detect PinAlarm wake since registers are getting reset
7171
// TODO: come up with a way to detect a TAMPER
7272
if (RTC->MODE0.TAMPID.reg || RTC->MODE0.INTFLAG.bit.TAMPER) {
@@ -192,6 +192,7 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
192192
(void)__get_FPSCR();
193193
}
194194

195+
// TODO: Be able to set PinAlarm and TimeAlarm together
195196
// PinAlarm (hacky way of checking if time alarm or pin alarm)
196197
if (RTC->MODE0.INTENSET.bit.TAMPER) {
197198
// Disable interrupts
@@ -274,7 +275,7 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
274275
}
275276
}
276277

277-
MP_NOINLINE void common_hal_alarm_pretending_deep_sleep(void) {
278+
void common_hal_alarm_pretending_deep_sleep(void) {
278279
// TODO:
279280
// If tamper detect interrupts cannot be used to wake from the Idle tier of sleep,
280281
// This section will need to re-initialize the pins to allow the PORT peripheral
@@ -286,8 +287,6 @@ MP_NOINLINE void common_hal_alarm_pretending_deep_sleep(void) {
286287
;
287288
}
288289
fake_sleep = true;
289-
} else {
290-
port_idle_until_interrupt();
291290
}
292291
}
293292

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

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@
3838

3939
// This variable stores whether a PinAlarm woke in light sleep or fake deep sleep
4040
// It CANNOT detect if the program woke from deep sleep.
41-
STATIC bool woke_up;
42-
STATIC bool deep_wkup_enabled;
41+
STATIC volatile bool woke_up;
42+
// TODO: replace pinalarm_on with SAMD_ALARM_FLAG bit flags
43+
STATIC volatile bool pinalarm_on;
4344

4445
// TODO: Create tables here reserving IRQ instances, and for the IRQ
4546
// callback to store what pin triggered the interrupt
@@ -55,12 +56,16 @@ void pin_alarm_callback(uint8_t num) { // parameters can be changed
5556
// Turn off interrupts while in handler
5657
// printf("Woke up from pin!!\n");
5758
// printf("EIC Flags: %lu\n",EIC->INTFLAG.reg);
58-
59-
// QUESTION: How to reference the correct EIC?
60-
// set_eic_handler(self->channel, EIC_HANDLER_NO_INTERRUPT);
61-
// turn_off_eic_channel(self->channel);
62-
// reset_pin_number(self->pin);
63-
woke_up = true;
59+
if (pinalarm_on) {
60+
// clear flag and interrupt setting
61+
RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_TAMPER;
62+
pinalarm_on = false;
63+
// QUESTION: How to reference the correct EIC?
64+
// set_eic_handler(self->channel, EIC_HANDLER_NO_INTERRUPT);
65+
// turn_off_eic_channel(self->channel);
66+
// reset_pin_number(self->pin);
67+
woke_up = true;
68+
}
6469
}
6570

6671
void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, const mcu_pin_obj_t *pin, bool value, bool edge, bool pull) {
@@ -89,9 +94,13 @@ void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, con
8994

9095
gpio_set_pin_function(pin->number, GPIO_PIN_FUNCTION_A);
9196
if (self->pull) {
92-
gpio_set_pin_pull_mode(pin->number, GPIO_PULL_UP);
93-
} else {
94-
gpio_set_pin_pull_mode(pin->number, GPIO_PULL_DOWN);
97+
if (self->value) {
98+
// detect rising edge means pull down
99+
gpio_set_pin_pull_mode(pin->number, GPIO_PULL_DOWN);
100+
} else {
101+
// detect falling edge means pull up
102+
gpio_set_pin_pull_mode(pin->number, GPIO_PULL_UP);
103+
}
95104
}
96105
set_eic_channel_data(self->channel, (void *)self);
97106

@@ -107,7 +116,6 @@ bool common_hal_alarm_pin_pinalarm_get_value(alarm_pin_pinalarm_obj_t *self) {
107116
}
108117

109118
bool common_hal_alarm_pin_pinalarm_get_edge(alarm_pin_pinalarm_obj_t *self) {
110-
// TODO: is SAMD edge or level only?
111119
return true;
112120
}
113121

@@ -116,9 +124,8 @@ bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self) {
116124
}
117125

118126
bool alarm_pin_pinalarm_woke_this_cycle(void) {
119-
if (RTC->MODE0.INTFLAG.bit.TAMPER) {
127+
if (pinalarm_on && RTC->MODE0.INTFLAG.bit.TAMPER) {
120128
woke_up = true;
121-
RTC->MODE0.INTENCLR.bit.TAMPER = 1; // clear flag and interrupt setting
122129
}
123130
return woke_up;
124131
}
@@ -135,9 +142,6 @@ mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t
135142
// TODO: Determine whether any pins have been marked as
136143
// triggering the alarm (using the static vars at
137144
// start of file) and if so return that alarm.
138-
139-
140-
141145
}
142146
// Return nothing if no matching alarms are found.
143147
return mp_const_none;
@@ -159,9 +163,22 @@ void alarm_pin_pinalarm_reset(void) {
159163
// sure to clear any reserved tables, deinit both PORT and TAMPER
160164
// settings, etc. If flags are set to indicate this module is in
161165
// use, reset them.
162-
166+
pinalarm_on = false;
167+
woke_up = false;
163168
// Disable TAMPER interrupt
164169
RTC->MODE0.INTENCLR.bit.TAMPER = 1;
170+
// Disable TAMPER control
171+
common_hal_mcu_disable_interrupts();
172+
RTC->MODE0.CTRLA.bit.ENABLE = 0; // Disable the RTC
173+
while (RTC->MODE0.SYNCBUSY.bit.ENABLE) { // Wait for synchronization
174+
;
175+
}
176+
RTC->MODE0.TAMPCTRL.reg = 0; // reset everything
177+
RTC->MODE0.CTRLA.bit.ENABLE = 1; // Enable the RTC
178+
while (RTC->MODE0.SYNCBUSY.bit.ENABLE) { // Wait for synchronization
179+
;
180+
}
181+
common_hal_mcu_enable_interrupts();
165182
}
166183

167184
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
@@ -177,9 +194,25 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob
177194
alarm->pin != &pin_PA02) {
178195
mp_raise_ValueError(translate("Pin cannot wake from Deep Sleep"));
179196
}
180-
deep_wkup_enabled = true;
197+
pinalarm_on = true;
181198
// Set tamper interrupt so deep sleep knows that's the intent
182199
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_TAMPER;
200+
common_hal_mcu_disable_interrupts();
201+
RTC->MODE0.CTRLA.bit.ENABLE = 0; // Disable the RTC
202+
while (RTC->MODE0.SYNCBUSY.bit.ENABLE) { // Wait for synchronization
203+
;
204+
}
205+
// TODO: map requested pin to limited selection of TAMPER pins
206+
// PA02 is n=2: IN2, LVL2, etc...
207+
RTC->MODE0.TAMPCTRL.bit.DEBNC2 = 1; // Edge triggered when INn is stable for 4 CLK_RTC_DEB periods
208+
RTC->MODE0.TAMPCTRL.bit.TAMLVL2 = alarm->value; // rising or falling edge
209+
RTC->MODE0.TAMPCTRL.bit.IN2ACT = 0x1; // WAKE on IN2 (doesn't save timestamp)
210+
common_hal_mcu_enable_interrupts();
211+
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_TAMPER;
212+
RTC->MODE0.CTRLA.bit.ENABLE = 1; // Enable the RTC
213+
while (RTC->MODE0.SYNCBUSY.bit.ENABLE) { // Wait for synchronization
214+
;
215+
}
183216
// TODO: Set up deep sleep alarms.
184217
// For deep sleep alarms, first check if the
185218
// alarm pin value is valid for RTC->TAMPER. Ensure

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

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@
2727
#include "py/runtime.h"
2828
#include "hpl/pm/hpl_pm_base.h"
2929
// #include <stdio.h>
30-
// #include "shared-bindings/microcontroller/__init__.h"
3130

3231
#include "shared-bindings/alarm/time/TimeAlarm.h"
3332
#include "shared-bindings/time/__init__.h"
3433
#include "supervisor/port.h"
3534

3635
STATIC volatile bool woke_up;
3736
STATIC uint32_t deep_sleep_ticks;
37+
// TODO: replace timealarm_on with SAMD_ALARM_FLAG bit flags
38+
STATIC bool timealarm_on;
3839

3940
void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) {
4041
// TODO: throw a ValueError if the input time exceeds the maximum
@@ -72,21 +73,28 @@ mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) {
7273
}
7374

7475
void timer_callback(void) {
75-
RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP1 | RTC_MODE0_INTENCLR_CMP0 | RTC_MODE0_INTENCLR_OVF; // clear flags
76-
woke_up = true;
76+
if (timealarm_on) {
77+
RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP1 | RTC_MODE0_INTENCLR_CMP0 | RTC_MODE0_INTENCLR_OVF; // clear flags
78+
woke_up = true;
79+
timealarm_on = false;
80+
}
7781
}
7882

7983
bool alarm_time_timealarm_woke_this_cycle(void) {
84+
if (timealarm_on && (((uint32_t)port_get_raw_ticks(NULL)<<4) > RTC->MODE0.COMP[1].reg)) {
85+
woke_up = true;
86+
}
8087
return woke_up;
8188
}
8289

8390
void alarm_time_timealarm_reset(void) {
91+
timealarm_on = false;
8492
woke_up = false;
8593
}
8694

8795
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
8896
// Turn on debug control
89-
RTC->MODE0.DBGCTRL.bit.DBGRUN = 1;
97+
// RTC->MODE0.DBGCTRL.bit.DBGRUN = 1;
9098
// Search through alarms for TimeAlarm instances, and check that there's only one
9199
bool timealarm_set = false;
92100
alarm_time_timealarm_obj_t *timealarm = MP_OBJ_NULL;
@@ -117,16 +125,19 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_
117125
} else {
118126
deep_sleep_ticks = 0;
119127
}
120-
// Set COMP1 for fake sleep. This will be reset for real deep sleep anyways.
121-
RTC->MODE0.COMP[1].reg = wakeup_in_ticks;
122-
while (RTC->MODE0.SYNCBUSY.reg) {
123-
;
128+
timealarm_on = true;
129+
// Set COMP1 for fake sleep. This will be read and reset for real deep sleep anyways.
130+
// RTC->MODE0.COMP[1].reg = wakeup_in_ticks;
131+
RTC->MODE0.COMP[1].reg = ((uint32_t)port_get_raw_ticks(NULL)+wakeup_in_ticks)<<4;
132+
while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COMP1)) != 0) {
124133
}
134+
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP1;
135+
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP1;
125136

126137
// This is set for fake sleep. Max fake sleep time is ~72 hours
127138
// True deep sleep isn't limited by this
128-
port_interrupt_after_ticks(wakeup_in_ticks);
129-
139+
// port_interrupt_after_ticks(wakeup_in_ticks);
140+
// printf("second t %lu, cmp0 %lu, cmp1 %lu\n", (uint32_t)port_get_raw_ticks(NULL),RTC->MODE0.COMP[0].reg,RTC->MODE0.COMP[1].reg);
130141
// TODO: set up RTC->COMP[1] and create a callback pointing to
131142
// timer_callback. See atmel-samd/supervisor/port.c -> _port_interrupt_after_ticks()
132143
// for how to set this up. I don't know how you do the callback, though. You MUST use
@@ -146,9 +157,9 @@ void alarm_time_timealarm_prepare_for_deep_sleep(void) {
146157
// is used for both fake and real deep sleep, so it still needs the callback.
147158
// See STM32 for reference.
148159

149-
// RTC->MODE0.COMP[1].reg = deep_sleep_ticks;
150-
// while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COMP1)) != 0) {
151-
// }
160+
RTC->MODE0.COMP[1].reg = deep_sleep_ticks;
161+
while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COMP1)) != 0) {
162+
}
152163
deep_sleep_ticks = 0;
153164
}
154165
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj
3838
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void);
3939
void timer_callback(void);
4040
bool alarm_time_timealarm_woke_this_cycle(void);
41-
uint32_t alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
41+
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
4242
void alarm_time_timealarm_reset(void);
4343

44-
uint32_t alarm_time_timealarm_prepare_for_deep_sleep(void);
44+
void alarm_time_timealarm_prepare_for_deep_sleep(void);
4545

4646
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H

ports/atmel-samd/eic_handler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#define EIC_HANDLER_INCREMENTAL_ENCODER 0x2
3232
#define EIC_HANDLER_PS2 0x3
3333
#define EIC_HANDLER_COUNTER 0x04
34+
#define EIC_HANDLER_ALARM 0x05
3435

3536
void set_eic_handler(uint8_t channel, uint8_t eic_handler);
3637
void shared_eic_handler(uint8_t channel);

ports/atmel-samd/supervisor/port.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
#include "shared-bindings/microcontroller/__init__.h"
8080
#include "shared-bindings/rtc/__init__.h"
8181
#include "shared-bindings/alarm/time/TimeAlarm.h"
82+
#include "shared-bindings/alarm/pin/PinAlarm.h"
8283
#include "shared_timers.h"
8384
#include "reset.h"
8485

@@ -490,6 +491,16 @@ void RTC_Handler(void) {
490491
// Do things common to all ports when the tick occurs
491492
supervisor_tick();
492493
}
494+
if (intflag & RTC_MODE0_INTFLAG_CMP1) {
495+
// Likely TimeAlarm fake sleep wake
496+
timer_callback();
497+
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP1;
498+
}
499+
if (intflag & RTC_MODE0_INTFLAG_TAMPER) {
500+
// Likely PinAlarm fake sleep wake
501+
pin_alarm_callback(1); // TODO: set channel?
502+
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_TAMPER;
503+
}
493504
#endif
494505
if (intflag & RTC_MODE0_INTFLAG_CMP0) {
495506
// Clear the interrupt because we may have hit a sleep
@@ -498,11 +509,6 @@ void RTC_Handler(void) {
498509
// SAMD21 ticks are handled by EVSYS
499510
#ifdef SAM_D5X_E5X
500511
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-
}
506512
#endif
507513
}
508514
}

0 commit comments

Comments
 (0)