Extract EXTI, create base sleep framework

This commit is contained in:
Lucian Copeland 2021-03-02 11:41:53 -05:00
parent 766e79ad3d
commit f1792c8474
27 changed files with 934 additions and 137 deletions

8
main.c
View File

@ -157,9 +157,9 @@ STATIC void start_mp(supervisor_allocation* heap) {
#if CIRCUITPY_ALARM #if CIRCUITPY_ALARM
// Record which alarm woke us up, if any. An object may be created so the heap must be functional. // Record which alarm woke us up, if any. An object may be created so the heap must be functional.
alarm_save_wake_alarm(); common_hal_alarm_save_wake_alarm();
// Reset alarm module only after we retrieved the wakeup alarm. // Reset alarm module only after we retrieved the wakeup alarm.
alarm_reset(); common_hal_alarm_reset();
#endif #endif
#if CIRCUITPY_NETWORK #if CIRCUITPY_NETWORK
@ -357,7 +357,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
// an alarm alerts faster than our USB delay or if we pretended to deep // an alarm alerts faster than our USB delay or if we pretended to deep
// sleep. // sleep.
#if CIRCUITPY_ALARM #if CIRCUITPY_ALARM
if (asleep && alarm_woken_from_sleep()) { if (asleep && common_hal_alarm_woken_from_sleep()) {
serial_write_compressed(translate("Woken up by alarm.\n")); serial_write_compressed(translate("Woken up by alarm.\n"));
board_init(); board_init();
supervisor_set_run_reason(RUN_REASON_STARTUP); supervisor_set_run_reason(RUN_REASON_STARTUP);
@ -409,7 +409,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
if (!supervisor_workflow_active()) { if (!supervisor_workflow_active()) {
// Enter true deep sleep. When we wake up we'll be back at the // Enter true deep sleep. When we wake up we'll be back at the
// top of main(), not in this loop. // top of main(), not in this loop.
alarm_enter_deep_sleep(); common_hal_alarm_enter_deep_sleep();
// Does not return. // Does not return.
} else { } else {
serial_write_compressed(translate("Pretending to deep sleep until alarm, CTRL-C or file write.\n")); serial_write_compressed(translate("Pretending to deep sleep until alarm, CTRL-C or file write.\n"));

View File

@ -54,7 +54,7 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
}, },
}; };
void alarm_reset(void) { void common_hal_alarm_reset(void) {
alarm_sleep_memory_reset(); alarm_sleep_memory_reset();
alarm_pin_pinalarm_reset(); alarm_pin_pinalarm_reset();
alarm_time_timealarm_reset(); alarm_time_timealarm_reset();
@ -75,10 +75,12 @@ STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) {
return esp_sleep_get_wakeup_cause(); return esp_sleep_get_wakeup_cause();
} }
bool alarm_woken_from_sleep(void) { bool common_hal_alarm_woken_from_sleep(void) {
return _get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED; return _get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED;
} }
// When called to populate the global dict, the module functions create new alarm objects.
// Otherwise, they scan the existing alarms for matches.
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(); esp_sleep_wakeup_cause_t cause = _get_wakeup_cause();
switch (cause) { switch (cause) {
@ -104,6 +106,8 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
return mp_const_none; return mp_const_none;
} }
// This function is used to create a new alarm object for the global dict after deep sleep,
// rather than finding an existing one during runtime.
mp_obj_t common_hal_alarm_get_wake_alarm(void) { mp_obj_t common_hal_alarm_get_wake_alarm(void) {
return _get_wake_alarm(0, NULL); return _get_wake_alarm(0, NULL);
} }
@ -120,8 +124,9 @@ STATIC void _idle_until_alarm(void) {
while (!mp_hal_is_interrupted()) { while (!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS; RUN_BACKGROUND_TASKS;
// Allow ctrl-C interrupt. // Allow ctrl-C interrupt.
if (alarm_woken_from_sleep()) { if (common_hal_alarm_woken_from_sleep()) {
alarm_save_wake_alarm(); // This saves the return of common_hal_alarm_get_wake_alarm through Shared Bindings
common_hal_alarm_save_wake_alarm();
return; return;
} }
port_idle_until_interrupt(); port_idle_until_interrupt();
@ -139,7 +144,7 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
} }
mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms); mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms);
alarm_reset(); alarm_pin_pinalarm_reset_alarms(n_alarms, alarms);
return wake_alarm; return wake_alarm;
} }
@ -147,7 +152,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala
_setup_sleep_alarms(true, n_alarms, alarms); _setup_sleep_alarms(true, n_alarms, alarms);
} }
void NORETURN alarm_enter_deep_sleep(void) { void NORETURN common_hal_alarm_enter_deep_sleep(void) {
alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_pin_pinalarm_prepare_for_deep_sleep();
alarm_touch_touchalarm_prepare_for_deep_sleep(); alarm_touch_touchalarm_prepare_for_deep_sleep();

View File

@ -31,6 +31,6 @@
const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
extern void alarm_reset(void); extern void common_hal_alarm_reset(void);
#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_ALARM__INIT__H #endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_ALARM__INIT__H

View File

@ -1,35 +0,0 @@
#include "shared-bindings/alarm_io/__init__.h"
#include "esp_sleep.h"
#include "driver/rtc_io.h"
mp_obj_t common_hal_alarm_io_pin_state (alarm_io_obj_t *self_in) {
if (!rtc_gpio_is_valid_gpio(self_in->gpio)) {
mp_raise_ValueError(translate("io must be rtc io"));
}
if (self_in->pull && !self_in->level) {
for (uint8_t i = 0; i<=4; i+=2) {
if (self_in->gpio == i) {
mp_raise_ValueError(translate("IOs 0, 2 & 4 do not support internal pullup in sleep"));
}
}
}
switch(esp_sleep_enable_ext0_wakeup(self_in->gpio, self_in->level)) {
case ESP_ERR_INVALID_ARG:
mp_raise_ValueError(translate("trigger level must be 0 or 1"));
case ESP_ERR_INVALID_STATE:
mp_raise_RuntimeError(translate("wakeup conflict"));
default:
break;
}
if (self_in->pull) { (self_in->level) ? rtc_gpio_pulldown_en(self_in->gpio) : rtc_gpio_pullup_en(self_in->gpio); }
return self_in;
}
void common_hal_alarm_io_disable (void) {
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0 | ESP_SLEEP_WAKEUP_EXT1);
}

View File

@ -220,6 +220,8 @@ SRC_C += \
boards/$(BOARD)/board.c \ boards/$(BOARD)/board.c \
boards/$(BOARD)/pins.c \ boards/$(BOARD)/pins.c \
peripherals/timers.c \ peripherals/timers.c \
peripherals/exti.c \
peripherals/rtc.c \
peripherals/stm32$(MCU_SERIES_LOWER)/clocks.c \ peripherals/stm32$(MCU_SERIES_LOWER)/clocks.c \
peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/pins.c \ peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/pins.c \
peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/gpio.c \ peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/gpio.c \

View File

@ -37,3 +37,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) { void reset_board(void) {
} }
void board_deinit(void) {
}

