Skip to content

Commit f748d66

Browse files
hierophectmaholli
authored andcommitted
Setup outline for SAMD alarm module
1 parent fd9c3d1 commit f748d66

File tree

14 files changed

+776
-4
lines changed

14 files changed

+776
-4
lines changed

.gitmodules

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,6 @@
154154
path = ports/espressif/esp-idf
155155
url = https://github.com/espressif/esp-idf.git
156156
branch = release/v4.3
157-
[submodule "ports/espressif/certificates/nina-fw"]
158-
path = ports/espressif/certificates/nina-fw
159-
url = https://github.com/adafruit/nina-fw.git
160157
[submodule "frozen/Adafruit_CircuitPython_ST7789"]
161158
path = frozen/Adafruit_CircuitPython_ST7789
162159
url = https://github.com/adafruit/Adafruit_CircuitPython_ST7789

locale/circuitpython.pot

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,7 @@ msgstr ""
17711771
msgid "Only one TouchAlarm can be set in deep sleep."
17721772
msgstr ""
17731773

1774+
#: ports/atmel-samd/common-hal/alarm/time/TimeAlarm.c
17741775
#: ports/espressif/common-hal/alarm/time/TimeAlarm.c
17751776
#: ports/nrf/common-hal/alarm/time/TimeAlarm.c
17761777
#: ports/raspberrypi/common-hal/alarm/time/TimeAlarm.c
@@ -1881,6 +1882,10 @@ msgstr ""
18811882
msgid "Pin must support hardware interrupts"
18821883
msgstr ""
18831884

1885+
#: ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c
1886+
msgid "PinAlarms not available"
1887+
msgstr ""
1888+
18841889
#: shared-bindings/rgbmatrix/RGBMatrix.c
18851890
#, c-format
18861891
msgid ""
@@ -2091,6 +2096,7 @@ msgstr ""
20912096
msgid "Size not supported"
20922097
msgstr ""
20932098

2099+
#: ports/atmel-samd/common-hal/alarm/SleepMemory.c
20942100
#: ports/raspberrypi/common-hal/alarm/SleepMemory.c
20952101
msgid "Sleep Memory not available"
20962102
msgstr ""
@@ -2245,6 +2251,7 @@ msgstr ""
22452251
msgid "Total data to write is larger than %q"
22462252
msgstr ""
22472253

