reworked fake sleep. functional for pin and time
This commit is contained in:
parent
6811c5e881
commit
8486502e65
@ -66,7 +66,7 @@ samd_sleep_source_t alarm_get_wakeup_cause(void) {
|
||||
if (alarm_time_timealarm_woke_this_cycle()) {
|
||||
return SAMD_WAKEUP_RTC;
|
||||
}
|
||||
if (RSTC->RCAUSE.bit.BACKUP) {
|
||||
if (!fake_sleep && RSTC->RCAUSE.bit.BACKUP) {
|
||||
// not able to detect PinAlarm wake since registers are getting reset
|
||||
// TODO: come up with a way to detect a TAMPER
|
||||
if (RTC->MODE0.TAMPID.reg || RTC->MODE0.INTFLAG.bit.TAMPER) {
|
||||
@ -192,6 +192,7 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
|
||||
(void)__get_FPSCR();
|
||||
}
|
||||
|
||||
// TODO: Be able to set PinAlarm and TimeAlarm together
|
||||
// PinAlarm (hacky way of checking if time alarm or pin alarm)
|
||||
if (RTC->MODE0.INTENSET.bit.TAMPER) {
|
||||
// Disable interrupts
|
||||
@ -274,7 +275,7 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
|
||||
}
|
||||
}
|
||||
|
||||
MP_NOINLINE void common_hal_alarm_pretending_deep_sleep(void) {
|
||||
void common_hal_alarm_pretending_deep_sleep(void) {
|
||||
// TODO:
|
||||
// If tamper detect interrupts cannot be used to wake from the Idle tier of sleep,
|
||||
// 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) {
|
||||
;
|
||||
}
|
||||
fake_sleep = true;
|
||||
} else {
|
||||
port_idle_until_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,9 @@
|
||||
|
||||
// This variable stores whether a PinAlarm woke in light sleep or fake deep sleep
|
||||
// It CANNOT detect if the program woke from deep sleep.
|
||||
STATIC bool woke_up;
|
||||
STATIC bool deep_wkup_enabled;
|
||||
STATIC volatile bool woke_up;
|
||||
// TODO: replace pinalarm_on with SAMD_ALARM_FLAG bit flags
|
||||
STATIC volatile bool pinalarm_on;
|
||||
|
||||
// TODO: Create tables here reserving IRQ instances, and for the IRQ
|
||||
// callback to store what pin triggered the interrupt
|
||||
@ -55,12 +56,16 @@ void pin_alarm_callback(uint8_t num) { // parameters can be changed
|
||||
// Turn off interrupts while in handler
|
||||
// printf("Woke up from pin!!\n");
|
||||
// printf("EIC Flags: %lu\n",EIC->INTFLAG.reg);
|
||||
|
||||
// QUESTION: How to reference the correct EIC?
|
||||
// set_eic_handler(self->channel, EIC_HANDLER_NO_INTERRUPT);
|
||||
// turn_off_eic_channel(self->channel);
|
||||
// reset_pin_number(self->pin);
|
||||
woke_up = true;
|
||||
if (pinalarm_on) {
|
||||
// clear flag and interrupt setting
|
||||
RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_TAMPER;
|
||||
pinalarm_on = false;
|
||||
// QUESTION: How to reference the correct EIC?
|
||||
// set_eic_handler(self->channel, EIC_HANDLER_NO_INTERRUPT);
|
||||
// turn_off_eic_channel(self->channel);
|
||||
// reset_pin_number(self->pin);
|
||||
woke_up = true;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
gpio_set_pin_function(pin->number, GPIO_PIN_FUNCTION_A);
|
||||
if (self->pull) {
|
||||
gpio_set_pin_pull_mode(pin->number, GPIO_PULL_UP);
|
||||
} else {
|
||||
gpio_set_pin_pull_mode(pin->number, GPIO_PULL_DOWN);
|
||||
if (self->value) {
|
||||
// detect rising edge means pull down
|
||||
gpio_set_pin_pull_mode(pin->number, GPIO_PULL_DOWN);
|
||||
} else {
|
||||
// detect falling edge means pull up
|
||||
gpio_set_pin_pull_mode(pin->number, GPIO_PULL_UP);
|
||||
}
|
||||
}
|
||||
set_eic_channel_data(self->channel, (void *)self);
|
||||
|
||||
@ -107,7 +116,6 @@ bool common_hal_alarm_pin_pinalarm_get_value(alarm_pin_pinalarm_obj_t *self) {
|
||||
}
|
||||
|
||||
bool common_hal_alarm_pin_pinalarm_get_edge(alarm_pin_pinalarm_obj_t *self) {
|
||||
// TODO: is SAMD edge or level only?
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -116,9 +124,8 @@ bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self) {
|
||||
}
|
||||
|
||||
bool alarm_pin_pinalarm_woke_this_cycle(void) {
|
||||
if (RTC->MODE0.INTFLAG.bit.TAMPER) {
|
||||
if (pinalarm_on && RTC->MODE0.INTFLAG.bit.TAMPER) {
|
||||
woke_up = true;
|
||||
RTC->MODE0.INTENCLR.bit.TAMPER = 1; // clear flag and interrupt setting
|
||||
}
|
||||
return woke_up;
|
||||
}
|
||||
@ -135,9 +142,6 @@ mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t
|
||||
// TODO: Determine whether any pins have been marked as
|
||||
// triggering the alarm (using the static vars at
|
||||
// start of file) and if so return that alarm.
|
||||
|
||||
|
||||
|
||||
}
|
||||
// Return nothing if no matching alarms are found.
|
||||
return mp_const_none;
|
||||
@ -159,9 +163,22 @@ void alarm_pin_pinalarm_reset(void) {
|
||||
// sure to clear any reserved tables, deinit both PORT and TAMPER
|
||||
// settings, etc. If flags are set to indicate this module is in
|
||||
// use, reset them.
|
||||
|
||||
pinalarm_on = false;
|
||||
woke_up = false;
|
||||
// Disable TAMPER interrupt
|
||||
RTC->MODE0.INTENCLR.bit.TAMPER = 1;
|
||||
// Disable TAMPER control
|
||||
common_hal_mcu_disable_interrupts();
|
||||
RTC->MODE0.CTRLA.bit.ENABLE = 0; // Disable the RTC
|
||||
while (RTC->MODE0.SYNCBUSY.bit.ENABLE) { // Wait for synchronization
|
||||
;
|
||||
}
|
||||
RTC->MODE0.TAMPCTRL.reg = 0; // reset everything
|
||||
RTC->MODE0.CTRLA.bit.ENABLE = 1; // Enable the RTC
|
||||
while (RTC->MODE0.SYNCBUSY.bit.ENABLE) { // Wait for synchronization
|
||||
;
|
||||
}
|
||||
common_hal_mcu_enable_interrupts();
|
||||
}
|
||||
|
||||
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
|
||||
alarm->pin != &pin_PA02) {
|
||||
mp_raise_ValueError(translate("Pin cannot wake from Deep Sleep"));
|
||||
}
|
||||
deep_wkup_enabled = true;
|
||||
pinalarm_on = true;
|
||||
// Set tamper interrupt so deep sleep knows that's the intent
|
||||
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_TAMPER;
|
||||
common_hal_mcu_disable_interrupts();
|
||||
RTC->MODE0.CTRLA.bit.ENABLE = 0; // Disable the RTC
|
||||
while (RTC->MODE0.SYNCBUSY.bit.ENABLE) { // Wait for synchronization
|
||||
;
|
||||
}
|
||||
// TODO: map requested pin to limited selection of TAMPER pins
|
||||
// PA02 is n=2: IN2, LVL2, etc...
|
||||
RTC->MODE0.TAMPCTRL.bit.DEBNC2 = 1; // Edge triggered when INn is stable for 4 CLK_RTC_DEB periods
|
||||
RTC->MODE0.TAMPCTRL.bit.TAMLVL2 = alarm->value; // rising or falling edge
|
||||
RTC->MODE0.TAMPCTRL.bit.IN2ACT = 0x1; // WAKE on IN2 (doesn't save timestamp)
|
||||
common_hal_mcu_enable_interrupts();
|
||||
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_TAMPER;
|
||||
RTC->MODE0.CTRLA.bit.ENABLE = 1; // Enable the RTC
|
||||
while (RTC->MODE0.SYNCBUSY.bit.ENABLE) { // Wait for synchronization
|
||||
;
|
||||
}
|
||||
// TODO: Set up deep sleep alarms.
|
||||
// For deep sleep alarms, first check if the
|
||||
// alarm pin value is valid for RTC->TAMPER. Ensure
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "py/runtime.h"
|
||||
#include "hpl/pm/hpl_pm_base.h"
|
||||
// #include <stdio.h>
|
||||
// #include "shared-bindings/microcontroller/__init__.h"
|
||||
|
||||
#include "shared-bindings/alarm/time/TimeAlarm.h"
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
@ -35,6 +34,8 @@
|
||||
|
||||
STATIC volatile bool woke_up;
|
||||
STATIC uint32_t deep_sleep_ticks;
|
||||
// TODO: replace timealarm_on with SAMD_ALARM_FLAG bit flags
|
||||
STATIC bool timealarm_on;
|
||||
|
||||
void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) {
|
||||
// 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) {
|
||||
}
|
||||
|
||||
void timer_callback(void) {
|
||||
RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP1 | RTC_MODE0_INTENCLR_CMP0 | RTC_MODE0_INTENCLR_OVF; // clear flags
|
||||
woke_up = true;
|
||||
if (timealarm_on) {
|
||||
RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP1 | RTC_MODE0_INTENCLR_CMP0 | RTC_MODE0_INTENCLR_OVF; // clear flags
|
||||
woke_up = true;
|
||||
timealarm_on = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool alarm_time_timealarm_woke_this_cycle(void) {
|
||||
if (timealarm_on && (((uint32_t)port_get_raw_ticks(NULL)<<4) > RTC->MODE0.COMP[1].reg)) {
|
||||
woke_up = true;
|
||||
}
|
||||
return woke_up;
|
||||
}
|
||||
|
||||
void alarm_time_timealarm_reset(void) {
|
||||
timealarm_on = false;
|
||||
woke_up = false;
|
||||
}
|
||||
|
||||
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
|
||||
// Turn on debug control
|
||||
RTC->MODE0.DBGCTRL.bit.DBGRUN = 1;
|
||||
// RTC->MODE0.DBGCTRL.bit.DBGRUN = 1;
|
||||
// Search through alarms for TimeAlarm instances, and check that there's only one
|
||||
bool timealarm_set = false;
|
||||
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_
|
||||
} else {
|
||||
deep_sleep_ticks = 0;
|
||||
}
|
||||
// Set COMP1 for fake sleep. This will be reset for real deep sleep anyways.
|
||||
RTC->MODE0.COMP[1].reg = wakeup_in_ticks;
|
||||
while (RTC->MODE0.SYNCBUSY.reg) {
|
||||
;
|
||||
timealarm_on = true;
|
||||
// Set COMP1 for fake sleep. This will be read and reset for real deep sleep anyways.
|
||||
// RTC->MODE0.COMP[1].reg = wakeup_in_ticks;
|
||||
RTC->MODE0.COMP[1].reg = ((uint32_t)port_get_raw_ticks(NULL)+wakeup_in_ticks)<<4;
|
||||
while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COMP1)) != 0) {
|
||||
}
|
||||
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP1;
|
||||
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP1;
|
||||
|
||||
// This is set for fake sleep. Max fake sleep time is ~72 hours
|
||||
// True deep sleep isn't limited by this
|
||||
port_interrupt_after_ticks(wakeup_in_ticks);
|
||||
|
||||
// port_interrupt_after_ticks(wakeup_in_ticks);
|
||||
// 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);
|
||||
// TODO: set up RTC->COMP[1] and create a callback pointing to
|
||||
// timer_callback. See atmel-samd/supervisor/port.c -> _port_interrupt_after_ticks()
|
||||
// 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) {
|
||||
// is used for both fake and real deep sleep, so it still needs the callback.
|
||||
// See STM32 for reference.
|
||||
|
||||
// RTC->MODE0.COMP[1].reg = deep_sleep_ticks;
|
||||
// while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COMP1)) != 0) {
|
||||
// }
|
||||
RTC->MODE0.COMP[1].reg = deep_sleep_ticks;
|
||||
while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COMP1)) != 0) {
|
||||
}
|
||||
deep_sleep_ticks = 0;
|
||||
}
|
||||
}
|
||||
|
@ -38,9 +38,9 @@ mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj
|
||||
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void);
|
||||
void timer_callback(void);
|
||||
bool alarm_time_timealarm_woke_this_cycle(void);
|
||||
uint32_t alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
|
||||
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
|
||||
void alarm_time_timealarm_reset(void);
|
||||
|
||||
uint32_t alarm_time_timealarm_prepare_for_deep_sleep(void);
|
||||
void alarm_time_timealarm_prepare_for_deep_sleep(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H
|
||||
|
@ -31,6 +31,7 @@
|
||||
#define EIC_HANDLER_INCREMENTAL_ENCODER 0x2
|
||||
#define EIC_HANDLER_PS2 0x3
|
||||
#define EIC_HANDLER_COUNTER 0x04
|
||||
#define EIC_HANDLER_ALARM 0x05
|
||||
|
||||
void set_eic_handler(uint8_t channel, uint8_t eic_handler);
|
||||
void shared_eic_handler(uint8_t channel);
|
||||
|
@ -79,6 +79,7 @@
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/rtc/__init__.h"
|
||||
#include "shared-bindings/alarm/time/TimeAlarm.h"
|
||||
#include "shared-bindings/alarm/pin/PinAlarm.h"
|
||||
#include "shared_timers.h"
|
||||
#include "reset.h"
|
||||
|
||||
@ -490,6 +491,16 @@ void RTC_Handler(void) {
|
||||
// Do things common to all ports when the tick occurs
|
||||
supervisor_tick();
|
||||
}
|
||||
if (intflag & RTC_MODE0_INTFLAG_CMP1) {
|
||||
// Likely TimeAlarm fake sleep wake
|
||||
timer_callback();
|
||||
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP1;
|
||||
}
|
||||
if (intflag & RTC_MODE0_INTFLAG_TAMPER) {
|
||||
// Likely PinAlarm fake sleep wake
|
||||
pin_alarm_callback(1); // TODO: set channel?
|
||||
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_TAMPER;
|
||||
}
|
||||
#endif
|
||||
if (intflag & RTC_MODE0_INTFLAG_CMP0) {
|
||||
// Clear the interrupt because we may have hit a sleep
|
||||
@ -498,11 +509,6 @@ void RTC_Handler(void) {
|
||||
// SAMD21 ticks are handled by EVSYS
|
||||
#ifdef SAM_D5X_E5X
|
||||
RTC->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0;
|
||||
// Check if we're sleeping
|
||||
if (SAMD_ALARM_FLAG) {
|
||||
timer_callback();
|
||||
SAMD_ALARM_FLAG = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user