View File

@ -0,0 +1,46 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "py/runtime.h"
#include "common-hal/alarm/SleepMemory.h"
void alarm_sleep_memory_reset(void) {
}
uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) {
return 0;
}
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) {
return false;
}
void common_hal_alarm_sleep_memory_get_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, uint8_t* values, uint32_t len) {
return;
}

View File

@ -0,0 +1,38 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_SLEEPMEMORY_H
#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_SLEEPMEMORY_H
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
} alarm_sleep_memory_obj_t;
extern void alarm_sleep_memory_reset(void);
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_SLEEPMEMORY_H

View File

@ -0,0 +1,158 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/gc.h"
#include "py/obj.h"
#include "py/objtuple.h"
#include "py/runtime.h"
#include "lib/utils/interrupt_char.h"
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/port.h"
#include "supervisor/shared/workflow.h"
#define STM_WAKEUP_GPIO 1
#define STM_WAKEUP_TIMER 2
void common_hal_alarm_reset(void) {
// alarm_sleep_memory_reset();
alarm_pin_pinalarm_reset();
// alarm_time_timealarm_reset();
// alarm_touch_touchalarm_reset();
// esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
}
STATIC uint8_t _get_wakeup_cause(void) {
if (alarm_pin_pinalarm_woke_us_up()) {
return STM_WAKEUP_GPIO;
}
if (alarm_time_timealarm_woke_us_up()) {
return STM_WAKEUP_TIMER;
}
return 0;
}
bool common_hal_alarm_woken_from_sleep(void) {
return _get_wakeup_cause() != 0;
}
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
if (alarm_pin_pinalarm_woke_us_up()) {
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
}
// esp_sleep_wakeup_cause_t cause = _get_wakeup_cause();
// switch (cause) {
// case ESP_SLEEP_WAKEUP_TIMER: {
// return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
// }
// case ESP_SLEEP_WAKEUP_GPIO:
// case ESP_SLEEP_WAKEUP_EXT0:
// case ESP_SLEEP_WAKEUP_EXT1: {
// return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
// }
// case ESP_SLEEP_WAKEUP_TOUCHPAD: {
// return alarm_touch_touchalarm_get_wakeup_alarm(n_alarms, alarms);
// }
// case ESP_SLEEP_WAKEUP_UNDEFINED:
// default:
// // Not a deep sleep reset.
// break;
// }
// return mp_const_none;
return mp_const_none;
}
mp_obj_t common_hal_alarm_get_wake_alarm(void) {
//return _get_wake_alarm(0, NULL);
return mp_const_none;
}
// Set up light sleep or deep sleep alarms.
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
// alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms);
// alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms);
}
STATIC void _idle_until_alarm(void) {
// Poll for alarms.
while (!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
// Allow ctrl-C interrupt.
if (common_hal_alarm_woken_from_sleep()) {
common_hal_alarm_save_wake_alarm();
return;
}
// port_idle_until_interrupt();
}
}
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
// if (supervisor_workflow_active()) {
// mp_raise_NotImplementedError(translate("Cannot sleep with USB connected"));
// }
_setup_sleep_alarms(false, n_alarms, alarms);
// If USB is active, only pretend to sleep. Otherwise, light sleep
if (supervisor_workflow_active()) {
_idle_until_alarm();
} else {
port_disable_tick();
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
port_enable_tick();
}
mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms);
common_hal_alarm_reset();
return wake_alarm;
}
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
_setup_sleep_alarms(true, n_alarms, alarms);
}
//#define NORETURN __attribute__((noreturn))
void NORETURN common_hal_alarm_enter_deep_sleep(void) {
// alarm_pin_pinalarm_prepare_for_deep_sleep();
// alarm_touch_touchalarm_prepare_for_deep_sleep();
while(1);
// The ESP-IDF caches the deep sleep settings and applies them before sleep.
// We don't need to worry about resetting them in the interim.
// esp_deep_sleep_start();
}
void common_hal_alarm_gc_collect(void) {
gc_collect_ptr(common_hal_alarm_get_wake_alarm());
}