2254+
#: ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.c
22482255
#: ports/raspberrypi/common-hal/alarm/touch/TouchAlarm.c
22492256
#: ports/stm/common-hal/alarm/touch/TouchAlarm.c
22502257
msgid "Touch alarms not available"
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include <string.h>
28+
29+
#include "py/runtime.h"
30+
#include "common-hal/alarm/SleepMemory.h"
31+
32+
void alarm_sleep_memory_reset(void) {
33+
34+
}
35+
36+
uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) {
37+
mp_raise_NotImplementedError(translate("Sleep Memory not available"));
38+
return 0;
39+
}
40+
41+
bool common_hal_alarm_sleep_memory_set_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, const uint8_t *values, uint32_t len) {
42+
mp_raise_NotImplementedError(translate("Sleep Memory not available"));
43+
return false;
44+
}
45+
46+
void common_hal_alarm_sleep_memory_get_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, uint8_t *values, uint32_t len) {
47+
mp_raise_NotImplementedError(translate("Sleep Memory not available"));
48+
return;
49+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
28+
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
29+
30+
#include "py/obj.h"
31+
32+
typedef struct {
33+
mp_obj_base_t base;
34+
} alarm_sleep_memory_obj_t;
35+
36+
extern void alarm_sleep_memory_reset(void);
37+
38+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "py/gc.h"
28+
#include "py/obj.h"
29+
#include "py/objtuple.h"
30+
#include "py/runtime.h"
31+
#include "lib/utils/interrupt_char.h"
32+
33+
#include "shared-bindings/alarm/__init__.h"
34+
#include "shared-bindings/alarm/SleepMemory.h"
35+
#include "shared-bindings/alarm/pin/PinAlarm.h"
36+
#include "shared-bindings/alarm/time/TimeAlarm.h"
37+
38+
#include "shared-bindings/microcontroller/__init__.h"
39+
40+
#include "supervisor/port.h"
41+
#include "supervisor/workflow.h"
42+
43+
// Singleton instance of SleepMemory.
44+
const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
45+
.base = {
46+
.type = &alarm_sleep_memory_type,
47+
},
48+
};
49+
50+
// TODO: make a custom enum to avoid weird values like PM_SLEEPCFG_SLEEPMODE_BACKUP_Val?
51+
52+
void alarm_reset(void) {
53+
// Reset the alarm flag
54+
SAMD_ALARM_FLAG = 0x00;
55+
alarm_pin_pinalarm_reset();
56+
alarm_time_timealarm_reset();
57+
}
58+
59+
samd_sleep_source_t alarm_get_wakeup_cause(void) {
60+
// If in light/fake sleep, check modules
61+
if (alarm_pin_pinalarm_woke_this_cycle()) {
62+
return SAMD_WAKEUP_GPIO;
63+
}
64+
if (alarm_time_timealarm_woke_this_cycle()) {
65+
return SAMD_WAKEUP_RTC;
66+
}
67+
// TODO: for deep sleep, manually determine how the chip woke up
68+
// TODO: try checking the interrupt flag tables for RTC TAMPER vs COMPARE
69+
return SAMD_WAKEUP_UNDEF;
70+
}
71+
72+
bool common_hal_alarm_woken_from_sleep(void) {
73+
return alarm_get_wakeup_cause() != SAMD_WAKEUP_UNDEF;
74+
}
75+
76+
mp_obj_t common_hal_alarm_create_wake_alarm(void) {
77+
// If woken from deep sleep, create a copy alarm similar to what would have
78+
// been passed in originally. Otherwise, just return none
79+
samd_sleep_source_t cause = alarm_get_wakeup_cause();
80+
switch (cause) {
81+
case SAMD_WAKEUP_RTC: {
82+
return alarm_time_timealarm_create_wakeup_alarm();
83+
}
84+
case SAMD_WAKEUP_GPIO: {
85+
return alarm_pin_pinalarm_create_wakeup_alarm();
86+
}
87+
case SAMD_WAKEUP_UNDEF:
88+
default:
89+
// Not a deep sleep reset.
90+
break;
91+
}
92+
return mp_const_none;
93+
}
94+
95+
// Set up light sleep or deep sleep alarms.
96+
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
97+
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
98+
alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms);
99+
}
100+
101+
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
102+
_setup_sleep_alarms(false, n_alarms, alarms);
103+
mp_obj_t wake_alarm = mp_const_none;
104+
105+
while (!mp_hal_is_interrupted()) {
106+
RUN_BACKGROUND_TASKS;
107+
// Detect if interrupt was alarm or ctrl-C interrupt.
108+
if (common_hal_alarm_woken_from_sleep()) {
109+
samd_sleep_source_t cause = alarm_get_wakeup_cause();
110+
switch (cause) {
111+
case SAMD_WAKEUP_RTC: {
112+
wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms,alarms);
113+
break;
114+
}
115+
case SAMD_WAKEUP_GPIO: {
116+
wake_alarm = alarm_pin_pinalarm_find_triggered_alarm(n_alarms,alarms);
117+
break;
118+
}
119+
default:
120+
// Should not reach this, if all light sleep types are covered correctly
121+
break;
122+
}
123+
shared_alarm_save_wake_alarm(wake_alarm);
124+
break;
125+
}
126+
// TODO: the SAMD implementation of this (purportedly) disables interrupts
127+
// Presumably this doesn't impact the RTC interrupts, somehow, or it would never wake up?
128+
// Will it prevent an external interrupt from waking?
129+
port_idle_until_interrupt();
130+
// Alternative would be `sleep(PM_SLEEPCFG_SLEEPMODE_IDLE2_Val)`, I think?
131+
}
132+
133+
if (mp_hal_is_interrupted()) {
134+
return mp_const_none; // Shouldn't be given to python code because exception handling should kick in.
135+
}
136+
137+
alarm_reset();
138+
return wake_alarm;
139+
}
140+
141+
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
142+
_setup_sleep_alarms(true, n_alarms, alarms);
143+
}
144+
145+
void NORETURN common_hal_alarm_enter_deep_sleep(void) {
146+
alarm_pin_pinalarm_prepare_for_deep_sleep();
147+
alarm_time_timealarm_prepare_for_deep_sleep();
148+
port_disable_tick(); // TODO: Required for SAMD?
149+
150+
// Set a flag in the backup registers to indicate sleep wakeup
151+
SAMD_ALARM_FLAG = 0x01;
152+
153+
// TODO: make sure this actually works, or replace with extracted register version
154+
// sleep(PM_SLEEPCFG_SLEEPMODE_BACKUP_Val);
155+
156+
// The above shuts down RAM, so we should never hit this
157+
while (1) {
158+
;
159+
}
160+
}
161+
162+
void common_hal_alarm_pretending_deep_sleep(void) {
163+
// TODO:
164+
// If tamper detect interrupts cannot be used to wake from the Idle tier of sleep,
165+
// This section will need to re-initialize the pins to allow the PORT peripheral
166+
// to generate external interrupts again. See STM32 for reference.
167+
}
168+
169+
void common_hal_alarm_gc_collect(void) {
170+
gc_collect_ptr(shared_alarm_get_wake_alarm());
171+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H
28+
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H
29+
30+
#include "common-hal/alarm/SleepMemory.h"
31+
32+
extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
33+
34+
// This is the first byte of the BKUP register bank.
35+
// It stores whether the last wakeup was because of an alarm.
36+
#define SAMD_ALARM_FLAG (RTC->MODE0.BKUP[0].reg)
37+
38+
typedef enum {
39+
SAMD_WAKEUP_UNDEF,
40+
SAMD_WAKEUP_GPIO,
41+
SAMD_WAKEUP_RTC
42+
} samd_sleep_source_t;
43+
44+
extern void alarm_set_wakeup_reason(samd_sleep_source_t reason);
45+
samd_sleep_source_t alarm_get_wakeup_cause(void);
46+
extern void alarm_reset(void);
47+
48+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H

0 commit comments

Comments
 (0)