Initial commit.

This commit is contained in:
jun2sak 2021-02-17 20:53:18 +09:00
parent 261b077209
commit e6350ff834
18 changed files with 1218 additions and 3 deletions

3
main.c
View File

@ -214,6 +214,7 @@ STATIC bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec
decompress(compressed, decompressed);
mp_hal_stdout_tx_str(decompressed);
pyexec_file(filename, exec_result);
dbg_printf("pyexec_file end result=(code=%d, line=%d)\r\n", exec_result->return_code, exec_result->exception_line);
return true;
}
@ -259,6 +260,7 @@ STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
}
STATIC bool run_code_py(safe_mode_t safe_mode) {
dbg_printf("run_code_py (%d)\r\n", (int)safe_mode);
bool serial_connected_at_start = serial_connected();
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
serial_write("\n");
@ -434,6 +436,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
FIL* boot_output_file;
STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
dbg_printf("run_boot_py (%d)\r\n", (int)safe_mode);
// If not in safe mode, run boot before initing USB and capture output in a
// file.
if (filesystem_present() && safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) {

View File

@ -87,6 +87,7 @@ INC += -I../../supervisor/shared/usb
#Debugging/Optimization
ifeq ($(DEBUG), 1)
CFLAGS += -ggdb3
CFLAGS += -DNDEBUG
OPTIMIZATION_FLAGS = -Og
else
OPTIMIZATION_FLAGS ?= -O2 -fno-inline-functions
@ -94,6 +95,13 @@ else
CFLAGS += -flto -flto-partition=none
endif
ifeq ($(MY_DBG), 1)
CFLAGS += -DMY_DBG
endif
ifeq ($(MY_DEBUGUART), 1)
CFLAGS += -DMY_DEBUGUART=1
endif
# option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk
CFLAGS += $(OPTIMIZATION_FLAGS)

View File

@ -0,0 +1,48 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 microDev
* Copyright (c) 2020 Dan Halbert 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"
//static RTC_DATA_ATTR uint8_t _sleep_mem[SLEEP_MEMORY_LENGTH];
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,41 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Dan Halbert 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_NRF_COMMON_HAL_ALARM_SLEEPMEMORY_H
#define MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM_SLEEPMEMORY_H
#include "py/obj.h"
// not implemented yet
#define SLEEP_MEMORY_LENGTH (4)
typedef struct {
mp_obj_base_t base;
} alarm_sleep_memory_obj_t;
extern void alarm_sleep_memory_reset(void);
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM_SLEEPMEMORY_H

View File

@ -0,0 +1,204 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
* Copyright (c) 2020 Dan Halbert 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 <stdio.h>
#include <string.h>
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/SleepMemory.h"
#include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/alarm/touch/TouchAlarm.h"
//#include "shared-bindings/wifi/__init__.h"
//#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/port.h"
#include "nrf.h"
#include "nrf_power.h"
#include "nrfx.h"
#include "nrfx_gpiote.h"
extern void _debug_print(const char* s);
extern void _xxx_dumpRTC(void);//XXXX
#define DEBUG_LED_PIN (NRF_GPIO_PIN_MAP(1, 11)) // P1_11 = LED
void _debug_led_init(void) {
nrf_gpio_cfg_output(DEBUG_LED_PIN);
}
void _debug_led_set(int v) {
nrf_gpio_pin_write(DEBUG_LED_PIN, v);
}
// Singleton instance of SleepMemory.
const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
.base = {
.type = &alarm_sleep_memory_type,
},
};
void alarm_reset(void) {
//alarm_sleep_memory_reset();
alarm_pin_pinalarm_reset();
alarm_time_timealarm_reset();
//alarm_touch_touchalarm_reset();
}
extern uint32_t reset_reason_saved;
STATIC uint32_t _get_wakeup_cause(void) {
if (alarm_pin_pinalarm_woke_us_up()) {
return NRF_SLEEP_WAKEUP_GPIO;
}
if (alarm_time_timealarm_woke_us_up()) {
return NRF_SLEEP_WAKEUP_TIMER;
}
#if 0
if (alarm_touch_touchalarm_woke_us_up()) {
return ESP_SLEEP_WAKEUP_TOUCHPAD;
}
return esp_sleep_get_wakeup_cause();
#endif
if (reset_reason_saved & NRF_POWER_RESETREAS_RESETPIN_MASK) {
return NRF_SLEEP_WAKEUP_RESETPIN;
}
else if (reset_reason_saved & NRF_POWER_RESETREAS_OFF_MASK) {
return NRF_SLEEP_WAKEUP_GPIO;
}
else if (reset_reason_saved & NRF_POWER_RESETREAS_VBUS_MASK) {
return NRF_SLEEP_WAKEUP_VBUS;
}
return NRF_SLEEP_WAKEUP_UNDEFINED;
}
bool alarm_woken_from_sleep(void) {
uint32_t cause = _get_wakeup_cause();
return (cause == NRF_SLEEP_WAKEUP_GPIO || cause == NRF_SLEEP_WAKEUP_TIMER
|| cause == NRF_SLEEP_WAKEUP_TOUCHPAD
|| cause == NRF_SLEEP_WAKEUP_RESETPIN);
}
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
uint32_t cause = _get_wakeup_cause();
if (cause & 0x80000000) {
printf("wakeup cause = 0x%08X\r\n", (int)cause);
}
switch (cause) {
case NRF_SLEEP_WAKEUP_TIMER: {
return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
}
case NRF_SLEEP_WAKEUP_TOUCHPAD: {
return mp_const_none;
}
case NRF_SLEEP_WAKEUP_GPIO: {
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
}
}
return mp_const_none;
}
mp_obj_t common_hal_alarm_get_wake_alarm(void) {
mp_obj_t obj = _get_wake_alarm(0, NULL);
//_xxx_dumpRTC();//XXX
return obj;
}
// 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);
#if 0
alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms);
#endif
//_xxx_dumpRTC();
}
STATIC void _idle_until_alarm(void) {
int ct = 40;
// Poll for alarms.
while (!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
// Allow ctrl-C interrupt.
if (alarm_woken_from_sleep()) {
alarm_save_wake_alarm();
int cause = _get_wakeup_cause();
printf("wakeup(%d)\r\n", cause); //XXX
return;
}
port_idle_until_interrupt();
if (ct > 0) {
printf("_"); --ct;
}
}
}
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
mp_obj_t r_obj = mp_const_none;
_setup_sleep_alarms(false, n_alarms, alarms);
_debug_print("\r\nsleep...");
_idle_until_alarm();
if (mp_hal_is_interrupted()) {
_debug_print("mp_hal_is_interrupted\r\n");
r_obj = mp_const_none;
}
else {
r_obj = _get_wake_alarm(n_alarms, alarms);
alarm_reset();
}
return r_obj;
}
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
_setup_sleep_alarms(true, n_alarms, alarms);
}
void nrf_deep_sleep_start(void) {
_debug_print("go system off..\r\n");
sd_power_system_off();
}
void NORETURN alarm_enter_deep_sleep(void) {
alarm_pin_pinalarm_prepare_for_deep_sleep();
//alarm_touch_touchalarm_prepare_for_deep_sleep();
nrf_deep_sleep_start();
// should not reach here..
while(1) ;
}
void common_hal_alarm_gc_collect(void) {
void* p = alarm_get_wake_alarm();
gc_collect_ptr(p);
}