View File

@ -0,0 +1,36 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H
#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H
#include "common-hal/alarm/SleepMemory.h"
const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
extern void common_hal_alarm_reset(void);
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H

View File

@ -0,0 +1,136 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "peripherals/exti.h"
STATIC bool woke_up;
STATIC uint16_t alarm_pin_triggered;
STATIC void pin_alarm_callback(uint8_t num) {
alarm_pin_triggered |= (1 << num);
woke_up = true;
HAL_GPIO_EXTI_IRQHandler(pin_mask(num));
}
void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) {
if (!edge) {
mp_raise_NotImplementedError(translate("Only edge detection is available on this hardware"));
}
if (!stm_peripherals_exti_is_free(pin->number)) {
mp_raise_RuntimeError(translate("Pin interrupt already in use"));
}
stm_peripherals_exti_reserve(pin->number);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = pin_mask(pin->number);
GPIO_InitStruct.Mode = value ? GPIO_MODE_IT_RISING : GPIO_MODE_IT_FALLING;
// Pull is automatically set to oppose value.
// TODO: match digitalIO API instead?
if (value) {
GPIO_InitStruct.Pull = pull ? GPIO_PULLDOWN : GPIO_NOPULL;
} else {
GPIO_InitStruct.Pull = pull ? GPIO_PULLUP : GPIO_NOPULL;
}
HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct);
stm_peripherals_exti_set_callback(pin_alarm_callback,pin->number);
self->pin = pin;
self->value = value;
self->pull = pull;
}
mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self) {
return self->pin;
}
bool common_hal_alarm_pin_pinalarm_get_value(alarm_pin_pinalarm_obj_t *self) {
return self->value;
}
bool common_hal_alarm_pin_pinalarm_get_edge(alarm_pin_pinalarm_obj_t *self) {
return true;
}
bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self) {
return self->pull;
}
bool alarm_pin_pinalarm_woke_us_up(void) {
return woke_up;
}
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
for (size_t i = 0; i < n_alarms; i++) {
if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) {
continue;
}
alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]);
if (alarm_pin_triggered & (1 << alarm->pin->number)) {
return alarms[i];
}
}
// Placeholder for deep sleep
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t);
alarm->base.type = &alarm_pin_pinalarm_type;
alarm->pin = NULL;
return alarm;
}
void alarm_pin_pinalarm_reset(void) {
alarm_pin_triggered = 0;
woke_up = false;
}
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
for (size_t i = 0; i < n_alarms; i++) {
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) {
alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]);
stm_peripherals_exti_enable(alarm->pin->number);
}
}
}
void alarm_pin_pinalarm_reset_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
alarm_pin_triggered = 0;
for (size_t i = 0; i < n_alarms; i++) {
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) {
alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]);
stm_peripherals_exti_disable(alarm->pin->number);
}
}
}
void alarm_pin_pinalarm_prepare_for_deep_sleep(void) {
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/obj.h"
#include "py/objtuple.h"
typedef struct {
mp_obj_base_t base;
mcu_pin_obj_t *pin;
bool value;
bool pull;
} alarm_pin_pinalarm_obj_t;
void alarm_pin_pinalarm_reset(void);
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
void alarm_pin_pinalarm_reset_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
bool alarm_pin_pinalarm_woke_us_up(void);

View File

@ -0,0 +1,78 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/time/__init__.h"
void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) {
self->monotonic_time = monotonic_time;
}
mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timealarm_obj_t *self) {
return self->monotonic_time;
}
// mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
// // First, check to see if we match
// for (size_t i = 0; i < n_alarms; i++) {
// if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) {
// return alarms[i];
// }
// }
// alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t);
// timer->base.type = &alarm_time_timealarm_type;
// // TODO: Set monotonic_time based on the RTC state.
// timer->monotonic_time = 0.0f;
// return timer;
// }
// This is run in the timer task. We use it to wake the main CircuitPython task.
// void timer_callback(void *arg) {
// (void) arg;
// woke_up = true;
// xTaskNotifyGive(circuitpython_task);
// }
bool alarm_time_timealarm_woke_us_up(void) {
// return woke_up;
return false;
}
// void alarm_time_timealarm_reset(void) {
// esp_timer_stop(pretend_sleep_timer);
// esp_timer_delete(pretend_sleep_timer);
// pretend_sleep_timer = NULL;
// woke_up = false;
// }
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
// HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 0xA017, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
// HAL_RTCEx_SetWakeUpTimer_IT(&_hrtc, rtc_clock_frequency / 1024 / 2, RTC_WAKEUPCLOCK_RTCCLK_DIV2);
// HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 1, 0U);
// HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
}

View File

@ -0,0 +1,40 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
mp_float_t monotonic_time; // values compatible with time.monotonic_time()
} alarm_time_timealarm_obj_t;
// // Find the alarm object that caused us to wake up or create an equivalent one.
// mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
// // Check for the wake up alarm from pretend deep sleep.
bool alarm_time_timealarm_woke_us_up(void);
// void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
// void alarm_time_timealarm_reset(void);

View File

@ -0,0 +1,32 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/alarm/touch/TouchAlarm.h"
#include "shared-bindings/microcontroller/__init__.h"
void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) {
mp_raise_NotImplementedError(translate("Touch alarms not available"));
}

View File

@ -0,0 +1,35 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TOUCHALARM_H
#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TOUCHALARM_H
typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t *pin;
} alarm_touch_touchalarm_obj_t;
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TOUCHALARM_H

View File

@ -35,17 +35,17 @@
#include "shared-bindings/pulseio/PulseIn.h" #include "shared-bindings/pulseio/PulseIn.h"
#include "timers.h" #include "timers.h"
#include "peripherals/exti.h"
#include STM32_HAL_H #include STM32_HAL_H
#define STM32_GPIO_PORT_SIZE 16 #define STM32_GPIO_PORT_SIZE 16
static pulseio_pulsein_obj_t* _objs[STM32_GPIO_PORT_SIZE]; STATIC pulseio_pulsein_obj_t* callback_obj_ref[STM32_GPIO_PORT_SIZE];
STATIC TIM_HandleTypeDef tim_handle; STATIC TIM_HandleTypeDef tim_handle;
static uint32_t overflow_count = 0; STATIC uint32_t overflow_count = 0;
STATIC uint8_t refcount = 0; STATIC uint8_t refcount = 0;
static void assign_EXTI_Interrupt(pulseio_pulsein_obj_t* self, uint8_t num);
void pulsein_timer_event_handler(void) void pulsein_timer_event_handler(void)
{ {
// Detect TIM Update event // Detect TIM Update event
@ -59,7 +59,7 @@ void pulsein_timer_event_handler(void)
} }
} }
static void pulsein_exti_event_handler(uint8_t num) { STATIC void pulsein_exti_event_handler(uint8_t num) {
// Grab the current time first. // Grab the current time first.
uint32_t current_overflow = overflow_count; uint32_t current_overflow = overflow_count;
uint32_t current_count = tim_handle.Instance->CNT; uint32_t current_count = tim_handle.Instance->CNT;
@ -67,7 +67,7 @@ static void pulsein_exti_event_handler(uint8_t num) {
// Interrupt register must be cleared manually // Interrupt register must be cleared manually
EXTI->PR = 1 << num; EXTI->PR = 1 << num;
pulseio_pulsein_obj_t* self = _objs[num]; pulseio_pulsein_obj_t* self = callback_obj_ref[num];
if ( !self ) return; if ( !self ) return;
if (self->first_edge) { if (self->first_edge) {
@ -97,11 +97,11 @@ static void pulsein_exti_event_handler(uint8_t num) {
void pulsein_reset(void) { void pulsein_reset(void) {
// Disable all active interrupts and clear array // Disable all active interrupts and clear array
for (uint i = 0; i < STM32_GPIO_PORT_SIZE; i++) { for (uint i = 0; i < STM32_GPIO_PORT_SIZE; i++) {
if (_objs[i] != NULL) { if (callback_obj_ref[i] != NULL) {
HAL_NVIC_DisableIRQ(_objs[i]->irq); stm_peripherals_exti_disable(callback_obj_ref[i]->pin->number);
} }
} }
memset(_objs, 0, sizeof(_objs)); memset(callback_obj_ref, 0, sizeof(callback_obj_ref));
HAL_TIM_Base_DeInit(&tim_handle); HAL_TIM_Base_DeInit(&tim_handle);
tim_clock_disable(stm_peripherals_timer_get_index(tim_handle.Instance)); tim_clock_disable(stm_peripherals_timer_get_index(tim_handle.Instance));
@ -112,15 +112,14 @@ void pulsein_reset(void) {
void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin, void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin,
uint16_t maxlen, bool idle_state) { uint16_t maxlen, bool idle_state) {
// STM32 has one shared EXTI for each pin number, 0-15 // STM32 has one shared EXTI for each pin number, 0-15
uint8_t p_num = pin->number; if (!stm_peripherals_exti_is_free(pin->number)) {
if(_objs[p_num]) { mp_raise_RuntimeError(translate("Pin interrupt already in use"));
mp_raise_ValueError(translate("Pin number already reserved by EXTI"));
} }
_objs[p_num] = self;
// Allocate pulse buffer // Allocate pulse buffer
self->buffer = (uint16_t *) m_malloc(maxlen * sizeof(uint16_t), false); self->buffer = (uint16_t *) m_malloc(maxlen * sizeof(uint16_t), false);
if (self->buffer == NULL) { if (self->buffer == NULL) {
//TODO: free the EXTI here?
mp_raise_msg_varg(&mp_type_MemoryError, translate("Failed to allocate RX buffer of %d bytes"), mp_raise_msg_varg(&mp_type_MemoryError, translate("Failed to allocate RX buffer of %d bytes"),
maxlen * sizeof(uint16_t)); maxlen * sizeof(uint16_t));
} }
@ -165,16 +164,21 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu
// Add to active PulseIns // Add to active PulseIns
refcount++; refcount++;
// EXTI pins can also be read as an input if (!stm_peripherals_exti_reserve(pin->number)) {
mp_raise_RuntimeError(translate("Pin interrupt already in use"));
}
GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = pin_mask(pin->number); GPIO_InitStruct.Pin = pin_mask(pin->number);
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct); HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct);
stm_peripherals_exti_set_callback(pulsein_exti_event_handler, pin->number);
// Store PulseIn object for use in callback
callback_obj_ref[pin->number] = self;
// Interrupt starts immediately // Interrupt starts immediately
assign_EXTI_Interrupt(self, pin->number); stm_peripherals_exti_enable(pin->number);
HAL_NVIC_EnableIRQ(self->irq);
common_hal_mcu_pin_claim(pin); common_hal_mcu_pin_claim(pin);
} }
@ -187,7 +191,8 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
return; return;
} }
//Remove pulsein slot from shared array //Remove pulsein slot from shared array
_objs[self->pin->number] = NULL; callback_obj_ref[self->pin->number] = NULL;
stm_peripherals_exti_free(self->pin->number);
reset_pin_number(self->pin->port, self->pin->number); reset_pin_number(self->pin->port, self->pin->number);
self->pin = NULL; self->pin = NULL;
@ -198,7 +203,7 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
} }
void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) { void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) {
HAL_NVIC_DisableIRQ(self->irq); stm_peripherals_exti_disable(self->pin->number);
self->paused = true; self->paused = true;
} }
@ -232,27 +237,27 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint16_t tri
self->last_count = 0; self->last_count = 0;
self->last_overflow = 0; self->last_overflow = 0;
HAL_NVIC_EnableIRQ(self->irq); stm_peripherals_exti_enable(self->pin->number);
} }
void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) { void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) {
HAL_NVIC_DisableIRQ(self->irq); stm_peripherals_exti_disable(self->pin->number);
self->start = 0; self->start = 0;
self->len = 0; self->len = 0;
HAL_NVIC_EnableIRQ(self->irq); stm_peripherals_exti_enable(self->pin->number);
} }
uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) { uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) {
HAL_NVIC_DisableIRQ(self->irq); stm_peripherals_exti_disable(self->pin->number);
if (index < 0) { if (index < 0) {
index += self->len; index += self->len;
} }
if (index < 0 || index >= self->len) { if (index < 0 || index >= self->len) {
HAL_NVIC_EnableIRQ(self->irq); stm_peripherals_exti_enable(self->pin->number);
mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_PulseIn); mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_PulseIn);
} }
uint16_t value = self->buffer[(self->start + index) % self->maxlen]; uint16_t value = self->buffer[(self->start + index) % self->maxlen];
HAL_NVIC_EnableIRQ(self->irq); stm_peripherals_exti_enable(self->pin->number);
return value; return value;
} }
@ -260,11 +265,11 @@ uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) {
if (self->len == 0) { if (self->len == 0) {
mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_PulseIn); mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_PulseIn);
} }
HAL_NVIC_DisableIRQ(self->irq); stm_peripherals_exti_disable(self->pin->number);
uint16_t value = self->buffer[self->start]; uint16_t value = self->buffer[self->start];
self->start = (self->start + 1) % self->maxlen; self->start = (self->start + 1) % self->maxlen;
self->len--; self->len--;
HAL_NVIC_EnableIRQ(self->irq); stm_peripherals_exti_enable(self->pin->number);
return value; return value;
} }
@ -280,62 +285,3 @@ bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t* self) {
uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self) { uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self) {
return self->len; return self->len;
} }
static void assign_EXTI_Interrupt(pulseio_pulsein_obj_t* self, uint8_t num) {
if (num == 0) {
self->irq = EXTI0_IRQn;
} else if (num == 1) {
self->irq = EXTI1_IRQn;
} else if (num == 2) {
self->irq = EXTI2_IRQn;
} else if (num == 3) {
self->irq = EXTI3_IRQn;
} else if (num == 4) {
self->irq = EXTI4_IRQn;
} else if (num >= 5 && num <= 9 ) {
self->irq = EXTI9_5_IRQn;
} else if (num >= 10 && num <= 15) {
self->irq = EXTI15_10_IRQn;
}
}
void EXTI0_IRQHandler(void)
{
pulsein_exti_event_handler(0);
}
void EXTI1_IRQHandler(void)
{
pulsein_exti_event_handler(1);
}
void EXTI2_IRQHandler(void)
{
pulsein_exti_event_handler(2);
}
void EXTI3_IRQHandler(void)
{
pulsein_exti_event_handler(3);
}
void EXTI4_IRQHandler(void)
{
pulsein_exti_event_handler(4);
}
void EXTI9_5_IRQHandler(void)
{
uint32_t pending = EXTI->PR;
for (uint i = 5; i <= 9; i++) {
if(pending & (1 << i)) {
pulsein_exti_event_handler(i);
}
}
}
void EXTI15_10_IRQHandler(void)
{
uint32_t pending = EXTI->PR;
for (uint i = 10; i <= 15; i++) {
if(pending & (1 << i)) {
pulsein_exti_event_handler(i);
}
}
}