View File

@ -0,0 +1,45 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Dan Halbert 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_NRF_COMMON_HAL_ALARM__INIT__H
#define MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM__INIT__H
#include "common-hal/alarm/SleepMemory.h"
typedef enum {
NRF_SLEEP_WAKEUP_UNDEFINED,
NRF_SLEEP_WAKEUP_GPIO,
NRF_SLEEP_WAKEUP_TIMER,
NRF_SLEEP_WAKEUP_TOUCHPAD,
NRF_SLEEP_WAKEUP_VBUS,
NRF_SLEEP_WAKEUP_RESETPIN,
} nrf_sleep_source_t;
extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
extern void alarm_reset(void);
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM__INIT__H

View File

@ -0,0 +1,260 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Dan Halbert for Adafruit Industries
* Copyright (c) 2020 Scott Shawcroft 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 <stdio.h>
#include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "nrfx.h"
#include "nrf_gpio.h"
#include "nrfx_gpiote.h"
#include "nrf_soc.h"
#include <string.h>
#include "supervisor/serial.h" // dbg_print
#define WPIN_UNUSED 0xFF
volatile char _pinhandler_gpiote_count;
volatile nrfx_gpiote_pin_t _pinhandler_ev_pin;
#define MYGPIOTE_EV_PIN_UNDEF 0xFF
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 0
if (edge) {
mp_raise_ValueError(translate("Cannot wake on pin edge. Only level."));
}
if (pull && !GPIO_IS_VALID_OUTPUT_GPIO(pin->number)) {
mp_raise_ValueError(translate("Cannot pull on input-only pin."));
}
#endif
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 false;
}
bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self) {
return self->pull;
}
static void pinalarm_gpiote_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
++_pinhandler_gpiote_count;
_pinhandler_ev_pin = pin;
}
bool alarm_pin_pinalarm_woke_us_up(void) {
return (_pinhandler_gpiote_count > 0 && _pinhandler_ev_pin != MYGPIOTE_EV_PIN_UNDEF);
}
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
// First, check to see if we match any given 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->number == _pinhandler_ev_pin) {
return alarms[i];
}
}
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t);
alarm->base.type = &alarm_pin_pinalarm_type;
alarm->pin = NULL;
// Map the pin number back to a pin object.
for (size_t i = 0; i < mcu_pin_globals.map.used; i++) {
const mcu_pin_obj_t* pin_obj = MP_OBJ_TO_PTR(mcu_pin_globals.map.table[i].value);
if ((size_t) pin_obj->number == _pinhandler_ev_pin) {
alarm->pin = mcu_pin_globals.map.table[i].value;
break;
}
}
return alarm;
}
// These must be static because we need to configure pulls later, right before
// deep sleep.
static uint64_t high_alarms = 0;
static uint64_t low_alarms = 0;
static uint64_t pull_pins = 0;
void alarm_pin_pinalarm_reset(void) {
for (size_t i = 0; i < 64; i++) {
uint64_t mask = 1ull << i;
bool high = (high_alarms & mask) != 0;
bool low = (low_alarms & mask) != 0;
if (!(high || low)) {
continue;
}
reset_pin_number(i);
nrfx_gpiote_in_event_disable((nrfx_gpiote_pin_t)i);
nrfx_gpiote_in_uninit((nrfx_gpiote_pin_t)i);
}
high_alarms = 0;
low_alarms = 0;
pull_pins = 0;
}
void _setup2(void) {
nrfx_gpiote_in_config_t cfg = {
.sense = NRF_GPIOTE_POLARITY_TOGGLE,
.pull = NRF_GPIO_PIN_PULLUP,
.is_watcher = false,
.hi_accuracy = true,
.skip_gpio_setup = false
};
for(size_t i = 0; i < 64; ++i) {
uint64_t mask = 1ull << i;
int pull = 0;
int sense = 0;
if (((high_alarms & mask) == 0) && ((low_alarms & mask) == 0)) {
continue;
}
if (((high_alarms & mask) != 0) && ((low_alarms & mask) == 0)) {
cfg.sense = NRF_GPIOTE_POLARITY_LOTOHI;
cfg.pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_NOPULL;
pull = -1; sense = 1;
}
else
if (((high_alarms & mask) == 0) && ((low_alarms & mask) != 0)) {
cfg.sense = NRF_GPIOTE_POLARITY_HITOLO;
cfg.pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLUP : NRF_GPIO_PIN_NOPULL;
pull = 1; sense = -1;
}
else {
cfg.sense = NRF_GPIOTE_POLARITY_TOGGLE;
cfg.pull = NRF_GPIO_PIN_NOPULL;
sense = 9;
}
nrfx_gpiote_in_init((nrfx_gpiote_pin_t)i, &cfg, pinalarm_gpiote_handler);
nrfx_gpiote_in_event_enable((nrfx_gpiote_pin_t)i, true);
printf("pin=%d, sense=%d, pull=%d\r\n", i, sense, pull);
}
}
void _setup_pin1_for_lightsleep(void) {
if ( nrfx_gpiote_is_init() ) {
nrfx_gpiote_uninit();
}
nrfx_gpiote_init(NRFX_GPIOTE_CONFIG_IRQ_PRIORITY);
_pinhandler_gpiote_count = 0;
_pinhandler_ev_pin = MYGPIOTE_EV_PIN_UNDEF;
_setup2();
}
void _setup_pin1_for_deepsleep(void) {
for(size_t i = 0; i < 64; ++i) {
uint64_t mask = 1ull << i;
int pull = 0;
int sense = 0;
if (((high_alarms & mask) == 0) && ((low_alarms & mask) == 0)) {
continue;
}
if (((high_alarms & mask) != 0) && ((low_alarms & mask) == 0)) {
pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_NOPULL;
nrf_gpio_cfg_input((uint32_t)i, (nrf_gpio_pin_pull_t)pull);
nrf_gpio_cfg_sense_set((uint32_t)i, NRF_GPIO_PIN_SENSE_HIGH);
sense = NRF_GPIO_PIN_SENSE_HIGH;
}
else
if (((high_alarms & mask) == 0) && ((low_alarms & mask) != 0)) {
pull = ((pull_pins & mask) != 0) ? NRF_GPIO_PIN_PULLUP : NRF_GPIO_PIN_NOPULL;
nrf_gpio_cfg_input((uint32_t)i, (nrf_gpio_pin_pull_t)pull);
nrf_gpio_cfg_sense_set((uint32_t)i, NRF_GPIO_PIN_SENSE_LOW);
sense = NRF_GPIO_PIN_SENSE_LOW;
}
printf("pin=%d, sense=%d, pull=%d\r\n", i, sense, pull);
}
#if 0
uint32_t pin_number = 2;
NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number);
dbg_printf(" 2 PIN_CNF=0x%08X\r\n", (unsigned int)(reg->PIN_CNF[pin_number]));
pin_number = 28;
reg = nrf_gpio_pin_port_decode(&pin_number);
dbg_printf("28 PIN_CNF=0x%08X\r\n", (unsigned int)(reg->PIN_CNF[pin_number]));
#endif
}
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
// Bitmask of wake up settings.
size_t high_count = 0;
size_t low_count = 0;
int pin_number = -1;
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]);
pin_number = alarm->pin->number;
dbg_printf("alarm_pin_pinalarm_set_alarms(pin#=%d, val=%d, pull=%d)\r\n", pin_number, alarm->value, alarm->pull);
if (alarm->value) {
high_alarms |= 1ull << pin_number;
high_count++;
} else {
low_alarms |= 1ull << pin_number;
low_count++;
}
if (alarm->pull) {
pull_pins |= 1ull << pin_number;
}
}
if (pin_number != -1) {
if (!deep_sleep) {
_setup_pin1_for_lightsleep();
}
else {
//_setup_pin1_for_deepsleep(pin_number);
}
}
else {
dbg_printf("alarm_pin_pinalarm_set_alarms() no valid pins\r\n");
}
}
void alarm_pin_pinalarm_prepare_for_deep_sleep(void) {
_setup_pin1_for_deepsleep();
}

View File

@ -0,0 +1,41 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Dan Halbert 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_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,38 @@
//#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 0
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); }
#endif
return self_in;
}
void common_hal_alarm_io_disable (void) {
#if 0
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0 | ESP_SLEEP_WAKEUP_EXT1);
#endif
}

View File

@ -0,0 +1,101 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Dan Halbert 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 "esp_sleep.h"
#include "py/runtime.h"
//#include "supervisor/esp_port.h"
#include <stdio.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;
}
extern volatile int rtc_woke_up_counter;
bool alarm_time_timealarm_woke_us_up(void) {
return rtc_woke_up_counter;
}
extern void port_disable_interrupt_after_ticks_ch(uint32_t channel);
void alarm_time_timealarm_reset(void) {
port_disable_interrupt_after_ticks_ch(1);
rtc_woke_up_counter = 0;
}
extern void port_interrupt_after_ticks_ch(uint32_t channel, uint32_t ticks);//XXX in port.c
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
bool timealarm_set = false;
alarm_time_timealarm_obj_t *timealarm = MP_OBJ_NULL;
for (size_t i = 0; i < n_alarms; i++) {
if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) {
continue;
}
if (timealarm_set) {
mp_raise_ValueError(translate("Only one alarm.time alarm can be set."));
}
timealarm = MP_OBJ_TO_PTR(alarms[i]);
timealarm_set = true;
}
if (!timealarm_set) {
return;
}
// Compute how long to actually sleep, considering the time now.
mp_float_t now_secs = uint64_to_float(common_hal_time_monotonic_ms()) / 1000.0f;
mp_float_t wakeup_in_secs = MAX(0.0f, timealarm->monotonic_time - now_secs);
int wsecs = (int)(wakeup_in_secs);
if (wsecs > 510) { //XXX
mp_raise_ValueError(translate("Alarm time is too far."));
}
uint32_t wakeup_in_ticks = (uint32_t)(wakeup_in_secs * 1024.0f);
//printf("alarm_time_timealarm_set_alarms() %d secs 0x%08X ticks\r\n", wsecs, (int)wakeup_in_ticks);
port_interrupt_after_ticks_ch(1, wakeup_in_ticks);
rtc_woke_up_counter = 0;
}