View File

@ -35,7 +35,6 @@ typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
const mcu_pin_obj_t* pin; const mcu_pin_obj_t* pin;
IRQn_Type irq;
bool idle_state; bool idle_state;
bool paused; bool paused;
volatile bool first_edge; volatile bool first_edge;

View File

@ -4,6 +4,7 @@ INTERNAL_LIBM ?= 1
USB_SERIAL_NUMBER_LENGTH ?= 24 USB_SERIAL_NUMBER_LENGTH ?= 24
ifeq ($(MCU_VARIANT),STM32F405xx) ifeq ($(MCU_VARIANT),STM32F405xx)
CIRCUITPY_ALARM = 1
CIRCUITPY_CANIO = 1 CIRCUITPY_CANIO = 1
CIRCUITPY_FRAMEBUFFERIO ?= 1 CIRCUITPY_FRAMEBUFFERIO ?= 1
CIRCUITPY_RGBMATRIX ?= 1 CIRCUITPY_RGBMATRIX ?= 1

View File

@ -0,0 +1,134 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdbool.h>
#include "py/mpconfig.h"
#include "py/gc.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "peripherals/exti.h"
STATIC bool stm_exti_reserved[STM32_GPIO_PORT_SIZE];
STATIC void (*stm_exti_callback[STM32_GPIO_PORT_SIZE])(uint8_t num);
void exti_reset(void) {
for (size_t i = 0;i < STM32_GPIO_PORT_SIZE; i++) {
stm_exti_reserved[i] = false;
stm_exti_callback[i] = NULL;
stm_peripherals_exti_disable(i);
}
}
bool stm_peripherals_exti_is_free(uint8_t num) {
return !stm_exti_reserved[num];
}
bool stm_peripherals_exti_reserve(uint8_t num) {
if (!stm_peripherals_exti_is_free(num)) {
return false;
}
stm_exti_reserved[num] = true;
return true;
}
void stm_peripherals_exti_enable(uint8_t num) {
HAL_NVIC_EnableIRQ(stm_peripherals_exti_get_irq(num));
}
void stm_peripherals_exti_disable(uint8_t num) {
HAL_NVIC_DisableIRQ(stm_peripherals_exti_get_irq(num));
}
void stm_peripherals_exti_set_callback(void(*callback)(uint8_t num), uint8_t number) {
stm_exti_callback[number] = callback;
}
void stm_peripherals_exti_free(uint8_t num) {
stm_exti_reserved[num] = true;
}
IRQn_Type stm_peripherals_exti_get_irq(uint8_t num) {
if (num == 0) {
return EXTI0_IRQn;
} else if (num == 1) {
return EXTI1_IRQn;
} else if (num == 2) {
return EXTI2_IRQn;
} else if (num == 3) {
return EXTI3_IRQn;
} else if (num == 4) {
return EXTI4_IRQn;
} else if (num >= 5 && num <= 9 ) {
return EXTI9_5_IRQn;
} else if (num >= 10 && num <= 15) {
return EXTI15_10_IRQn;
} else {
return 0;
}
}
void EXTI0_IRQHandler(void)
{
stm_exti_callback[0](0);
}
void EXTI1_IRQHandler(void)
{
stm_exti_callback[1](1);
}
void EXTI2_IRQHandler(void)
{
stm_exti_callback[2](2);
}
void EXTI3_IRQHandler(void)
{
stm_exti_callback[3](3);
}
void EXTI4_IRQHandler(void)
{
stm_exti_callback[4](4);
}
void EXTI9_5_IRQHandler(void)
{
uint32_t pending = EXTI->PR;
for (uint i = 5; i <= 9; i++) {
if(pending & (1 << i)) {
stm_exti_callback[i](i);
}
}
}
void EXTI15_10_IRQHandler(void)
{
uint32_t pending = EXTI->PR;
for (uint i = 10; i <= 15; i++) {
if(pending & (1 << i)) {
stm_exti_callback[i](i);
}
}
}

View File

@ -0,0 +1,43 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __MICROPY_INCLUDED_STM32_PERIPHERALS_EXTI_H__
#define __MICROPY_INCLUDED_STM32_PERIPHERALS_EXTI_H__
#include STM32_HAL_H
#define STM32_GPIO_PORT_SIZE 16
void exti_reset(void);
bool stm_peripherals_exti_is_free(uint8_t num);
bool stm_peripherals_exti_reserve(uint8_t num);
void stm_peripherals_exti_enable(uint8_t num);
void stm_peripherals_exti_disable(uint8_t num);
void stm_peripherals_exti_set_callback(void(*callback)(uint8_t num), uint8_t number);
void stm_peripherals_exti_free(uint8_t num);
IRQn_Type stm_peripherals_exti_get_irq(uint8_t num);
#endif // __MICROPY_INCLUDED_STM32_PERIPHERALS_EXTI_H__

View File

@ -0,0 +1,25 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

View File

@ -0,0 +1,25 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

View File

@ -50,6 +50,9 @@
#if CIRCUITPY_SDIOIO #if CIRCUITPY_SDIOIO
#include "common-hal/sdioio/SDCard.h" #include "common-hal/sdioio/SDCard.h"
#endif #endif
#if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM
#include "exti.h"
#endif
#include "clocks.h" #include "clocks.h"
#include "gpio.h" #include "gpio.h"
@ -247,6 +250,9 @@ void reset_port(void) {
#if CIRCUITPY_PWMIO #if CIRCUITPY_PWMIO
pwmout_reset(); pwmout_reset();
#endif #endif
#if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM
exti_reset();
#endif
} }
void reset_to_bootloader(void) { void reset_to_bootloader(void) {
@ -380,6 +386,7 @@ void RTC_WKUP_IRQHandler(void) {
supervisor_tick(); supervisor_tick();
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&_hrtc, RTC_FLAG_WUTF); __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&_hrtc, RTC_FLAG_WUTF);
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
_hrtc.State = HAL_RTC_STATE_READY;
} }
volatile bool alarmed_already = false; volatile bool alarmed_already = false;