View File

@ -0,0 +1,40 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Dan Halbert 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,185 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 microDev
*
* 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"
//#include "esp_sleep.h"
//#include "peripherals/touch.h"
//#include "supervisor/esp_port.h"
static uint16_t touch_channel_mask;
static volatile bool woke_up = false;
void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) {
#if 0
if (pin->touch_channel == TOUCH_PAD_MAX) {
mp_raise_ValueError(translate("Invalid pin"));
}
claim_pin(pin);
#endif
self->pin = pin;
}
mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(const size_t n_alarms, const mp_obj_t *alarms) {
// First, check to see if we match any given alarms.
for (size_t i = 0; i < n_alarms; i++) {
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_touch_touchalarm_type)) {
return alarms[i];
}
}
// Create TouchAlarm object.
alarm_touch_touchalarm_obj_t *alarm = m_new_obj(alarm_touch_touchalarm_obj_t);
alarm->base.type = &alarm_touch_touchalarm_type;
alarm->pin = NULL;
#if 0
touch_pad_t wake_channel = touch_pad_get_current_meas_channel();
if (wake_channel == TOUCH_PAD_MAX) {
return alarm;
}
// Map the pin number back to a pin object.
for (size_t i = 0; i < mcu_pin_globals.map.used; i++) {
const mcu_pin_obj_t* pin_obj = MP_OBJ_TO_PTR(mcu_pin_globals.map.table[i].value);
if (pin_obj->touch_channel == wake_channel) {
alarm->pin = mcu_pin_globals.map.table[i].value;
break;
}
}
#endif
return alarm;
}
// This is used to wake the main CircuitPython task.
void touch_interrupt(void *arg) {
(void) arg;
#if 0
woke_up = true;
BaseType_t task_wakeup;
vTaskNotifyGiveFromISR(circuitpython_task, &task_wakeup);
if (task_wakeup) {
portYIELD_FROM_ISR();
}
#endif
}
void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms) {
#if 0
bool touch_alarm_set = false;
alarm_touch_touchalarm_obj_t *touch_alarm = MP_OBJ_NULL;
for (size_t i = 0; i < n_alarms; i++) {
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_touch_touchalarm_type)) {
if (deep_sleep && touch_alarm_set) {
mp_raise_ValueError(translate("Only one TouchAlarm can be set in deep sleep."));
}
touch_alarm = MP_OBJ_TO_PTR(alarms[i]);
touch_channel_mask |= 1 << touch_alarm->pin->number;
touch_alarm_set = true;
}
}
if (!touch_alarm_set) {
return;
}
// configure interrupt for pretend to deep sleep
// this will be disabled if we actually deep sleep
// reset touch peripheral
peripherals_touch_reset();
peripherals_touch_never_reset(true);
for (uint8_t i = 1; i <= 14; i++) {
if ((touch_channel_mask & 1 << i) != 0) {
touch_pad_t touch_channel = (touch_pad_t)i;
// intialize touchpad
peripherals_touch_init(touch_channel);
// wait for touch data to reset
mp_hal_delay_ms(10);
// configure trigger threshold
uint32_t touch_value;
touch_pad_read_benchmark(touch_channel, &touch_value);
touch_pad_set_thresh(touch_channel, touch_value * 0.1); //10%
}
}
// configure touch interrupt
touch_pad_timeout_set(true, SOC_TOUCH_PAD_THRESHOLD_MAX);
touch_pad_isr_register(touch_interrupt, NULL, TOUCH_PAD_INTR_MASK_ALL);
touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE);
}
void alarm_touch_touchalarm_prepare_for_deep_sleep(void) {
if (!touch_channel_mask) {
return;
}
touch_pad_t touch_channel = TOUCH_PAD_MAX;
for (uint8_t i = 1; i <= 14; i++) {
if ((touch_channel_mask & 1 << i) != 0) {
touch_channel = (touch_pad_t)i;
break;
}
}
// reset touch peripheral
peripherals_touch_never_reset(false);
peripherals_touch_reset();
// intialize touchpad
peripherals_touch_init(touch_channel);
// configure touchpad for sleep
touch_pad_sleep_channel_enable(touch_channel, true);
touch_pad_sleep_channel_enable_proximity(touch_channel, false);
// wait for touch data to reset
mp_hal_delay_ms(10);
// configure trigger threshold
uint32_t touch_value;
touch_pad_sleep_channel_read_smooth(touch_channel, &touch_value);
touch_pad_sleep_set_threshold(touch_channel, touch_value * 0.1); //10%
// enable touchpad wakeup
esp_sleep_enable_touchpad_wakeup();
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
#endif
}
bool alarm_touch_touchalarm_woke_us_up(void) {
return woke_up;
}
void alarm_touch_touchalarm_reset(void) {
woke_up = false;
touch_channel_mask = 0;
// peripherals_touch_never_reset(false);
}

View File

@ -0,0 +1,46 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 microDev
*
* 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_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H
#define MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H
#include "py/obj.h"
#include "common-hal/microcontroller/Pin.h"
typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t *pin;
} alarm_touch_touchalarm_obj_t;
// Find the alarm object that caused us to wake up or create an equivalent one.
mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(const size_t n_alarms, const mp_obj_t *alarms);
// Check for the wake up alarm from pretend deep sleep.
void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms);
void alarm_touch_touchalarm_prepare_for_deep_sleep(void);
bool alarm_touch_touchalarm_woke_us_up(void);
void alarm_touch_touchalarm_reset(void);
#endif // MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H

View File

@ -42,6 +42,9 @@ CIRCUITPY_FRAMEBUFFERIO ?= 1
CIRCUITPY_COUNTIO = 0
CIRCUITPY_WATCHDOG ?= 1
# Sleep and Wakeup
CIRCUITPY_ALARM = 1
# nRF52840-specific
ifeq ($(MCU_CHIP),nrf52840)

View File

@ -116,7 +116,7 @@
// GPIO interrupt
#define NRFX_GPIOTE_ENABLED 1
#define NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 1
#define NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 2
#define NRFX_GPIOTE_CONFIG_IRQ_PRIORITY 7
// NVM controller