View File

@ -228,7 +228,7 @@ mp_obj_t alarm_get_wake_alarm(void) {
} }
// Initialize .wake_alarm value. // Initialize .wake_alarm value.
void alarm_save_wake_alarm(void) { void common_hal_alarm_save_wake_alarm(void) {
// Equivalent of: // Equivalent of:
// alarm.wake_alarm = alarm // alarm.wake_alarm = alarm
mp_map_elem_t *elem = mp_map_elem_t *elem =

View File

@ -41,20 +41,20 @@ extern mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const
// it will exit idle as if deep sleep was exited. // it will exit idle as if deep sleep was exited.
extern void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms); extern void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms);
// Deep sleep is entered outside of the VM so we omit the `common_hal_` prefix. // Deep sleep is entered outside of the VM so we omit the `common_hal_` prefix.
extern NORETURN void alarm_enter_deep_sleep(void); extern NORETURN void common_hal_alarm_enter_deep_sleep(void);
// Fetches value from module dict. // Fetches value from module dict.
extern mp_obj_t alarm_get_wake_alarm(void); extern mp_obj_t common_hal_alarm_get_wake_alarm(void);
extern void common_hal_alarm_gc_collect(void); extern void common_hal_alarm_gc_collect(void);
extern mp_obj_t common_hal_alarm_get_wake_alarm(void); extern mp_obj_t common_hal_alarm_get_wake_alarm(void);
// Used by wake-up code. // Used by wake-up code.
void alarm_save_wake_alarm(void); void common_hal_alarm_save_wake_alarm(void);
// True if an alarm is alerting. This is most useful for pretend deep sleep. // True if an alarm is alerting. This is most useful for pretend deep sleep.
extern bool alarm_woken_from_sleep(void); extern bool common_hal_alarm_woken_from_sleep(void);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H #endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H

View File

@ -58,6 +58,7 @@ mp_obj_t MP_WEAK rtc_get_time_source_time(void) {
//| //|
STATIC mp_obj_t alarm_time_timealarm_make_new(const mp_obj_type_t *type, STATIC mp_obj_t alarm_time_timealarm_make_new(const mp_obj_type_t *type,
mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
alarm_time_timealarm_obj_t *self = m_new_obj(alarm_time_timealarm_obj_t); alarm_time_timealarm_obj_t *self = m_new_obj(alarm_time_timealarm_obj_t);
self->base.type = &alarm_time_timealarm_type; self->base.type = &alarm_time_timealarm_type;