View File

@ -27,6 +27,10 @@
#include <stdint.h>
#include "supervisor/port.h"
#include "supervisor/board.h"
#ifdef MY_DEBUGUART
#include "supervisor/serial.h" // dbg_printf()
extern void _debug_uart_init(void);
#endif
#include "nrfx/hal/nrf_clock.h"
#include "nrfx/hal/nrf_power.h"
@ -90,6 +94,9 @@ static volatile struct {
uint32_t suffix;
} overflow_tracker __attribute__((section(".uninitialized")));
uint32_t reset_reason_saved = 0;
volatile int rtc_woke_up_counter = 0;
void rtc_handler(nrfx_rtc_int_type_t int_type) {
if (int_type == NRFX_RTC_INT_OVERFLOW) {
// Our RTC is 24 bits and we're clocking it at 32.768khz which is 32 (2 ** 5) subticks per
@ -100,9 +107,25 @@ void rtc_handler(nrfx_rtc_int_type_t int_type) {
supervisor_tick();
} else if (int_type == NRFX_RTC_INT_COMPARE0) {
nrfx_rtc_cc_set(&rtc_instance, 0, 0, false);
} else if (int_type == NRFX_RTC_INT_COMPARE1) {
// used in light sleep
++rtc_woke_up_counter;
nrfx_rtc_cc_set(&rtc_instance, 1, 0, false);
}
}
void _xxx_dumpRTC(void) {
dbg_printf("\r\nRTC2\r\n");
NRF_RTC_Type *r = rtc_instance.p_reg;
dbg_printf("PRESCALER=%08X, ", (int)r->PRESCALER);
dbg_printf("COUNTER=%08X ", (int)r->COUNTER);
dbg_printf("INTENSET=%08X ", (int)r->INTENSET);
dbg_printf("EVTENSET=%08X\r\n", (int)r->EVTENSET);
dbg_printf("EVENTS_COMPARE[0..3]=%X,%X,%X,%X ", (int)r->EVENTS_COMPARE[0], (int)r->EVENTS_COMPARE[1], (int)r->EVENTS_COMPARE[2], (int)r->EVENTS_COMPARE[3]);
dbg_printf("CC[0..3]=%08X,%08X,%08X,%08X\r\n", (int)r->CC[0], (int)r->CC[1], (int)r->CC[2], (int)r->CC[3]);
dbg_printf("woke_up=%d\r\n", rtc_woke_up_counter);
}
void tick_init(void) {
if (!nrf_clock_lf_is_running(NRF_CLOCK)) {
nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTART);
@ -124,6 +147,7 @@ void tick_init(void) {
}
}
safe_mode_t port_init(void) {
nrf_peripherals_clocks_init();
@ -153,6 +177,8 @@ safe_mode_t port_init(void) {
analogin_init();
#endif
reset_reason_saved = NRF_POWER->RESETREAS;
// If the board was reset by the WatchDogTimer, we may
// need to boot into safe mode. Reset the RESETREAS bit
// for the WatchDogTimer so we don't encounter this the
@ -171,6 +197,7 @@ safe_mode_t port_init(void) {
return NO_SAFE_MODE;
}
void reset_port(void) {
#ifdef CIRCUITPY_GAMEPAD_TICKS
gamepad_reset();
@ -219,6 +246,10 @@ void reset_port(void) {
#endif
reset_all_pins();
#ifdef MY_DEBUGUART
_debug_uart_init();
#endif
}
void reset_to_bootloader(void) {
@ -295,7 +326,7 @@ void port_disable_tick(void) {
nrfx_rtc_tick_disable(&rtc_instance);
}
void port_interrupt_after_ticks(uint32_t ticks) {
void port_interrupt_after_ticks_ch(uint32_t channel, uint32_t ticks) {
uint32_t current_ticks = nrfx_rtc_counter_get(&rtc_instance);
uint32_t diff = 3;
if (ticks > diff) {
@ -304,7 +335,15 @@ void port_interrupt_after_ticks(uint32_t ticks) {
if (diff > 0xffffff) {
diff = 0xffffff;
}
nrfx_rtc_cc_set(&rtc_instance, 0, current_ticks + diff, true);
nrfx_rtc_cc_set(&rtc_instance, channel, current_ticks + diff, true);
}
void port_disable_interrupt_after_ticks_ch(uint32_t channel) {
nrfx_rtc_cc_disable(&rtc_instance, channel);
}
void port_interrupt_after_ticks(uint32_t ticks) {
port_interrupt_after_ticks_ch(0, ticks);
}
void port_idle_until_interrupt(void) {

View File

@ -29,6 +29,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "py/mpconfig.h"
@ -47,4 +48,6 @@ char serial_read(void);
bool serial_bytes_available(void);
bool serial_connected(void);
int dbg_printf(const char *fmt, ...)__attribute__((format (printf, 1, 2)));
#endif // MICROPY_INCLUDED_SUPERVISOR_SERIAL_H

View File

@ -36,6 +36,103 @@
#include "tusb.h"
#ifdef MY_DEBUGUART
#include <stdio.h>
#include <stdarg.h>
#include "nrfx.h"
#include "nrf_uart.h"
#include "nrfx_uart.h"
const nrfx_uarte_t _dbg_uart_inst = NRFX_UARTE_INSTANCE(1);
static int _dbg_uart_initialized = 0;
#define DBG_PBUF_LEN 80
static char _dbg_pbuf[DBG_PBUF_LEN+1];
void _debug_uart_init(void) {
//if (_dbg_uart_initialized) return;
nrfx_uarte_config_t config = {
.pseltxd = 26,
.pselrxd = 15,
.pselcts = NRF_UARTE_PSEL_DISCONNECTED,
.pselrts = NRF_UARTE_PSEL_DISCONNECTED,
.p_context = NULL,
.baudrate = NRF_UART_BAUDRATE_115200,
.interrupt_priority = 7,
.hal_cfg = {
.hwfc = NRF_UARTE_HWFC_DISABLED,
.parity = NRF_UARTE_PARITY_EXCLUDED
}
};
nrfx_uarte_init(&_dbg_uart_inst, &config, NULL);
// drive config
nrf_gpio_cfg(config.pseltxd,
NRF_GPIO_PIN_DIR_OUTPUT,
NRF_GPIO_PIN_INPUT_DISCONNECT,
NRF_GPIO_PIN_PULLUP, // orig=NOPULL
NRF_GPIO_PIN_H0H1, // orig=S0S1
NRF_GPIO_PIN_NOSENSE);
_dbg_uart_initialized = 1;
return;
}
void _debug_printbuf(char* data) {
int siz, l;
while((l = strlen(data)) != 0) {
if (l <= DBG_PBUF_LEN) {
siz = l;
}
else {
siz = DBG_PBUF_LEN;
}
memcpy(_dbg_pbuf, data, siz);
_dbg_pbuf[siz] = 0;
nrfx_uarte_tx(&_dbg_uart_inst, (uint8_t const*)_dbg_pbuf, siz);
data += siz;
}
}
void _debug_print_substr(const char* text, uint32_t length) {
char* data = (char*)text;
int siz;
while(length != 0) {
if (length <= DBG_PBUF_LEN) {
siz = length;
}
else {
siz = DBG_PBUF_LEN;
}
memcpy(_dbg_pbuf, data, siz);
_dbg_pbuf[siz] = 0;
nrfx_uarte_tx(&_dbg_uart_inst, (uint8_t const*)_dbg_pbuf, siz);
data += siz;
length -= siz;
}
}
void _debug_print(const char* s) {
_debug_printbuf((char*)s);
}
void _debug_uart_deinit(void) {
nrfx_uarte_uninit(&_dbg_uart_inst);
}
int dbg_printf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int ret = vprintf(fmt, ap);
va_end(ap);
return ret;
}
extern void _debug_led_init(void);
extern void _debug_led_set(int v);
#else /*!MY_DEBUGUART*/
int dbg_printf(const char *fmt, ...) {
return 0;
}
#endif
/*
* Note: DEBUG_UART currently only works on STM32,
* enabling on another platform will cause a crash.
@ -63,10 +160,19 @@ void serial_early_init(void) {
buf_array, true);
common_hal_busio_uart_never_reset(&debug_uart);
#endif
#ifdef MY_DEBUGUART
_debug_uart_init();
_debug_led_init();
_debug_print("\r\ndebug_uart start\r\n");
#endif
}
void serial_init(void) {
usb_init();
#ifdef MY_DEBUGUART
_debug_uart_init();
#endif
}
bool serial_connected(void) {
@ -144,6 +250,10 @@ void serial_write_substring(const char* text, uint32_t length) {
int uart_errcode;
common_hal_busio_uart_write(&debug_uart, (const uint8_t*) text, length, &uart_errcode);
#endif
#ifdef MY_DEBUGUART
_debug_print_substr(text, length);
#endif
}
void serial_write(const char* text) {